X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/b7a189f38294c745ae4ea6efb55891c8196e275b..3d88e64dfcf5dc0fd361ce0c504c67a9196ce44c:/unix/uxnet.c diff --git a/unix/uxnet.c b/unix/uxnet.c index 3440d19e..9dd4aa62 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -117,9 +117,9 @@ char *error_string(int error) return strerror(error); } -SockAddr sk_namelookup(char *host, char **canonicalname) +SockAddr sk_namelookup(const char *host, char **canonicalname) { - SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); + SockAddr ret = snew(struct SockAddr_tag); unsigned long a; struct hostent *h = NULL; char realhost[8192]; @@ -195,14 +195,15 @@ SockAddr sk_namelookup(char *host, char **canonicalname) } ret->address = ntohl(a); realhost[lenof(realhost)-1] = '\0'; - *canonicalname = smalloc(1+strlen(realhost)); + *canonicalname = snewn(1+strlen(realhost), char); strcpy(*canonicalname, realhost); return ret; } -SockAddr sk_nonamelookup(char *host) +SockAddr sk_nonamelookup(const char *host) { - SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); + SockAddr ret = snew(struct SockAddr_tag); + ret->error = NULL; ret->family = AF_UNSPEC; strncpy(ret->hostname, host, lenof(ret->hostname)); ret->hostname[lenof(ret->hostname)-1] = '\0'; @@ -297,34 +298,34 @@ static void sk_tcp_flush(Socket s) } static void sk_tcp_close(Socket s); -static int sk_tcp_write(Socket s, char *data, int len); -static int sk_tcp_write_oob(Socket s, char *data, int len); +static int sk_tcp_write(Socket s, const char *data, int len); +static int sk_tcp_write_oob(Socket s, const char *data, int len); static void sk_tcp_set_private_ptr(Socket s, void *ptr); static void *sk_tcp_get_private_ptr(Socket s); static void sk_tcp_set_frozen(Socket s, int is_frozen); static char *sk_tcp_socket_error(Socket s); +static struct socket_function_table tcp_fn_table = { + sk_tcp_plug, + sk_tcp_close, + sk_tcp_write, + sk_tcp_write_oob, + sk_tcp_flush, + sk_tcp_set_private_ptr, + sk_tcp_get_private_ptr, + sk_tcp_set_frozen, + sk_tcp_socket_error +}; + Socket sk_register(void *sock, Plug plug) { - static struct socket_function_table fn_table = { - sk_tcp_plug, - sk_tcp_close, - sk_tcp_write, - sk_tcp_write_oob, - sk_tcp_flush, - sk_tcp_set_private_ptr, - sk_tcp_get_private_ptr, - sk_tcp_set_frozen, - sk_tcp_socket_error - }; - Actual_Socket ret; /* * Create Socket structure. */ - ret = smalloc(sizeof(struct Socket_tag)); - ret->fn = &fn_table; + ret = snew(struct Socket_tag); + ret->fn = &tcp_fn_table; ret->error = NULL; ret->plug = plug; bufchain_init(&ret->output_data); @@ -354,18 +355,6 @@ Socket sk_register(void *sock, Plug plug) Socket sk_new(SockAddr addr, int port, int privport, int oobinline, int nodelay, Plug plug) { - static struct socket_function_table fn_table = { - sk_tcp_plug, - sk_tcp_close, - sk_tcp_write, - sk_tcp_write_oob, - sk_tcp_flush, - sk_tcp_set_private_ptr, - sk_tcp_get_private_ptr, - sk_tcp_set_frozen, - sk_tcp_socket_error - }; - int s; #ifdef IPV6 struct sockaddr_in6 a6; @@ -378,8 +367,8 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, /* * Create Socket structure. */ - ret = smalloc(sizeof(struct Socket_tag)); - ret->fn = &fn_table; + ret = snew(struct Socket_tag); + ret->fn = &tcp_fn_table; ret->error = NULL; ret->plug = plug; bufchain_init(&ret->output_data); @@ -489,6 +478,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, a.sin_port = htons((short) port); } + { + int i = 1; + ioctl(s, FIONBIO, &i); + } + if (( #ifdef IPV6 connect(s, ((addr->family == AF_INET6) ? @@ -498,13 +492,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, connect(s, (struct sockaddr *) &a, sizeof(a)) #endif ) < 0) { - /* - * FIXME: We are prepared to receive EWOULDBLOCK here, - * because we might want the connection to be made - * asynchronously; but how do we actually arrange this in - * Unix? I forget. - */ - if ( errno != EWOULDBLOCK ) { + if ( errno != EINPROGRESS ) { ret->error = error_string(errno); return (Socket) ret; } @@ -524,18 +512,6 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) { - static struct socket_function_table fn_table = { - sk_tcp_plug, - sk_tcp_close, - sk_tcp_write, - sk_tcp_write_oob, - sk_tcp_flush, - sk_tcp_set_private_ptr, - sk_tcp_get_private_ptr, - sk_tcp_set_frozen, - sk_tcp_socket_error - }; - int s; #ifdef IPV6 struct sockaddr_in6 a6; @@ -549,8 +525,8 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) /* * Create Socket structure. */ - ret = smalloc(sizeof(struct Socket_tag)); - ret->fn = &fn_table; + ret = snew(struct Socket_tag); + ret->fn = &tcp_fn_table; ret->error = NULL; ret->plug = plug; bufchain_init(&ret->output_data); @@ -661,6 +637,35 @@ static void sk_tcp_close(Socket sock) sfree(s); } +int sk_getxdmdata(void *sock, unsigned long *ip, int *port) +{ + Actual_Socket s = (Actual_Socket) sock; + struct sockaddr_in addr; + socklen_t addrlen; + + /* + * We must check that this socket really _is_ an Actual_Socket. + */ + if (s->fn != &tcp_fn_table) + return 0; /* failure */ + + /* + * If we ever implement connecting to a local X server through + * a Unix socket, we return 0xFFFFFFFF for the IP address and + * our current pid for the port. Bizarre, but such is life. + */ + + addrlen = sizeof(addr); + if (getsockname(s->s, (struct sockaddr *)&addr, &addrlen) < 0 || + addr.sin_family != AF_INET) + return 0; + + *ip = ntohl(addr.sin_addr.s_addr); + *port = ntohs(addr.sin_port); + + return 1; +} + /* * The function which tries to send on a socket once it's deemed * writable. @@ -726,7 +731,7 @@ void try_send(Actual_Socket s) } } -static int sk_tcp_write(Socket sock, char *buf, int len) +static int sk_tcp_write(Socket sock, const char *buf, int len) { Actual_Socket s = (Actual_Socket) sock; @@ -744,7 +749,7 @@ static int sk_tcp_write(Socket sock, char *buf, int len) return bufchain_size(&s->output_data); } -static int sk_tcp_write_oob(Socket sock, char *buf, int len) +static int sk_tcp_write_oob(Socket sock, const char *buf, int len) { Actual_Socket s = (Actual_Socket) sock; @@ -781,11 +786,6 @@ int select_result(int fd, int event) noise_ultralight(event); switch (event) { -#ifdef FIXME_NONBLOCKING_CONNECTIONS - case FIXME: /* connected */ - s->connected = s->writable = 1; - break; -#endif case 4: /* exceptional */ if (!s->oobinline) { /* @@ -882,7 +882,14 @@ int select_result(int fd, int event) } break; case 2: /* writable */ - { + if (!s->connected) { + /* + * select() reports a socket as _writable_ when an + * asynchronous connection is completed. + */ + s->connected = s->writable = 1; + break; + } else { int bufsize_before, bufsize_after; s->writable = 1; bufsize_before = s->sending_oob + bufchain_size(&s->output_data); @@ -987,6 +994,8 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen) static void set_rwx(Actual_Socket s, int *rwx) { int val = 0; + if (!s->connected) + val |= 2; /* write == connect */ if (s->connected && !s->frozen) val |= 1 | 4; /* read, except */ if (bufchain_size(&s->output_data))