sockets: Replace select() with poll()

select() has been deprecated for a very long time and is considered harmful
pull/12/head
Andri Yngvason 2022-06-05 13:54:10 +00:00
parent d4faccba28
commit 8970accb86
1 changed files with 66 additions and 75 deletions

View File

@ -28,6 +28,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <assert.h> #include <assert.h>
#include <sys/param.h> #include <sys/param.h>
#include <poll.h>
#include "rfb/rfbclient.h" #include "rfb/rfbclient.h"
#include "sockets.h" #include "sockets.h"
#include "tls.h" #include "tls.h"
@ -94,96 +95,86 @@ rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n)
rfbBool rfbBool
WriteToRFBServer(rfbClient* client, const char *buf, unsigned int n) WriteToRFBServer(rfbClient* client, const char *buf, unsigned int n)
{ {
fd_set fds; struct pollfd fds;
int i = 0; int i = 0;
int j; int j;
const char *obuf = buf; const char *obuf = buf;
#ifdef LIBVNCSERVER_HAVE_SASL #ifdef LIBVNCSERVER_HAVE_SASL
const char *output; const char *output;
unsigned int outputlen; unsigned int outputlen;
int err; int err;
#endif /* LIBVNCSERVER_HAVE_SASL */ #endif /* LIBVNCSERVER_HAVE_SASL */
if (client->serverPort==-1) if (client->serverPort==-1)
return TRUE; /* vncrec playing */ return TRUE; /* vncrec playing */
if (client->tlsSession) { if (client->tlsSession) {
/* WriteToTLS() will guarantee either everything is written, or error/eof returns */ /* WriteToTLS() will guarantee either everything is written, or error/eof returns */
i = WriteToTLS(client, buf, n); i = WriteToTLS(client, buf, n);
if (i <= 0) return FALSE; if (i <= 0) return FALSE;
return TRUE; return TRUE;
}
#ifdef LIBVNCSERVER_HAVE_SASL
if (client->saslconn) {
err = sasl_encode(client->saslconn,
buf, n,
&output, &outputlen);
if (err != SASL_OK) {
rfbClientLog("Failed to encode SASL data %s",
sasl_errstring(err, NULL, NULL));
return FALSE;
}
obuf = output;
n = outputlen;
}
#endif /* LIBVNCSERVER_HAVE_SASL */
while (i < n) {
j = write(client->sock, obuf + i, (n - i));
if (j <= 0) {
if (j < 0) {
if (errno == EWOULDBLOCK ||
errno == EAGAIN) {
FD_ZERO(&fds);
FD_SET(client->sock,&fds);
if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) {
rfbClientErr("select\n");
return FALSE;
}
j = 0;
} else {
rfbClientErr("write\n");
return FALSE;
} }
} else { #ifdef LIBVNCSERVER_HAVE_SASL
rfbClientLog("write failed\n"); if (client->saslconn) {
return FALSE; err = sasl_encode(client->saslconn,
} buf, n,
} &output, &outputlen);
i += j; if (err != SASL_OK) {
} rfbClientLog("Failed to encode SASL data %s",
return TRUE; sasl_errstring(err, NULL, NULL));
} return FALSE;
}
obuf = output;
n = outputlen;
}
#endif /* LIBVNCSERVER_HAVE_SASL */
// TODO: Dispatch events while waiting
while (i < n) {
j = write(client->sock, obuf + i, (n - i));
if (j <= 0) {
if (j < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
fds.fd = client->sock;
fds.events = POLLIN;
if (poll(&fds, 1, -1) <= 0) {
rfbClientErr("select\n");
return FALSE;
}
j = 0;
} else {
rfbClientErr("write\n");
return FALSE;
}
} else {
rfbClientLog("write failed\n");
return FALSE;
}
}
i += j;
}
return TRUE;
}
static rfbBool WaitForConnected(int socket, unsigned int secs) static rfbBool WaitForConnected(int socket, unsigned int secs)
{ {
fd_set writefds; struct pollfd fds = {
fd_set exceptfds; .fd = socket,
struct timeval timeout; .events = POLLIN | POLLOUT | POLLERR | POLLHUP,
};
timeout.tv_sec=secs; if (poll(&fds, 1, secs * 1000) != 1)
timeout.tv_usec=0; return FALSE;
FD_ZERO(&writefds); int so_error = 0;
FD_SET(socket, &writefds); socklen_t len = sizeof(so_error);
FD_ZERO(&exceptfds); getsockopt(socket, SOL_SOCKET, SO_ERROR, &so_error, &len);
FD_SET(socket, &exceptfds);
if (select(socket+1, NULL, &writefds, &exceptfds, &timeout)==1) {
int so_error;
socklen_t len = sizeof so_error;
getsockopt(socket, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error!=0)
return FALSE;
return TRUE;
}
return FALSE; return so_error == 0 ? TRUE : FALSE;
} }
rfbSocket rfbSocket
ConnectClientToTcpAddr(unsigned int host, int port) ConnectClientToTcpAddr(unsigned int host, int port)
{ {