Skip to content

Commit

Permalink
nopoll:
Browse files Browse the repository at this point in the history
* [fix] Several updates to detect when __nopoll_conn_get_ssl_context fails
  to report a valid SSL_CTX (fixed updated test_19). 

* [fix] Updated header read handling to support all cases when a
  splitted/broken header is received. Added regression tests test_31,
  test_32, test_33, test_34 and test_35 to simulate and support different
  scenarios where part of the header is received and then the rest...
  • Loading branch information
francisbrosnan committed May 15, 2016
1 parent d65ecb1 commit 4bc7339
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 21 deletions.
45 changes: 32 additions & 13 deletions src/nopoll_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@ nopoll_bool __nopoll_conn_set_ssl_client_options (noPollCtx * ctx, noPollConn *
} /* end if */

/* enable default verification paths */
/* printf ("conn = %p, conn->ssl_ctx = %p\n", conn, conn->ssl_ctx); */
if (SSL_CTX_set_default_verify_paths (conn->ssl_ctx) != 1) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Unable to configure default verification paths, SSL_CTX_set_default_verify_paths () failed");
return nopoll_false;
Expand Down Expand Up @@ -774,10 +775,15 @@ noPollConn * __nopoll_conn_new_common (noPollCtx * ctx,
if (enable_tls) {
/* found TLS connection request, enable it */
conn->ssl_ctx = __nopoll_conn_get_ssl_context (ctx, conn, options, nopoll_true);
if (conn->ssl_ctx == NULL) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Unable to enable TLS, internal __nopoll_conn_get_ssl_context (ctx=%p, conn=%p, options=%p, nopoll_true) failed",
ctx, conn, options);
goto fail_ssl_connection;
} /* end if */

/* check for client side SSL configuration */
if (! __nopoll_conn_set_ssl_client_options (ctx, conn, options)) {
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Unable to configure additional SSL options, unable to continue",
nopoll_log (ctx, NOPOLL_LEVEL_CRITICAL, "Unable to configure additional SSL options, unable to continue, conn->ssl_ctx=%p, conn->ssl=%p",
conn->ssl_ctx, conn->ssl);
goto fail_ssl_connection;
} /* end if */
Expand Down Expand Up @@ -2885,11 +2891,21 @@ noPollMsg * nopoll_conn_get_msg (noPollConn * conn)
unsigned integer */
bytes = __nopoll_conn_receive (conn, buffer + 2, 2);
if (bytes != 2) {
nopoll_log (conn->ctx, NOPOLL_LEVEL_WARNING, "Failed to get next 2 bytes to read header from the wire, failed to received content, shutting down id=%d the connection, errno=%d (%s)", conn->id, errno, strerror (errno));
if (errno == NOPOLL_EWOULDBLOCK) {
nopoll_log (conn->ctx, NOPOLL_LEVEL_WARNING, "Failed to get next 2 bytes to read header from the wire, but received=%d, failed to received content, shutting down id=%d the connection, errno=%d (%s)",
bytes, conn->id, errno, strerror (errno));
if (errno == NOPOLL_EWOULDBLOCK || errno == 0) {
/* connection is not ready at this point */
conn->previous_msg = msg;
conn->read_pending_header = nopoll_true;

/* check amount of bytes to reuse them */
nopoll_log (conn->ctx, NOPOLL_LEVEL_WARNING, "Detected broken WebSocket peer sending header content using different frames, trying to save and resume later");
if (bytes > 0) {
/* ok, store content read into the pending buffer for next call */
memcpy (conn->pending_buf + conn->pending_buf_bytes, buffer + 2, bytes);
conn->pending_buf_bytes += bytes;
}

return NULL;
}

Expand All @@ -2902,6 +2918,8 @@ noPollMsg * nopoll_conn_get_msg (noPollConn * conn)
header_size += bytes;

msg->payload_size = nopoll_get_16bit (buffer + 2);

nopoll_log (conn->ctx, NOPOLL_LEVEL_DEBUG, "Received (%d) bytes in header (size %d) for payload size indication, which finally is: %d", bytes, header_size,(int) msg->payload_size);

} else if (msg->payload_size == 127) {
#if defined(NOPOLL_64BIT_PLATFORM)
Expand Down Expand Up @@ -3054,7 +3072,7 @@ noPollMsg * nopoll_conn_get_msg (noPollConn * conn)

/* flag that this message doesn't have FIN = 0 because
* we wasn't able to read it entirely */
msg->has_fin = 0;
/* msg->has_fin = 0; */
} /* end if */

/* flag the message was being a fragment according to previous flag */
Expand Down Expand Up @@ -3844,21 +3862,22 @@ int nopoll_conn_send_frame (noPollConn * conn, nopoll_bool fin, nopoll_bool mask
desp = 0;
tries = 0;

/***** BEGIN INTERNAL debug code for test_30 : nopoll-regression-client.c ******/
if (conn->__force_stop_after_header) {
nopoll_log (conn->ctx, NOPOLL_LEVEL_WARNING, "Sending broken header and implement a pause on purpose...");
/***** BEGIN INTERNAL debug code for test_30, test_31, test_32, test_33, test_34, test_35 : nopoll-regression-client.c ******/
if ((conn->__force_stop_after_header > 0) && (conn->__force_stop_after_header < (length + header_size))) {

nopoll_log (conn->ctx, NOPOLL_LEVEL_WARNING, "Sending broken header (just %d bytes) and implement a pause on purpose...", conn->__force_stop_after_header);

/* send just 2 bytes for the header and then implement a very long pause */
bytes_written = conn->send (conn, send_buffer, 2);
desp = 2;
if (bytes_written != 2) {
nopoll_log (conn->ctx, NOPOLL_LEVEL_WARNING, "Requested to write 2 bytes for the header but %d were written",
bytes_written);
bytes_written = conn->send (conn, send_buffer, conn->__force_stop_after_header);
desp = conn->__force_stop_after_header;
if (bytes_written != conn->__force_stop_after_header) {
nopoll_log (conn->ctx, NOPOLL_LEVEL_WARNING, "Requested to write %d bytes for the header but %d were written",
conn->__force_stop_after_header, bytes_written);
desp = 0;
} /* end if */

/* sleep after header ... */
nopoll_sleep (5000); /* 5 seconds */
nopoll_sleep (5000000); /* 5 seconds */

} /* end if */
/****** END INTERNAL debug code for test_30 : nopoll-regression-client.c ******/
Expand Down
85 changes: 77 additions & 8 deletions test/nopoll-regression-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -2415,7 +2415,7 @@ nopoll_bool test_29 (void) {
relases ****/
#include <nopoll_private.h>

nopoll_bool test_30 (void) {
nopoll_bool test_30_common_header_stop (const char * label, int bytes_to_send_before_stop) {

noPollConn * conn;
noPollCtx * ctx;
Expand All @@ -2434,16 +2434,19 @@ nopoll_bool test_30 (void) {
return nopoll_false;
} /* end if */

printf ("Test 30: waiting until connection is ready..\n");
printf ("Test %s: waiting until connection is ready..\n", label);
/* wait until it is connected */
nopoll_conn_wait_until_connection_ready (conn, 5);
printf ("Test 30: ok..\n");
printf ("Test %s: ok..\n", label);

/* send a message to request connection close with a particular message */
conn->__force_stop_after_header = nopoll_true;
conn->__force_stop_after_header = bytes_to_send_before_stop;

printf ("Test 30: sending first message..\n");
length = strlen (msg);

printf ("Test %s: sending first message (of %d bytes, sending broken header of %d, pausing then, and then sending the rest..)\n",
label, length, bytes_to_send_before_stop);

if (nopoll_conn_send_text (conn, msg, length) != length) {
printf ("ERROR: failed to send message..");
return nopoll_false;
Expand All @@ -2455,7 +2458,7 @@ nopoll_bool test_30 (void) {
return nopoll_false;
} /* end if */

printf ("Test 30: getting reply to the message..\n");
printf ("Test %s: getting reply to the message..\n", label);
tries = 10;
while (tries > 0 ) {
/* get message */
Expand All @@ -2480,13 +2483,16 @@ nopoll_bool test_30 (void) {
/* release message */
nopoll_msg_unref (msg_ref);

printf ("Test 30: send second message..\n");

printf ("Test %s: sending second message (of %d bytes, sending broken header of %d, pausing then, and then sending the rest..)\n",
label, length, bytes_to_send_before_stop);

if (nopoll_conn_send_text (conn, msg, length) != length) {
printf ("ERROR: failed to send message..");
return nopoll_false;
} /* end while */

printf ("Test 30: getting reply to the message (to the second message)..\n");
printf ("Test %s: getting reply to the message (to the second message)..\n", label);
tries = 10;
while (tries > 0 ) {
/* get message */
Expand Down Expand Up @@ -2520,7 +2526,35 @@ nopoll_bool test_30 (void) {
return nopoll_true;
}

nopoll_bool test_30 (void) {
/* call to test send 1 byte and stop */
return test_30_common_header_stop ("30", 2);
}

nopoll_bool test_31 (void) {
/* call to test send 1 byte and stop */
return test_30_common_header_stop ("31", 1);
}

nopoll_bool test_32 (void) {
/* call to test send 1 byte and stop */
return test_30_common_header_stop ("32", 3);
}

nopoll_bool test_33 (void) {
/* call to test send 1 byte and stop */
return test_30_common_header_stop ("33", 4);
}

nopoll_bool test_34 (void) {
/* call to test send 1 byte and stop */
return test_30_common_header_stop ("34", 5);
}

nopoll_bool test_35 (void) {
/* call to test send 1 byte and stop */
return test_30_common_header_stop ("35", 8);
}

int main (int argc, char ** argv)
{
Expand Down Expand Up @@ -2832,6 +2866,41 @@ int main (int argc, char ** argv)
return -1;
} /* end if */

if (test_31 ()) {
printf ("Test 31: simulate stop in the middle of the header send (II) [ OK ]\n");
} else {
printf ("Test 31: simulate stop in the middle of the header send (II) [ FAILED ]\n");
return -1;
} /* end if */

if (test_32 ()) {
printf ("Test 32: simulate stop in the middle of the header send (III) [ OK ]\n");
} else {
printf ("Test 32: simulate stop in the middle of the header send (III) [ FAILED ]\n");
return -1;
} /* end if */

if (test_33 ()) {
printf ("Test 33: simulate stop in the middle of the header send (IV) [ OK ]\n");
} else {
printf ("Test 33: simulate stop in the middle of the header send (IV) [ FAILED ]\n");
return -1;
} /* end if */

if (test_34 ()) {
printf ("Test 34: simulate stop in the middle of the header send (V) [ OK ]\n");
} else {
printf ("Test 34: simulate stop in the middle of the header send (V) [ FAILED ]\n");
return -1;
} /* end if */

if (test_35 ()) {
printf ("Test 35: simulate stop in the middle of the header send (VI) [ OK ]\n");
} else {
printf ("Test 35: simulate stop in the middle of the header send (VI) [ FAILED ]\n");
return -1;
} /* end if */

/* add support to reply with redirect 301 to an opening
* request: page 19 and 22 */

Expand Down

0 comments on commit 4bc7339

Please sign in to comment.