diff --git a/src/authradius.c b/src/authradius.c index 279aa81..635547c 100644 --- a/src/authradius.c +++ b/src/authradius.c @@ -560,7 +560,7 @@ int radsend(struct clientparam * param, int auth, int stop){ memset(fds, 0, sizeof(fds)); fds[0].fd = remsock; fds[0].events = POLLIN; - if(so._poll(so.state, fds, 1, param->srv->config->timeouts[SINGLEBYTE_L]*1000) <= 0) { + if(sockpoll(&so, so.state, fds, 1, param->srv->config->timeouts[SINGLEBYTE_L]*1000) <= 0) { continue; } diff --git a/src/common.c b/src/common.c index 8b87887..3bd4462 100644 --- a/src/common.c +++ b/src/common.c @@ -360,16 +360,8 @@ int int WINAPI def_setsockopt(void* state, SOCKET s, int level, int optname, const char *optval, int optlen){ return setsockopt(s, level, optname, optval, optlen); } - int WINAPI def_poll(void* state, struct pollfd *fds, unsigned int nfds, int timeout){ -#ifndef WITH_POLL -#ifndef WITH_WSAPOLL - return mypoll(fds, nfds, timeout); -#else - return WSAPoll(fds, nfds, timeout); -#endif -#else - return poll(fds, nfds, timeout); -#endif + int WINAPI def_prepoll(void* state, struct pollfd *fds, unsigned int nfds){ + return 0; } int WINAPI def_send(void* state, SOCKET s, const char *msg, int len, int flags){ return send(s, msg, len, flags); @@ -419,12 +411,8 @@ int return setsockopt(s, level, optname, optval, optlen); } - int def_poll(void* state, struct pollfd *fds, nfds_t nfds, int timeout){ -#ifndef WITH_POLL - return mypoll(fds, nfds, timeout); -#else - return poll(fds, nfds, timeout); -#endif + int def_prepoll(void* state, struct pollfd *fds, nfds_t nfds){ + return 0; } /* a peer gone is an error of the send, not SIGPIPE, where the system can @@ -466,7 +454,7 @@ struct sockfuncs so = { def_getsockname, def_getsockopt, def_setsockopt, - def_poll, + def_prepoll, def_send, def_sendto, def_recv, @@ -475,6 +463,43 @@ struct sockfuncs so = { def_closesocket }; +/* Waits as poll() does for fds of sockets made with sf, once their layers + know of nothing ready already. A layer may have a socket waited for + other than as asked, a TLS read for it to be writable: whatever it gets + is then the caller's chance to try again, revents what the caller asked + for, and events are given back as they were. With no fds it only + sleeps. */ +#define POLLFAIL (POLLERR|POLLHUP|POLLNVAL) +int sockpoll(struct sockfuncs *sf, void *state, struct pollfd *fds, unsigned nfds, int timeout){ + short own[64], *events = own; + unsigned i; + int res; + + if(!nfds){ + if(timeout > 0) usleep(timeout * SLEEPTIME); + return 0; + } + if(nfds > sizeof(own)/sizeof(own[0]) && !(events = malloc(nfds * sizeof(*events)))) return -1; + for(i = 0; i < nfds; i++) events[i] = fds[i].events; + if(!(res = sf->_prepoll(state, fds, nfds))){ +#ifndef WITH_POLL +#ifndef WITH_WSAPOLL + res = mypoll(fds, nfds, timeout); +#else + res = WSAPoll(fds, nfds, timeout); +#endif +#else + res = poll(fds, (nfds_t)nfds, timeout); +#endif + for(i = 0; res > 0 && i < nfds; i++) + if(fds[i].events != events[i] && (fds[i].revents & ~POLLFAIL)) + fds[i].revents = events[i] | (fds[i].revents & POLLFAIL); + } + for(i = 0; i < nfds; i++) fds[i].events = events[i]; + if(events != own) free(events); + return res; +} + #ifdef _WINCE static char cebuf[1024]; @@ -664,7 +689,7 @@ int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, memset(fds, 0, sizeof(fds)); fds[0].fd = sock; fds[0].events = POLLOUT; - if((param?param->srv->so._poll(param->sostate, fds, 1, to*1000):so._poll(so.state, fds, 1, to*1000)) <= 0 || !(fds[0].revents & POLLOUT) || (fds[0].revents & (POLLERR|POLLHUP))) { + if((param?sockpoll(¶m->srv->so, param->sostate, fds, 1, to*1000):sockpoll(&so, so.state, fds, 1, to*1000)) <= 0 || !(fds[0].revents & POLLOUT) || (fds[0].revents & (POLLERR|POLLHUP))) { return 13; } return 0; diff --git a/src/ftppr.c b/src/ftppr.c index 486de53..70bc513 100644 --- a/src/ftppr.c +++ b/src/ftppr.c @@ -222,7 +222,7 @@ void * ftpprchild(struct clientparam* param) { fds.fd = clidatasock; fds.events = POLLIN; - res = param->srv->so._poll (param->sostate, &fds, 1, param->srv->timeouts[STRING_L]*1000); + res = sockpoll(¶m->srv->so, param->sostate, &fds, 1, param->srv->timeouts[STRING_L]*1000); if(res != 1) { RETURN(857); } diff --git a/src/httpsrv.c b/src/httpsrv.c index 36a6b47..559536c 100644 --- a/src/httpsrv.c +++ b/src/httpsrv.c @@ -1190,7 +1190,7 @@ static void httpsrv_linger(struct clientparam *param) memset(&fd, 0, sizeof(fd)); fd.fd = param->clisock; fd.events = POLLIN; - if(param->srv->so._poll(param->sostate, &fd, 1, timeo * 1000) <= 0) break; + if(sockpoll(¶m->srv->so, param->sostate, &fd, 1, timeo * 1000) <= 0) break; got = (int)param->srv->so._recv(param->sostate, param->clisock, buf, (left > HTTPSRV_BLOCK)? (int)HTTPSRV_BLOCK : (int)left, 0); if(got <= 0) break; @@ -1225,7 +1225,7 @@ static int proxypass(struct clientparam *param, struct httpreq *r) memset(&fd, 0, sizeof(fd)); fd.fd = param->remsock; fd.events = POLLIN; - if(param->srv->so._poll(param->sostate, &fd, 1, 0) > 0 + if(sockpoll(¶m->srv->so, param->sostate, &fd, 1, 0) > 0 && (fd.revents & (POLLIN|POLLHUP|POLLERR|POLLNVAL))){ /* anything arriving now belongs to no request */ stale = 1; diff --git a/src/mainclient.c b/src/mainclient.c index d205429..6c17f5e 100644 --- a/src/mainclient.c +++ b/src/mainclient.c @@ -47,7 +47,7 @@ static void serveparam(struct clientparam *param){ fds.events = POLLIN; fds.revents = 0; for(i=5+(param->srv->maxchild>>10); i; i--){ - if(param->srv->so._poll(param->sostate, &fds, 1, 1000*CONNBACK_TO)!=1){ + if(sockpoll(¶m->srv->so, param->sostate, &fds, 1, 1000*CONNBACK_TO)!=1){ dolog(param, (unsigned char *)"Connect back not received, check connback client"); i = 0; break; @@ -86,7 +86,7 @@ static void serveparam(struct clientparam *param){ rf.fd = param->remsock; rf.events = POLLIN; rf.revents = 0; - if(param->srv->so._poll(param->sostate, &rf, 1, 0) == 1){ + if(sockpoll(¶m->srv->so, param->sostate, &rf, 1, 0) == 1){ param->srv->so._closesocket(param->sostate, param->remsock); param->remsock = INVALID_SOCKET; if(skips > 0){ skips--; i++; } diff --git a/src/maintcp.c b/src/maintcp.c index 336bc71..6c72a4c 100644 --- a/src/maintcp.c +++ b/src/maintcp.c @@ -210,7 +210,7 @@ static int tcploop(struct srvstart *s, int *haveslot){ } if (connectback) break; if (srv->config->paused != srv->paused) break; - error = srv->so._poll(srv->so.state, &srv->fds, 1, 1000); + error = sockpoll(&srv->so, srv->so.state, &srv->fds, 1, 1000); if (error >= 1) break; if (error == 0) continue; if (errno != EAGAIN && errno != EINTR) { diff --git a/src/mainudp.c b/src/mainudp.c index d7b68f1..fe21368 100644 --- a/src/mainudp.c +++ b/src/mainudp.c @@ -638,7 +638,7 @@ static int udploop(struct srvstart *s){ st.of[nfds++] = ss; } } - n = srv->so._poll(srv->so.state, st.fds, nfds, timeo); + n = sockpoll(&srv->so, srv->so.state, st.fds, nfds, timeo); if(n < 0 && errno != EINTR && errno != EAGAIN){ res = 91; break; diff --git a/src/plugins/FilePlugin/FilePlugin.c b/src/plugins/FilePlugin/FilePlugin.c index efe6db6..116c869 100644 --- a/src/plugins/FilePlugin/FilePlugin.c +++ b/src/plugins/FilePlugin/FilePlugin.c @@ -411,9 +411,9 @@ static int copyfdtosock(struct fp_stream * fps, DIRECTION which, long len){ } #ifdef _WIN32 -static int WINAPI fp_poll(void *state, struct pollfd *fds, unsigned int nfds, int timeout){ +static int WINAPI fp_prepoll(void *state, struct pollfd *fds, unsigned int nfds){ #else -static int fp_poll(void *state, struct pollfd *fds, nfds_t nfds, int timeout){ +static int fp_prepoll(void *state, struct pollfd *fds, nfds_t nfds){ #endif struct fp_stream *fps = NULL; int res; @@ -458,7 +458,7 @@ static int fp_poll(void *state, struct pollfd *fds, nfds_t nfds, int timeout){ } } - return sso._poll(sso.state, fds, nfds, timeout); + return sso._prepoll(sso.state, fds, nfds); } #ifdef _WIN32 @@ -916,7 +916,7 @@ static int file_loaded=0; file_loaded = 1; pl = pluginlink; memcpy(&sso, pl->so, sizeof(struct sockfuncs)); - pl->so->_poll = fp_poll; + pl->so->_prepoll = fp_prepoll; pl->so->_send = fp_send; pl->so->_sendto = fp_sendto; pl->so->_recv = fp_recv; diff --git a/src/proxy.c b/src/proxy.c index 923f094..8f8ef71 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -567,7 +567,7 @@ for(;;){ fds[0].events = POLLIN; fds[1].fd = param->remsock; fds[1].events = POLLIN; - res = param->srv->so._poll(param->sostate, fds, 2, param->srv->timeouts[STRING_S]*1000); + res = sockpoll(¶m->srv->so, param->sostate, fds, 2, param->srv->timeouts[STRING_S]*1000); if(res<=0) { RETURN(555); } diff --git a/src/proxy.h b/src/proxy.h index c738c0e..7538307 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -332,6 +332,7 @@ int nsbroken(void); /* a function everywhere, never a macro: its callers have preprocessor lines among its arguments */ SOCKET nssocket(struct srvparam *srv, struct sockfuncs *sf, void *state, int side, int domain, int type, int protocol); +int sockpoll(struct sockfuncs *sf, void *state, struct pollfd *fds, unsigned nfds, int timeout); int socksend(struct clientparam *param, SOCKET sock, unsigned char * buf, int bufsize, int to); int socksendto(struct clientparam *param, SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to); int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to); diff --git a/src/sockgetchar.c b/src/sockgetchar.c index e971040..c803da6 100644 --- a/src/sockgetchar.c +++ b/src/sockgetchar.c @@ -23,7 +23,7 @@ int socksend(struct clientparam *param, SOCKET sock, unsigned char * buf, int bu continue; } if(res < 0 && errno != EAGAIN && errno != EINTR) break; - res = param?param->srv->so._poll(param->sostate, &fds, 1, to*1000):so._poll(so.state, &fds, 1, to*1000); + res = param?sockpoll(¶m->srv->so, param->sostate, &fds, 1, to*1000):sockpoll(&so, so.state, &fds, 1, to*1000); if(res < 0 && (errno == EAGAIN || errno == EINTR)) continue; if(res < 1) break; } while (sent < bufsize); @@ -40,7 +40,7 @@ int socksendto(struct clientparam *param, SOCKET sock, struct sockaddr * sin, un do { if(timetoexit) return 0; fds.events = POLLOUT; - res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to); + res = param?sockpoll(¶m->srv->so, param->sostate, &fds, 1, to):sockpoll(&so, so.state, &fds, 1, to); if(res < 0 && (errno == EAGAIN || errno == EINTR)) continue; if(res < 1) break; res = param?param->srv->so._sendto(param->sostate, sock, (char *)buf + sent, bufsize - sent, 0, sin, SASIZE(sin)):so._sendto(so.state, sock, (char *)buf + sent, bufsize - sent, 0, sin, SASIZE(sin)); @@ -62,7 +62,7 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin, fds.events = POLLIN; for(;;){ if(timetoexit) return EOF; - res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to); + res = param?sockpoll(¶m->srv->so, param->sostate, &fds, 1, to):sockpoll(&so, so.state, &fds, 1, to); if (res<1) return 0; sasize = sizeof(PROXYSOCKADDRTYPE); /* sin NULL for a stream socket: nothing to learn the address into */ diff --git a/src/sockmap.c b/src/sockmap.c index e8715e1..2e6309e 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -260,7 +260,7 @@ log(logbuf); memset(fds, 0, sizeof(fds)); fds[0].fd = param->clisock; fds[1].fd = param->remsock; - param->srv->so._poll(param->sostate, fds, 2, sleeptime); + sockpoll(¶m->srv->so, param->sostate, fds, 2, sleeptime); sleeptime = 0; } if((param->srv->logdumpsrv && (param->statssrv64 > param->srv->logdumpsrv)) || @@ -966,7 +966,7 @@ log("ready reading from server pipe"); #ifdef WITHLOG log("entering poll"); #endif - res = param->srv->so._poll(param->sostate, fds, fdsc, + res = sockpoll(¶m->srv->so, param->sostate, fds, fdsc, ((CLIENTTERMREAD || SERVERTERMREAD)? MIN(timeo, param->srv->timeouts[LINGER_TO]) : timeo) * 1000); #ifdef WITHLOG diff --git a/src/socks.c b/src/socks.c index f696611..467e3c8 100644 --- a/src/socks.c +++ b/src/socks.c @@ -355,7 +355,7 @@ fflush(stderr); fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[0].events = fds[1].events = POLLIN; - res = param->srv->so._poll(param->sostate, fds, 2, param->srv->timeouts[CONNECTION_L] * 1000); + res = sockpoll(¶m->srv->so, param->sostate, fds, 2, param->srv->timeouts[CONNECTION_L] * 1000); if (res < 1 || fds[1].revents) { res = 460; break; diff --git a/src/ssl.c b/src/ssl.c index b64ceeb..a3abef2 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -75,6 +75,9 @@ static int ktls = 0; struct SSLsock { SOCKET s; SSL_CONN conn; + /* what a read and a write which could not be done wait for, POLLIN + or POLLOUT, 0 once one is: TLS may have to write to read */ + short rwant, wwant; }; struct SSLstate { @@ -103,10 +106,12 @@ static void addSSL( if (cli_s != INVALID_SOCKET){ SOSTATE->cli.s = cli_s; SOSTATE->cli.conn = cli_conn; + SOSTATE->cli.rwant = SOSTATE->cli.wwant = 0; } if (srv_s != INVALID_SOCKET){ SOSTATE->srv.s = srv_s; SOSTATE->srv.conn = srv_conn; + SOSTATE->srv.rwant = SOSTATE->srv.wwant = 0; } } @@ -137,12 +142,14 @@ static ssize_t ssl_send(void *state, SOCKET s, const void *msg, size_t len, int int res, err; if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0){ err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); - if (err == SSL_ERROR_WANT_WRITE){ + if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ){ + sslq->wwant = (err == SSL_ERROR_WANT_READ)? POLLIN : POLLOUT; seterrno3(EAGAIN); return -1; } else seterrno3(err); } + else sslq->wwant = 0; return res; } @@ -159,14 +166,16 @@ static ssize_t ssl_sendto(void *state, SOCKET s, const void *msg, size_t len, in if ((sslq = searchSSL(state, s))){ int res, err; - if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0) { + if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0){ err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); - if (err == SSL_ERROR_WANT_WRITE){ + if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ){ + sslq->wwant = (err == SSL_ERROR_WANT_READ)? POLLIN : POLLOUT; seterrno3(EAGAIN); return -1; } else seterrno3(err); } + else sslq->wwant = 0; return res; } @@ -184,12 +193,14 @@ static ssize_t ssl_recvfrom(void *state, SOCKET s, void *msg, size_t len, int f int res, err; if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) { err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); - if (err == SSL_ERROR_WANT_READ) { + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + sslq->rwant = (err == SSL_ERROR_WANT_WRITE)? POLLOUT : POLLIN; seterrno3(EAGAIN); return -1; } else seterrno3(err); } + else sslq->rwant = 0; return res; } return sso._recvfrom(sso.state, s, msg, len, flags, from, fromlen); @@ -206,12 +217,14 @@ static ssize_t ssl_recv(void *state, SOCKET s, void *msg, size_t len, int flags) int res, err; if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) { err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); - if (err == SSL_ERROR_WANT_READ) { + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + sslq->rwant = (err == SSL_ERROR_WANT_WRITE)? POLLOUT : POLLIN; seterrno3(EAGAIN); return -1; } else seterrno3(err); } + else sslq->rwant = 0; return res; } @@ -228,14 +241,18 @@ static int WINAPI ssl_closesocket(void *state, SOCKET s){ return sso._closesocket(sso.state, s); } +/* Data already decrypted makes its socket readable. A read or a write TLS + could not do has its socket waited for as TLS needs it. */ #ifdef _WIN32 -static int WINAPI ssl_poll(void *state, struct pollfd *fds, unsigned int nfds, int timeout){ +static int WINAPI ssl_prepoll(void *state, struct pollfd *fds, unsigned int nfds){ #else -static int ssl_poll(void *state, struct pollfd *fds, nfds_t nfds, int timeout){ +static int ssl_prepoll(void *state, struct pollfd *fds, nfds_t nfds){ #endif struct SSLsock *sslq = NULL; unsigned int i; int ret = 0; + short events; + for(i = 0; i < nfds; i++){ if((fds[i].events & POLLIN) && (sslq = searchSSL(state, fds[i].fd)) && ssl_pending(sslq->conn)){ fds[i].revents = POLLIN; @@ -244,9 +261,14 @@ static int ssl_poll(void *state, struct pollfd *fds, nfds_t nfds, int timeout){ else fds[i].revents = 0; } if(ret) return ret; - - ret = sso._poll(state, fds, nfds, timeout); - return ret; + for(i = 0; i < nfds; i++){ + if(!(sslq = searchSSL(state, fds[i].fd))) continue; + events = fds[i].events & ~(POLLIN|POLLOUT); + if(fds[i].events & POLLIN) events |= sslq->rwant? sslq->rwant : POLLIN; + if(fds[i].events & POLLOUT) events |= sslq->wwant? sslq->wwant : POLLOUT; + fds[i].events = events; + } + return sso._prepoll(sso.state, fds, nfds); } SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config, SSL_CERT *server_cert, char **errSSL) @@ -298,7 +320,7 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config, fds[0].events = POLLOUT; } else break; - if(sso._poll(sso.state, fds, 1, config->timeout*1000) <= 0 || !(fds[0].revents & (POLLOUT|POLLIN))) break; + if(sockpoll(&sso, sso.state, fds, 1, config->timeout*1000) <= 0 || !(fds[0].revents & (POLLOUT|POLLIN))) break; } while (err == -1); if ( err != 1 ) { @@ -373,7 +395,7 @@ SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CONFIG *config, X509 *server_cert fds[0].events = POLLOUT; } else break; - if(sso._poll(sso.state, fds, 1, config->timeout*1000) <= 0 || !(fds[0].revents & (POLLOUT|POLLIN))) break; + if(sockpoll(&sso, sso.state, fds, 1, config->timeout*1000) <= 0 || !(fds[0].revents & (POLLOUT|POLLIN))) break; } while (err == -1); @@ -737,7 +759,7 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){ srv->so._recvfrom = ssl_recvfrom; srv->so._shutdown = ssl_shutdown; srv->so._closesocket = ssl_closesocket; - srv->so._poll = ssl_poll; + srv->so._prepoll = ssl_prepoll; } if(sc && (sc->mitm || sc->cli)){ #if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER < 0x10100000L diff --git a/src/structures.h b/src/structures.h index a7744ad..2ef8bf4 100644 --- a/src/structures.h +++ b/src/structures.h @@ -573,6 +573,14 @@ struct sockoptset { }; +/* _prepoll never waits: it tells what a layer over the socket knows to be + ready without asking the system, data a TLS connection has already + decrypted, and what the system is to be asked instead of what the caller + asked, events rewritten: a TLS read waiting for its socket to be + writable. It returns the number of fds it has set revents of, the rest + to be ignored and events left as they are; 0 when the sockets have to be + polled, for their events as it leaves them, revents left to the poll; + or -1. The wait itself is sockpoll()'s, which calls it first. */ struct sockfuncs { void * state; void (*freefunc)(void* state); @@ -586,7 +594,7 @@ struct sockfuncs { int (WINAPI *_getsockname)(void* state, SOCKET s, struct sockaddr * name, int * namelen); int (WINAPI *_getsockopt)(void* state, SOCKET s, int level, int optname, char * optval, int * optlen); int (WINAPI *_setsockopt)(void* state, SOCKET s, int level, int optname, const char *optval, int optlen); - int (WINAPI *_poll)(void* state, struct pollfd *fds, unsigned int nfds, int timeout); + int (WINAPI *_prepoll)(void* state, struct pollfd *fds, unsigned int nfds); int (WINAPI *_send)(void* state, SOCKET s, const char *msg, int len, int flags); int (WINAPI *_sendto)(void* state, SOCKET s, const char *msg, int len, int flags, const struct sockaddr *to, int tolen); int (WINAPI *_recv)(void* state, SOCKET s, char *buf, int len, int flags); @@ -603,7 +611,7 @@ struct sockfuncs { int (*_getsockname)(void* state, SOCKET s, struct sockaddr * name, socklen_t * namelen); int (*_getsockopt)(void* state, SOCKET s, int level, int optname, void * optval, socklen_t * optlen); int (*_setsockopt)(void* state, int s, int level, int optname, const void *optval, socklen_t optlen); - int (*_poll)(void* state, struct pollfd *fds, nfds_t nfds, int timeout); + int (*_prepoll)(void* state, struct pollfd *fds, nfds_t nfds); ssize_t (*_send)(void* state, SOCKET s, const void *msg, size_t len, int flags); ssize_t (*_sendto)(void* state, SOCKET s, const void *msg, size_t len, int flags, const struct sockaddr *to, SASIZETYPE tolen); ssize_t (*_recv)(void* state, SOCKET s, void *buf, size_t len, int flags); diff --git a/src/udpsockmap.c b/src/udpsockmap.c index 340a725..2fce3cf 100644 --- a/src/udpsockmap.c +++ b/src/udpsockmap.c @@ -209,7 +209,7 @@ int udpsockmap(struct clientparam *param, int timeo) udpfds(param, &p); for (;;) { - res = param->srv->so._poll(param->sostate, p.fds, p.nfds, timeo * 1000); + res = sockpoll(¶m->srv->so, param->sostate, p.fds, p.nfds, timeo * 1000); if (res < 0) return 481; if (res == 0) return 92;