sketching support for upgrade handling

This commit is contained in:
Christian Grothoff
2016-08-27 18:08:00 +00:00
parent 63eb4c75a3
commit e0a43cb194
6 changed files with 75 additions and 28 deletions
+4
View File
@@ -1,3 +1,7 @@
Sat Aug 27 20:07:53 CEST 2016
Adding completely *untested* logic for HTTP "Upgrade"
handling. -CG
Sat Aug 27 18:20:38 CEST 2016
Releasing libmicrohttpd 0.9.51. -CG
+3 -4
View File
@@ -126,7 +126,7 @@ typedef intptr_t ssize_t;
* Current version of the library.
* 0x01093001 = 1.9.30-1.
*/
#define MHD_VERSION 0x00095100
#define MHD_VERSION 0x00095101
/**
* MHD-internal return code for "YES".
@@ -2221,7 +2221,6 @@ MHD_create_response_from_fd_at_offset64 (uint64_t size,
uint64_t offset);
#if 0
/**
* Enumeration for actions MHD should perform on the underlying socket
* of the upgrade. This API is not finalized, and in particular
@@ -2334,7 +2333,7 @@ typedef void
struct MHD_Connection *connection,
const char *extra_in,
size_t extra_in_size,
MHD_SOCKET sock,
MHD_socket sock,
struct MHD_UpgradeResponseHandle *urh);
@@ -2370,7 +2369,7 @@ typedef void
_MHD_EXTERN struct MHD_Response *
MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
void *upgrade_handler_cls);
#endif
/**
* Destroy a response object and associated resources. Note that
+29 -4
View File
@@ -736,7 +736,8 @@ keepalive_possible (struct MHD_Connection *connection)
if (NULL == end)
return MHD_YES;
if ( (MHD_str_equal_caseless_ (end, "close")) ||
(MHD_str_equal_caseless_ (end, "upgrade")) )
( (MHD_str_equal_caseless_ (end, "upgrade")) &&
(NULL == connection->response->upgrade_handler) ) )
return MHD_NO;
return MHD_YES;
}
@@ -2222,6 +2223,9 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
break;
case MHD_CONNECTION_CLOSED:
return MHD_YES;
case MHD_CONNECTION_UPGRADE:
EXTRA_CHECK (0);
break;
default:
/* shrink read buffer to how much is actually used */
MHD_pool_reallocate (connection->pool,
@@ -2305,7 +2309,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
do_write (connection);
if (connection->state != MHD_CONNECTION_HEADERS_SENDING)
break;
check_write_done (connection, MHD_CONNECTION_HEADERS_SENT);
check_write_done (connection,
MHD_CONNECTION_HEADERS_SENT);
break;
case MHD_CONNECTION_HEADERS_SENT:
EXTRA_CHECK (0);
@@ -2395,6 +2400,9 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
case MHD_TLS_CONNECTION_INIT:
EXTRA_CHECK (0);
break;
case MHD_CONNECTION_UPGRADE:
EXTRA_CHECK (0);
break;
default:
EXTRA_CHECK (0);
CONNECTION_CLOSE_ERROR (connection,
@@ -2586,9 +2594,9 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
}
if ( (NULL != connection->response) &&
( (MHD_str_equal_caseless_ (connection->method,
MHD_HTTP_METHOD_POST)) ||
MHD_HTTP_METHOD_POST)) ||
(MHD_str_equal_caseless_ (connection->method,
MHD_HTTP_METHOD_PUT))) )
MHD_HTTP_METHOD_PUT))) )
{
/* we refused (no upload allowed!) */
connection->remaining_upload_size = 0;
@@ -2722,6 +2730,21 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
}
else
socket_start_normal_buffering (connection);
if (NULL != connection->response->upgrade_handler)
{
/* This connection is "upgraded". Pass socket to application. */
if (MHD_YES !=
MHD_response_execute_upgrade_ (connection->response,
connection))
{
/* upgrade failed, fail hard */
CONNECTION_CLOSE_ERROR (connection,
NULL);
continue;
}
connection->state = MHD_CONNECTION_UPGRADE;
continue;
}
if (connection->have_chunked_upload)
connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
@@ -2882,6 +2905,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
case MHD_CONNECTION_CLOSED:
cleanup_connection (connection);
return MHD_NO;
case MHD_CONNECTION_UPGRADE:
return MHD_YES; /* keep open */
default:
EXTRA_CHECK (0);
break;
+7 -3
View File
@@ -274,7 +274,6 @@ struct MHD_Response
*/
MHD_ContentReaderFreeCallback crfc;
#if 0
/**
* Application function to call once we are done sending the headers
* of the response; NULL unless this is a response created with
@@ -286,7 +285,6 @@ struct MHD_Response
* Closure for @e uh.
*/
void *upgrade_handler_cls;
#endif
/**
* Mutex to synchronize access to @e data, @e size and
@@ -476,7 +474,13 @@ enum MHD_CONNECTION_STATE
* Handshake messages will be processed in this state & while
* in the #MHD_TLS_HELLO_REQUEST state
*/
MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_IN_CLEANUP + 1
MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_IN_CLEANUP + 1,
/**
* Connection was "upgraded" and socket is now under the
* control of the application.
*/
MHD_CONNECTION_UPGRADE = MHD_TLS_CONNECTION_INIT + 1
};
+14 -17
View File
@@ -1,6 +1,6 @@
/*
This file is part of libmicrohttpd
Copyright (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
Copyright (C) 2007, 2009, 2010, 2016 Daniel Pittman and Christian Grothoff
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -29,6 +29,9 @@
#include "internal.h"
#include "response.h"
#include "mhd_limits.h"
#include "mhd_sockets.h"
#include "mhd_itc.h"
#include "connection.h"
#if defined(_WIN32) && defined(MHD_W32_MUTEX_)
#ifndef WIN32_LEAN_AND_MEAN
@@ -577,7 +580,6 @@ MHD_create_response_from_buffer (size_t size,
}
#if 0
/**
* Handle given to the application to manage special
* actions relating to MHD responses that "upgrade"
@@ -596,13 +598,13 @@ struct MHD_UpgradeResponseHandle
/**
* The socket we gave to the application (r/w).
*/
MHD_SOCKET app_sock;
MHD_socket app_socket;
/**
* If @a app_sock was a socketpair, our end of it, otherwise
* #MHD_INVALID_SOCKET; (r/w).
*/
MHD_SOCKET mhd_sock;
MHD_socket mhd_socket;
};
@@ -629,12 +631,12 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
case MHD_UPGRADE_ACTION_CLOSE:
/* Application is done with this connection, tear it down! */
if ( (MHD_INVALID_SOCKET != urh->app_socket) &&
(0 != MHD_socket_close (urh->app_socket)) )
(0 != MHD_socket_close_ (urh->app_socket)) )
MHD_PANIC ("close failed\n");
if ( (MHD_INVALID_SOCKET != urh->mhd_socket) &&
(0 != MHD_socket_close (urh->mhd_socket)) )
(0 != MHD_socket_close_ (urh->mhd_socket)) )
MHD_PANIC ("close failed\n");
MHD_connection_resume (urh->connection);
MHD_resume_connection (urh->connection);
MHD_connection_close_ (urh->connection,
MHD_REQUEST_TERMINATED_COMPLETED_OK);
free (urh);
@@ -659,9 +661,6 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
* @return #MHD_YES on success, #MHD_NO on failure (will cause
* connection to be closed)
*/
// FIXME: This function will need to be called at the right place(s)
// in the connection processing (just after we are done sending the header)
// (for responses that have the 'upgrade_header' callback set).
int
MHD_response_execute_upgrade_ (struct MHD_Response *response,
struct MHD_Connection *connection)
@@ -674,7 +673,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
if (NULL == urh)
return MHD_NO;
#if HTTPS_SUPPORT
if (0 != (connection->daemon->flags & MHD_USE_SSL) )
if (0 != (connection->daemon->options & MHD_USE_SSL) )
{
/* FIXME: this is non-portable for now; W32 port pending... */
if (0 != socketpair (AF_UNIX,
@@ -694,12 +693,12 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
connection,
connection->read_buffer,
rbo,
urh->app_sock,
urh->app_socket,
urh);
/* As far as MHD is concerned, this connection is
suspended; it will be resumed once we are done
in the #MHD_upgrade_action() function */
MHD_connection_suspend (connection);
MHD_suspend_connection (connection);
/* FIXME: also need to start some processing logic in _all_ MHD
event loops for the sv traffic! (NOT IMPLEMENTED!!!) */
return MHD_YES;
@@ -718,7 +717,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
/* As far as MHD is concerned, this connection is
suspended; it will be resumed once we are done
in the #MHD_upgrade_action() function */
MHD_connection_suspend (connection);
MHD_suspend_connection (connection);
return MHD_YES;
}
@@ -758,7 +757,7 @@ MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
{
struct MHD_Response *response;
if (NULL == upgrade_header)
if (NULL == upgrade_handler)
return NULL; /* invalid request */
response = malloc (sizeof (struct MHD_Response));
if (NULL == response)
@@ -769,14 +768,12 @@ MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
free (response);
return NULL;
}
urh->response = response;
response->upgrade_handler = upgrade_handler;
response->upgrade_handler_cls = upgrade_handler_cls;
response->total_size = MHD_SIZE_UNKNOWN;
response->reference_count = 1;
return response;
}
#endif
/**
+18
View File
@@ -36,4 +36,22 @@ void
MHD_increment_response_rc (struct MHD_Response *response);
/**
* We are done sending the header of a given response
* to the client. Now it is time to perform the upgrade
* and hand over the connection to the application.
*
* @param response the response that was created for an upgrade
* @param connection the specific connection we are upgrading
* @return #MHD_YES on success, #MHD_NO on failure (will cause
* connection to be closed)
*/
// FIXME: This function will need to be called at the right place(s)
// in the connection processing (just after we are done sending the header)
// (for responses that have the 'upgrade_header' callback set).
int
MHD_response_execute_upgrade_ (struct MHD_Response *response,
struct MHD_Connection *connection);
#endif