Socket.st
changeset 3059 8be3c1e8dc05
parent 3043 8b7ec7116ae3
child 3072 fbad791801f2
--- a/Socket.st	Tue Jul 16 09:34:26 2013 +0200
+++ b/Socket.st	Tue Jul 16 09:57:18 2013 +0200
@@ -687,25 +687,49 @@
 
 !Socket class methodsFor:'instance creation'!
 
+bindTo:aSocketAddress type:aTypeSymbol
+    "create a socket for a specific type
+     and bind it to aSocketAddress.
+     Type must be:
+        #stream, #datagram or #raw
+
+     Neither connect nor connect-wait is done."
+
+    |newSock|
+
+    newSock := self domain:aSocketAddress domain type:aTypeSymbol.
+    [
+        newSock bindTo:aSocketAddress reuseAddress:true.
+    ] ifCurtailed:[
+        newSock close.
+    ].
+    ^ newSock
+
+
+    "
+        Socket bindTo:(IPSocketAddress anyHost port:8081) type:#stream.
+        Socket bindTo:(IPv6SocketAddress anyHost port:8081) type:#datagram.
+    "
+!
+
 domain:domainSymbol type:type
     "create a socket for domain and type -
      neither any connect nor binding is done.
      Domain must be one of the symbols:
-	#inet, #unix, #appletalk, #decnet, #xns, ...;
+        #inet, #unix, #appletalk, #decnet, #xns, ...;
      Type must be:
-	#stream, #datagram or #raw
-
-     XXX: currently only the #inet domain is supported"
+        #stream, #datagram or #raw
+
+     XXX: currently only the #AF_INET and #AF_INET6 and #AF_UNIX domains are supported"
 
     ^ self new domain:domainSymbol type:type
 
     "
-     Socket domain:#inet type:#stream
-     Socket domain:#inet type:#datagram
-     Socket domain:#unix type:#stream
-     Socket domain:#appletalk type:#stream
-     Socket domain:#decnet type:#stream
-     Socket domain:#irda type:#stream
+     Socket domain:#AF_INET type:#stream
+     Socket domain:#AF_INET type:#datagram
+     Socket domain:#AF_INET6 type:#stream
+     Socket domain:#AF_INET6 type:#datagram
+     Socket domain:#AF_UNIX type:#stream
     "
 !
 
@@ -719,31 +743,36 @@
     "create a TCP socket - no binding or other setup is done,
      neither connect nor connect-wait is done."
 
-    ^ self new domain:#inet type:#stream
-
-    "Socket newUDP"
+    ^ self new domain:#'AF_INET' type:#stream
+
+    "
+      Socket newTCP
+    "
 !
 
 newTCP:aServiceOrNil
     "create a TCP socket for a service -
      neither connect nor connect-wait is done."
 
-    |newSock|
+    |newSock socketAddress socketAddressClass|
 
     newSock := self newTCP.
     (newSock notNil and:[aServiceOrNil notNil]) ifTrue:[
-	[
-	    newSock bindTo:(self portOfService:aServiceOrNil) address:nil.
-	] ifCurtailed:[
-	    newSock close.
-	]
+        [
+            socketAddressClass := newSock socketAddressClass.
+            socketAddress := socketAddressClass hostName:nil serviceName:aServiceOrNil type:#stream.
+            socketAddress hostAddress:socketAddressClass anyAddress.
+            newSock bindTo:socketAddress.
+        ] ifCurtailed:[
+            newSock close.
+        ]
     ].
     ^ newSock
 
 
     "
-	Socket newTCP:'nntp'.
-	Socket newTCP:9995.
+        Socket newTCP:'http-alt'.
+        Socket newTCP:9996.
     "
 !
 
@@ -757,62 +786,137 @@
     ^ self newTCPclientToAddress:aHostAddress port:aService withTimeout:nil
 !
 
-newTCPclientToAddress:aHostAddress port:aService withTimeout:millis
+newTCPclientToAddress:aSocketAddressOrByteArray port:aService withTimeout:millis
     "create a new TCP client socket connecting to a service.
      Return a socket instance if ok, nil on failure.
      If the millis arg is nonNil, stop trying to connect after that many milliseconds
      and return nil."
 
-    ^ self newTCPclientToHost:aHostAddress port:aService withTimeout:millis
+    |port socketAddress|
+
+    aService isString ifTrue:[
+        port := self portOfService:aService protocol:#tcp.
+    ] ifFalse:[
+        port := aService.
+    ].
+    socketAddress := aSocketAddressOrByteArray isSocketAddress 
+                        ifTrue:[aSocketAddressOrByteArray]
+                        ifFalse:[
+                            "Passing ByteArrays is obsolete and only supported for IPv4"
+                            IPSocketAddress hostAddress:aSocketAddressOrByteArray
+                        ].
+    port notNil ifTrue:[
+        socketAddress port:port.
+    ].
+    ^ self newTCPclientToAddress:socketAddress withTimeout:millis
 !
 
-newTCPclientToHost:hostname port:aService
+newTCPclientToAddress:aSocketAddress withTimeout:millis
     "create a new TCP client socket connecting to a service.
      Return a socket instance if ok, nil on failure.
+     If the millis arg is nonNil, stop trying to connect after that many milliseconds
+     and return nil."
+
+    |socket|
+
+    socket := self domain:aSocketAddress domain type:#stream.
+    (socket connectTo:aSocketAddress withTimeout:millis) ifFalse:[
+        socket close.
+        ^ nil
+    ].
+    ^ socket.
+
+    "
+        self newTCPclientToAddress:(IPv6SocketAddress hostName:'www.exept.de' port:80) withTimeout:nil
+    "
+!
+
+newTCPclientToHost:hostNameOrAddress port:aPortOrServiceName
+    "create a new TCP client socket connecting to a service.
+     If hostNameOrAddress is a string, try all the resolved adresses regardless
+     whether fpr IPv4 or IPv6.
+     Return a socket instance if ok, nil on failure.
      Block until a connection is established (but only the current thread;
      not the whole smalltalk).
      See also: #newTCPclientToHost:port:withTimeout:"
 
-    ^ self newTCPclientToHost:hostname port:aService withTimeout:nil
+    ^ self newTCPclientToHost:hostNameOrAddress port:aPortOrServiceName domain:nil withTimeout:nil
 
     "
-      Socket newTCPclientToHost:'localhost' port:'nntp'
+      Socket newTCPclientToHost:'www.exept.de' port:'http'
     "
 
     "Created: 31.10.1995 / 18:54:11 / cg"
 !
 
-newTCPclientToHost:hostname port:aService withTimeout:millis
-    "create a new TCP client socket connecting to a service.
+newTCPclientToHost:hostNameOrAddress port:aPortOrServiceName domain:aDomainSymbolOrNil withTimeout:millis
+    "create a new TCP client socket connecting to a service on hostNameOrAddress.
+     If hostNameOrAddress is a string, try all the resolved adresses.
      Return a socket instance if ok, nil on failure.
+     Set aDomainSymbolOrNil to #AF_INET of #AF_INET6 to connect via a defined protocol.
+     Set aDomainSymbolOrNil to nil, to try all protocols.
      If the millis arg is nonNil, stop trying to connect after that many milliseconds
-     and return nil.."
-
-    |newSock|
-
-    newSock := self newTCP.
-    newSock notNil ifTrue:[
-	(newSock connectTo:hostname
-		 port:(self portOfService:aService protocol:'tcp')
-		 withTimeout:millis
-	) ifFalse:[
-	    newSock close.
-	    ^ nil
-	]
+     and return nil."
+
+    |socket addressInfoList|
+
+    hostNameOrAddress isString ifFalse:[
+        ^ self newTCPclientToAddress:hostNameOrAddress port:aPortOrServiceName withTimeout:millis.
     ].
-    ^ newSock
-"
-same as:
-    ^ (self new) for:hostname port:(self portOfService:aPort).
-"
+
+    addressInfoList := SocketAddress 
+                            getAddressInfo:hostNameOrAddress 
+                            serviceName:aPortOrServiceName 
+                            domain:aDomainSymbolOrNil 
+                            type:#stream
+                            protocol:nil 
+                            flags:0.
+
+    addressInfoList do:[:eachAddressInfo|
+        |domainSymbol lastDomainSymbol|
+
+        domainSymbol := eachAddressInfo domain.
+        domainSymbol ~~ lastDomainSymbol ifTrue:[
+            socket notNil ifTrue:[
+                socket close.
+            ].
+            socket := self domain:domainSymbol type:#stream.
+            lastDomainSymbol := domainSymbol.
+        ].
+        (socket connectTo:eachAddressInfo socketAddress withTimeout:millis) ifTrue:[
+            ^ socket.
+        ].
+    ].
+    socket notNil ifTrue:[
+        socket close.
+    ].
+    ^ nil.
+
     "
-      Socket newTCPclientToHost:'slsv6bt' port:'nntp'
+      Socket newTCPclientToHost:'www.exept.de' port:80 domain:#'AF_INET' withTimeout:1000.
+      Socket newTCPclientToHost:'www.exept.de' port:80 domain:#'AF_INET6' withTimeout:1000.
+      Socket newTCPclientToHost:'www.exept.de' port:80 domain:nil withTimeout:1000.
       Socket newTCPclientToHost:'localhost' port:'nntp' withTimeout:1000
     "
 
     "Modified: / 16.1.1998 / 09:47:06 / stefan"
 !
 
+newTCPclientToHost:hostNameOrAddress port:aPortOrServiceName withTimeout:millis 
+    "create a new TCP client socket connecting to a service on hostNameOrAddress.
+     If hostNameOrAddress is a string, try all the resolved adresses regardless
+     whether fpr IPv4 or IPv6.
+     Return a socket instance if ok, nil on failure.
+     If the millis arg is nonNil, stop trying to connect after that many milliseconds
+     and return nil."
+    
+    ^ self 
+        newTCPclientToHost:hostNameOrAddress
+        port:aPortOrServiceName
+        domain:self defaultIpDomainForConnect
+        withTimeout:millis
+!
+
 newTCPserverAtAnonymousPort
     "create a new TCP server socket providing service on
      a new anonymous port. The portNr is assigned by the OS."
@@ -831,7 +935,7 @@
     "create a UDP socket - no binding or other setup is done,
      neither connect nor connect-wait is done."
 
-    ^ self new domain:#inet type:#datagram
+    ^ self new domain:#'AF_INET' type:#datagram
 
     "Socket newUDP"
 !
@@ -840,21 +944,24 @@
     "create a UDP socket for a service -
      neither connect nor connect-wait is done."
 
-    |newSock|
+    |newSock socketAddressClass socketAddress|
 
     newSock := self newUDP.
     (newSock notNil and:[aServiceOrNil notNil]) ifTrue:[
-	[
-	    newSock bindTo:(self portOfService:aServiceOrNil) address:nil.
-	] ifCurtailed:[
-	    newSock close.
-	]
+        [
+            socketAddressClass := newSock socketAddressClass.
+            socketAddress := socketAddressClass hostName:nil serviceName:aServiceOrNil type:#stream.
+            socketAddress hostAddress:socketAddressClass anyAddress.
+            newSock bindTo:socketAddress.
+        ] ifCurtailed:[
+            newSock close.
+        ]
     ].
     ^ newSock
 
     "
-	Socket newUDP:nil.
-	Socket newUDP:'rwho'.
+        Socket newUDP:4444.
+        Socket newUDP:'activesync'.
     "
 !
 
@@ -870,7 +977,7 @@
      If the system does not support unix domain sockets (i.e. VMS or MSDOS),
      return nil."
 
-    ^ self new domain:#unix type:#stream
+    ^ self new domain:#'AF_UNIX' type:#stream
 
     "
      Socket newUNIX
@@ -902,17 +1009,15 @@
 
     newSock := self newUNIX.
     newSock notNil ifTrue:[
-	(newSock connectTo:'localhost' port:pathName withTimeout:millis) ifFalse:[
-	    newSock close.
-	    ^ nil
-	]
+        (newSock connectTo:(UDSocketAddress name:pathName) withTimeout:millis) ifFalse:[
+            newSock close.
+            ^ nil
+        ]
     ].
     ^ newSock
 
     "
-     |s|
-
-     s := Socket newUNIXclientTo:'/tmp/foo'
+        Socket newUNIXclientTo:'/tmp/foo'
     "
 !
 
@@ -921,21 +1026,12 @@
      If the system does not support unix domain sockets (i.e. VMS or MSDOS),
      return nil."
 
-    |newSock|
-
-    newSock := self newUNIX.
-    newSock notNil ifTrue:[
-	[
-	    newSock bindTo:pathName address:nil.
-	] ifCurtailed:[
-	    newSock close.
-	]
-    ].
-    ^ newSock
+    ^ self bindTo:(UDSocketAddress name:pathName) type:#stream.
 
     "
      |s s2|
 
+    '/tmp/foo' asFilename remove.
      s := Socket newUNIXserverAt:'/tmp/foo'.
      s listenFor:5.
      s2 := s accept.
@@ -952,9 +1048,9 @@
     ^ self domain:domainSymbol type:typeSymbol
 
     "
-     Socket family:#inet type:#stream
-     Socket family:#inet type:#datagram
-     Socket family:#unix type:#stream
+     Socket family:#AF_INET type:#stream
+     Socket family:#AF_INET type:#datagram
+     Socket family:#AF_UNIX type:#stream
     "
 !
 
@@ -1034,6 +1130,17 @@
     "
 ! !
 
+!Socket class methodsFor:'defaults'!
+
+defaultIpDomainForConnect
+    "answer the domain used to look up host names for connect:
+        #AF_INET    use only IPv4
+        #AF_INET6   use only IPv6
+        nil         use both IPv4 and IPv6"
+
+    ^ #AF_INET
+! !
+
 !Socket class methodsFor:'obsolete'!
 
 connectTo:service on:host
@@ -1248,40 +1355,6 @@
 
 !Socket class methodsFor:'queries'!
 
-domainOfProtocol:aProtocol
-    "given a protocols name (i.e. tcp, udp etc) return the domain.
-     This method needs more ... - or is there a way to get this from the system ?"
-
-    "
-     tcp/ip stuff
-    "
-    (aProtocol = 'tcp') ifTrue:[^ #inet].
-    (aProtocol = 'udp') ifTrue:[^ #inet].
-    (aProtocol = 'ip')  ifTrue:[^ #inet].
-    "
-     unix domain
-    "
-    (aProtocol = 'ud')  ifTrue:[^ #unix].
-
-    "
-     add x25 stuff (if any) here ...
-    "
-    "
-     add appletalk stuff (if any) here ...
-    "
-    "
-     add other stuff (if any) here ...
-    "
-    ^ nil
-
-    "
-     Socket domainOfProtocol:'tcp'
-     Socket domainOfProtocol:'ucp'
-     Socket domainOfProtocol:(Socket protocolOfService:'nntp')
-     Socket domainOfProtocol:(Socket protocolOfService:'echo')
-    "
-!
-
 peerFromDomain:domain name:peerName port:port
     |addrClass|
 
@@ -1404,8 +1477,8 @@
     ^ SocketAddress knownClassFromCode:domain
 
     "
-     self socketAddressClassForDomain:#inet
-     self socketAddressClassForDomain:#unix
+     self socketAddressClassForDomain:#AF_INET
+     self socketAddressClassForDomain:#AF_UNIX
     "
 !
 
@@ -1468,10 +1541,6 @@
     ^ self accept
 !
 
-connectTo:aSocketAddress
-    ^ self connectTo:aSocketAddress hostAddress port:aSocketAddress port
-!
-
 errorReporter
     "ST-80 mimicry."
 
@@ -1675,27 +1744,24 @@
      Our own socket address will be determined after conection set up.
      This is the default after the socket has been created"
 
-    ^ self
-	bindTo:nil
-	address:nil
-	reuseAddress:false
+    ^ self bindTo:nil reuseAddress:false
 
     "
       self newTCP bindAnonymously; listenFor:1; yourself
     "
 !
 
-bindAnonymouslyToAddress:addressString
+bindAnonymouslyToAddress:aSocketAddress
     "bind to address addressString.
      A free port will be allocated"
 
     ^ self
-	bindTo:nil
-	address:addressString
-	reuseAddress:false
+        bindTo:0
+        address:aSocketAddress
+        reuseAddress:false
 
     "
-      self newTCP bindAnonymouslyToAddress:IPSocketAddress local; listenFor:1; yourself
+      self newTCP bindAnonymouslyToAddress:IPSocketAddress localHost; listenFor:1; yourself
     "
 !
 
@@ -1704,76 +1770,92 @@
      The socketAddress object (an instance of SocketAddress)
      is supposed to respond to #portOrName and #address requests."
 
-    ^ self bindTo:(aSocketAddress portOrName)
-	   address:(aSocketAddress address)
-	   reuseAddress:true
+    ^ self bindTo:aSocketAddress reuseAddress:true
 !
 
 bindTo:portNrOrNameString address:addressString
-    "low level bind - returns true if ok, false otherwise.
-     Currently only non-address binding is supported;
-     i.e. the address must always be nil.
-
-     The interpretation of portNrOrName depends on the domain:
-	inet domain uses (4byte) byteArray like internet numbers,
-	unix domain uses pathname strings,
-	others use whatever will come up in the future
-     "
+    "Old interface: bind the socket to an address
+     - returns true if ok, false otherwise.
+
+     The interpretation of hostOrPathNameOrSocketAddrOrNil portNrOrName depends on the domain:
+        Best use a SocketAddress
+        For backward compatibility:
+            AF_INET domain can also use (4byte) byteArray like internet numbers,
+            AF_UNIX domain cab use pathname strings."
 
     ^ self
-	bindTo:portNrOrNameString
-	address:addressString
-	reuseAddress:true
+        bindTo:portNrOrNameString
+        address:addressString
+        reuseAddress:true
 !
 
 bindTo:portNrOrNameOrNil address:hostOrPathNameOrSocketAddrOrNil reuseAddress:reuse
-    "low level bind - returns true if ok, false otherwise.
-     Currently only non-address binding is supported;
-     i.e. address must always be nil.
-
-     The interpretation of portNrOrName depends on the domain:
-	inet domain uses (4byte) byteArray like internet numbers,
-	unix domain uses pathname strings,
-	others use whatever will come up in the future
+    "Old interface: bind the socket to an address
+     - returns true if ok, false otherwise.
+
+     The interpretation of hostOrPathNameOrSocketAddrOrNil portNrOrName depends on the domain:
+        Best use a SocketAddress
+        For backward compatibility:
+            AF_INET domain can also use (4byte) byteArray like internet numbers,
+            AF_UNIX domain cab use pathname strings.
 
      The reuse boolean argument controls if the SO_REUSEADDR socket option
      is to be set (to avoid the 'bind: address in use' error).
     "
 
-    |ok addr addrName domainClass error|
+    |socketAddress|
 
     handle isNil ifTrue:[
-	^ self errorNotOpen
-    ].
-
-    domainClass := self class socketAddressClassForDomain:domain.
-    domainClass isNil ifTrue:[
-	^ self error:'invalid (unsupported) domain'.
+        ^ self errorNotOpen
     ].
 
     hostOrPathNameOrSocketAddrOrNil isNil ifTrue:[
-	addr := domainClass anyHost.
+        socketAddress := self socketAddressClass anyHost.
     ] ifFalse:[
-	(hostOrPathNameOrSocketAddrOrNil isKindOf:SocketAddress) ifTrue:[
-	    addr := hostOrPathNameOrSocketAddrOrNil.
-	] ifFalse:[
-	    "backward compatibility: support for byteArray and string arg"
-	    hostOrPathNameOrSocketAddrOrNil isString ifTrue:[
-		addr := domainClass hostName:hostOrPathNameOrSocketAddrOrNil.
-		addrName := hostOrPathNameOrSocketAddrOrNil.
-	    ] ifFalse:[
-		hostOrPathNameOrSocketAddrOrNil isByteArray ifFalse:[
-		    ^ self error:'bad host (socketAddress) argument'
-		].
-		addr := domainClass hostAddress:hostOrPathNameOrSocketAddrOrNil.
-	    ].
-	].
+        (hostOrPathNameOrSocketAddrOrNil isSocketAddress) ifTrue:[
+            socketAddress := hostOrPathNameOrSocketAddrOrNil.
+        ] ifFalse:[
+            "backward compatibility: support for byteArray and string arg"
+            hostOrPathNameOrSocketAddrOrNil isString ifTrue:[
+                socketAddress := self socketAddressClass hostName:hostOrPathNameOrSocketAddrOrNil.
+            ] ifFalse:[
+                hostOrPathNameOrSocketAddrOrNil isByteArray ifFalse:[
+                    ^ self error:'bad host (socketAddress) argument'
+                ].
+                socketAddress := self socketAddressClass hostAddress:hostOrPathNameOrSocketAddrOrNil.
+            ].
+        ].
     ].
     portNrOrNameOrNil notNil ifTrue:[
-	addr port:portNrOrNameOrNil.
+        socketAddress port:portNrOrNameOrNil.
     ].
-    (portNrOrNameOrNil isNil or:[portNrOrNameOrNil == 0]) ifTrue:[
-	addr := addr copy.
+
+    ^ self bindTo:socketAddress reuseAddress:reuse.
+
+    "
+     (Socket domain:#'AF_INET' type:#stream)
+         bindTo:2144 address:nil; yourself
+    "
+!
+
+bindTo:aSocketAddress reuseAddress:reuse
+    "Bind the socket to aSocketAddress - returns true if ok, false otherwise.
+
+     The reuse boolean argument controls if the SO_REUSEADDR socket option
+     is to be set (to avoid the 'bind: address in use' error).
+
+     You cvan bind to nil to bind to anyHost and assign a random port."
+
+    |ok error socketAddress|
+
+    handle isNil ifTrue:[
+        ^ self errorNotOpen
+    ].
+    socketAddress := aSocketAddress.
+    socketAddress isNil ifTrue:[
+        "ok, get a all zero socket address, so it is for anyHost
+         and the port will be assigned"
+        socketAddress := self socketAddressClass new.
     ].
     ok := false.
 
@@ -1786,54 +1868,51 @@
     INT ret;
     int sockAddrOffs;
 
-    if (! __isBytes(addr)) {
-	error = __mkSmallInteger(-1);
-	addr = nil;
-	goto getOutOfHere;
+    if (fp == nil) {
+        goto getOutOfHere;
     }
-    if (fp == nil) {
-	goto getOutOfHere;
+
+    if (! __isBytes(socketAddress)) {
+        error = __mkSmallInteger(-1);
+        goto getOutOfHere;
     }
-
     /* get the socket-address */
-    {
-	int nIndex;
-	OBJ cls;
-
-	sockAddrOffs = 0;
-	if ((cls = __qClass(addr)) != @global(ByteArray))
-	    sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
-	nIndex = __qSize(addr) - OHDR_SIZE;
-	sockaddr_size = nIndex - sockAddrOffs;
-	if (sockaddr_size > sizeof(sa)) {
-	    error=__mkSmallInteger(-2);
-	    goto getOutOfHere;
-	}
-	memcpy(&sa, __byteArrayVal(addr) + sockAddrOffs, sockaddr_size);
+    if (__isNonNilObject(socketAddress)){
+        int nIndex;
+        OBJ cls = __qClass(socketAddress);
+
+        sockAddrOffs = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+        nIndex = __qSize(socketAddress) - OHDR_SIZE;
+        sockaddr_size = nIndex - sockAddrOffs;
+        if (sockaddr_size > sizeof(sa)) {
+            error=__mkSmallInteger(-2);
+            goto getOutOfHere;
+        }
+        memcpy(&sa, __byteArrayVal(socketAddress) + sockAddrOffs, sockaddr_size);
     }
 
     sock = SOCKET_FROM_FILE_OBJECT(fp);
 
 # ifdef SO_REUSEADDR
     if (reuse == true) {
-	int on = 1;
-
-	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
-	    DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
-	}
+        int on = 1;
+
+        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
+            DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
+        }
     }
 # endif /* SO_REUSEADDR */
 
 # ifdef BIND_BLOCKS
 #  ifdef DO_WRAP_CALLS
     do {
-	__threadErrno = 0;
-	ret = STX_WSA_NOINT_CALL3("bind", bind, sock, &sa, sockaddr_size);
+        __threadErrno = 0;
+        ret = STX_WSA_NOINT_CALL3("bind", bind, sock, &sa, sockaddr_size);
     } while ((ret < 0) && (__threadErrno == EINTR));
 #  else
     __BEGIN_INTERRUPTABLE__
     do {
-	ret = bind(sock, (struct sockaddr *)&sa, sockaddr_size);
+        ret = bind(sock, (struct sockaddr *)&sa, sockaddr_size);
     } while ((ret < 0) && (errno == EINTR));
     __END_INTERRUPTABLE__
 #  endif
@@ -1841,64 +1920,56 @@
     ret = bind(sock, (struct sockaddr *)&sa, sockaddr_size);
 # endif
     if (ret < 0) {
-	DBGPRINTF(("SOCKET: bind failed errno=%d\n", errno));
-	error = __INST(lastErrorNumber) = __MKSMALLINT(errno);
-	goto getOutOfHere;
+        DBGPRINTF(("SOCKET: bind failed errno=%d\n", errno));
+        error = __INST(lastErrorNumber) = __MKSMALLINT(errno);
+        goto getOutOfHere;
     } else {
-	ok = true;
-
-	if (! __isSmallInteger(portNrOrNameOrNil)
-	    || (portNrOrNameOrNil == __MKSMALLINT(0))) {
-	    unsigned int alen = sockaddr_size;
-
-	    /*
-	     * anonymous port - get the actual portNr
-	     */
-	    if (getsockname(sock, (struct sockaddr *)&sa, &alen) < 0) {
-# ifdef WIN32
-		errno = WSAGetLastError();
-# endif
-		console_fprintf(stderr, "SOCKET: cannot get socketname: %d\n", errno);
-	    }
-	    memcpy(__byteArrayVal(addr) + sockAddrOffs, &sa, alen);
-	}
+        ok = true;
     }
 #endif /* NO_SOCKET */
 
 getOutOfHere: ;
 %}.
     ok ~~ true ifTrue:[
-	"maybe someone catches the error and binds to some other port..."
-	OpenError
-	    raiseRequestWith:self
-	    errorString:('cannot bind socket to port: <1p> address: <2p> (error=<3p>)'
-				expandMacrosWith:portNrOrNameOrNil
-				with:hostOrPathNameOrSocketAddrOrNil
-				with:error).
-	^ true.
+        "maybe someone catches the error and binds to some other port..."
+        OpenError
+            raiseRequestWith:self
+            errorString:('cannot bind socket to address: <1p> (error=<2p>)'
+                                expandMacrosWith:socketAddress
+                                with:error).
+        ^ true.
     ].
 
-    port := addr port.
-
+    port := socketAddress port.
+    port == 0 ifTrue:[
+        "this is a bind to a random port, now we can get the real port"
+        port := self getFullSocketAddress port.
+    ].
     ^ true
 
     "
-     (Socket domain:#inet type:#stream)
-	 bindTo:21
-	 address:nil
+     (Socket domain:#'AF_INET' type:#stream)
+        bindTo:(IPSocketAddress anyHost port:2122) reuseAddress:false;
+        yourself.
+
+     (Socket domain:#'AF_INET' type:#stream)
+        bindTo:nil reuseAddress:false;
+        yourself.
+
+     (Socket domain:#'AF_INET6' type:#stream)
+        bindTo:nil reuseAddress:false;
+        yourself.
+
+     (Socket domain:#'AF_INET' type:#stream)
+        bindTo:(IPSocketAddress localHost port:2122) reuseAddress:false;
+        yourself.
+
+     (Socket domain:#'AF_UNIX' type:#stream)
+        bindTo:nil reuseAddress:false;
+        yourself.
     "
 !
 
-bindTo:aSocketAddress reuseAddress:reuseAddressBoolean
-    "ST80 compatible bind, expecting a socketAddress argument.
-     The socketAddress object (an instance of SocketAddress)
-     is supposed to respond to #portOrName and #address requests."
-
-    ^ self bindTo:(aSocketAddress portOrName)
-	   address:(aSocketAddress address)
-	   reuseAddress:reuseAddressBoolean
-!
-
 listenFor:aNumber
     "start listening; return true if ok, false on error
      aNumber is the number of connect requests, that may be queued on the socket"
@@ -1978,10 +2049,14 @@
 
 !Socket methodsFor:'connecting'!
 
+connectTo:aSocketAddress
+    ^ self connectTo:aSocketAddress withTimeout:nil
+!
+
 connectTo:hostOrPathName port:portNrOrName
-    "low level connect; connect to port, portNrOrNameOrNil on host, hostName.
-     For backward compatibility, host may be also a string or a byteArray,
-     but it is recommended to pass socketAddress instances.
+    "Backward compatibility connect; connect to port, portNrOrNameOrNil on host, hostOrPathNameOrSocketAddr.
+     For backward compatibility, hostOrPathNameOrSocketAddr may be also a string or a byteArray,
+     but it is recommended to pass SocketAddress instances.
 
      Return true if ok, false otherwise.
      The current process will block (but not the whole Smalltalk) until the connection is established.
@@ -1991,45 +2066,68 @@
 !
 
 connectTo:hostOrPathNameOrSocketAddr port:portNrOrNameOrNil withTimeout:timeout
-    "low level connect; connect to port, portNrOrNameOrNil on host, hostName.
-     For backward compatibility, host may be also a string or a byteArray,
-     but it is recommended to pass socketAddress instances.
+    "Backward compatibility connect; connect to port, portNrOrNameOrNil on host, hostOrPathNameOrSocketAddr.
+     For backward compatibility, hostOrPathNameOrSocketAddr may be also a string or a byteArray,
+     but it is recommended to pass SocketAddress instances.
 
      Return true if ok, false otherwise.
      The current process will block (but not the whole Smalltalk) until the connection is established,
      or timeout millliseconds have passed."
 
-    |isAsync err domainClass addr addrName|
+    |domainClass socketAddress|
+
+    (hostOrPathNameOrSocketAddr isSocketAddress) ifTrue:[
+        socketAddress := hostOrPathNameOrSocketAddr.
+        portNrOrNameOrNil notNil ifTrue:[
+            socketAddress port:portNrOrNameOrNil.
+        ].
+    ] ifFalse:[
+        "backward compatibility: support for byteArray and string arg"
+        domainClass := self class socketAddressClassForDomain:domain.
+        domainClass isNil ifTrue:[
+            ^ self error:'invalid (unsupported) domain'.
+        ].
+
+        hostOrPathNameOrSocketAddr isString ifTrue:[
+            socketAddress := domainClass hostName:hostOrPathNameOrSocketAddr serviceName:portNrOrNameOrNil type:#SOCK_STREAM.
+            peerName := hostOrPathNameOrSocketAddr.
+        ] ifFalse:[
+            hostOrPathNameOrSocketAddr isByteCollection ifFalse:[
+                ^ self error:'bad host (socketAddress) argument'
+            ].
+            socketAddress := domainClass hostAddress:hostOrPathNameOrSocketAddr port:portNrOrNameOrNil.
+        ].
+    ].
+
+    ^ self connectTo:socketAddress withTimeout:timeout.
+
+    "
+       |sock|
+       sock := Socket newTCP.
+       sock connectTo:'localhost' port:21 withTimeout:1000.
+       sock
+
+       |sock|
+       sock := Socket newTCP.
+       sock connectTo:'localhost' port:9876 withTimeout:2000.
+       sock
+    "
+!
+
+connectTo:aSocketAddress withTimeout:timeout
+    "Connect to a SocketAddress.
+
+     Return true if ok, false otherwise.
+     The current process will block (but not the whole Smalltalk) until the connection is established,
+     or timeout millliseconds have passed."
+
+    |isAsync err|
 
     handle isNil ifTrue:[
-	^ self errorNotOpen
-    ].
-
-    (hostOrPathNameOrSocketAddr isKindOf:SocketAddress) ifTrue:[
-	addr := hostOrPathNameOrSocketAddr.
-	portNrOrNameOrNil notNil ifTrue:[
-	    addr port:portNrOrNameOrNil.
-	].
-    ] ifFalse:[
-	"backward compatibility: support for byteArray and string arg"
-	domainClass := self class socketAddressClassForDomain:domain.
-	domainClass isNil ifTrue:[
-	    ^ self error:'invalid (unsupported) domain'.
-	].
-
-	hostOrPathNameOrSocketAddr isString ifTrue:[
-	    addr := domainClass hostName:hostOrPathNameOrSocketAddr serviceName:portNrOrNameOrNil type:#SOCK_STREAM.
-	    addrName := hostOrPathNameOrSocketAddr.
-	] ifFalse:[
-	    hostOrPathNameOrSocketAddr isByteCollection ifFalse:[
-		^ self error:'bad host (socketAddress) argument'
-	    ].
-	    addr := domainClass hostAddress:hostOrPathNameOrSocketAddr port:portNrOrNameOrNil.
-	].
+        ^ self errorNotOpen
     ].
 
 %{  /* STACK: 100000 */
-
 #ifndef NO_SOCKET
     OBJ fp = __INST(handle);
     union sockaddr_u sa;
@@ -2040,25 +2138,25 @@
     int on = 1;
     int sockaddr_size;
 
-    if (!__isNonNilObject(addr) || !__isBytes(addr)) {
-	DBGPRINTF(("SOCKET: invalid addrBytes\n"));
-	RETURN (false);
+    if (!__isNonNilObject(aSocketAddress) || !__isBytes(aSocketAddress)) {
+        DBGPRINTF(("SOCKET: invalid socketAddress\n"));
+        RETURN (false);
     }
 
     {
-	int sockAddrOffs, nIndex;
-	OBJ cls;
-
-	sockAddrOffs = 0;
-	if ((cls = __qClass(addr)) != @global(ByteArray))
-	    sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
-	nIndex = __qSize(addr) - OHDR_SIZE;
-	sockaddr_size = nIndex - sockAddrOffs;
-	if (sockaddr_size > sizeof(sa)) {
-	    console_fprintf(stderr, "Socket: bad socketAddr\n");
-	    RETURN (false);
-	}
-	bcopy((__byteArrayVal(addr) + sockAddrOffs), &sa, sockaddr_size);
+        int sockAddrOffs, nIndex;
+        OBJ cls;
+
+        sockAddrOffs = 0;
+        if ((cls = __qClass(aSocketAddress)) != @global(ByteArray))
+            sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+        nIndex = __qSize(aSocketAddress) - OHDR_SIZE;
+        sockaddr_size = nIndex - sockAddrOffs;
+        if (sockaddr_size > sizeof(sa)) {
+            console_fprintf(stderr, "Socket: bad socketAddr\n");
+            RETURN (false);
+        }
+        bcopy((__byteArrayVal(aSocketAddress) + sockAddrOffs), &sa, sockaddr_size);
     }
 
     sock = SOCKET_FROM_FILE_OBJECT(fp);
@@ -2081,60 +2179,60 @@
     /* __setWrapCallDebugging(1,1); */
 
     do {
-	DBGFPRINTF((stderr, "SOCKET: connect...\n"));
-	__threadErrno = 0;
-	ret = (INT)STX_WSA_NOINT_CALL3("connect", connect, sock, &sa, (INT)sockaddr_size);
-	DBGFPRINTF((stderr, "SOCKET: connect(%d) -> %"_ld_" (%d)\n", sock, (INT)ret, __threadErrno));
+        DBGFPRINTF((stderr, "SOCKET: connect...\n"));
+        __threadErrno = 0;
+        ret = (INT)STX_WSA_NOINT_CALL3("connect", connect, sock, &sa, (INT)sockaddr_size);
+        DBGFPRINTF((stderr, "SOCKET: connect(%d) -> %"_ld_" (%d)\n", sock, (INT)ret, __threadErrno));
     } while ((ret < 0) && (__threadErrno == EINTR));
     /* __setWrapCallDebugging(1,0); */
 # else
     __BEGIN_INTERRUPTABLE__
     do {
-	ret = connect(sock, (struct sockaddr *)&sa, sockaddr_size);
+        ret = connect(sock, (struct sockaddr *)&sa, sockaddr_size);
     } while ((ret < 0)
-	     && ((errno == EINTR)
+             && ((errno == EINTR)
 # ifdef EAGAIN
-		 || (errno == EAGAIN)
+                 || (errno == EAGAIN)
 # endif
-		));
+                ));
     __END_INTERRUPTABLE__
 #endif
 
     if (ret < 0) {
 # if defined(EINPROGRESS) || defined(EALREADY)
-	if (0
+        if (0
 #  ifdef EINPROGRESS
-	    || (errno == EINPROGRESS)
+            || (errno == EINPROGRESS)
 #  endif
 #  ifdef EALREADY
-	    || (errno == EALREADY)
+            || (errno == EALREADY)
 #  endif
-	) {
-	    /*
-	     * This was a nonblocking operation that will take some time.
-	     * Do a select on read to get informed when the operation is ready.
-	     */
-	    DBGFPRINTF((stderr, "SOCKET: isAsync is true\n"));
-	    isAsync = true;
-	} else
+        ) {
+            /*
+             * This was a nonblocking operation that will take some time.
+             * Do a select on read to get informed when the operation is ready.
+             */
+            DBGFPRINTF((stderr, "SOCKET: isAsync is true\n"));
+            isAsync = true;
+        } else
 # endif /* EINPROGRESS or EALREADY */
-	{
-	    DBGFPRINTF((stderr, "SOCKET: connect failed ret=%"_ld_" errno=%d __threadErrno=%d\n",
-			(INT)ret, errno, __threadErrno ));
+        {
+            DBGFPRINTF((stderr, "SOCKET: connect failed ret=%"_ld_" errno=%d __threadErrno=%d\n",
+                        (INT)ret, errno, __threadErrno ));
 # ifdef DUMP_ADDRESS
-	    {
-		char *cp = (char *)(&sa);
-		int i;
-
-		console_printf("address data:\n");
-		for (i=0; i<sockaddr_size; i++) {
-		    console_printf(" %02x\n", *cp++);
-		}
-	    }
+            {
+                char *cp = (char *)(&sa);
+                int i;
+
+                console_printf("address data:\n");
+                for (i=0; i<sockaddr_size; i++) {
+                    console_printf(" %02x\n", *cp++);
+                }
+            }
 # endif
-	    err = __INST(lastErrorNumber) = __MKSMALLINT(errno);
-	    RETURN (false);
-	}
+            err = __INST(lastErrorNumber) = __MKSMALLINT(errno);
+            RETURN (false);
+        }
     }
 
 # if defined(O_NONBLOCK)
@@ -2148,16 +2246,16 @@
 # endif /* NO_SOCKET */
 %}.
     isAsync == true ifTrue:[
-	(self writeWaitWithTimeoutMs:timeout) ifTrue:[
-	    "/ a timeout occured
-	    "/ should I cancel the connect?
-	    ^ false.
-	].
-	err := self getSocketError.
-	err ~~ 0 ifTrue:[
-	    lastErrorNumber := err.
-	    ^ false.
-	].
+        (self writeWaitWithTimeoutMs:timeout) ifTrue:[
+            "/ a timeout occured
+            "/ should I cancel the connect?
+            ^ false.
+        ].
+        err := self getSocketError.
+        err ~~ 0 ifTrue:[
+            lastErrorNumber := err.
+            ^ false.
+        ].
     ].
 
 "/ Once we will raise an exception instead of returning false (and have to change some code above):
@@ -2165,24 +2263,23 @@
 "/        (OperatingSystem errorHolderForNumber:err) reportError.
 "/    ].
 
-    peer := addr.
-    peerName := addrName.
+    peer := aSocketAddress.
     port isNil ifTrue:[
-	"socket has not been explicitly bound,
-	 after connect it has been bound implicitly - fetch the port"
-	port := self getFullSocketAddress port.
+        "socket has not been explicitly bound,
+         after connect it has been bound implicitly - fetch the port"
+        port := self getFullSocketAddress port.
     ].
     ^ true
 
     "
        |sock|
        sock := Socket newTCP.
-       sock connectTo:'localhost' port:21 withTimeout:1000.
+       sock connectTo:(IPSocketAddress localHost port:21) withTimeout:1000.
        sock
 
        |sock|
        sock := Socket newTCP.
-       sock connectTo:'localhost' port:9876 withTimeout:2000.
+       sock connectTo:(IPSocketAddress localHost port:9876) withTimeout:2000.
        sock
     "
 ! !
@@ -2653,7 +2750,7 @@
     self primitiveFailed
 ! !
 
-!Socket methodsFor:'low level'!
+!Socket privateMethodsFor:'low level'!
 
 closeFile
     "low level close"
@@ -2730,7 +2827,9 @@
     }
 #endif /* NO_SOCKET */
 %}
-!
+! !
+
+!Socket methodsFor:'low level'!
 
 getSocketAdress
     "BAD SPELLING, of #getSocketAddress, kept for compatibility with swazoo"
@@ -2774,7 +2873,7 @@
 listenWithBacklog:aNumber
     <resource: #obsolete>
     "same as listenFor: - backward compatibility with old ST/X"
-
+    self obsoleteMethodWarning.
     ^ self listenFor:aNumber
 !
 
@@ -2824,34 +2923,33 @@
 !
 
 primAcceptOn:aSocket blocking:blocking
-    "accept a connection on a server port (created with:'Socket>>onIPPort:')
-     usage is: (Socket basicNew acceptOn:(Socket onIPPort:9999)).
+    "accept a connection on a server port (created with:'Socket>>newTCP:')
+     usage is: (Socket basicNew acceptOn:(Socket newTCP:9999)).
      Return the true if ok; false if not.
      If blocking is true, the accept() syscall (and the whole smalltalk image)
      will block, until a connection is accepted.
      If blocking is false, this call will return immediately, if there is no connection pending."
 
-    |serverSocketFd addr addrLen domainClass|
+    |serverSocketFd addr domainClass|
 
     handle notNil ifTrue:[
-	^ self errorAlreadyOpen
+        ^ self errorAlreadyOpen
     ].
 
     domain := aSocket domain.
     socketType := aSocket type.
     serverSocketFd := aSocket fileDescriptor.
     serverSocketFd isNil ifTrue:[
-	^ self error:'invalid server socket'
+        ^ self error:'invalid server socket'
     ].
     (serverSocketFd isMemberOf:SmallInteger) ifFalse:[
-	^ self error:'invalid server socket'
+        ^ self error:'invalid server socket'
     ].
-
+    "unix domain sockets do not return a valid peer name on accept"
     domainClass := self class socketAddressClassForDomain:domain.
     domainClass isNil ifTrue:[
-	^ self error:'invalid (unsupported) domain'.
+        ^ self error:'invalid (unsupported) domain'.
     ].
-    addrLen := domainClass socketAddressSize.
     addr := domainClass new.
 
 %{  /* STACK: 100000 */
@@ -2860,35 +2958,28 @@
     int flags;
     SOCKET sock, newSock;
     union sockaddr_u sa;
-    unsigned int alen, alen0;
-    struct hostent *he ;
-    char dotted[20] ;
-
-    if (!__isSmallInteger(addrLen)) {
-	DBGPRINTF(("SOCKET: bad addrLen\n"));
-	RETURN (false);
-    }
-    alen0 = __intVal(addrLen);
+    unsigned int alen;
+
     sock = SOCKET_FROM_FD(__intVal(serverSocketFd));
 
     if (blocking == false) {
 # if defined(O_NONBLOCK) && defined(SET_NDELAY)
-	flags = fcntl(sock, F_GETFL);
-	fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+        flags = fcntl(sock, F_GETFL);
+        fcntl(sock, F_SETFL, flags | O_NONBLOCK);
 # endif
     }
 
 # ifdef DO_WRAP_CALLS
     do {
-	__threadErrno = 0;
-	alen = alen0;
-	newSock = (SOCKET)STX_WSA_CALL3("accept", accept, sock, &sa, &alen);
+        __threadErrno = 0;
+        alen = sizeof(sa);
+        newSock = (SOCKET)STX_WSA_CALL3("accept", accept, sock, &sa, &alen);
     } while ((newSock < 0) && (__threadErrno == EINTR));
 # else
     __BEGIN_INTERRUPTABLE__
     do {
-	alen = alen0;
-	newSock = accept(sock, (struct sockaddr *) &sa, &alen);
+        alen = sizeof(sa);
+        newSock = accept(sock, (struct sockaddr *) &sa, &alen);
     } while ((newSock < 0) && (errno == EINTR));
     __END_INTERRUPTABLE__
 # endif
@@ -2896,43 +2987,41 @@
 
     if (blocking == false) {
 # if defined(O_NDELAY) && defined(SET_NDELAY)
-	fcntl(sock, F_SETFL, flags);
+        fcntl(sock, F_SETFL, flags);
 # endif
     }
 
     if (newSock < 0) {
-	DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
-	__INST(lastErrorNumber) = __MKSMALLINT(errno);
-	RETURN (false);
+        DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno));
+        __INST(lastErrorNumber) = __MKSMALLINT(errno);
+        RETURN (false);
     }
 
     if (__isNonNilObject(addr)) {
-	OBJ oClass;
-	int nInstVars, nInstBytes, objSize;
-	char *cp;
-
-	oClass = __qClass(addr);
-	if (! __isBytes(addr) ) {
-	    DBGPRINTF(("SOCKET: bad addr\n"));
-	    closesocket(newSock);
-	    RETURN (false);
-	}
-
-	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-	nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
-	objSize = __qSize(addr) - nInstBytes;
-	cp = (char *)__InstPtr(addr) + nInstBytes;
-	if (objSize < alen) {
-	    DBGPRINTF(("SOCKET: bad addr\n"));
-	    closesocket(newSock);
-	    RETURN (false);
-	}
-
-	/*
-	 * extract the partners address
-	 */
-	bcopy((char *)&sa, cp, alen);
-	addrLen = __MKSMALLINT(alen);
+        OBJ oClass = __qClass(addr);
+        int nInstVars, nInstBytes, objSize;
+        char *addrP;
+
+        if (! __isBytes(addr) ) {
+            DBGPRINTF(("SOCKET: bad addr\n"));
+            closesocket(newSock);
+            RETURN (false);
+        }
+
+        nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+        nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
+        objSize = __qSize(addr) - nInstBytes;
+        addrP = (char *)__InstPtr(addr) + nInstBytes;
+        if (objSize < alen) {
+            DBGPRINTF(("SOCKET: bad addr\n"));
+            closesocket(newSock);
+            RETURN (false);
+        }
+
+        /*
+         * extract the partners address
+         */
+        memcpy(addrP, (char *)&sa, alen);
     }
 
     /*
@@ -2940,51 +3029,51 @@
      */
 # ifdef WIN32
     {
-	int _fd;
-	__stxWrapApiEnterCritical();
+        int _fd;
+        __stxWrapApiEnterCritical();
 #  if defined( __BORLANDC__ ) || defined( __MINGW__ )
-	_fd = _open_osfhandle((long)newSock, 0);
+        _fd = _open_osfhandle((long)newSock, 0);
 #  else
-	_fd = (int)newSock;
+        _fd = (int)newSock;
 #  endif
-	fp = fdopen(_fd, "r+");
-	__stxWrapApiLeaveCritical();
-	DBGPRINTF(("SOCKET: sock=%d fd=%d fp=%"_lx_"\n",newSock, _fd, (INT)fp));
+        fp = fdopen(_fd, "r+");
+        __stxWrapApiLeaveCritical();
+        DBGPRINTF(("SOCKET: sock=%d fd=%d fp=%"_lx_"\n",newSock, _fd, (INT)fp));
     }
 # else
     fp = fdopen(newSock, "r+");
 # endif
 
     if (! fp) {
-	DBGPRINTF(("SOCKET: fdopen call failed\n"));
-	__INST(lastErrorNumber) = __MKSMALLINT(errno);
+        DBGPRINTF(("SOCKET: fdopen call failed\n"));
+        __INST(lastErrorNumber) = __MKSMALLINT(errno);
 #  ifdef DO_WRAP_CALLS
-	{
-	  INT ret;
-	  do {
-	      __threadErrno = 0;
-	      ret = (INT)STX_WSA_CALL1("closesocket", closesocket, newSock);
-	  } while ((ret < 0) && (__threadErrno == EINTR));
-	}
+        {
+          INT ret;
+          do {
+              __threadErrno = 0;
+              ret = (INT)STX_WSA_CALL1("closesocket", closesocket, newSock);
+          } while ((ret < 0) && (__threadErrno == EINTR));
+        }
 #  else
-	closesocket(newSock);
+        closesocket(newSock);
 #  endif
-	DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
-	RETURN (false);
+        DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock));
+        RETURN (false);
     }
     __INST(handleType) = @symbol(socketFilePointer);
 
     if ((@global(FileOpenTrace) == true) || __debugging__) {
 # ifdef WIN32
-	{
-	    HANDLE h;
-
-	    int _fd = fileno(fp);
-	    h = (HANDLE)_get_osfhandle(_fd);
-	    console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d) (H: %"_lx_")\n", (INT)fp, _fd, (INT)h);
-	}
+        {
+            HANDLE h;
+
+            int _fd = fileno(fp);
+            h = (HANDLE)_get_osfhandle(_fd);
+            console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d) (H: %"_lx_")\n", (INT)fp, _fd, (INT)h);
+        }
 # else
-	console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock);
+        console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock);
 # endif
     }
 
@@ -3002,11 +3091,11 @@
     // object.
 # endif
     {
-	OBJ t;
-
-	t = __MKEXTERNALADDRESS(fp);
-	__INST(handle) = t;
-	__STORE(self, t);
+        OBJ t;
+
+        t = __MKEXTERNALADDRESS(fp);
+        __INST(handle) = t;
+        __STORE(self, t);
     }
 #endif /* not NO_SOCKET */
 %}.
@@ -3014,10 +3103,7 @@
     Lobby register:self.
     binary := false.
     port := aSocket port.
-
-    addr notNil ifTrue:[
-	peer := addr.
-    ].
+    peer := addr.
 
     ^ true
 !
@@ -3313,27 +3399,26 @@
 !Socket methodsFor:'queries'!
 
 domain
-    "return the sockets addressing domain (i.e. #inet, #unix, #x25, #appletalk)"
+    "return the sockets addressing domain (i.e. #AF_INET, #AF_INET6, #AF_UNIX, ...)"
 
     ^ domain
 !
 
-getFullSocketAddress
+getFullPeerAddress
     "implemented for swazoo project (primitive code can't be loaded as extension)
      Answer my own address (I am bound to this address).
      Note that this address may change after a connect or accept."
 
-    |error domainClass addr addrLen|
+    |error domainClass addr|
 
     handle isNil ifTrue:[
-	^ self errorNotOpen
+        ^ self errorNotOpen
     ].
 
     domainClass := self class socketAddressClassForDomain:domain.
     domainClass isNil ifTrue:[
-	^ self error:'invalid (unsupported) domain'.
+        ^ self error:'invalid (unsupported) domain'.
     ].
-    addrLen := domainClass socketAddressSize.
     addr := domainClass new.
 
 %{
@@ -3342,36 +3427,98 @@
     SOCKET sock;
     int ret;
     union sockaddr_u sa;
-    unsigned int alen, alen0;
+    unsigned int alen = sizeof(sa);
     char *addrP;
     int addrObjSize, nAddrInstBytes;
-
-    if (!__isSmallInteger(addrLen)) {
-	DBGPRINTF(("SOCKET: bad addrLen\n"));
-	error = @symbol(badArgument);
-	goto err;
-    }
-    alen = alen0 = __intVal(addrLen);
+    OBJ addrClass;
+    int nAddrInstVars;
 
     if (!__isNonNilObject(addr) || !__isBytes(addr)) {
-	DBGPRINTF(("SOCKET: bad addr\n"));
-	error = @symbol(badArgument);
-	goto err;
+        DBGPRINTF(("SOCKET: bad addr\n"));
+        error = @symbol(badArgument);
+        goto err;
+    }
+
+    addrClass = __qClass(addr);
+    nAddrInstVars = __intVal(__ClassInstPtr(addrClass)->c_ninstvars);
+    nAddrInstBytes = OHDR_SIZE + (nAddrInstVars * sizeof(OBJ));
+    addrObjSize = __qSize(addr) - nAddrInstBytes;
+
+    sock = SOCKET_FROM_FILE_OBJECT(fp);
+# ifdef WIN32
+    __threadErrno = 0;
+# endif
+    ret = getpeername(sock, (struct sockaddr *)&sa, &alen);
+    if (ret < 0) {
+# ifdef WIN32
+        errno = WSAGetLastError();
+# endif
+        DBGPRINTF(("SOCKET: getsocketname failed ret=%d errno=%d\n", ret, errno));
+        error = __MKSMALLINT(errno);
+        goto err;
+    }
+
+    if (addrObjSize < alen) {
+        DBGPRINTF(("SOCKET: bad addr\n"));
+        error = @symbol(badArgument);
+        goto err;
+    }
+
+    addrP = (char *)__InstPtr(addr) + nAddrInstBytes;
+    memcpy(addrP, (char *)&sa, alen);
+
+err:;
+#else /* NO_SOCKET */
+    error = @symbol(notImplemented);
+#endif /* NO_SOCKET */
+%}.
+    error notNil ifTrue:[
+        ^ self errorReporter reportOn:error
+    ].
+    ^ addr
+!
+
+getFullSocketAddress
+    "implemented for swazoo project (primitive code can't be loaded as extension)
+     Answer my own address (I am bound to this address).
+     Note that this address may change after a connect or accept."
+
+    |error domainClass addr|
+
+    handle isNil ifTrue:[
+        ^ self errorNotOpen
+    ].
+
+    domainClass := self class socketAddressClassForDomain:domain.
+    domainClass isNil ifTrue:[
+        ^ self error:'invalid (unsupported) domain'.
+    ].
+    addr := domainClass new.
+
+%{
+#ifndef NO_SOCKET
+    OBJ fp = __INST(handle);
+    SOCKET sock;
+    int ret;
+    union sockaddr_u sa;
+    unsigned int alen = sizeof(sa);
+    char *addrP;
+    int addrObjSize, nAddrInstBytes;
+
+    if (!__isNonNilObject(addr) || !__isBytes(addr)) {
+        DBGPRINTF(("SOCKET: bad addr\n"));
+        error = @symbol(badArgument);
+        goto err;
     }
 
     {
-	OBJ addrClass;
-	int nAddrInstVars;
-
-	addrClass = __qClass(addr);
-	nAddrInstVars = __intVal(__ClassInstPtr(addrClass)->c_ninstvars);
-	nAddrInstBytes = OHDR_SIZE + (nAddrInstVars * sizeof(OBJ));
-	addrObjSize = __qSize(addr) - nAddrInstBytes;
-	if (addrObjSize < alen0) {
-	    DBGPRINTF(("SOCKET: bad addr/alen\n"));
-	    error = @symbol(badArgument);
-	    goto err;
-	}
+        OBJ addrClass;
+        int nAddrInstVars;
+
+        addrClass = __qClass(addr);
+        nAddrInstVars = __intVal(__ClassInstPtr(addrClass)->c_ninstvars);
+        nAddrInstBytes = OHDR_SIZE + (nAddrInstVars * sizeof(OBJ));
+        addrObjSize = __qSize(addr) - nAddrInstBytes;
     }
 
     sock = SOCKET_FROM_FILE_OBJECT(fp);
@@ -3381,23 +3528,21 @@
     ret = getsockname(sock, (struct sockaddr *)&sa, &alen);
     if (ret < 0) {
 # ifdef WIN32
-	errno = WSAGetLastError();
+        errno = WSAGetLastError();
 # endif
-	DBGPRINTF(("SOCKET: getsocketname failed ret=%d errno=%d\n", ret, errno));
-	error = __MKSMALLINT(errno);
-	goto err;
+        DBGPRINTF(("SOCKET: getsocketname failed ret=%d errno=%d\n", ret, errno));
+        error = __MKSMALLINT(errno);
+        goto err;
     }
 
     if (addrObjSize < alen) {
-	DBGPRINTF(("SOCKET: bad addr\n"));
-	error = @symbol(badArgument);
-	goto err;
+        DBGPRINTF(("SOCKET: bad addr\n"));
+        error = @symbol(badArgument);
+        goto err;
     }
 
     addrP = (char *)__InstPtr(addr) + nAddrInstBytes;
-    bcopy((char *)&sa, addrP, alen);
-
-    addrLen = __MKSMALLINT(alen);
+    memcpy(addrP, (char *)&sa, alen);
 
 err:;
 #else /* NO_SOCKET */
@@ -3405,7 +3550,7 @@
 #endif /* NO_SOCKET */
 %}.
     error notNil ifTrue:[
-	^ self errorReporter reportOn:error
+        ^ self errorReporter reportOn:error
     ].
     ^ addr
 !
@@ -3466,6 +3611,18 @@
     ^ port
 !
 
+socketAddressClass
+    "get the matchon SocketAddress class for this socket"
+
+    |domainClass|
+
+    domainClass := self class socketAddressClassForDomain:domain.
+    domainClass isNil ifTrue:[
+        ^ self error:'invalid (unsupported) domain'.
+    ].
+    ^ domainClass.
+!
+
 type
     "return the sockets connection type (i.e. #datagram, #stream etc)"
 
@@ -3478,7 +3635,7 @@
     "set up socket with domain and type.
      This is a low level entry; no binding, listening or connect
      is done. Both arguments must be symbols from one of
-     #inet,#unix, #appletalk, #x25 .. and #stream, #datagram, #raw resp."
+      #AF_INET, #AF_INET6, #AF_UNIX ... and #stream, #datagram, #raw resp."
 
     ^ self domain:domainArg type:typeArg protocol:0 reuseAddress:true
 !
@@ -3487,13 +3644,13 @@
     "set up socket with domain, type and protocol number.
      This is a low level entry; no binding, listening or connect
      is done. Both arguments must be symbols from one of
-     #inet,#unix, #appletalk, #x25 .. and #stream, #datagram, #raw resp."
+     #AF_INET, #AF_INET6, #AF_UNIX ... and #stream, #datagram, #raw resp."
 
     ^ self domain:domainArg type:typeArg protocol:protocolNumber reuseAddress:true
 
     "
-     Socket new domain:#inet type:#stream
-     Socket new domain:#unix type:#stream
+     Socket new domain:#AF_INET type:#stream
+     Socket new domain:#AF_UNIX type:#stream
     "
 !
 
@@ -3501,7 +3658,7 @@
     "set up socket with domain, type and protocol number.
      This is a low level entry; no binding, listening or connect
      is done. Both arguments must be symbols from one of
-     #inet,#unix, #appletalk, #x25 .. and #stream, #datagram, #raw resp.
+     #AF_INET, #AF_INET6, #AF_UNIX ... and #stream, #datagram, #raw resp.
 
      The reuse boolean argument controls if the SO_REUSEADDR socket option
      is to be set (to avoid the 'bind: address in use' error)."
@@ -3509,7 +3666,7 @@
     |domainName domainCode typeCode error|
 
     handle notNil ifTrue:[
-	^ self errorAlreadyOpen
+        ^ self errorAlreadyOpen
     ].
     domainName := SocketAddress domainCodeFromName:domainArg.
     domainCode := OperatingSystem domainCodeOf:domainName.
@@ -3523,19 +3680,19 @@
     SOCKET sock;
 
     if (! __isSmallInteger(domainCode)) {
-	error = @symbol(badArgument1);
-	goto out;
+        error = @symbol(badArgument1);
+        goto out;
     }
     if (! __isSmallInteger(typeCode)) {
-	error = @symbol(badArgument2);
-	goto out;
+        error = @symbol(badArgument2);
+        goto out;
     }
     if (protocolNumber != nil) {
-	if (!__isSmallInteger(protocolNumber)) {
-	    error = @symbol(badArgument3);
-	    goto out;
-	}
-	proto = __intVal(protocolNumber);
+        if (!__isSmallInteger(protocolNumber)) {
+            error = @symbol(badArgument3);
+            goto out;
+        }
+        proto = __intVal(protocolNumber);
     }
 
 
@@ -3548,20 +3705,20 @@
 # ifdef SOCKET_BLOCKS
 #  ifdef DO_WRAP_CALLS
     do {
-	__threadErrno = 0;
-	sock = STX_WSA_NOINT_CALL3("socket", socket, dom, typ, proto);
+        __threadErrno = 0;
+        sock = STX_WSA_NOINT_CALL3("socket", socket, dom, typ, proto);
     } while ((sock < 0) && (__threadErrno == EINTR));
 #  else
     __BEGIN_INTERRUPTABLE__
     do {
-	DBGPRINTF(("SOCKET: opening socket domain=%d type=%d proto=%d\n", dom, typ, proto));
-	sock = socket(dom, typ, proto);
+        DBGPRINTF(("SOCKET: opening socket domain=%d type=%d proto=%d\n", dom, typ, proto));
+        sock = socket(dom, typ, proto);
 #   if defined(EPROTONOSUPPORT) /* for SGI */
-	if ((proto != 0) && (sock < 0) && (errno == EPROTONOSUPPORT)) {
-	    DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
-	    proto = 0;
-	    sock = socket(dom, typ, 0);
-	}
+        if ((proto != 0) && (sock < 0) && (errno == EPROTONOSUPPORT)) {
+            DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
+            proto = 0;
+            sock = socket(dom, typ, 0);
+        }
 #   endif
     } while ((sock < 0) && (errno == EINTR));
     __END_INTERRUPTABLE__
@@ -3570,9 +3727,9 @@
     sock = socket(dom, typ, proto);
 #  if defined(EPROTONOSUPPORT) /* for SGI */
     if ((proto != 0) && (sock < 0) && (errno == EPROTONOSUPPORT)) {
-	DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
-	proto = 0;
-	sock = socket(dom, typ, 0);
+        DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n"));
+        proto = 0;
+        sock = socket(dom, typ, 0);
     }
 #  endif
 # endif
@@ -3585,99 +3742,99 @@
     if (sock < 0)
 # endif
     {
-	DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno));
-	__INST(lastErrorNumber) = __MKSMALLINT(errno);
+        DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno));
+        __INST(lastErrorNumber) = __MKSMALLINT(errno);
     } else {
 # ifdef SO_REUSEADDR
-	if (reuse == true) {
-	    DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR\n"));
-	    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
-		DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
-	    }
-	}
+        if (reuse == true) {
+            DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR\n"));
+            if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
+                DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
+            }
+        }
 # endif /* SO_REUSEADDR */
 
 # ifdef SET_LINGER_WHEN_CREATING_SOCKET
 #  ifdef SO_LINGER
-	{
-	    struct linger l;
-
-	    l.l_onoff = 1;
-	    l.l_linger = 30;
-	    setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
-	}
+        {
+            struct linger l;
+
+            l.l_onoff = 1;
+            l.l_linger = 30;
+            setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
+        }
 #  endif
 # endif
 # ifdef WIN32
-	/*
-	 * make it blocking
-	 */
-	{
-	    unsigned long zero = 0;
-
-	    ioctlsocket(sock, FIONBIO, &zero);
-	}
+        /*
+         * make it blocking
+         */
+        {
+            unsigned long zero = 0;
+
+            ioctlsocket(sock, FIONBIO, &zero);
+        }
 # endif
-	/*
-	 * make it a FILE *
-	 */
+        /*
+         * make it a FILE *
+         */
 # ifdef WIN32
-	{
-	    int _fd;
-	    __stxWrapApiEnterCritical();
+        {
+            int _fd;
+            __stxWrapApiEnterCritical();
 #  if defined( __BORLANDC__ ) || defined( __MINGW__ )
-	    _fd = _open_osfhandle((long)sock, 0);
+            _fd = _open_osfhandle((long)sock, 0);
 #  else
-	    _fd = (int)sock;
+            _fd = (int)sock;
 #  endif
-	    fp = fdopen(_fd, "r+");
-	    __stxWrapApiLeaveCritical();
-	    DBGPRINTF(("SOCKET: sock=%d fd=%d fp=%"_lx_"\n",sock, _fd, (INT)fp));
-	}
+            fp = fdopen(_fd, "r+");
+            __stxWrapApiLeaveCritical();
+            DBGPRINTF(("SOCKET: sock=%d fd=%d fp=%"_lx_"\n",sock, _fd, (INT)fp));
+        }
 # else
-	fp = fdopen(sock, "r+");
+        fp = fdopen(sock, "r+");
 # endif
-	if (! fp) {
-	    DBGPRINTF(("SOCKET: fdopen call failed\n"));
-	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
+        if (! fp) {
+            DBGPRINTF(("SOCKET: fdopen call failed\n"));
+            __INST(lastErrorNumber) = __MKSMALLINT(errno);
 # ifdef DO_WRAP_CALLS
-	    {
-		INT ret;
-
-		do {
-		  __threadErrno = 0;
-		  ret = (INT)STX_WSA_NOINT_CALL1("closesocket", closesocket, sock);
-		} while ((ret < 0) && (__threadErrno == EINTR));
-	    }
+            {
+                INT ret;
+
+                do {
+                  __threadErrno = 0;
+                  ret = (INT)STX_WSA_NOINT_CALL1("closesocket", closesocket, sock);
+                } while ((ret < 0) && (__threadErrno == EINTR));
+            }
 # else
-	    __BEGIN_INTERRUPTABLE__
-	    closesocket(sock);
-	    DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock));
-	    __END_INTERRUPTABLE__
+            __BEGIN_INTERRUPTABLE__
+            closesocket(sock);
+            DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock));
+            __END_INTERRUPTABLE__
 # endif
-	} else {
-	    __INST(handleType) = @symbol(socketFilePointer);
-
-	    if ((@global(FileOpenTrace) == true) || __debugging__) {
-		console_fprintf(stderr, "fdopen [Socket] -> %"_lx_"\n", (INT)fp);
-	    }
+        } else {
+            __INST(handleType) = @symbol(socketFilePointer);
+
+            if ((@global(FileOpenTrace) == true) || __debugging__) {
+                console_fprintf(stderr, "fdopen [Socket] -> %"_lx_"\n", (INT)fp);
+            }
 
 # if 0
-	    // The original code was:
-	    __INST(handle) = __MKEXTERNALADDRESS(fp); __STORESELF(handle);
-	    // but for that, gcc generates wrong code, which loads self (volatile) into
-	    // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
-	    // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
-	    // object.
+            // The original code was:
+            __INST(handle) = __MKEXTERNALADDRESS(fp); __STORESELF(handle);
+            // but for that, gcc generates wrong code, which loads self (volatile) into
+            // a register (bp), then calls __MKEXTERNALADDRESS, then stores indirect bp.
+            // That is wrong if a scavenge occurs in __MKEXTERNALADDRESS, as bp is now still pointing to the old
+            // object.
 # endif
-	    {
-		OBJ t;
-
-		t = __MKEXTERNALADDRESS(fp);
-		__INST(handle) = t;
-		__STORE(self, t);
-	    }
-	}
+            {
+                OBJ t;
+
+                t = __MKEXTERNALADDRESS(fp);
+                __INST(handle) = t;
+                __STORE(self, t);
+            }
+        }
     }
 #endif
 out:;
@@ -3685,19 +3842,19 @@
 
     "all ok?"
     handle notNil ifTrue:[
-	domain := domainArg.
-	socketType := typeArg.
-	Lobby register:self.
+        domain := domainArg.
+        socketType := typeArg.
+        Lobby register:self.
     ] ifFalse:[
-	error notNil ifTrue:[
-	    ^ self primitiveFailed:error.
-	].
-	^ self openError:lastErrorNumber.
+        error notNil ifTrue:[
+            ^ self primitiveFailed:error.
+        ].
+        ^ self openError:lastErrorNumber.
     ].
 
     "
-     Socket new domain:#inet type:#stream
-     Socket new domain:#unix type:#stream
+     Socket new domain:#AF_INET type:#stream
+     Socket new domain:#AF_UNIX type:#stream
     "
 ! !
 
@@ -4058,10 +4215,10 @@
 !Socket class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.282 2013-07-09 14:22:38 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.283 2013-07-16 07:57:18 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.282 2013-07-09 14:22:38 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.283 2013-07-16 07:57:18 stefan Exp $'
 ! !