96
96
* A connection in state SSL_ACCEPT can be closed and removed without
99
* XXX We should ONLY consider the the states of fd and proxy->fd, and
100
* neither rely on any control information received regarding their
101
* desired states, nor send any control information about their actual
102
* states. In particular, FROMNET_CLOSE should never be sent.
104
* XXX If we do not go through the JOINED state, we may leak proxy
105
* file descriptors. It is when a connection is in the state CONNECTED
106
* that a proxy file descriptor is created. It is ssl_broker.erl that
107
* makes the connect. It knows cp->fd, and the port number of its own
108
* socket. It is however only if the broker crashes (or gets killed)
109
* that we lose a descriptor. */
112
104
#include "esock_winsock.h"
165
158
#define JOINED_STATE_INVALID(cp) (!(PROXY_TO_SSL_VALID(cp)) && \
166
159
!(SSL_TO_PROXY_VALID(cp)))
167
160
static int loop(void);
161
static int set_poll_conns(Connection *cp, EsockPoll *ep, int verbose);
162
static Connection *next_polled_conn(Connection *cp, Connection **cpnext,
163
EsockPoll *ep, int set_wq_fds);
168
165
static void leave_joined_state(Connection *cp);
169
166
static void do_shutdown(Connection *cp);
170
167
static void close_and_remove_connection(Connection *cp);
174
171
static int get_pars(unsigned char *buf, char *fmt, va_list args);
175
172
static FD do_connect(char *lipstring, int lport, char *fipstring, int fport);
176
173
static FD do_listen(char *ipstring, int lport, int backlog, int *aport);
174
static FD do_accept(FD listensock, struct sockaddr *saddr, int *len);
177
175
static void print_connections(void);
176
static int check_num_sock_fds(FD fd);
178
177
static void safe_close(FD fd);
179
178
static Connection *new_connection(int state, FD fd);
180
179
static Connection *get_connection(FD fd);
186
185
static void clean_up(void);
188
187
static Connection *connections = NULL;
189
static fd_set readmask, writemask, exceptmask;
188
static int num_sock_fds; /* On UNIX all file descriptors */
190
189
static Proxy *proxies = NULL;
191
190
static int proxy_listensock = INVALID_FD;
192
191
static int proxy_listenport = 0;
193
static int proxy_backlog = 5;
192
static int proxy_backlog = 128;
194
193
static int proxysock_last_err = 0;
195
194
static int proxysock_err_cnt = 0;
196
195
static char rwbuf[RWBUFLEN];
197
196
static unsigned char *ebuf = NULL; /* Set by read_ctrl() */
198
static unsigned long one = 1;
199
static struct timeval timeout = {SELECT_TIMEOUT, 0};
201
198
static char *connstr[] = {
346
354
static int loop(void)
348
357
FD fd, msgsock, listensock, connectsock, proxysock;
349
358
int cc, wc, fport, lport, pport, length, backlog, intref, op;
351
360
char *lipstring, *fipstring;
362
char *protocol_vsn, *cipher;
353
363
unsigned char *cert, *bin;
354
364
int certlen, binlen;
355
365
struct sockaddr_in iserv_addr;
357
367
Connection *cp, *cpnext, *newcp;
360
369
time_t last_time = 0, now = 0;
372
esock_poll_init(&pollfd);
375
esock_poll_zero(&pollfd);
376
esock_poll_fd_set_read(&pollfd, proxy_listensock);
377
esock_poll_fd_set_read(&pollfd, local_read_fd);
367
FD_ZERO(&exceptmask);
368
FD_SET(local_read_fd, &readmask);
369
FD_SET(proxy_listensock, &readmask);
370
tv = timeout; /* select() might change tv */
373
381
if (sret) /* sret == 1 the first time. */
374
382
DEBUGF(("==========LOOP=============\n"));
376
cc = esock_ssl_set_masks(connections, &readmask, &writemask,
377
&exceptmask, sret) + 1;
384
cc = set_poll_conns(connections, &pollfd, sret) + 1;
379
387
print_connections();
380
DEBUGF(("Before select: %d descriptor%s\n", cc,
381
(cc == 1) ? "" : "s"));
388
DEBUGF(("Before poll/select: %d descriptor%s (total %d)\n",
389
cc, (cc == 1) ? "" : "s", num_sock_fds));
384
sret = select(FD_SETSIZE, &readmask, &writemask, &exceptmask, &tv);
392
sret = esock_poll(&pollfd, SELECT_TIMEOUT);
386
DEBUGF(("select error: %s\n", psx_errstr()));
394
DEBUGF(("select/poll error: %s\n", psx_errstr()));
388
} else if (sret == 0) {
391
FD_ZERO(&exceptmask);
395
DEBUGF(("After select: %d descriptor%s: ", sret,
396
(sret == 1) ? "" : "s"));
398
for (j = 0; j < FD_SETSIZE; j++) {
399
if (FD_ISSET(j, &readmask) ||
400
FD_ISSET(j, &writemask) ||
401
FD_ISSET(j, &exceptmask))
405
/* XXX Make this better */
406
DEBUGF(("(not shown)"));
419
406
* is later used as a reference for joining a proxy
420
407
* connection with a network connection.
422
if (FD_ISSET(proxy_listensock, &readmask)) {
410
if (esock_poll_fd_isset_read(&pollfd, proxy_listensock)) {
424
412
length = sizeof(iserv_addr);
425
proxysock = accept(proxy_listensock,
426
(struct sockaddr *)&iserv_addr,
413
proxysock = do_accept(proxy_listensock,
414
(struct sockaddr *)&iserv_addr,
428
416
if(proxysock == INVALID_FD) {
429
417
if (sock_errno() != ERRNO_BLOCK) {
430
/* XXX Here we have a major flaw. We can here
431
* for example get the error EMFILE, i.e. no
432
* more file descriptor available, but we do
433
* not have any specific connection to report
435
* We increment the error counter and saves the
418
/* We can here for example get the error
419
* EMFILE, i.e. no more file descriptors
420
* available, but we do not have any specific
421
* connection to report the error to. We
422
* increment the error counter and saves the
438
425
proxysock_err_cnt++;
439
426
proxysock_last_err = sock_errno();
529
case ESOCK_GETCONNINFO_CMD:
531
* ebuf = {cmd(1), fd(4)}
534
DEBUGF(("[GETCONNINFO_CMD] fd = %d\n", fd));
535
cp = get_connection(fd);
537
sock_set_errno(ERRNO_NOTSOCK);
538
reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
540
if (esock_ssl_getprotocol_version(cp,
542
reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
543
else if (esock_ssl_getcipher(cp, &cipher) < 0)
544
reply(ESOCK_GETCONNINFO_ERR, "4s", fd, psx_errstr());
547
* reply = {cmd(1), fd(4), protocol(N), 0(1),
550
reply(ESOCK_GETCONNINFO_REP, "4ss", fd,
551
protocol_vsn, cipher);
542
555
case ESOCK_GETPEERCERT_CMD:
544
557
* ebuf = {cmd(1), fd(4)}
613
626
cp->proxy->bp = 1;
614
627
switch (cp->state) {
615
628
case ESOCK_JOINED:
630
if (JOINED_STATE_INVALID(cp))
631
leave_joined_state(cp);
616
633
case ESOCK_SSL_SHUTDOWN:
617
635
DEBUGF((" close flag set\n"));
621
638
DEBUGF(("-> (removal)\n"));
622
639
close_and_remove_connection(cp);
625
DEBUGF(("%s[ERLANG_CLOSE]: ERROR: fd = %d not found\n",
642
DEBUGF(("%s[CLOSE_CMD]: ERROR: fd = %d not found\n",
626
643
connstr[cp->state], fd));
789
806
/* Note: We may remove the current connection (cp). Thus we
790
807
* must be careful not to read cp->next after cp has been
792
for (cp = esock_ssl_read_masks(connections, &cpnext, &readmask,
793
&writemask, &exceptmask, set_wq_fds);
809
for (cp = next_polled_conn(connections, &cpnext, &pollfd, set_wq_fds);
795
cp = esock_ssl_read_masks(cpnext, &cpnext, &readmask,
796
&writemask, &exceptmask, set_wq_fds)
811
cp = next_polled_conn(cpnext, &cpnext, &pollfd, set_wq_fds)
799
814
switch(cp->state) {
810
825
DEBUGF(("ACTIVE_LISTENING - trying to accept on %d\n",
812
827
length = sizeof(iserv_addr);
813
msgsock = accept(cp->fd, (struct sockaddr*)&iserv_addr,
828
msgsock = do_accept(cp->fd, (struct sockaddr*)&iserv_addr,
815
830
if(msgsock == INVALID_FD) {
816
831
DEBUGF(("accept error: %s\n", psx_errstr()));
817
832
reply(ESOCK_ACCEPT_ERR, "4s", cp->fd, psx_errstr());
859
874
/* SSL handshake successful: publish */
860
875
reply(ESOCK_ACCEPT_REP, "44", cp->listen_fd, msgsock);
861
876
DEBUGF(("-> CONNECTED\n"));
877
DEBUGF((" Session was %sreused.\n",
878
(esock_ssl_session_reused(cp)) ? "" : "NOT "));
862
879
cp->state = ESOCK_CONNECTED;
992
1009
leave_joined_state(cp);
996
/* This should not happen */
997
DEBUGF(("ERROR: proxy readmask set, cc < 0, fd = %d"
998
" proxyfd = %d\n", cp->fd, cp->proxy->fd));
1002
1015
* Reading from SSL, writing to proxy
1004
if (FD_ISSET(cp->proxy->fd, &writemask)) {
1017
if (esock_poll_fd_isset_write(&pollfd, cp->proxy->fd)) {
1005
1018
/* If there is a write queue, write to proxy only */
1006
1019
if (cp->proxy->wq.len > 0) {
1007
1020
DEBUGF(("-----------------------------------\n"));
1182
static int set_poll_conns(Connection *cp, EsockPoll *ep, int verbose)
1187
DEBUGF(("MASKS SET FOR FD: "));
1189
switch (cp->state) {
1190
case ESOCK_ACTIVE_LISTENING:
1192
DEBUGF(("%d (read) ", cp->fd));
1193
esock_poll_fd_set_read(ep, cp->fd);
1195
case ESOCK_WAIT_CONNECT:
1197
DEBUGF(("%d (write) ", cp->fd));
1198
esock_poll_fd_set_write(ep, cp->fd);
1200
esock_poll_fd_set_exception(ep, cp->fd); /* Failure shows in exceptions */
1203
case ESOCK_SSL_CONNECT:
1204
case ESOCK_SSL_ACCEPT:
1205
if (cp->ssl_want == ESOCK_SSL_WANT_READ) {
1207
DEBUGF(("%d (read) ", cp->fd));
1208
esock_poll_fd_set_read(ep, cp->fd);
1209
} else if (cp->ssl_want == ESOCK_SSL_WANT_WRITE) {
1211
DEBUGF(("%d (write) ", cp->fd));
1212
esock_poll_fd_set_write(ep, cp->fd);
1219
DEBUGF(("%d (write) ", cp->fd));
1220
esock_poll_fd_set_write(ep, cp->fd);
1221
} else if (!cp->proxy->eof) {
1223
DEBUGF(("%d (read) ", cp->proxy->fd));
1224
esock_poll_fd_set_read(ep, cp->proxy->fd);
1227
if (!cp->proxy->bp) {
1228
if (cp->proxy->wq.len) {
1230
DEBUGF(("%d (write) ", cp->proxy->fd));
1231
esock_poll_fd_set_write(ep, cp->proxy->fd);
1232
} else if (!cp->eof) {
1234
DEBUGF(("%d (read) ", cp->fd));
1235
esock_poll_fd_set_read(ep, cp->fd);
1239
case ESOCK_SSL_SHUTDOWN:
1240
if (cp->ssl_want == ESOCK_SSL_WANT_READ) {
1242
DEBUGF(("%d (read) ", cp->fd));
1243
esock_poll_fd_set_read(ep, cp->fd);
1244
} else if (cp->ssl_want == ESOCK_SSL_WANT_WRITE) {
1246
DEBUGF(("%d (write) ", cp->fd));
1247
esock_poll_fd_set_write(ep, cp->fd);
1262
static Connection *next_polled_conn(Connection *cp, Connection **cpnext,
1263
EsockPoll *ep, int set_wq_fds)
1266
if (esock_poll_fd_isset_read(ep, cp->fd) ||
1267
(cp->proxy && esock_poll_fd_isset_read(ep, cp->proxy->fd)) ||
1268
(esock_poll_fd_isset_write(ep, cp->fd)) ||
1269
(cp->proxy && esock_poll_fd_isset_write(ep, cp->proxy->fd))
1271
|| esock_poll_fd_isset_exception(ep, cp->fd) /* Connect failure in WIN32 */
1273
|| (set_wq_fds && (cp->wq.len ||
1274
(cp->proxy && cp->proxy->wq.len)))) {
1169
1284
static void leave_joined_state(Connection *cp)
1171
1286
shutdown(cp->proxy->fd, SHUTDOWN_ALL);
1419
1536
static FD do_listen(char *ipstring, int lport, int backlog, int *aport)
1538
static int one = 1; /* Type must be int, not long */
1421
1539
struct sockaddr_in sock_addr;
1426
if((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_FD) {
1544
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_FD) {
1427
1545
DEBUGF(("Error calling socket()\n"));
1548
if (check_num_sock_fds(fd) < 0)
1430
1550
DEBUGF((" fd = %d\n", fd));
1431
1551
if ((inaddr = inet_addr(ipstring)) == INADDR_NONE) {
1432
1552
DEBUGF(("Error in inet_addr(): ipstring = %s\n", ipstring));