|
|
|
@ -45,6 +45,126 @@ typedef struct __sntll_bundle_type {
|
|
|
|
|
conn_t *conn;
|
|
|
|
|
} sntllv2_bundle_t;
|
|
|
|
|
|
|
|
|
|
static int __conn_read(conn_t *co, void *buf, size_t buf_len)
|
|
|
|
|
{
|
|
|
|
|
int rfd = SSL_get_fd(co->ssl), r;
|
|
|
|
|
fd_set readset, writeset;
|
|
|
|
|
int ofcmode, read_blocked = 0, read_blocked_on_write = 0;
|
|
|
|
|
|
|
|
|
|
/* First we make the socket nonblocking */
|
|
|
|
|
#ifndef WIN32
|
|
|
|
|
ofcmode = fcntl(rfd, F_GETFL,0);
|
|
|
|
|
ofcmode |= O_NDELAY;
|
|
|
|
|
if(fcntl(rfd, F_SETFL, ofcmode))
|
|
|
|
|
fprintf(stderr, "Couldn't make socket nonblocking");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
__retry:
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
__try_again:
|
|
|
|
|
r = SSL_read(co->ssl, buf, (int)buf_len);
|
|
|
|
|
switch(SSL_get_error (co->ssl, r)) {
|
|
|
|
|
case SSL_ERROR_NONE:
|
|
|
|
|
return r;
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_WANT_READ:
|
|
|
|
|
/* get prepare to select */
|
|
|
|
|
read_blocked = 1;
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_WANT_WRITE: /* here we blocked on write */
|
|
|
|
|
read_blocked_on_write = 1;
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_SYSCALL:
|
|
|
|
|
if(errno == EAGAIN || errno == EINTR) goto __try_again;
|
|
|
|
|
else {
|
|
|
|
|
fprintf(stderr, "SSL syscall error.\n");
|
|
|
|
|
goto __close_conn;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_WANT_CONNECT:
|
|
|
|
|
case SSL_ERROR_WANT_ACCEPT:
|
|
|
|
|
fprintf(stderr, "SSL negotiation required. Trying again.\n");
|
|
|
|
|
goto __try_again;
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_SSL:
|
|
|
|
|
fprintf(stderr, "SSL error occured. Connection will be closed.\n");
|
|
|
|
|
goto __close_conn;
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_ZERO_RETURN:
|
|
|
|
|
fprintf(stderr, "SSL connection is cleary closed.\n");
|
|
|
|
|
default:
|
|
|
|
|
__close_conn:
|
|
|
|
|
fprintf(stderr, "(RD)Unknown error on %s (errno = %d)\n", co->uuid, errno);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} while(SSL_pending(co->ssl) && !read_blocked);
|
|
|
|
|
|
|
|
|
|
__select_retry:
|
|
|
|
|
|
|
|
|
|
if(read_blocked) {
|
|
|
|
|
FD_ZERO(&readset);
|
|
|
|
|
FD_SET(rfd, &readset);
|
|
|
|
|
/* waits until something will be ready to read */
|
|
|
|
|
r = select(rfd + 1, &readset, NULL, NULL, NULL);
|
|
|
|
|
if(r < 0) {
|
|
|
|
|
if(errno == EINTR || errno == EAGAIN) goto __select_retry;
|
|
|
|
|
printf("(RD) select (%d) on %s\n", errno, co->uuid);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if(!r) {
|
|
|
|
|
printf("Nothing to wait for\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
read_blocked = 0;
|
|
|
|
|
if(r && FD_ISSET(rfd, &readset)) goto __retry; /* try to read again */
|
|
|
|
|
}
|
|
|
|
|
if(read_blocked_on_write) { /* we was blocked on write */
|
|
|
|
|
FD_ZERO(&readset);
|
|
|
|
|
FD_ZERO(&writeset);
|
|
|
|
|
FD_SET(rfd, &readset);
|
|
|
|
|
FD_SET(rfd, &writeset);
|
|
|
|
|
|
|
|
|
|
r = select(rfd + 1, &readset, &writeset, NULL, NULL);
|
|
|
|
|
read_blocked_on_write = 0;
|
|
|
|
|
if(r && FD_ISSET(rfd, &writeset)) goto __retry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __conn_write(conn_t *co, void *buf, size_t buf_len)
|
|
|
|
|
{
|
|
|
|
|
int r, rfd = SSL_get_fd(co->ssl);
|
|
|
|
|
fd_set writeset;
|
|
|
|
|
|
|
|
|
|
__retry:
|
|
|
|
|
r = SSL_write(co->ssl, buf, (int)buf_len);
|
|
|
|
|
switch(SSL_get_error(co->ssl, r)) {
|
|
|
|
|
case SSL_ERROR_WANT_READ:
|
|
|
|
|
case SSL_ERROR_WANT_WRITE:
|
|
|
|
|
/* here we should block */
|
|
|
|
|
FD_ZERO(&writeset);
|
|
|
|
|
FD_SET(rfd, &writeset);
|
|
|
|
|
r = select(rfd + 1, NULL, &writeset, NULL, NULL);
|
|
|
|
|
if(r && FD_ISSET(rfd, &writeset)) goto __retry;
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_SYSCALL:
|
|
|
|
|
if(errno == EAGAIN || errno == EINTR) goto __retry;
|
|
|
|
|
else goto __close_conn;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pthread_mutex_unlock(&(co->oplock));
|
|
|
|
|
__close_conn:
|
|
|
|
|
if(r < 0) {
|
|
|
|
|
fprintf(stderr, "[sntllv2] (WR)Unknown error on %s (%d)\n", co->uuid, r);
|
|
|
|
|
return -1;
|
|
|
|
|
} else return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static sntllv2_bundle_t *__sntll_bundle_create(conn_t *co)
|
|
|
|
|
{
|
|
|
|
|
sntllv2_bundle_t *n = malloc(sizeof(sntllv2_bundle_t));
|
|
|
|
|