psckt_t * psckt_connect(const char *addr, int port, void *ctx, psckt_cb_t *callback) { int sfd; psckt_t *sock = p_malloc(sizeof(psckt_t)); struct addrinfo *ai, *ailist = sock? psckt_get_ailist(addr, port, 0) : 0; if (!ailist) { if (sock) p_free(sock); return 0; } for (ai=ailist ; ai ; ai=ai->ai_next) { sfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sfd == -1) continue; if (connect(sfd, ai->ai_addr, ai->ai_addrlen) != -1) break; close(sfd); } if (!ai) { p_free(sock); sock = 0; } freeaddrinfo(ailist); if (!sock) return 0; sock->fd = sfd; sock->peer = p_strcpy(addr); return psckt_setup(sock, ctx, callback); }
psckt_t * psckt_accept(psckt_t *listener, char **ppeer, void *ctx, psckt_cb_t *callback) { struct sockaddr_storage sad; socklen_t lsad = sizeof(struct sockaddr_storage); struct sockaddr *psad = (struct sockaddr *)&sad; char host[NI_MAXHOST]; psckt_t *sock = p_malloc(sizeof(psckt_t)); int sfd, lfd = sock->fd; *ppeer = 0; if (listener->peer || !sock) { /* listeners have no peer */ if (sock) p_free(sock); return 0; } sfd = accept(listener->fd, psad, &lsad); if (sfd==-1 || getnameinfo(psad, lsad, host, NI_MAXHOST, 0, 0, 0)) { close(sfd); p_free(sock); return 0; } sock->fd = sfd; sock->peer = *ppeer = p_strcpy(host); return psckt_setup(sock, ctx, callback); }
psckt_t * psckt_listen(int *pport, void *ctx, psckt_cb_t *callback) { int lfd; int port = *pport; psckt_t *listener = p_malloc(sizeof(psckt_t)); struct addrinfo *ai, *ailist = listener? psckt_get_ailist(0, port, 1) : 0; if (!ailist) { if (listener) p_free(listener); return 0; } for (ai=ailist ; ai ; ai=ai->ai_next) { lfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (lfd == -1) continue; if (!bind(lfd, ai->ai_addr, ai->ai_addrlen)) break; close(lfd); } if (ailist) freeaddrinfo(ailist); if (lfd < 0) { p_free(listener); return 0; } if (port == 0) { struct sockaddr_storage sad; socklen_t lsad = sizeof(struct sockaddr_storage); struct sockaddr *psad = (struct sockaddr *)&sad; char sport[NI_MAXSERV]; if (getsockname(lfd, psad, &lsad) || getnameinfo(psad, lsad, 0, 0, sport, NI_MAXSERV, NI_NUMERICSERV)) { close(lfd); p_free(listener); return 0; } pport[0] = port = strtod(sport, 0); } if (listen(lfd, 10)) { close(lfd); p_free(listener); return 0; } listener->fd = lfd; listener->peer = 0; /* listener has no peer, could usefully be port */ return psckt_setup(listener, ctx, callback); }
psckt_t * psckt_accept(psckt_t *listener, char **ppeer, void *ctx, psckt_cb_t *callback) { struct sockaddr_storage sad; socklen_t lsad = sizeof(struct sockaddr_storage); struct sockaddr *psad = (struct sockaddr *)&sad; char host[NI_MAXHOST]; psckt_t *sock = p_malloc(sizeof(psckt_t)); SOCKET sfd, lfd = sock->fd; *ppeer = 0; if (listener->peer || !sock) { /* listeners have no peer */ if (sock) p_free(sock); return 0; } if (listener->callback && listener->waiting) { if (WaitForSingleObject(listener->ready, INFINITE) != WAIT_OBJECT_0) psckt_stop_thread(listener); listener->waiting = 0; if (listener->ready != INVALID_HANDLE_VALUE) ResetEvent(listener->ready); } sfd = accept(listener->fd, psad, &lsad); if (sfd==INVALID_SOCKET || getnameinfo(psad, lsad, host, NI_MAXHOST, 0, 0, 0)) { closesocket(sfd); p_free(sock); return 0; } sock->fd = sfd; sock->peer = *ppeer = p_strcpy(host); return psckt_setup(sock, ctx, callback); }