tlsio function;

master
Alexander Vdolainen 4 years ago
parent f6e850b8f2
commit 3aa1f97545

@ -27,6 +27,11 @@ struct tlsport {
SSL_CTX *sslctx; SSL_CTX *sslctx;
}; };
typedef enum {
TLSIO_READ = 1,
TLSIO_WRITE = 2,
} tls_io_dir_t;
/* this function shall be called before main loop */ /* this function shall be called before main loop */
int ssllib_init(void); int ssllib_init(void);
@ -45,4 +50,9 @@ int tls_connect(const char *, const char *, struct tlsport *);
*/ */
int tls_close(struct tlsport *); int tls_close(struct tlsport *);
/* read or write (depends on tls_io_dir_t) data via tlsport
* returns amount of bytes ridden or written, -1 in case of error
*/
ssize_t tls_io(struct tlsport *, void *, size_t, tls_io_dir_t);
#endif /* __TLSPORT_H__ */ #endif /* __TLSPORT_H__ */

@ -186,3 +186,84 @@ int tls_close(struct tlsport *p)
return e; return e;
} }
ssize_t tls_io(struct tlsport *p, void *buf, size_t bf_size, tls_io_dir_t dr)
{
int sel_read, sel_write;
int r, w = 0;
fd_set readfd, writefd;
if(!p || !buf) {
errno = EINVAL;
return -1;
}
if(!bf_size) {
errno = EINVAL;
return -1;
}
ssllib_io:
sel_read = sel_write = 0;
do {
switch(dr) {
case TLSIO_READ:
r = SSL_read(p->ssl, buf, bf_size);
if(r > 0) return r;
break;
case TLSIO_WRITE:
r = SSL_write(p->ssl, (char *)buf + sizeof(char)*w, bf_size - w);
if(r == (bf_size - w)) return bf_size;
else if(r > 0) w += r;
break;
default:
errno = EINVAL;
return -1;
}
switch(SSL_get_error(p->ssl, r)) {
case SSL_ERROR_NONE:
break;
case SSL_ERROR_WANT_READ:
sel_read = 1; /* is required to wait during read */ break;
case SSL_ERROR_WANT_WRITE:
sel_write = 1; /* is required to wait during write */ break;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_WANT_ACCEPT:
break;
case SSL_ERROR_SYSCALL:
if(errno == EAGAIN || errno == EINTR) break;
case SSL_ERROR_SSL:
case SSL_ERROR_ZERO_RETURN: /* expected close */
default:
return -1;
break;
}
} while(SSL_pending(p->ssl) && !sel_read);
/* wait to read */
if(r != SSL_ERROR_NONE && sel_read) {
FD_ZERO(&readfd);
FD_SET(p->fd, &readfd);
ioread_select:
r = select(p->fd + 1, &readfd, NULL, NULL, NULL);
if(r <= 0) {
if(errno == EAGAIN || errno == EINTR) goto ioread_select;
else return -1;
} else if(FD_ISSET(p->fd, &readfd)) goto ssllib_io;
}
/* wait to write */
if(r != SSL_ERROR_NONE && sel_write) {
FD_ZERO(&readfd);
FD_ZERO(&writefd);
FD_SET(p->fd, &readfd);
FD_SET(p->fd, &writefd);
r = select(p->fd + 1, &readfd, &writefd, NULL, NULL);
if(r && FD_ISSET(p->fd, &writefd)) goto ssllib_io;
}
return 0;
}

Loading…
Cancel
Save