mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-25 12:10:18 +00:00
FS-5325
This commit is contained in:
parent
cb7a6bd34b
commit
5761624f5a
@ -60,40 +60,78 @@ struct stream_data {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define WANT_READ 1
|
||||||
|
#define WANT_WRITE 0
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
static int sock_read_ready(struct stream_data *data, uint32_t ms)
|
static int sock_ready(struct stream_data *data, int ms, int w_read)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0, e = 0;
|
||||||
fd_set fds;
|
fd_set rfds, wfds, efds, *fds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&rfds);
|
||||||
|
FD_ZERO(&wfds);
|
||||||
|
FD_ZERO(&efds);
|
||||||
|
|
||||||
|
if (w_read) {
|
||||||
|
fds = &rfds;
|
||||||
|
} else {
|
||||||
|
fds = &wfds;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#pragma warning( push )
|
#pragma warning( push )
|
||||||
#pragma warning( disable : 4127 )
|
#pragma warning( disable : 4127 )
|
||||||
FD_SET(SSL_get_fd(data->ssl), &fds);
|
FD_SET(SSL_get_fd(data->ssl), fds);
|
||||||
#pragma warning( pop )
|
#pragma warning( pop )
|
||||||
#else
|
#else
|
||||||
FD_SET(SSL_get_fd(data->ssl), &fds);
|
FD_SET(SSL_get_fd(data->ssl), fds);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tv.tv_sec = ms / 1000;
|
tv.tv_sec = ms / 1000;
|
||||||
tv.tv_usec = (ms % 1000) * ms;
|
tv.tv_usec = (ms % 1000) * ms;
|
||||||
|
|
||||||
r = select (SSL_get_fd(data->ssl) + 1, &fds, NULL, NULL, &tv);
|
r = select (SSL_get_fd(data->ssl) + 1, w_read ? &rfds : NULL, w_read ? NULL : &wfds, &efds, &tv);
|
||||||
|
|
||||||
|
if (r > 0) {
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning( push )
|
||||||
|
#pragma warning( disable : 4127 )
|
||||||
|
e = FD_ISSET(SSL_get_fd(data->ssl), &efds);
|
||||||
|
#pragma warning( pop )
|
||||||
|
#else
|
||||||
|
e = FD_ISSET(SSL_get_fd(data->ssl), &efds);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
r = -1;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning( push )
|
||||||
|
#pragma warning( disable : 4127 )
|
||||||
|
r = FD_ISSET(SSL_get_fd(data->ssl), fds);
|
||||||
|
#pragma warning( pop )
|
||||||
|
#else
|
||||||
|
r = FD_ISSET(SSL_get_fd(data->ssl), fds);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int sock_read_ready(struct stream_data *data, int ms)
|
static int sock_ready(struct stream_data *data, int ms, int w_read)
|
||||||
{
|
{
|
||||||
struct pollfd pfds[2] = { { 0 } };
|
struct pollfd pfds[2] = { { 0 } };
|
||||||
int s = 0, r = 0;
|
int s = 0, r = 0, w = w_read ? POLLIN : POLLOUT;
|
||||||
|
|
||||||
pfds[0].fd = SSL_get_fd(data->ssl);
|
pfds[0].fd = SSL_get_fd(data->ssl);
|
||||||
pfds[0].events = POLLIN | POLLHUP | POLLERR;
|
pfds[0].events = w | POLLHUP | POLLERR;
|
||||||
|
|
||||||
s = poll(pfds, 1, ms);
|
s = poll(pfds, 1, ms);
|
||||||
|
|
||||||
@ -101,7 +139,7 @@ static int sock_read_ready(struct stream_data *data, int ms)
|
|||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
r = s;
|
r = s;
|
||||||
} else if (s > 0) {
|
} else if (s > 0) {
|
||||||
if ((pfds[0].revents & POLLIN)) {
|
if ((pfds[0].revents & w)) {
|
||||||
r = 1;
|
r = 1;
|
||||||
} else if ((pfds[0].revents & POLLHUP) || (pfds[0].revents & POLLERR)) {
|
} else if ((pfds[0].revents & POLLHUP) || (pfds[0].revents & POLLERR)) {
|
||||||
r = -1;
|
r = -1;
|
||||||
@ -201,26 +239,68 @@ static int wait_for_data(struct stream_data *data, int ret, int timeout)
|
|||||||
switch(err)
|
switch(err)
|
||||||
{
|
{
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
|
ret = sock_ready(data, timeout*1000, WANT_READ);
|
||||||
|
break;
|
||||||
case SSL_ERROR_WANT_WRITE:
|
case SSL_ERROR_WANT_WRITE:
|
||||||
ret = sock_read_ready(data, timeout*1000);
|
ret = sock_ready(data, timeout*1000, WANT_WRITE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (data->logHook) {
|
||||||
|
data->logHook(data->user_data, ERR_error_string(err, NULL), strlen(ERR_error_string(err, NULL)), 1);
|
||||||
|
}
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
retval = IKS_NET_TLSFAIL;
|
retval = IKS_NET_TLSFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if(data->logHook)
|
|
||||||
data->logHook(data->user_data, ERR_error_string(err, NULL), strlen(ERR_error_string(err, NULL)), 1);
|
|
||||||
retval = IKS_NET_TLSFAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int iks_set_blocking(void *fd, int blocking)
|
||||||
|
{
|
||||||
|
if (!fd) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
ULONG mode = !blocking;
|
||||||
|
|
||||||
|
if (ioctlsocket((SOCKET)(intptr_t) fd, FIONBIO, &mode)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
int flags;
|
||||||
|
int mfd = (int)(intptr_t)fd;
|
||||||
|
|
||||||
|
if ((flags = fcntl(mfd, F_GETFL, 0)) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcntl(mfd, F_SETFL, flags | (!blocking ? O_NONBLOCK : ~O_NONBLOCK)) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handshake (struct stream_data *data)
|
handshake (struct stream_data *data)
|
||||||
{
|
{
|
||||||
@ -236,6 +316,8 @@ handshake (struct stream_data *data)
|
|||||||
data->ssl = SSL_new(data->ssl_ctx);
|
data->ssl = SSL_new(data->ssl_ctx);
|
||||||
if(!data->ssl) return IKS_NOMEM;
|
if(!data->ssl) return IKS_NOMEM;
|
||||||
|
|
||||||
|
iks_set_blocking(data->sock, 0);
|
||||||
|
|
||||||
if( SSL_set_fd(data->ssl, (int)(intptr_t)data->sock) != 1 ) return IKS_NOMEM;
|
if( SSL_set_fd(data->ssl, (int)(intptr_t)data->sock) != 1 ) return IKS_NOMEM;
|
||||||
|
|
||||||
/* Set both the read and write BIO's to non-blocking mode */
|
/* Set both the read and write BIO's to non-blocking mode */
|
||||||
@ -681,7 +763,7 @@ iks_recv (iksparser *prs, int timeout)
|
|||||||
} else
|
} else
|
||||||
#elif HAVE_SSL
|
#elif HAVE_SSL
|
||||||
if (data->flags & SF_SECURE) {
|
if (data->flags & SF_SECURE) {
|
||||||
ret = sock_read_ready(data, timeout*1000);
|
ret = sock_ready(data, timeout*1000, WANT_READ);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
return IKS_NET_TLSFAIL;
|
return IKS_NET_TLSFAIL;
|
||||||
@ -765,7 +847,16 @@ iks_send_raw (iksparser *prs, const char *xmlstr)
|
|||||||
} else
|
} else
|
||||||
#elif HAVE_SSL
|
#elif HAVE_SSL
|
||||||
if (data->flags & SF_SECURE) {
|
if (data->flags & SF_SECURE) {
|
||||||
if (SSL_write(data->ssl, xmlstr, strlen (xmlstr)) < 0) return IKS_NET_RWERR;
|
int r, err;
|
||||||
|
|
||||||
|
do {
|
||||||
|
r = SSL_write(data->ssl, xmlstr, strlen (xmlstr));
|
||||||
|
} while (r == -1 && (err = SSL_get_error(data->ssl, r)) == SSL_ERROR_WANT_WRITE);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
return IKS_NET_RWERR;
|
||||||
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user