* [new] Updated noPoll conn API to include a new function to allow closing
  a connection, sending an error message and an error code along with it:

  - nopoll_conn_close_ext

* [fix] Added regression test (test_28) to check connection close frame
  with status and reason to check functions added:

  - nopoll_conn_get_close_status 
  - nopoll_conn_get_close_reason

  Everything working as expected..
This commit is contained in:
Francis Brosnan Blázquez
2015-08-16 17:10:42 +00:00
parent 8539e6ccd8
commit d8a292fd3a
5 changed files with 124 additions and 3 deletions

View File

@@ -30,6 +30,7 @@ nopoll_conn_accept_complete
nopoll_conn_accept_socket
nopoll_conn_check_mime_header_repeated
nopoll_conn_close
nopoll_conn_close_ext
nopoll_conn_complete_handshake
nopoll_conn_complete_handshake_check
nopoll_conn_complete_handshake_check_client

View File

@@ -1455,10 +1455,18 @@ void nopoll_conn_shutdown (noPollConn * conn)
* (\ref noPollRole).
*
* @param conn The connection to close.
*
* @param status Optional status code to send to remote side. If
* status is < 0, no status code is sent.
*
* @param reason Pointer to the content to be sent.
*
* @param reason_size The amount of bytes that should be used from content pointer.
*/
void nopoll_conn_close (noPollConn * conn)
void nopoll_conn_close_ext (noPollConn * conn, int status, const char * reason, int reason_size)
{
int refs;
int refs;
char * content;
#if defined(SHOW_DEBUG_LOG)
const char * role = "unknown";
#endif
@@ -1483,7 +1491,28 @@ void nopoll_conn_close (noPollConn * conn)
if (conn->session != NOPOLL_INVALID_SOCKET) {
nopoll_log (conn->ctx, NOPOLL_LEVEL_DEBUG, "requested proper connection close id=%d (session %d)", conn->id, conn->session);
/* send close message */
/* build reason indication */
content = NULL;
if (reason && reason_size > 0) {
/* send content */
content = nopoll_new (char, reason_size + 3);
if (content) {
nopoll_set_16bit (status, content);
memcpy (content + 2, reason, reason_size);
} /* end if */
} /* end if */
/* send close without reason */
nopoll_conn_send_frame (conn, nopoll_true /* has_fin */,
/* masked */
conn->role == NOPOLL_ROLE_CLIENT, NOPOLL_CLOSE_FRAME,
/* content size and content */
reason_size > 0 ? reason_size + 2 : 0, content,
/* sleep in header */
0);
/* release content (if defined) */
nopoll_free (content);
/* call to shutdown connection */
nopoll_conn_shutdown (conn);
@@ -1501,6 +1530,23 @@ void nopoll_conn_close (noPollConn * conn)
/* call to unref connection */
nopoll_conn_unref (conn);
return;
}
/**
* @brief Allows to close an opened \ref noPollConn no matter its role
* (\ref noPollRole).
*
* @param conn The connection to close.
*
* There is available an alternative extended version that allows to
* send the status code and the error message: \ref
* nopoll_conn_close_ext
*/
void nopoll_conn_close (noPollConn * conn)
{
/* call to close without providing a reason */
nopoll_conn_close_ext (conn, 0, NULL, 0);
return;
}

View File

@@ -125,6 +125,8 @@ void nopoll_conn_shutdown (noPollConn * conn);
void nopoll_conn_close (noPollConn * conn);
void nopoll_conn_close_ext (noPollConn * conn, int status, const char * reason, int reason_size);
void nopoll_conn_set_hook (noPollConn * conn, noPollPtr ptr);
noPollPtr nopoll_conn_get_hook (noPollConn * conn);

View File

@@ -2318,6 +2318,65 @@ nopoll_bool test_27 (void) {
}
nopoll_bool test_28 (void) {
noPollConn * conn;
noPollCtx * ctx;
noPollMsg * msg;
/* init context */
ctx = create_ctx ();
/* create connection */
conn = nopoll_conn_new (ctx, "localhost", "1234", NULL, NULL, NULL, NULL);
if (! nopoll_conn_is_ok (conn)) {
printf ("ERROR: Expected to find proper client connection status, but found error..\n");
return nopoll_false;
} /* end if */
/* wait until it is connected */
nopoll_conn_wait_until_connection_ready (conn, 5);
/* send a message to request connection close with a particular message */
if (nopoll_conn_send_text (conn, "close with message", 18) != 18) {
printf ("ERROR: failed to send close with message..");
return nopoll_false;
} /* end while */
/* wait for the reply */
while ((msg = nopoll_conn_get_msg (conn)) == NULL) {
if (! nopoll_conn_is_ok (conn)) {
/* connection was closed by remote side */
break;
} /* end if */
nopoll_sleep (10000);
} /* end if */
printf ("Test 28: close reason received, statud=%d, message=%s\n",
nopoll_conn_get_close_status (conn),
nopoll_conn_get_close_reason (conn));
if (nopoll_conn_get_close_status (conn) != 1048) {
printf ("ERROR: expected different error code..\n");
return nopoll_false;
}
if (! nopoll_cmp (nopoll_conn_get_close_reason (conn), "Hey, this is a very reasonable error message")) {
printf ("ERROR: expected different error message..\n");
return nopoll_false;
} /* end if */
/* close connection */
nopoll_conn_close (conn);
/* release context */
nopoll_ctx_unref (ctx);
return nopoll_true;
}
int main (int argc, char ** argv)
{
int iterator;
@@ -2607,6 +2666,13 @@ int main (int argc, char ** argv)
return -1;
} /* end if */
if (test_28 ()) {
printf ("Test 28: checking setting protocol [ OK ]\n");
} else {
printf ("Test 28: chekcing setting protocol [ FAILED ]\n");
return -1;
} /* end if */
/* add support to reply with redirect 301 to an opening
* request: page 19 and 22 */

View File

@@ -149,6 +149,12 @@ void listener_on_message (noPollCtx * ctx, noPollConn * conn, noPollMsg * msg, n
} /* end if */
printf ("Message received: %s\n", content);
if (nopoll_ncmp (content, "close with message", 18)) {
printf ("Listener: RELEASING connection (closing it) with reason..\n");
nopoll_conn_close_ext (conn, 1048, "Hey, this is a very reasonable error message", 44);
return;
} /* end if */
if (nopoll_ncmp (content, "release-message", 15)) {
printf ("Listener: RELEASING previous message..\n");
nopoll_msg_unref (previous_msg);