tlsio function;
This commit is contained in:
parent
f6e850b8f2
commit
3aa1f97545
@ -27,6 +27,11 @@ struct tlsport {
|
||||
SSL_CTX *sslctx;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
TLSIO_READ = 1,
|
||||
TLSIO_WRITE = 2,
|
||||
} tls_io_dir_t;
|
||||
|
||||
/* this function shall be called before main loop */
|
||||
int ssllib_init(void);
|
||||
|
||||
@ -45,4 +50,9 @@ int tls_connect(const char *, const char *, 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__ */
|
||||
|
81
src/tls.c
81
src/tls.c
@ -186,3 +186,84 @@ int tls_close(struct tlsport *p)
|
||||
|
||||
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…
x
Reference in New Issue
Block a user