X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/ab0873ab80d0c927315329be0cbeb96bb4ace89a..e8fa8f62da443bfc89c416d3eeafcde69c8c6403:/unix/uxnet.c diff --git a/unix/uxnet.c b/unix/uxnet.c index 82b413dc..08da8f42 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -117,7 +117,7 @@ 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)); unsigned long a; @@ -200,7 +200,7 @@ SockAddr sk_namelookup(char *host, char **canonicalname) return ret; } -SockAddr sk_nonamelookup(char *host) +SockAddr sk_nonamelookup(const char *host) { SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); ret->error = NULL; @@ -298,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->fn = &tcp_fn_table; ret->error = NULL; ret->plug = plug; bufchain_init(&ret->output_data); @@ -355,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; @@ -380,7 +368,7 @@ 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->fn = &tcp_fn_table; ret->error = NULL; ret->plug = plug; bufchain_init(&ret->output_data); @@ -490,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) ? @@ -499,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; } @@ -525,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; @@ -551,7 +526,7 @@ 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->fn = &tcp_fn_table; ret->error = NULL; ret->plug = plug; bufchain_init(&ret->output_data); @@ -662,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. @@ -727,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; @@ -745,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; @@ -782,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) { /* @@ -883,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); @@ -988,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))