Skip to content

Commit

Permalink
sync to freeswitch version of ws.c
Browse files Browse the repository at this point in the history
  • Loading branch information
davehorton committed Mar 6, 2024
1 parent fde7188 commit bae4d6f
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 50 deletions.
126 changes: 76 additions & 50 deletions libsofia-sip-ua/tport/ws.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
#pragma warning(disable: 4706)
#endif

#define WS_BLOCK 1
#define WS_BLOCK 10000 /* ms, blocks read operation for 10 seconds */
#define WS_SOFT_BLOCK 1000 /* ms, blocks read operation for 1 second */
#define WS_NOBLOCK 0

#define WS_INIT_SANITY 5000
Expand Down Expand Up @@ -267,7 +268,7 @@ int ws_handshake(wsh_t *wsh)
return -3;
}

while((bytes = ws_raw_read(wsh, wsh->buffer + wsh->datalen, wsh->buflen - wsh->datalen, WS_BLOCK)) > 0) {
while((bytes = ws_raw_read(wsh, wsh->buffer + wsh->datalen, wsh->buflen - wsh->datalen, WS_NOBLOCK)) > 0) {
wsh->datalen += bytes;
if (strstr(wsh->buffer, "\r\n\r\n") || strstr(wsh->buffer, "\n\n")) {
break;
Expand Down Expand Up @@ -344,20 +345,26 @@ int ws_handshake(wsh_t *wsh)
ws_raw_write(wsh, respond, strlen(respond));
}

if (bytes == -2) {
return 0;
}

ws_close(wsh, WS_NONE);
}

return -1;

}

#define SSL_IO_ERROR(err) (err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL)
#define SSL_WANT_READ_WRITE(err) (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
int wss_error(wsh_t *wsh, int ssl_err, char const *who);

ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
{
ssize_t r;
int ssl_err = 0;
int block_n = block / 10;

wsh->x++;
if (wsh->x > 250) ms_sleep(1);
Expand All @@ -367,7 +374,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
//ERR_clear_error();
r = SSL_read(wsh->ssl, data, bytes);

if (r < 0) {
if (r <= 0) {
ssl_err = SSL_get_error(wsh->ssl, r);

if (SSL_WANT_READ_WRITE(ssl_err)) {
Expand All @@ -379,12 +386,16 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
ms_sleep(10);
} else {
wss_error(wsh, ssl_err, "ws_raw_read: SSL_read");
if (SSL_IO_ERROR(ssl_err)) {
wsh->ssl_io_error = 1;
}

r = -1;
goto end;
}
}

} while (r < 0 && SSL_WANT_READ_WRITE(ssl_err) && wsh->x < 1000);
} while (r < 0 && SSL_WANT_READ_WRITE(ssl_err) && wsh->x < block_n);

goto end;
}
Expand All @@ -404,11 +415,11 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
ms_sleep(10);
}
}
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 1000);
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < block_n);

end:

if (wsh->x >= 10000 || (block && wsh->x >= 1000)) {
if (wsh->x >= 10000 || (block && wsh->x >= block_n)) {
r = -1;
}

Expand Down Expand Up @@ -510,6 +521,11 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
r = SSL_write(wsh->ssl, buf, size);

if (r == 0) {
ssl_err = SSL_get_error(wsh->ssl, r);
if (SSL_IO_ERROR(ssl_err)) {
wsh->ssl_io_error = 1;
}

ssl_err = -42;
break;
}
Expand All @@ -528,16 +544,22 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
ms = 50;
}
}

ms_sleep(ms);
}

if (r < 0) {
ssl_err = SSL_get_error(wsh->ssl, r);

if (!SSL_WANT_READ_WRITE(ssl_err)) {
if (SSL_IO_ERROR(ssl_err)) {
wsh->ssl_io_error = 1;
}

ssl_err = wss_error(wsh, ssl_err, "ws_raw_write: SSL_write");
break;
}

ssl_err = 0;
}

Expand Down Expand Up @@ -600,18 +622,6 @@ static int setup_socket(ws_socket_t sock)

}

static int restore_socket(ws_socket_t sock)
{
unsigned long v = 0;

if (ioctlsocket(sock, FIONBIO, &v) == SOCKET_ERROR) {
return -1;
}

return 0;

}

#else

static int setup_socket(ws_socket_t sock)
Expand All @@ -620,16 +630,6 @@ static int setup_socket(ws_socket_t sock)
return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}

static int restore_socket(ws_socket_t sock)
{
int flags = fcntl(sock, F_GETFL, 0);

flags &= ~O_NONBLOCK;

return fcntl(sock, F_SETFL, flags);

}

#endif


Expand Down Expand Up @@ -723,7 +723,7 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int
memset(wsh, 0, sizeof(*wsh));

wsh->payload_size_max = ws_global_payload_size_max;
wsh->sock = sock;
wsh->sock = sock;
wsh->block = block;
wsh->sanity = WS_INIT_SANITY;
wsh->ssl_ctx = ssl_ctx;
Expand Down Expand Up @@ -814,35 +814,61 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)
ws_raw_write(wsh, fr, 4);
}

restore_socket(wsh->sock);

if (wsh->ssl) {
int code = 0;
int code = 0, rcode = 0;
int ssl_error = 0;
const char* buf = "0";
int n = 0, block_n = WS_SOFT_BLOCK / 10;

/* if SSL connection was never established, the SSL_write would block this thread */
if (!wsh->logical_established) {
goto ssl_finish_it;
}
/* SSL layer was never established or underlying IO error occured */
if (!wsh->secure_established || wsh->ssl_io_error) {
goto ssl_finish_it;
}

/* check if no fatal error occurs on connection */
code = SSL_write(wsh->ssl, buf, 1);
ssl_error = SSL_get_error(wsh->ssl, code);
/* connection has been already closed */
if (SSL_get_shutdown(wsh->ssl) & SSL_SENT_SHUTDOWN) {
goto ssl_finish_it;
}

if (ssl_error == SSL_ERROR_SYSCALL || ssl_error == SSL_ERROR_SSL) {
/* peer closes the connection */
if (SSL_get_shutdown(wsh->ssl) & SSL_RECEIVED_SHUTDOWN) {
SSL_shutdown(wsh->ssl);
goto ssl_finish_it;
}

code = SSL_shutdown(wsh->ssl);
/**
* for a bidirectional shutdown, we would call SSL_shutdown again
* if the return code is 0 (and would expect a return code of 1 on the second call).
* However, the spec says that performing uni-directional shutdown
* is sufficient, so we don't call SSL_shutdown again here.
* We are in blocking mode and do not want the possibility of blocking this thread
* for a nicety that is optional in the first place.
*/
/* us closes the connection. We do bidirection shutdown handshake */
for(;;) {
code = SSL_shutdown(wsh->ssl);
ssl_error = SSL_get_error(wsh->ssl, code);
if (code <= 0 && ssl_error == SSL_ERROR_WANT_READ) {
/* need to make sure there are no more data to read */
for(;;) {
if ((rcode = SSL_read(wsh->ssl, wsh->buffer, 9)) <= 0) {
ssl_error = SSL_get_error(wsh->ssl, rcode);
if (ssl_error == SSL_ERROR_ZERO_RETURN) {
break;
} else if (SSL_IO_ERROR(ssl_error)) {
goto ssl_finish_it;
} else if (ssl_error == SSL_ERROR_WANT_READ) {
if (++n == block_n) {
goto ssl_finish_it;
}

ms_sleep(10);
} else {
goto ssl_finish_it;
}
}
}
} else if (code == 0 || (code < 0 && ssl_error == SSL_ERROR_WANT_WRITE)) {
if (++n == block_n) {
goto ssl_finish_it;
}

ms_sleep(10);
} else { /* code != 0 */
goto ssl_finish_it;
}
}

ssl_finish_it:
SSL_free(wsh->ssl);
Expand Down
1 change: 1 addition & 0 deletions libsofia-sip-ua/tport/ws.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ typedef struct wsh_s {
int logical_established;
int stay_open;
int x;
int ssl_io_error;
void *write_buffer;
size_t write_buffer_len;

Expand Down

0 comments on commit bae4d6f

Please sign in to comment.