> This structure have to be different on BSDs. > I am unable to fix it my self.
I see why the fix in experimental does not work. Apparently BSD systems actually do not care much about the content of sa_len, it's just that it is there. I had tested the fix with Mac OS on a big-endian PowerPC. So sa_len was always 0, but sa_family was set correctly. On little-endian systems it's the other way round, and sa_family is set incorrectly to 0. I'm now always passing to C sockaddrs with sa_len, and removing the sa_len on platforms that do not have it. 2008-08-29 Paolo Bonzini <[EMAIL PROTECTED]> * IP6SocketImpl.st: Fill in sa_len dutifully for BSD systems. * IPSocketImpl.st: Fill in sa_len dutifully for BSD systems. * UnixSocketImpl.st: Fill in sa_len dutifully for BSD systems. * sockets.c: Undo the above dutifully for non-BSD systems. diff --git a/build-aux/sockets.m4 b/build-aux/sockets.m4 index 3020534..2f62e83 100644 --- a/build-aux/sockets.m4 +++ b/build-aux/sockets.m4 @@ -25,6 +25,9 @@ AC_CHECK_MEMBER([struct addrinfo.ai_family], [Define if your system's netdb.h has struct addrinfo])], [], [#include <netdb.h>]) +dnl This is wrong for Windows, but anyway Windows does not have sa_len +AC_CHECK_MEMBERS([struct sockaddr.sa_len], , , [#include <sys/socket.h>]) + if test "$ac_cv_lib_ws2_32_listen" = "yes"; then gst_cv_sockets=yes fi diff --git a/packages/sockets/IP6SocketImpl.st b/packages/sockets/IP6SocketImpl.st index 4c043a2..d437632 100644 --- a/packages/sockets/IP6SocketImpl.st +++ b/packages/sockets/IP6SocketImpl.st @@ -248,8 +248,9 @@ stream (TCP), datagram (UDP) and raw sockets.'> with: address startingAt: 1; - "Write sin_family = AF_INET in host order" - shortAt: 1 put: self class addressFamily; + "Write sin_len and sin_family = AF_INET6" + at: 1 put: 28; + at: 2 put: self class addressFamily; "Write sin_port in network order (big endian)" at: 3 put: port // 256; diff --git a/packages/sockets/IPSocketImpl.st b/packages/sockets/IPSocketImpl.st index b298d80..f1837a7 100644 --- a/packages/sockets/IPSocketImpl.st +++ b/packages/sockets/IPSocketImpl.st @@ -315,8 +315,9 @@ stream (TCP), datagram (UDP) and raw sockets.'> with: address startingAt: 1; - "Write sin_family = AF_INET in host order" - shortAt: 1 put: self class addressFamily; + "Write sin_len and sin_family = AF_INET" + at: 1 put: 16; + at: 2 put: self class addressFamily; "Write sin_port in network order (big endian)" at: 3 put: port // 256; diff --git a/packages/sockets/UnixSocketImpl.st b/packages/sockets/UnixSocketImpl.st index 794c5ef..58b6ddd 100644 --- a/packages/sockets/UnixSocketImpl.st +++ b/packages/sockets/UnixSocketImpl.st @@ -138,8 +138,9 @@ a String or a File object. portString size > 108 ifTrue: [self error: 'socket path too long']. ^(ByteArray new: 110) - "Write sin_family = AF_INET in host order" - shortAt: 1 put: self class addressFamily; + "Write sin_len and sin_family = AF_UNIX" + at: 1 put: portString size + 2; + at: 2 put: self class addressFamily; replaceFrom: 3 to: portString size + 2 with: portString startingAt: 1; yourself ] diff --git a/packages/sockets/sockets.c b/packages/sockets/sockets.c index a7cc1a1..c34b1b5 100644 --- a/packages/sockets/sockets.c +++ b/packages/sockets/sockets.c @@ -270,9 +270,25 @@ mySocket (int domain, int type, int protocol) return fd; } + +/* BSD systems have sa_len, others have not. Smalltalk will always + write sockaddr structs as if they had it. So for Linux and Winsock + we read the second byte (sa_family on BSD systems) and write it in the + entire sa_family field. */ +static inline void +fix_sockaddr (struct sockaddr *sockaddr) +{ +#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN + /* Make sure sa_family is a short. */ + char verify[sizeof (sockaddr->sa_family) == 2 ? 1 : -1]; + + sockaddr->sa_family = ((unsigned char *) sockaddr)[1]; +#endif +} + /* Same as connect, but forces the socket to be in non-blocking mode */ static void -myConnect (int fd, const struct sockaddr *sockaddr, int len) +myConnect (int fd, struct sockaddr *sockaddr, int len) { SOCKET sock = FD_TO_SOCKET (fd); #ifdef __MSVCRT__ @@ -286,6 +302,7 @@ myConnect (int fd, const struct sockaddr *sockaddr, int len) fcntl (sock, F_SETFL, oldflags | O_NONBLOCK); #endif + fix_sockaddr (sockaddr); connect (sock, sockaddr, len); if (is_socket_error (EINPROGRESS)) errno = 0; @@ -299,8 +316,9 @@ myAccept (int fd, struct sockaddr *addr, int *addrlen) } static int -myBind (int fd, const struct sockaddr *addr, int addrlen) +myBind (int fd, struct sockaddr *addr, int addrlen) { + fix_sockaddr (addr); return bind (FD_TO_SOCKET (fd), addr, addrlen); } @@ -345,8 +363,9 @@ myRecvfrom (int fd, char *buf, int len, int flags, struct sockaddr *from, static int mySendto (int fd, const char *buf, int len, int flags, - const struct sockaddr *to, int tolen) + struct sockaddr *to, int tolen) { + fix_sockaddr (to); return sendto (FD_TO_SOCKET (fd), buf, len, flags, to, tolen); } @@ -355,6 +374,7 @@ mySetsockopt (int fd, int level, int optname, const char *optval, int optlen) { return setsockopt (FD_TO_SOCKET (fd), level, optname, optval, optlen); } + static int getSoError (int fd) { Blaaargh. Paolo -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]