--- a/Socket.st Tue May 20 17:47:09 2003 +0200
+++ b/Socket.st Tue May 20 18:27:08 2003 +0200
@@ -3566,7 +3566,7 @@
!
shutDown
- "shutDown without flushing "
+ "shutDown and close without flushing "
filePointer isNil ifTrue:[^ self].
Lobby unregister:self.
@@ -3578,21 +3578,21 @@
fp = __INST(filePointer);
if (fp != nil) {
- FILE *f;
- int fd;
-
- __INST(filePointer) = nil;
- f = __FILEVal(fp);
- fd = fileno(f);
- __BEGIN_INTERRUPTABLE__
- shutdown(fd, 2);
- DBGFPRINTF((stderr, "socket fclose %x (%d)\n", fp, fd));
- if (@global(FileOpenTrace) == true) {
- fprintf(stderr, "fclose [Socket] %x\n", f);
- }
- fclose(f);
- /* close(fd); */
- __END_INTERRUPTABLE__
+ FILE *f;
+ int fd;
+
+ __INST(filePointer) = nil;
+ f = __FILEVal(fp);
+ fd = fileno(f);
+ __BEGIN_INTERRUPTABLE__
+ shutdown(fd, 2);
+ DBGFPRINTF((stderr, "socket fclose %x (%d)\n", fp, fd));
+ if (@global(FileOpenTrace) == true) {
+ fprintf(stderr, "fclose [Socket] %x\n", f);
+ }
+ fclose(f);
+ /* close(fd); */
+ __END_INTERRUPTABLE__
}
#endif
%}
@@ -4052,413 +4052,168 @@
!Socket methodsFor:'low level-connecting'!
connectTo:hostOrPathName port:portNrOrName
- "low level connect; connect to port, portNrOrName on host, hostName.
- For unix-domain sockets, the port argument is ignored and pathName is taken.
- Other sockets are not yet implemented.
+ "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.
+
Return true if ok, false otherwise.
- Hostname must be a string, portNrOrName an integer port number (in inet domain).
- The current process will block (but not the whole Smalltalk) until the connection
- is established.
+ The current process will block (but not the whole Smalltalk) until the connection is established.
See also: #connectTo:port:withTimeout: for a somewhat nicer interface."
^ self connectTo:hostOrPathName port:portNrOrName withTimeout:nil
!
-connectTo:hostOrPathName port:portNrOrName withTimeout:timeout
- "low level connect; connect to port, portNrOrName on host, hostName.
- For unix-domain sockets, the port argument is ignored and pathName is taken.
- Other sockets are not yet implemented.
+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.
+
Return true if ok, false otherwise.
- Hostname must be a string, portNrOrName an integer port number (in inet domain).
- The current process will block (but not the whole Smalltalk) until the connection
- is established.
- See also: #connectTo:port:withTimeout: for a somewhat nicer interface."
-
- |isAsync err|
+ 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|
filePointer isNil ifTrue:[
- ^ self errorNotOpen
+ ^ self errorNotOpen
+ ].
+
+ domainClass := self class socketAddressClassForDomain:domain.
+ domainClass isNil ifTrue:[
+ ^ self error:'invalid (unsupported) domain'.
].
+
+ "/ backward compatibility: support for byteArray and string arg
+
+ hostOrPathNameOrSocketAddr isString ifTrue:[
+ addr := domainClass hostName:hostOrPathNameOrSocketAddr port:portNrOrNameOrNil.
+ addrName := hostOrPathNameOrSocketAddr.
+ ] ifFalse:[
+ hostOrPathNameOrSocketAddr isBytes ifFalse:[
+ ^ self error:'bad host (socketAddress) argument'
+ ].
+ (hostOrPathNameOrSocketAddr isKindOf:SocketAddress) ifTrue:[
+ addr := hostOrPathNameOrSocketAddr.
+ portNrOrNameOrNil notNil ifTrue:[
+ addr port:portNrOrNameOrNil.
+ ].
+ ] ifFalse:[
+ addr := domainClass hostAddress:hostOrPathNameOrSocketAddr port:portNrOrNameOrNil.
+ ].
+ ].
+
%{ /* STACK: 100000 */
#ifndef NO_SOCKET
OBJ t = __INST(filePointer);
- OBJ myDomain;
- union sockaddr_u sa;
- struct hostent *hp ;
- int a, sock ;
- long addr;
+ struct sockaddr *sockaddr_ptr;
+ int a, sock;
FILE *fp;
int ret, oldFlags;
int on = 1;
- int ok;
int sockaddr_size;
- if (!__isString(__INST(domain)) && !__isSymbol(__INST(domain))) {
- DBGPRINTF(("SOCKET: invalid domain arg\n"));
- RETURN (false);
- }
-
- ok = 0;
- myDomain = __INST(domain);
- bzero((char *) &sa, sizeof(sa)) ;
-
- if (0) {
- /* for ese below */
- }
-#ifdef AF_INET
- else if (myDomain == @symbol(inet)) {
- /*
- * INET addressing: port must be a smallInteger;
- * hostOrPathName the name of the host (dot notation allowed)
- * or a byteArray containing the 4 address bytes.
- */
- if (! __isSmallInteger(portNrOrName)) {
- DBGPRINTF(("SOCKET: invalid port arg\n"));
- RETURN (false);
- }
-
- sa.in.sin_family = AF_INET;
- sa.in.sin_port = htons((u_short) __intVal(portNrOrName)) ;
-
- if (__isByteArray(hostOrPathName)) {
- unsigned char *cp;
- int n;
- unsigned intAddr;
-
- cp = __ByteArrayInstPtr(hostOrPathName)->ba_element;
- n = __byteArraySize(hostOrPathName);
- if (n < 4) {
- DBGPRINTF(("SOCKET: invalid ipAddr arg\n"));
- RETURN (false);
- }
- intAddr = cp[0];
- intAddr = (intAddr << 8) | cp[1];
- intAddr = (intAddr << 8) | cp[2];
- intAddr = (intAddr << 8) | cp[3];
- sa.in.sin_addr.s_addr = htonl(intAddr);
- /* bcopy(cp, &sa.in.sin_addr.s_addr, n); */
- } else {
- if (! __isString(hostOrPathName)) {
- DBGPRINTF(("SOCKET: invalid hostname arg\n"));
- RETURN (false);
- }
-
- if ((addr = inet_addr(__stringVal(hostOrPathName))) != -1) {
- /*
- * is Internet addr in octet notation
- */
- bcopy(&addr, (char *) &sa.in.sin_addr, sizeof(addr)) ; /* set address */
- } else {
- /*
- * do we know the host's address?
- */
- GETHOSTBYNAME(hp, __stringVal(hostOrPathName))
- if (hp == NULL) {
- DBGPRINTF(("SOCKET: unknown host:%s\n", __stringVal(hostOrPathName)));
- RETURN (false);
- }
- bcopy(hp->h_addr, (char *) &sa.in.sin_addr, hp->h_length) ;
- sa.in.sin_family = hp->h_addrtype;
- }
- }
-
- DBGPRINTF(("SOCKET: connect addr:%d.%d.%d.%d port: %d\n",
- ((unsigned char *)(&sa.in.sin_addr.s_addr))[0],
- ((unsigned char *)(&sa.in.sin_addr.s_addr))[1],
- ((unsigned char *)(&sa.in.sin_addr.s_addr))[2],
- ((unsigned char *)(&sa.in.sin_addr.s_addr))[3],
- ntohs(sa.in.sin_port)));
-
- sockaddr_size = sizeof(struct sockaddr_in);
- ok = 1;
- }
-#endif /* AF_INET */
-
-#ifdef AF_INET6
- else if (myDomain == @symbol(inet6)) {
- /*
- * INET6 addressing: port must be a smallInteger;
- * hostOrPathName the name of the host
- * or a byteArray containing the address bytes.
- */
- if (! __isSmallInteger(portNrOrName)) {
- DBGPRINTF(("SOCKET: invalid port arg\n"));
- RETURN (false);
- }
-
- sa.in6.sin6_family = AF_INET6;
- sa.in6.sin6_port = htons((u_short) __intVal(portNrOrName)) ;
-
- if (__isByteArray(hostOrPathName)) {
- unsigned char *cp;
- int n;
-
- cp = __ByteArrayInstPtr(hostOrPathName)->ba_element;
- n = __byteArraySize(hostOrPathName);
- if (n > sizeof(sa.in6.sin6_addr.s6_addr)) n = sizeof(sa.in6.sin6_addr.s6_addr);
- bcopy(cp, sa.in6.sin6_addr.s6_addr, n);
- } else {
- if (! __isString(hostOrPathName)) {
- DBGPRINTF(("SOCKET: invalid hostname arg\n"));
- RETURN (false);
- }
-
- /*
- * do we know the host's address?
- */
- GETHOSTBYNAME(hp, __stringVal(hostOrPathName))
- if (hp == NULL) {
- DBGPRINTF(("SOCKET: unknown host:%s\n", __stringVal(hostOrPathName)));
- RETURN (false);
- }
- bcopy(hp->h_addr, (char *) &sa.in.sin_addr, hp->h_length) ;
- sa.in.sin_family = hp->h_addrtype;
- }
-
- DBGPRINTF(("SOCKET: connect addr: %x.%x.%x.%x.%x.%x... port: %d\n",
- sa.in6.sin6_addr.s6_addr[0],
- sa.in6.sin6_addr.s6_addr[1],
- sa.in6.sin6_addr.s6_addr[2],
- sa.in6.sin6_addr.s6_addr[3],
- sa.in6.sin6_addr.s6_addr[4],
- sa.in6.sin6_addr.s6_addr[5],
- sa.in6.sin6_port));
-
- sockaddr_size = sizeof(struct sockaddr_in6);
- ok = 1;
+ if (!__isNonNilObject(addr) || !__isBytes(addr)) {
+ DBGPRINTF(("SOCKET: invalid addrBytes\n"));
+ RETURN (false);
}
-#endif /* AF_INET6 */
-
-#ifdef AF_UNIX
- else if (myDomain == @symbol(unix)) {
- char *pathName;
- int l;
-
- /*
- * UNIX domain: port is ignored;
- * hostOrPathName is a pathName
- */
- if (! __isString(hostOrPathName)) {
- DBGPRINTF(("SOCKET: invalid port (pathname) arg\n"));
- RETURN (false);
- }
- pathName = (char *) __stringVal(hostOrPathName);
- l = strlen(pathName);
- if ((l + sizeof ( sa.un.sun_family )) > sizeof(struct sockaddr_un)) {
- DBGPRINTF(("SOCKET: pathname too long\n"));
- RETURN (false);
- }
-
- strcpy(sa.un.sun_path, pathName);
- sa.un.sun_family = AF_UNIX;
- sockaddr_size = l + sizeof ( sa.un.sun_family );
- ok = 1;
- }
-#endif /* AF_UNIX */
-
-#ifdef AF_APPLETALK
- else if (myDomain == @symbol(appletalk)) {
- /*
- * APPLETALK addressing: port must be a smallInteger;
- * hostOrPathName the name of the host
- * or a byteArray containing the 3 address bytes.
- */
- if (! __isSmallInteger(portNrOrName)) {
- DBGPRINTF(("SOCKET: invalid port arg\n"));
- RETURN (false);
- }
-
- sa.at.sat_family = AF_APPLETALK;
- sa.at.sat_port = __intVal(portNrOrName);
-
- if (__isByteArray(hostOrPathName)) {
- unsigned char *cp;
- int n;
-
- cp = __ByteArrayInstPtr(hostOrPathName)->ba_element;
- n = __byteArraySize(hostOrPathName);
- if (n > 3) n = 3;
- bcopy(cp, &sa.at.sat_addr, n);
- } else {
- if (! __isString(hostOrPathName)) {
- DBGPRINTF(("SOCKET: invalid hostname arg\n"));
- RETURN (false);
- }
-
- /*
- * do we know the host's address?
- */
- GETHOSTBYNAME(hp, __stringVal(hostOrPathName))
- if (hp == NULL) {
- DBGPRINTF(("SOCKET: unknown host:%s\n", __stringVal(hostOrPathName)));
- RETURN (false);
- }
- if (hp->h_addrtype != AF_APPLETALK) {
- DBGPRINTF(("SOCKET: host:%s is not an appletalk host\n", __stringVal(hostOrPathName)));
- RETURN (false);
- }
-
- bcopy(hp->h_addr, (char *) &sa.at.sat_addr, hp->h_length) ;
- sa.at.sat_family = hp->h_addrtype;
- }
-
- DBGPRINTF(("SOCKET: connect addr: %x port: %d\n", sa.in.sin_addr, sa.in.sin_port));
-
- sockaddr_size = sizeof(struct sockaddr_at);
- ok = 1;
- }
-#endif /* APPLETALK */
-
- /*
- * XXXX add addressing stuff for other domains here ...
- */
-#ifdef AF_X25
- else if (myDomain == @symbol(x25)) {
- }
-#endif
-#ifdef AF_AX25
- else if (myDomain == @symbol(ax25)) {
- }
-#endif
-#ifdef AF_NS
- else if ((myDomain == @symbol(ns))
- || (myDomain == @symbol(xns))) {
- }
-#endif
-# ifdef AF_DECnet
- else if (myDomain == @symbol(decnet)) {
- }
-# endif
-#ifdef AF_SNA
- else if (myDomain == @symbol(sna)) {
- }
-#endif
-#ifdef AF_RAW
- else if (myDomain == @symbol(raw)) {
- }
-#endif
-# ifdef AF_ISO
- else if (myDomain == @symbol(iso)) {
- }
-# endif
-# ifdef AF_NETBIOS
- else if (myDomain == @symbol(netbios)) {
- }
-# endif
-# ifdef AF_IPX
- else if (myDomain == @symbol(ipx)) {
- }
-# endif
-# ifdef AF_BRIDGE
- else if (myDomain == @symbol(bridge)) {
- }
-# endif
-# ifdef AF_BSC
- else if (myDomain == @symbol(bsc)) {
- }
-# endif
-# ifdef AF_ROSE
- else if (myDomain == @symbol(rose)) {
- }
-# endif
-# ifdef AF_IRDA
- else if (__INST(domain) == @symbol(irda)) {
- }
-# endif
-# if defined(AF_CCITT) && (AF_CCITT != AF_X25)
- else if (myDomain == @symbol(ccitt)) {
- }
-# endif
-
- if (! ok) {
- DBGPRINTF(("SOCKET: unsupported domain\n"));
- RETURN (false);
+
+ {
+ int indx, nIndex;
+ OBJ cls;
+
+ indx = 0;
+ if ((cls = __qClass(addr)) != @global(ByteArray))
+ indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ nIndex = __qSize(addr) - OHDR_SIZE;
+ sockaddr_size = nIndex - indx;
+ sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + indx);
}
sock = fileno(__FILEVal(t));
-#if defined(O_NONBLOCK)
+# if defined(O_NONBLOCK)
/*
* set to non-blocking and wait later
*/
oldFlags = fcntl(sock, F_GETFL, 0);
/* on SUNOS4.x, would use fcntl(osfd, F_SETFL, flags | FNDELAY); */
fcntl(sock, F_SETFL, oldFlags | O_NONBLOCK);
-#endif
+# endif
/*
* connect
*/
__BEGIN_INTERRUPTABLE__
do {
- ret = connect(sock, (struct sockaddr *)&sa, sockaddr_size);
+ ret = connect(sock, sockaddr_ptr, sockaddr_size);
} while ((ret < 0)
- && ((errno == EINTR)
-#ifdef EAGAIN
- || (errno == EAGAIN)
-#endif
- ));
+ && ((errno == EINTR)
+# ifdef EAGAIN
+ || (errno == EAGAIN)
+# endif
+ ));
__END_INTERRUPTABLE__
if (ret < 0) {
-#if defined(EINPROGRESS) || defined(EALREADY)
- if (0
-# ifdef EINPROGRESS
- || (errno == EINPROGRESS)
-# endif
-# ifdef EALREADY
- || (errno == EALREADY)
+# if defined(EINPROGRESS) || defined(EALREADY)
+ if (0
+# ifdef EINPROGRESS
+ || (errno == EINPROGRESS)
+# endif
+# ifdef 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.
+ */
+
+ isAsync = true;
+ } else
+# endif /* EINPROGRESS or EALREADY */
+ {
+ DBGPRINTF(("SOCKET: connect failed errno=%d\n", errno));
+# ifdef DUMP_ADDRESS
+ {
+ char *cp = (char *)(&sa);
+ int i;
+
+ printf("address data:\n");
+ for (i=0; i<sockaddr_size; i++) {
+ printf(" %02x\n", *cp++);
+ }
+ }
# endif
- ) {
- /*
- * This was a nonblocking operation that will take some time.
- * Do a select on read to get informed when the operation is ready.
- */
-
- isAsync = true;
- } else
-#endif /* EINPROGRESS or EALREADY */
- {
- DBGPRINTF(("SOCKET: connect failed errno=%d\n", errno));
-#ifdef DUMP_ADDRESS
- {
- char *cp = (char *)(&sa);
- int i;
-
- printf("address data:\n");
- for (i=0; i<sockaddr_size; i++) {
- printf(" %02x\n", *cp++);
- }
- }
-#endif
- __INST(lastErrorNumber) = __MKSMALLINT(errno);
- RETURN (false);
- }
+ __INST(lastErrorNumber) = __MKSMALLINT(errno);
+ RETURN (false);
+ }
}
-#if defined(O_NONBLOCK)
+# if defined(O_NONBLOCK)
fcntl(sock, F_SETFL, oldFlags);
-#endif
-
-#else /* NO_SOCKET */
+# endif
+
+# else /* NO_SOCKET */
RETURN (false);
-#endif /* NO_SOCKET */
+# endif /* NO_SOCKET */
%}.
isAsync == true ifTrue:[
- (self writeWaitWithTimeoutMs:timeout) ifTrue:[
- "/ a timeout occured
- "/ should cancel the connect?
- ^ false.
- ].
- err := self getSocketError.
- err ~~ 0 ifTrue:[
- lastErrorNumber := err.
- ^ false.
- ].
+ (self writeWaitWithTimeoutMs:timeout) ifTrue:[
+ "/ a timeout occured
+ "/ should cancel the connect?
+ ^ false.
+ ].
+ err := self getSocketError.
+ err ~~ 0 ifTrue:[
+ lastErrorNumber := err.
+ ^ false.
+ ].
].
- port := portNrOrName.
- peerName := hostOrPathName.
+ port := portNrOrNameOrNil.
+ peer := addr.
+ peerName := addrName.
^ true
"
@@ -4574,7 +4329,7 @@
^ self isActive
and:[port notNil
- and:[peerName notNil]]
+ and:[peerName notNil or:[peer notNil]]]
!
port
@@ -5194,5 +4949,5 @@
!Socket class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.175 2003-05-19 11:12:19 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.176 2003-05-20 16:27:08 cg Exp $'
! !