int sock_connected (sock_t sock, int timeout) { struct pollfd check; int val = SOCK_ERROR; socklen_t size = sizeof val; check.fd = sock; check.events = POLLOUT; switch (poll (&check, 1, timeout*1000)) { case 0: return SOCK_TIMEOUT; default: /* on windows getsockopt.val is defined as char* */ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*) &val, &size) == 0) { if (val == 0) return 1; sock_set_error (val); } /* fall through */ case -1: if (sock_recoverable (sock_error())) return 0; return SOCK_ERROR; } }
/* create a new and unconnected socket */ static struct object *create_socket( int family, int type, int protocol, unsigned int flags ) { struct sock *sock; int sockfd; sockfd = socket( family, type, protocol ); if (debug_level) fprintf(stderr,"socket(%d,%d,%d)=%d\n",family,type,protocol,sockfd); if (sockfd == -1) { sock_set_error(); return NULL; } fcntl(sockfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ if (!(sock = alloc_object( &sock_ops ))) { close( sockfd ); return NULL; } sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0; sock->mask = 0; sock->hmask = 0; sock->pmask = 0; sock->polling = 0; sock->flags = flags; sock->type = type; sock->family = family; sock->event = NULL; sock->window = 0; sock->message = 0; sock->wparam = 0; sock->deferred = NULL; sock->read_q = NULL; sock->write_q = NULL; memset( sock->errors, 0, sizeof(sock->errors) ); if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj, (flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT ))) { release_object( sock ); return NULL; } sock_reselect( sock ); clear_error(); return &sock->obj; }
/* accepts a socket and inits it */ static int accept_new_fd( struct sock *sock ) { /* Try to accept(2). We can't be safe that this an already connected socket * or that accept() is allowed on it. In those cases we will get -1/errno * return. */ int acceptfd; struct sockaddr saddr; socklen_t slen = sizeof(saddr); acceptfd = accept( get_unix_fd(sock->fd), &saddr, &slen); if (acceptfd == -1) { sock_set_error(); return acceptfd; } fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ return acceptfd; }
int sock_connected (sock_t sock, int timeout) { fd_set wfds; int val = SOCK_ERROR; socklen_t size = sizeof val; struct timeval tv, *timeval = NULL; /* make a timeout of <0 be indefinite */ if (timeout >= 0) { tv.tv_sec = timeout; tv.tv_usec = 0; timeval = &tv; } FD_ZERO(&wfds); FD_SET(sock, &wfds); switch (select(sock + 1, NULL, &wfds, NULL, timeval)) { case 0: return SOCK_TIMEOUT; default: /* on windows getsockopt.val is defined as char* */ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*) &val, &size) == 0) { if (val == 0) return 1; sock_set_error (val); } /* fall through */ case -1: if (sock_recoverable (sock_error())) return 0; return SOCK_ERROR; } }
/* accept a socket (creates a new fd) */ static struct sock *accept_socket( obj_handle_t handle ) { struct sock *acceptsock; struct sock *sock; int acceptfd; struct sockaddr saddr; sock = (struct sock *)get_handle_obj( current->process, handle, FILE_READ_DATA, &sock_ops ); if (!sock) return NULL; if ( sock->deferred ) { acceptsock = sock->deferred; sock->deferred = NULL; } else { /* Try to accept(2). We can't be safe that this an already connected socket * or that accept() is allowed on it. In those cases we will get -1/errno * return. */ unsigned int slen = sizeof(saddr); acceptfd = accept( get_unix_fd(sock->fd), &saddr, &slen); if (acceptfd==-1) { sock_set_error(); release_object( sock ); return NULL; } if (!(acceptsock = alloc_object( &sock_ops ))) { close( acceptfd ); release_object( sock ); return NULL; } /* newly created socket gets the same properties of the listening socket */ fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE; if (sock->state & FD_WINE_NONBLOCKING) acceptsock->state |= FD_WINE_NONBLOCKING; acceptsock->mask = sock->mask; acceptsock->hmask = 0; acceptsock->pmask = 0; acceptsock->polling = 0; acceptsock->type = sock->type; acceptsock->family = sock->family; acceptsock->event = NULL; acceptsock->window = sock->window; acceptsock->message = sock->message; acceptsock->wparam = 0; if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event ); acceptsock->flags = sock->flags; acceptsock->deferred = NULL; acceptsock->read_q = NULL; acceptsock->write_q = NULL; memset( acceptsock->errors, 0, sizeof(acceptsock->errors) ); if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj, get_fd_options( sock->fd ) ))) { release_object( acceptsock ); release_object( sock ); return NULL; } } clear_error(); sock->pmask &= ~FD_ACCEPT; sock->hmask &= ~FD_ACCEPT; sock_reselect( sock ); release_object( sock ); return acceptsock; }