mirror of
https://github.com/stefanocasazza/ULib.git
synced 2025-09-28 19:05:55 +08:00
sync
This commit is contained in:
parent
7177337f9a
commit
d4dfd5d9a8
|
@ -53,7 +53,7 @@ extern U_EXPORT void runDynamicPage_ir_web(int param);
|
|||
{
|
||||
if (param == U_DPAGE_INIT) { usp_init_ir_web(); return; }
|
||||
if (param == U_DPAGE_DESTROY) { usp_end_ir_web(); return; }
|
||||
if (param >= U_DPAGE_FORK) return;
|
||||
return;
|
||||
}
|
||||
|
||||
UHTTP::mime_index = U_html;
|
||||
|
|
|
@ -19,7 +19,7 @@ extern U_EXPORT void runDynamicPage_wi_auth2(int param);
|
|||
if (param == U_DPAGE_INIT) { usp_init_wi_auth2(); return; }
|
||||
if (param == U_DPAGE_DESTROY) { usp_end_wi_auth2(); return; }
|
||||
if (param == U_DPAGE_FORK) { usp_fork_wi_auth2(); return; }
|
||||
if (param > U_DPAGE_FORK) return;
|
||||
return;
|
||||
}
|
||||
|
||||
U_http_info.endHeader = 0;
|
||||
|
|
|
@ -94,10 +94,10 @@ loop:
|
|||
U_INTERNAL_ASSERT(lnetmask)
|
||||
U_ASSERT(vnetmask.empty())
|
||||
|
||||
U_INTERNAL_DUMP("tok.current() = %C", tok.current())
|
||||
U_INTERNAL_DUMP("tok.previous() = %C tok.current() = %C", tok.previous(), tok.current())
|
||||
|
||||
if (u__isdigit(tok.current())) name.clear();
|
||||
else (void) tok.next(name, (bool*)U_NULLPTR);
|
||||
if (tok.previous() != ',') name.clear();
|
||||
else (void) tok.next(name, (bool*)U_NULLPTR);
|
||||
|
||||
vnetmask.push_back(lnetmask);
|
||||
|
||||
|
@ -613,7 +613,7 @@ static void deleteSession()
|
|||
(void) rc->zrem(U_CONSTANT_TO_PARAM("SESSION:byCaptiveIdAndApId deviceId:%v;ip:%v"), mac->rep, ip->rep);
|
||||
(void) rc->zrem(U_CONSTANT_TO_PARAM("SESSION:byLastUpdate %v"), key_session->rep);
|
||||
|
||||
U_LOGGER("*** SESSION(%V) deleted at deleteSession() ***", key_session->rep);
|
||||
// U_LOGGER("*** SESSION(%V) deleted at deleteSession() ***", key_session->rep);
|
||||
}
|
||||
|
||||
static void resetDeviceDailyCounter()
|
||||
|
@ -1111,7 +1111,7 @@ static void POST_login()
|
|||
(void) rc->hmset(U_CONSTANT_TO_PARAM("SESSION:%v captiveId %u apId %v deviceId %v ip %v created %u pId %v notify %c consume %c counter 0 lastUpdate %u"), key_session->rep,
|
||||
addr, ap_label->rep, mac->rep, ip->rep, u_now->tv_sec, policySessionId->rep, buffer[1], '0'+ap_consume, u_now->tv_sec);
|
||||
|
||||
U_LOGGER("*** SESSION(%V) created at POST_login() ***", key_session->rep);
|
||||
// U_LOGGER("*** SESSION(%V) created at POST_login() ***", key_session->rep);
|
||||
|
||||
(void) rc->zadd(U_CONSTANT_TO_PARAM("SESSION:byCaptiveIdAndApId %u%06u deviceId:%v;ip:%v"), addr, ap_label->strtoul(), mac->rep, ip->rep);
|
||||
(void) rc->zadd(U_CONSTANT_TO_PARAM("SESSION:byLastUpdate %u %v"), u_now->tv_sec, key_session->rep);
|
||||
|
|
|
@ -19,7 +19,7 @@ extern U_EXPORT void runDynamicPage_wi_auth(int param);
|
|||
if (param == U_DPAGE_INIT) { usp_init_wi_auth(); return; }
|
||||
if (param == U_DPAGE_DESTROY) { usp_end_wi_auth(); return; }
|
||||
if (param == U_DPAGE_SIGHUP) { usp_sighup_wi_auth(); return; }
|
||||
if (param >= U_DPAGE_FORK) return;
|
||||
return;
|
||||
}
|
||||
|
||||
U_http_info.endHeader = 0;
|
||||
|
|
|
@ -416,8 +416,8 @@ http {
|
|||
# ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
# socket - plugin parameters
|
||||
# ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
# COMMAND command (alternative to USP websocket) to execute
|
||||
# ENVIRONMENT environment for command (alternative to USP websocket) to execute
|
||||
# COMMAND command (alternative to USP modsocket) to execute
|
||||
# ENVIRONMENT environment for command (alternative to USP modsocket) to execute
|
||||
#
|
||||
# MAX_MESSAGE_SIZE Maximum size (in bytes) of a message to accept; default is approximately 4GB
|
||||
# ------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
# include <ulib/ssl/digest.h>
|
||||
# include <ulib/ssl/certificate.h>
|
||||
# include <ulib/net/client/twilio.h>
|
||||
# include <ulib/net/client/websocket.h>
|
||||
# include <ulib/ssl/mime/mime_pkcs7.h>
|
||||
# include <ulib/ssl/net/ssl_session.h>
|
||||
# ifdef HAVE_SSL_TS
|
||||
|
|
|
@ -41,7 +41,9 @@ enum DynamicPageType {
|
|||
U_DPAGE_RESET = -2,
|
||||
U_DPAGE_DESTROY = -3,
|
||||
U_DPAGE_SIGHUP = -4,
|
||||
U_DPAGE_FORK = -5
|
||||
U_DPAGE_FORK = -5,
|
||||
U_DPAGE_OPEN = -6,
|
||||
U_DPAGE_CLOSE = -7
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -4163,7 +4163,9 @@ static bool runAuthCmd(const char* password, const char* prealm)
|
|||
|
||||
*output = UCommand::outputCommand(cmd, U_NULLPTR, -1, fd_stderr);
|
||||
|
||||
#ifdef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(cmd.data(), true);
|
||||
#endif
|
||||
|
||||
if (UCommand::exit_value ||
|
||||
output->empty())
|
||||
|
|
|
@ -178,9 +178,8 @@ public:
|
|||
|
||||
U_ASSERT(empty() == false)
|
||||
|
||||
if (getHeader(U_CONSTANT_TO_PARAM("Connection")).equal(U_CONSTANT_TO_PARAM("close")))
|
||||
if (getHeader(U_CONSTANT_TO_PARAM("Connection")).equal(U_CONSTANT_TO_PARAM("close"))) U_RETURN(true);
|
||||
|
||||
U_RETURN(true);
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <ulib/url.h>
|
||||
#include <ulib/net/rpc/rpc.h>
|
||||
#include <ulib/mime/header.h>
|
||||
#include <ulib/utility/uhttp.h>
|
||||
|
||||
#ifdef USE_LIBSSL
|
||||
|
@ -39,6 +40,7 @@ class USCGIPlugIn;
|
|||
class UProxyPlugIn;
|
||||
class UNoCatPlugIn;
|
||||
class UServer_Base;
|
||||
class UWebSocketClient;
|
||||
class UHttpClient_Base;
|
||||
class UClientImage_Base;
|
||||
class UREDISClient_Base;
|
||||
|
@ -297,6 +299,8 @@ protected:
|
|||
|
||||
bool sendRequestAndReadResponse() { return sendRequest(true); }
|
||||
|
||||
bool processHeader(UMimeHeader* responseHeader) { return responseHeader->readHeader(socket, response); }
|
||||
|
||||
#ifdef USE_LIBSSL
|
||||
void setSSLContext();
|
||||
|
||||
|
@ -329,6 +333,7 @@ private:
|
|||
friend class UProxyPlugIn;
|
||||
friend class UNoCatPlugIn;
|
||||
friend class UServer_Base;
|
||||
friend class UWebSocketClient;
|
||||
friend class UHttpClient_Base;
|
||||
friend class UClientImage_Base;
|
||||
friend class UREDISClient_Base;
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
*/
|
||||
|
||||
class UHTTP;
|
||||
class UMimeHeader;
|
||||
class Application;
|
||||
class WiAuthNodog;
|
||||
class UServer_Base;
|
||||
|
|
104
include/ulib/net/client/websocket.h
Normal file
104
include/ulib/net/client/websocket.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
// ============================================================================
|
||||
//
|
||||
// = LIBRARY
|
||||
// ULib - c++ library
|
||||
//
|
||||
// = FILENAME
|
||||
// websocket.h - simple websocket client
|
||||
//
|
||||
// = AUTHOR
|
||||
// Stefano Casazza
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
#ifndef ULIB_WEBSOCKET_CLIENT_H
|
||||
#define ULIB_WEBSOCKET_CLIENT_H 1
|
||||
|
||||
#include <ulib/net/client/client.h>
|
||||
#include <ulib/ssl/net/sslsocket.h>
|
||||
#include <ulib/utility/websocket.h>
|
||||
|
||||
/**
|
||||
* @class UWebSocketClient
|
||||
*/
|
||||
|
||||
class U_EXPORT UWebSocketClient {
|
||||
public:
|
||||
|
||||
// Check for memory error
|
||||
U_MEMORY_TEST
|
||||
|
||||
// Allocator e Deallocator
|
||||
U_MEMORY_ALLOCATOR
|
||||
U_MEMORY_DEALLOCATOR
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
||||
UWebSocketClient()
|
||||
{
|
||||
U_TRACE_CTOR(0, UWebSocketClient, "", 0)
|
||||
|
||||
U_NEW(UClient<USSLSocket>, client, UClient<USSLSocket>(U_NULLPTR));
|
||||
}
|
||||
|
||||
~UWebSocketClient()
|
||||
{
|
||||
U_TRACE_DTOR(0, UWebSocketClient)
|
||||
|
||||
U_INTERNAL_ASSERT_POINTER(client)
|
||||
|
||||
U_DELETE(client)
|
||||
}
|
||||
|
||||
// SERVICES
|
||||
|
||||
bool readMessage()
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "UWebSocketClient::readMessage()")
|
||||
|
||||
U_INTERNAL_ASSERT_POINTER(client)
|
||||
|
||||
UWebSocket::rbuffer->setEmpty();
|
||||
|
||||
if (UWebSocket::handleDataFraming(client->UClient_Base::socket) == U_WS_STATUS_CODE_OK) U_RETURN(true);
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
bool sendMessage(const UString& msg, int type = U_WS_MESSAGE_TYPE_TEXT)
|
||||
{
|
||||
U_TRACE(0, "UWebSocketClient::sendMessage(%V,%d)", msg.rep, type)
|
||||
|
||||
U_INTERNAL_ASSERT_POINTER(client)
|
||||
|
||||
return UWebSocket::sendData(client->UClient_Base::socket, type, msg);
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "UWebSocketClient::close()")
|
||||
|
||||
U_INTERNAL_ASSERT_POINTER(client)
|
||||
|
||||
(void) UWebSocket::sendClose(client->UClient_Base::socket);
|
||||
|
||||
client->UClient_Base::close();
|
||||
}
|
||||
|
||||
bool connectServer(const UString& url);
|
||||
|
||||
UClient<USSLSocket>* getClient() const { return client; }
|
||||
|
||||
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
||||
const char* dump(bool reset) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
UClient<USSLSocket>* client;
|
||||
|
||||
private:
|
||||
U_DISALLOW_COPY_AND_ASSIGN(UWebSocketClient)
|
||||
};
|
||||
#endif
|
|
@ -300,9 +300,7 @@ protected:
|
|||
|
||||
(void) peer->fw.executeAndWait(U_NULLPTR, -1, fd_stderr);
|
||||
|
||||
# ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(peer->fw.getCommand(), false);
|
||||
# endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(peer->fw, false);
|
||||
|
||||
U_peer_status = type;
|
||||
}
|
||||
|
|
|
@ -266,7 +266,7 @@ protected:
|
|||
{
|
||||
U_TRACE(0, "UNoDogPlugIn::setRedirect(%p,%u)", buffer, bufsize)
|
||||
|
||||
return u__snprintf(buffer, bufsize, U_CONSTANT_TO_PARAM("http://%.*s/%.*s"), U_HTTP_HOST_TO_TRACE, U_HTTP_URI_QUERY_TO_TRACE);
|
||||
return u__snprintf(buffer, bufsize, U_CONSTANT_TO_PARAM("http://%.*s%.*s"), U_HTTP_HOST_TO_TRACE, U_HTTP_URI_QUERY_TO_TRACE);
|
||||
}
|
||||
|
||||
static uint32_t getApInfo(char* buffer, uint32_t bufsize, const UString& lbl)
|
||||
|
|
|
@ -45,8 +45,10 @@ public:
|
|||
#endif
|
||||
|
||||
protected:
|
||||
static int fd_stderr;
|
||||
static vPFi on_message;
|
||||
static UCommand* command;
|
||||
static UString* penvironment;
|
||||
|
||||
static RETSIGTYPE handlerForSigTERM(int signo);
|
||||
|
||||
|
|
|
@ -86,7 +86,11 @@ vClientImage = new client_type[UNotifier::max_connection]; } }
|
|||
|
||||
# define U_SRV_LOG( fmt,args...) {}
|
||||
# define U_SRV_LOG_WITH_ADDR(fmt,args...) {}
|
||||
|
||||
# define U_SRV_LOG_CMD_MSG_ERR(cmd,balways) {}
|
||||
#else
|
||||
# define U_SRV_LOG_CMD_MSG_ERR(cmd,balways) { if (UServer_Base::isLog()) UServer_Base::logCommandMsgError((cmd).getCommand(),balways); }
|
||||
|
||||
# define U_RESET_MODULE_NAME { if (UServer_Base::isLog()) (void) strcpy(UServer_Base::mod_name[0], UServer_Base::mod_name[1]); }
|
||||
# define U_SET_MODULE_NAME(name) { if (UServer_Base::isLog()) { (void) strcpy(UServer_Base::mod_name[1], UServer_Base::mod_name[0]); \
|
||||
(void) strcpy(UServer_Base::mod_name[0], "["#name"] "); } }
|
||||
|
@ -94,6 +98,7 @@ vClientImage = new client_type[UNotifier::max_connection]; } }
|
|||
# define U_SRV_LOG( fmt,args...) { if (UServer_Base::isLog()) UServer_Base::log->log(U_CONSTANT_TO_PARAM("%s" fmt), UServer_Base::mod_name[0] , ##args); }
|
||||
# define U_SRV_LOG_WITH_ADDR(fmt,args...) { if (UServer_Base::isLog()) UServer_Base::log->log(U_CONSTANT_TO_PARAM("%s" fmt " %v"), UServer_Base::mod_name[0] , ##args, \
|
||||
UServer_Base::pClientImage->logbuf->rep); }
|
||||
|
||||
#endif
|
||||
|
||||
class UHTTP;
|
||||
|
@ -617,13 +622,12 @@ public:
|
|||
U_TRACE(0, "UServer_Base::logCommandMsgError(%S,%b)", cmd, balways)
|
||||
|
||||
# ifndef U_LOG_DISABLE
|
||||
if (isLog())
|
||||
{
|
||||
if (UCommand::setMsgError(cmd, !balways) || balways) log->log(U_CONSTANT_TO_PARAM("%s%.*s"), mod_name[0], u_buffer_len, u_buffer);
|
||||
U_INTERNAL_ASSERT_POINTER(log)
|
||||
|
||||
errno = 0;
|
||||
u_buffer_len = 0;
|
||||
}
|
||||
if (UCommand::setMsgError(cmd, !balways) || balways) log->log(U_CONSTANT_TO_PARAM("%s%.*s"), mod_name[0], u_buffer_len, u_buffer);
|
||||
|
||||
errno = 0;
|
||||
u_buffer_len = 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,17 @@ public:
|
|||
--s;
|
||||
}
|
||||
|
||||
// get previous char
|
||||
|
||||
char previous()
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "UTokenizer::previous()")
|
||||
|
||||
U_INTERNAL_ASSERT(s <= end)
|
||||
|
||||
U_RETURN(*(s-1));
|
||||
}
|
||||
|
||||
// get current char
|
||||
|
||||
char current()
|
||||
|
|
|
@ -232,12 +232,34 @@ public:
|
|||
U_RETURN_STRING(srv);
|
||||
}
|
||||
|
||||
bool isLDAP() const
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "Url::isLDAP()")
|
||||
|
||||
if (u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('l','d','a','p')) U_RETURN(true);
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
bool isHTTP() const
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "Url::isHTTP()")
|
||||
|
||||
if (service_end == 4 &&
|
||||
UString::str_http->equal(url.data(), (uint32_t)service_end))
|
||||
u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('h','t','t','p'))
|
||||
{
|
||||
U_RETURN(true);
|
||||
}
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
bool isWS() const
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "Url::isWS()")
|
||||
|
||||
if (service_end == 2 &&
|
||||
u_get_unalignedp16(url.data()) == U_MULTICHAR_CONSTANT16('w','s'))
|
||||
{
|
||||
U_RETURN(true);
|
||||
}
|
||||
|
@ -251,7 +273,7 @@ public:
|
|||
|
||||
if (service_end == 5 &&
|
||||
url.c_char(4) == 's' &&
|
||||
UString::str_http->equal(url.data(), 4))
|
||||
u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('h','t','t','p'))
|
||||
{
|
||||
U_RETURN(true);
|
||||
}
|
||||
|
@ -259,11 +281,16 @@ public:
|
|||
U_RETURN(false);
|
||||
}
|
||||
|
||||
bool isLDAP() const
|
||||
bool isWSS() const
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "Url::isLDAP()")
|
||||
U_TRACE_NO_PARAM(0, "Url::isWSS()")
|
||||
|
||||
if (getService().equal(U_CONSTANT_TO_PARAM("ldap"))) U_RETURN(true);
|
||||
if (service_end == 3 &&
|
||||
url.c_char(2) == 's' &&
|
||||
u_get_unalignedp16(url.data()) == U_MULTICHAR_CONSTANT16('w','s'))
|
||||
{
|
||||
U_RETURN(true);
|
||||
}
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
@ -272,7 +299,12 @@ public:
|
|||
{
|
||||
U_TRACE_NO_PARAM(0, "Url::isLDAPS()")
|
||||
|
||||
if (getService().equal(U_CONSTANT_TO_PARAM("ldaps"))) U_RETURN(true);
|
||||
if (service_end == 5 &&
|
||||
url.c_char(4) == 's' &&
|
||||
u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('l','d','a','p'))
|
||||
{
|
||||
U_RETURN(true);
|
||||
}
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
|
|
@ -16,26 +16,33 @@
|
|||
|
||||
#include <ulib/string.h>
|
||||
|
||||
#define MESSAGE_TYPE_INVALID -1
|
||||
#define MESSAGE_TYPE_TEXT 0
|
||||
#define MESSAGE_TYPE_BINARY 128
|
||||
#define MESSAGE_TYPE_CLOSE 255
|
||||
#define MESSAGE_TYPE_PING 256
|
||||
#define MESSAGE_TYPE_PONG 257
|
||||
#define U_WS_MESSAGE_TYPE_INVALID -1
|
||||
#define U_WS_MESSAGE_TYPE_TEXT 0
|
||||
#define U_WS_MESSAGE_TYPE_BINARY 128
|
||||
#define U_WS_MESSAGE_TYPE_CLOSE 255
|
||||
#define U_WS_MESSAGE_TYPE_PING 256
|
||||
#define U_WS_MESSAGE_TYPE_PONG 257
|
||||
|
||||
#define STATUS_CODE_OK 1000
|
||||
#define STATUS_CODE_GOING_AWAY 1001
|
||||
#define STATUS_CODE_PROTOCOL_ERROR 1002
|
||||
#define STATUS_CODE_INVALID_TYPE 1003
|
||||
#define STATUS_CODE_RESERVED1 1004 /* Protocol 8: frame too large */
|
||||
#define STATUS_CODE_RESERVED2 1005
|
||||
#define STATUS_CODE_RESERVED3 1006
|
||||
#define STATUS_CODE_INVALID_UTF8 1007
|
||||
#define STATUS_CODE_POLICY_VIOLATION 1008
|
||||
#define STATUS_CODE_MESSAGE_TOO_LARGE 1009
|
||||
#define STATUS_CODE_EXTENSION_ERROR 1010
|
||||
#define STATUS_CODE_INTERNAL_ERROR 1011
|
||||
#define STATUS_CODE_RESERVED4 1015
|
||||
#define U_WS_OPCODE_CONTINUATION 0x0
|
||||
#define U_WS_OPCODE_TEXT 0x1
|
||||
#define U_WS_OPCODE_BINARY 0x2
|
||||
#define U_WS_OPCODE_CLOSE 0x8
|
||||
#define U_WS_OPCODE_PING 0x9
|
||||
#define U_WS_OPCODE_PONG 0xA
|
||||
|
||||
#define U_WS_STATUS_CODE_OK 1000
|
||||
#define U_WS_STATUS_CODE_GOING_AWAY 1001
|
||||
#define U_WS_STATUS_CODE_PROTOCOL_ERROR 1002
|
||||
#define U_WS_STATUS_CODE_INVALID_TYPE 1003
|
||||
#define U_WS_STATUS_CODE_RESERVED1 1004 /* Protocol 8: frame too large */
|
||||
#define U_WS_STATUS_CODE_RESERVED2 1005
|
||||
#define U_WS_STATUS_CODE_RESERVED3 1006
|
||||
#define U_WS_STATUS_CODE_INVALID_UTF8 1007
|
||||
#define U_WS_STATUS_CODE_POLICY_VIOLATION 1008
|
||||
#define U_WS_STATUS_CODE_MESSAGE_TOO_LARGE 1009
|
||||
#define U_WS_STATUS_CODE_EXTENSION_ERROR 1010
|
||||
#define U_WS_STATUS_CODE_INTERNAL_ERROR 1011
|
||||
#define U_WS_STATUS_CODE_RESERVED4 1015
|
||||
|
||||
class USocket;
|
||||
|
||||
|
@ -44,11 +51,6 @@ public:
|
|||
|
||||
// SERVICES
|
||||
|
||||
static UString* rbuffer;
|
||||
static uint32_t max_message_size;
|
||||
static const char* upgrade_settings;
|
||||
static int message_type, status_code;
|
||||
|
||||
typedef struct _WebSocketFrameData {
|
||||
unsigned char* application_data;
|
||||
uint32_t application_data_offset;
|
||||
|
@ -57,17 +59,24 @@ public:
|
|||
unsigned int utf8_state;
|
||||
} WebSocketFrameData;
|
||||
|
||||
static UString* rbuffer;
|
||||
static UString* message;
|
||||
static uint32_t max_message_size;
|
||||
static const char* upgrade_settings;
|
||||
static int message_type, status_code;
|
||||
static WebSocketFrameData control_frame;
|
||||
static WebSocketFrameData message_frame;
|
||||
|
||||
static bool sendAccept();
|
||||
static void checkForInitialData();
|
||||
static bool sendAccept(USocket* socket);
|
||||
static int handleDataFraming(USocket* socket);
|
||||
static bool sendData(int type, const unsigned char* buffer, uint32_t buffer_size);
|
||||
static bool sendData(USocket* socket, int type, const char* data, uint32_t len);
|
||||
|
||||
static bool sendClose()
|
||||
static bool sendData(USocket* socket, int type, const UString& data) { return sendData(socket, type, U_STRING_TO_PARAM(data)); }
|
||||
|
||||
static bool sendClose(USocket* socket)
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "UWebSocket::sendClose()")
|
||||
U_TRACE(0, "UWebSocket::sendClose(%p)", socket)
|
||||
|
||||
// Send server-side closing handshake
|
||||
|
||||
|
@ -76,12 +85,14 @@ public:
|
|||
unsigned char status_code_buffer[2] = { (unsigned char)((status_code >> 8) & 0xFF),
|
||||
(unsigned char)( status_code & 0xFF) };
|
||||
|
||||
if (sendData(MESSAGE_TYPE_CLOSE, status_code_buffer, sizeof(status_code_buffer))) U_RETURN(true);
|
||||
if (sendControlFrame(socket, U_WS_OPCODE_CLOSE, status_code_buffer, sizeof(status_code_buffer))) U_RETURN(true);
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool sendControlFrame(USocket* socket, int opcode, const unsigned char* payload, uint32_t payload_length);
|
||||
|
||||
U_DISALLOW_COPY_AND_ASSIGN(UWebSocket)
|
||||
};
|
||||
|
||||
|
|
1905
nativejson-benchmark/travis-ci.log
Normal file
1905
nativejson-benchmark/travis-ci.log
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -174,7 +174,7 @@ endif
|
|||
|
||||
if SSL
|
||||
SRC_C += base/ssl/cdes3.c base/ssl/dgst.c
|
||||
SRC_CPP += ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp \
|
||||
SRC_CPP += ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp net/client/uwebsocket.cpp \
|
||||
ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp ssl/net/ssl_session.cpp utility/des3.cpp
|
||||
if SSL_TS
|
||||
SRC_CPP += ssl/timestamp.cpp
|
||||
|
|
|
@ -115,7 +115,7 @@ target_triplet = @target@
|
|||
@USE_PARSER_TRUE@am__append_33 = flex/flexer.cpp flex/bison.cpp
|
||||
@PCRE_TRUE@am__append_34 = pcre/pcre.cpp
|
||||
@SSL_TRUE@am__append_35 = base/ssl/cdes3.c base/ssl/dgst.c
|
||||
@SSL_TRUE@am__append_36 = ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp \
|
||||
@SSL_TRUE@am__append_36 = ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp net/client/uwebsocket.cpp \
|
||||
@SSL_TRUE@ ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp ssl/net/ssl_session.cpp utility/des3.cpp
|
||||
|
||||
@SSL_TRUE@@SSL_TS_TRUE@am__append_37 = ssl/timestamp.cpp
|
||||
|
@ -267,10 +267,11 @@ am__lib@ULIB@_la_SOURCES_DIST = base/base.c base/base_error.c \
|
|||
debug/objectDB.cpp internal/memory_pool.cpp zip/zip.cpp \
|
||||
flex/flexer.cpp flex/bison.cpp pcre/pcre.cpp \
|
||||
ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp \
|
||||
net/client/twilio.cpp ssl/mime/mime_pkcs7.cpp \
|
||||
ssl/net/sslsocket.cpp ssl/net/ssl_session.cpp utility/des3.cpp \
|
||||
ssl/timestamp.cpp ssh/net/sshsocket.cpp ldap/ldap.cpp \
|
||||
curl/curl.cpp xml/expat/attribute.cpp xml/expat/element.cpp \
|
||||
net/client/twilio.cpp net/client/uwebsocket.cpp \
|
||||
ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp \
|
||||
ssl/net/ssl_session.cpp utility/des3.cpp ssl/timestamp.cpp \
|
||||
ssh/net/sshsocket.cpp ldap/ldap.cpp curl/curl.cpp \
|
||||
xml/expat/attribute.cpp xml/expat/element.cpp \
|
||||
xml/expat/xml_parser.cpp xml/expat/xml2txt.cpp \
|
||||
xml/soap/soap_fault.cpp xml/soap/soap_gen_method.cpp \
|
||||
xml/soap/soap_parser.cpp xml/soap/soap_encoder.cpp \
|
||||
|
@ -347,8 +348,9 @@ am__objects_26 = base/base.lo base/base_error.lo base/hash.lo \
|
|||
@PCRE_TRUE@am__objects_37 = pcre/pcre.lo
|
||||
@SSL_TRUE@am__objects_38 = ssl/certificate.lo ssl/pkcs7.lo ssl/crl.lo \
|
||||
@SSL_TRUE@ ssl/pkcs10.lo net/client/twilio.lo \
|
||||
@SSL_TRUE@ ssl/mime/mime_pkcs7.lo ssl/net/sslsocket.lo \
|
||||
@SSL_TRUE@ ssl/net/ssl_session.lo utility/des3.lo
|
||||
@SSL_TRUE@ net/client/uwebsocket.lo ssl/mime/mime_pkcs7.lo \
|
||||
@SSL_TRUE@ ssl/net/sslsocket.lo ssl/net/ssl_session.lo \
|
||||
@SSL_TRUE@ utility/des3.lo
|
||||
@SSL_TRUE@@SSL_TS_TRUE@am__objects_39 = ssl/timestamp.lo
|
||||
@SSH_TRUE@am__objects_40 = ssh/net/sshsocket.lo
|
||||
@LDAP_TRUE@am__objects_41 = ldap/ldap.lo
|
||||
|
@ -1256,6 +1258,8 @@ ssl/crl.lo: ssl/$(am__dirstamp) ssl/$(DEPDIR)/$(am__dirstamp)
|
|||
ssl/pkcs10.lo: ssl/$(am__dirstamp) ssl/$(DEPDIR)/$(am__dirstamp)
|
||||
net/client/twilio.lo: net/client/$(am__dirstamp) \
|
||||
net/client/$(DEPDIR)/$(am__dirstamp)
|
||||
net/client/uwebsocket.lo: net/client/$(am__dirstamp) \
|
||||
net/client/$(DEPDIR)/$(am__dirstamp)
|
||||
ssl/mime/$(am__dirstamp):
|
||||
@$(MKDIR_P) ssl/mime
|
||||
@: > ssl/mime/$(am__dirstamp)
|
||||
|
@ -1608,6 +1612,7 @@ distclean-compile:
|
|||
@AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/redis.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/smtp.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/twilio.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/uwebsocket.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@net/rpc/$(DEPDIR)/rpc.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@net/rpc/$(DEPDIR)/rpc_client.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@net/rpc/$(DEPDIR)/rpc_encoder.Plo@am__quote@
|
||||
|
|
|
@ -119,6 +119,7 @@
|
|||
# include "ssl/crl.cpp"
|
||||
# include "ssl/pkcs10.cpp"
|
||||
# include "net/client/twilio.cpp"
|
||||
# include "net/client/uwebsocket.cpp"
|
||||
# include "ssl/mime/mime_pkcs7.cpp"
|
||||
# include "ssl/net/sslsocket.cpp"
|
||||
# include "ssl/net/ssl_session.cpp"
|
||||
|
|
|
@ -104,9 +104,7 @@ bool UFileConfig::processData(bool bload)
|
|||
|
||||
(void) cmd.execute(&data, &output, -1, fd_stderr);
|
||||
|
||||
# ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(cmd.getCommand(), true);
|
||||
# endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(cmd, true);
|
||||
|
||||
# ifdef HAVE_MCPP
|
||||
if (data.empty())
|
||||
|
@ -117,9 +115,7 @@ bool UFileConfig::processData(bool bload)
|
|||
|
||||
(void) _cmd.execute(&data, &output, -1, fd_stderr);
|
||||
|
||||
# ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(_cmd.getCommand(), true);
|
||||
# endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(_cmd, true);
|
||||
}
|
||||
# endif
|
||||
|
||||
|
|
|
@ -378,7 +378,7 @@ bool UClient_Base::setUrl(const char* str, uint32_t len)
|
|||
|
||||
url.set(str, len);
|
||||
|
||||
if (socket->isSSL()) socket->setSSLActive(url.isHTTPS());
|
||||
if (socket->isSSL()) socket->setSSLActive(url.isHTTPS() | url.isWSS());
|
||||
|
||||
uri = url.getPathAndQuery();
|
||||
|
||||
|
|
|
@ -882,7 +882,7 @@ bool UHttpClient_Base::sendRequestEngine()
|
|||
responseHeader->clear();
|
||||
|
||||
result = (UClient_Base::sendRequestAndReadResponse() &&
|
||||
responseHeader->readHeader(UClient_Base::socket, UClient_Base::response) // read the HTTP response header
|
||||
UClient_Base::processHeader(responseHeader)
|
||||
? checkResponse(redirectCount, _uri)
|
||||
: -1);
|
||||
|
||||
|
|
77
src/ulib/net/client/uwebsocket.cpp
Normal file
77
src/ulib/net/client/uwebsocket.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
// ============================================================================
|
||||
//
|
||||
// = LIBRARY
|
||||
// ULib - c++ library
|
||||
//
|
||||
// = FILENAME
|
||||
// uwebsocket.cpp
|
||||
//
|
||||
// = AUTHOR
|
||||
// Stefano Casazza
|
||||
//
|
||||
// ============================================================================
|
||||
|
||||
#include <ulib/net/client/websocket.h>
|
||||
|
||||
bool UWebSocketClient::connectServer(const UString& url)
|
||||
{
|
||||
U_TRACE(0, "UWebSocketClient::connectServer(%V)", url.rep)
|
||||
|
||||
U_INTERNAL_ASSERT_POINTER(client)
|
||||
|
||||
if (client->UClient_Base::connectServer(url))
|
||||
{
|
||||
UMimeHeader responseHeader;
|
||||
UString buffer(U_CAPACITY);
|
||||
|
||||
buffer.snprintf(U_CONSTANT_TO_PARAM(
|
||||
"GET %v HTTP/1.1\r\n"
|
||||
"Host: %v:%u\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
"\r\n"),
|
||||
client->UClient_Base::uri.rep, client->UClient_Base::server.rep, client->UClient_Base::port);
|
||||
|
||||
client->UClient_Base::prepareRequest(buffer);
|
||||
|
||||
if (client->UClient_Base::sendRequestAndReadResponse() &&
|
||||
(responseHeader.setIgnoreCase(true), client->UClient_Base::processHeader(&responseHeader)))
|
||||
{
|
||||
/**
|
||||
* HTTP/1.1 101 Switching Protocols\r\n
|
||||
* Upgrade: websocket\r\n
|
||||
* Connection: Upgrade\r\n
|
||||
* Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n
|
||||
*/
|
||||
|
||||
if (U_http_info.nResponseCode != 101) U_RETURN(false); // invalid HTTP status response code
|
||||
|
||||
if (responseHeader.getHeader(U_CONSTANT_TO_PARAM("Upgrade")).equalnocase(U_CONSTANT_TO_PARAM("websocket")) == false) U_RETURN(false); // invalid HTTP upgrade header
|
||||
if (responseHeader.getHeader(U_CONSTANT_TO_PARAM("Connection")).equalnocase(U_CONSTANT_TO_PARAM("Upgrade")) == false) U_RETURN(false); // invalid HTTP connection header
|
||||
|
||||
if (responseHeader.getHeader(U_CONSTANT_TO_PARAM("Sec-WebSocket-Accept")).equal(U_CONSTANT_TO_PARAM("s3pPLMBiTxaQ9kYGzzhZRbK+xOo="))) U_RETURN(true);
|
||||
}
|
||||
}
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
|
||||
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
||||
const char* UWebSocketClient::dump(bool _reset) const
|
||||
{
|
||||
*UObjectIO::os << "client (UClient<USSLSocket> " << (void*)client << ')';
|
||||
|
||||
if (_reset)
|
||||
{
|
||||
UObjectIO::output();
|
||||
|
||||
return UObjectIO::buffer_output;
|
||||
}
|
||||
|
||||
return U_NULLPTR;
|
||||
}
|
||||
#endif
|
|
@ -923,7 +923,9 @@ void UClientImage_Base::manageReadBufferResize(uint32_t n)
|
|||
if (U_http_info.user_agent_len) U_http_info.user_agent += diff;
|
||||
if (U_http_accept_language_len) U_http_info.accept_language += diff;
|
||||
|
||||
# if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL)
|
||||
if (U_http_websocket_len) UWebSocket::upgrade_settings += diff;
|
||||
# endif
|
||||
|
||||
U_INTERNAL_DUMP("host = %.*S", U_HTTP_HOST_TO_TRACE)
|
||||
U_INTERNAL_DUMP("vhost = %.*S", U_HTTP_VHOST_TO_TRACE)
|
||||
|
|
|
@ -657,9 +657,7 @@ loop:
|
|||
|
||||
ok = fw->execute(U_NULLPTR, &output, -1, fd_stderr);
|
||||
|
||||
#ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(fw->getCommand(), false);
|
||||
#endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(*fw, false);
|
||||
|
||||
if (ok == false)
|
||||
{
|
||||
|
@ -771,9 +769,7 @@ bool UNoCatPlugIn::checkFirewall()
|
|||
|
||||
(void) _fw.executeAndWait(U_NULLPTR, -1, fd_stderr);
|
||||
|
||||
# ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(_fw.getCommand(), false);
|
||||
# endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(_fw, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1057,9 +1053,7 @@ UString UNoCatPlugIn::getSignedData(const char* ptr, uint32_t len)
|
|||
|
||||
(void) pgp.execute(&input, &output, -1, fd_stderr);
|
||||
|
||||
# ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(pgp.getCommand(), false);
|
||||
# endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(pgp, false);
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -2337,9 +2331,7 @@ int UNoCatPlugIn::handlerFork()
|
|||
|
||||
(void) fw->executeAndWait(U_NULLPTR, -1, fd_stderr);
|
||||
|
||||
#ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(fw->getCommand(), false);
|
||||
#endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(*fw, false);
|
||||
|
||||
fw->delArgument();
|
||||
fw->setLastArgument("openlist");
|
||||
|
|
|
@ -360,9 +360,7 @@ void UNoDogPlugIn::executeCommand(const char* type, uint32_t len)
|
|||
|
||||
(void) cmd.executeAndWait(U_NULLPTR, -1, fd_stderr);
|
||||
|
||||
#ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(cmd.getCommand(), false);
|
||||
#endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(cmd, false);
|
||||
}
|
||||
|
||||
U_NO_EXPORT void UNoDogPlugIn::setMAC()
|
||||
|
@ -989,9 +987,7 @@ end:
|
|||
|
||||
(void) fw->executeAndWait(U_NULLPTR, -1, fd_stderr);
|
||||
|
||||
#ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(fw->getCommand(), false);
|
||||
#endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(*fw, false);
|
||||
|
||||
fw->delArgument();
|
||||
fw->setLastArgument("openlist");
|
||||
|
@ -1277,7 +1273,7 @@ next1: eraseTimer();
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (U_HTTP_URI_STREQ("/nodog_peer_delay.sh"))
|
||||
if (U_HTTP_URI_MEMEQ("/nodog_peer_delay.sh"))
|
||||
{
|
||||
if (U_peer_delay_disable == false)
|
||||
{
|
||||
|
|
|
@ -146,6 +146,7 @@ int UProxyPlugIn::handlerRequest()
|
|||
client_http->UClient_Base::close();
|
||||
}
|
||||
|
||||
# if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL)
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// A WebSocket is a long-lived connection, lasting hours or days. If each WebSocket proxy holds the original thread,
|
||||
// won't that consume all of the workers very quickly? It looks as if my server, with 16 workers, will be unable to
|
||||
|
@ -158,9 +159,9 @@ int UProxyPlugIn::handlerRequest()
|
|||
{
|
||||
UWebSocket::checkForInitialData(); // check if we have read more data than necessary...
|
||||
|
||||
while (UWebSocket::handleDataFraming(UServer_Base::csocket) == STATUS_CODE_OK &&
|
||||
while (UWebSocket::handleDataFraming(UServer_Base::csocket) == U_WS_STATUS_CODE_OK &&
|
||||
(client_http->UClient_Base::prepareRequest(*UClientImage_Base::wbuffer), client_http->UClient_Base::sendRequestAndReadResponse()) &&
|
||||
UWebSocket::sendData(UWebSocket::message_type, (const unsigned char*)U_STRING_TO_PARAM(client_http->UClient_Base::response)))
|
||||
UWebSocket::sendData(UServer_Base::csocket, UWebSocket::message_type, client_http->UClient_Base::response))
|
||||
{
|
||||
client_http->UClient_Base::clearData();
|
||||
|
||||
|
@ -169,6 +170,7 @@ int UProxyPlugIn::handlerRequest()
|
|||
|
||||
U_RETURN(U_PLUGIN_HANDLER_ERROR);
|
||||
}
|
||||
# endif
|
||||
|
||||
client_http->setFollowRedirects(UHTTP::service->isFollowRedirects(), true);
|
||||
if (UHTTP::service->isAuthorization()) client_http->setRequestPasswordAuthentication(UHTTP::service->getUser(), UHTTP::service->getPassword());
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
U_CREAT_FUNC(server_plugin_socket, UWebSocketPlugIn)
|
||||
|
||||
int UWebSocketPlugIn::fd_stderr;
|
||||
vPFi UWebSocketPlugIn::on_message;
|
||||
UString* UWebSocketPlugIn::penvironment;
|
||||
UCommand* UWebSocketPlugIn::command;
|
||||
|
||||
UWebSocketPlugIn::UWebSocketPlugIn()
|
||||
|
@ -33,8 +35,17 @@ UWebSocketPlugIn::~UWebSocketPlugIn()
|
|||
{
|
||||
U_TRACE_DTOR(0, UWebSocketPlugIn)
|
||||
|
||||
if (command) U_DELETE(command)
|
||||
if (UWebSocket::rbuffer) U_DELETE(UWebSocket::rbuffer)
|
||||
if (command)
|
||||
{
|
||||
U_DELETE(command)
|
||||
U_DELETE(penvironment)
|
||||
}
|
||||
|
||||
if (UWebSocket::rbuffer)
|
||||
{
|
||||
U_DELETE(UWebSocket::rbuffer)
|
||||
U_DELETE(UWebSocket::message)
|
||||
}
|
||||
}
|
||||
|
||||
RETSIGTYPE UWebSocketPlugIn::handlerForSigTERM(int signo)
|
||||
|
@ -50,10 +61,11 @@ int UWebSocketPlugIn::handlerConfig(UFileConfig& cfg)
|
|||
{
|
||||
U_TRACE(0, "UWebSocketPlugIn::handlerConfig(%p)", &cfg)
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// Perform registration of web socket method
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// COMMAND command (alternative to USP websocket) to execute
|
||||
// ENVIRONMENT environment for command (alternative to USP websocket) to execute
|
||||
// COMMAND command (alternative to USP modsocket) to execute
|
||||
// ENVIRONMENT environment for command (alternative to USP modsocket) to execute
|
||||
//
|
||||
// MAX_MESSAGE_SIZE Maximum size (in bytes) of a message to accept; default is approximately 4GB
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
@ -62,8 +74,12 @@ int UWebSocketPlugIn::handlerConfig(UFileConfig& cfg)
|
|||
{
|
||||
command = UServer_Base::loadConfigCommand();
|
||||
|
||||
U_NEW_STRING(penvironment, UString(U_CAPACITY));
|
||||
|
||||
UWebSocket::max_message_size = cfg.readLong(U_CONSTANT_TO_PARAM("MAX_MESSAGE_SIZE"), U_STRING_MAX_SIZE);
|
||||
|
||||
fd_stderr = UServices::getDevNull("/tmp/UWebSocketPlugIn.err");
|
||||
|
||||
U_RETURN(U_PLUGIN_HANDLER_PROCESSED);
|
||||
}
|
||||
|
||||
|
@ -75,21 +91,21 @@ int UWebSocketPlugIn::handlerRun()
|
|||
U_TRACE_NO_PARAM(0, "UWebSocketPlugIn::handlerRun()")
|
||||
|
||||
U_INTERNAL_ASSERT_EQUALS(UWebSocket::rbuffer, U_NULLPTR)
|
||||
U_INTERNAL_ASSERT_EQUALS(UWebSocket::message, U_NULLPTR)
|
||||
|
||||
U_NEW_STRING(UWebSocket::rbuffer, UString(U_CAPACITY));
|
||||
U_NEW_STRING(UWebSocket::message, UString(U_CAPACITY));
|
||||
|
||||
if (UHTTP::getUSP(U_CONSTANT_TO_PARAM("modsocket")))
|
||||
if (command == U_NULLPTR)
|
||||
{
|
||||
if (UHTTP::getUSP(U_CONSTANT_TO_PARAM("modsocket")) == false) U_RETURN(U_PLUGIN_HANDLER_ERROR);
|
||||
|
||||
U_INTERNAL_DUMP("modsocket->runDynamicPage = %p", UHTTP::usp->runDynamicPage)
|
||||
|
||||
U_INTERNAL_ASSERT_POINTER(UHTTP::usp->runDynamicPage)
|
||||
|
||||
on_message = UHTTP::usp->runDynamicPage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (command == U_NULLPTR) U_RETURN(U_PLUGIN_HANDLER_ERROR);
|
||||
}
|
||||
|
||||
U_RETURN(U_PLUGIN_HANDLER_OK);
|
||||
}
|
||||
|
@ -102,45 +118,40 @@ int UWebSocketPlugIn::handlerRequest()
|
|||
|
||||
if (U_http_websocket_len)
|
||||
{
|
||||
int fdmax = 0;
|
||||
int fdmax = 0; // NB: to avoid 'warning: fdmax may be used uninitialized in this function'...
|
||||
fd_set fd_set_read, read_set;
|
||||
bool bcommand = (command && on_message == U_NULLPTR);
|
||||
|
||||
if (bcommand)
|
||||
{
|
||||
// Set environment for the command application server
|
||||
|
||||
static int fd_stderr;
|
||||
|
||||
if (fd_stderr == 0) fd_stderr = UServices::getDevNull("/tmp/UWebSocketPlugIn.err");
|
||||
|
||||
UString environment(U_CAPACITY);
|
||||
|
||||
(void) environment.append(command->getStringEnvironment());
|
||||
|
||||
if (UHTTP::getCGIEnvironment(environment, U_GENERIC) == false) U_RETURN(U_PLUGIN_HANDLER_ERROR);
|
||||
|
||||
command->setEnvironment(&environment);
|
||||
|
||||
if (command->execute((UString*)-1, (UString*)-1, -1, fd_stderr))
|
||||
{
|
||||
# ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(command->getCommand(), true);
|
||||
# endif
|
||||
|
||||
UInterrupt::setHandlerForSignal(SIGTERM, (sighandler_t)UWebSocketPlugIn::handlerForSigTERM); // sync signal
|
||||
}
|
||||
|
||||
FD_ZERO(&fd_set_read);
|
||||
FD_SET(UProcess::filedes[2], &fd_set_read);
|
||||
FD_SET(UServer_Base::csocket->iSockDesc, &fd_set_read);
|
||||
|
||||
fdmax = U_max(UServer_Base::csocket->iSockDesc, UProcess::filedes[2]) + 1;
|
||||
}
|
||||
|
||||
UWebSocket::checkForInitialData(); // check if we have read more data than necessary...
|
||||
|
||||
if (bcommand == false) goto handle_data;
|
||||
if (command == U_NULLPTR)
|
||||
{
|
||||
on_message(U_DPAGE_OPEN);
|
||||
|
||||
goto data;
|
||||
}
|
||||
|
||||
// Set environment for the command application server
|
||||
|
||||
penvironment->setBuffer(U_CAPACITY);
|
||||
|
||||
(void) penvironment->append(command->getStringEnvironment());
|
||||
|
||||
if (UHTTP::getCGIEnvironment(*penvironment, U_GENERIC) == false) U_RETURN(U_PLUGIN_HANDLER_ERROR);
|
||||
|
||||
command->setEnvironment(penvironment);
|
||||
|
||||
if (command->execute((UString*)-1, (UString*)-1, -1, fd_stderr))
|
||||
{
|
||||
U_SRV_LOG_CMD_MSG_ERR(*command, true);
|
||||
|
||||
UInterrupt::setHandlerForSignal(SIGTERM, (sighandler_t)UWebSocketPlugIn::handlerForSigTERM); // sync signal
|
||||
}
|
||||
|
||||
FD_ZERO(&fd_set_read);
|
||||
FD_SET(UProcess::filedes[2], &fd_set_read);
|
||||
FD_SET(UServer_Base::csocket->iSockDesc, &fd_set_read);
|
||||
|
||||
fdmax = U_max(UServer_Base::csocket->iSockDesc, UProcess::filedes[2]) + 1;
|
||||
|
||||
loop: read_set = fd_set_read;
|
||||
|
||||
|
@ -151,7 +162,7 @@ loop: read_set = fd_set_read;
|
|||
UWebSocket::rbuffer->setEmpty();
|
||||
|
||||
if (UServices::read(UProcess::filedes[2], *UWebSocket::rbuffer) &&
|
||||
UWebSocket::sendData(UWebSocket::message_type, (const unsigned char*)U_STRING_TO_PARAM(*UWebSocket::rbuffer)))
|
||||
UWebSocket::sendData(UServer_Base::csocket, UWebSocket::message_type, *UWebSocket::rbuffer))
|
||||
{
|
||||
UWebSocket::rbuffer->setEmpty();
|
||||
|
||||
|
@ -160,16 +171,25 @@ loop: read_set = fd_set_read;
|
|||
}
|
||||
else if (FD_ISSET(UServer_Base::csocket->iSockDesc, &read_set))
|
||||
{
|
||||
handle_data:
|
||||
if (UWebSocket::handleDataFraming(UServer_Base::csocket) == STATUS_CODE_OK &&
|
||||
(bcommand == false ? (on_message(0), U_http_info.nResponseCode != HTTP_INTERNAL_ERROR)
|
||||
: UNotifier::write(UProcess::filedes[1], U_STRING_TO_PARAM(*UClientImage_Base::wbuffer))))
|
||||
data: if (UWebSocket::handleDataFraming(UServer_Base::csocket) == U_WS_STATUS_CODE_OK)
|
||||
{
|
||||
UWebSocket::rbuffer->setEmpty();
|
||||
if (command == U_NULLPTR)
|
||||
{
|
||||
on_message(0);
|
||||
|
||||
if (bcommand == false) goto handle_data;
|
||||
if (U_http_info.nResponseCode != HTTP_INTERNAL_ERROR)
|
||||
{
|
||||
UWebSocket::rbuffer->setEmpty();
|
||||
|
||||
goto loop;
|
||||
goto data;
|
||||
}
|
||||
}
|
||||
else if (UNotifier::write(UProcess::filedes[1], U_STRING_TO_PARAM(*UClientImage_Base::wbuffer)))
|
||||
{
|
||||
UWebSocket::rbuffer->setEmpty();
|
||||
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +197,7 @@ handle_data:
|
|||
// Send server-side closing handshake
|
||||
|
||||
if (UServer_Base::csocket->isOpen() &&
|
||||
UWebSocket::sendClose())
|
||||
UWebSocket::sendClose(UServer_Base::csocket))
|
||||
{
|
||||
UClientImage_Base::close();
|
||||
}
|
||||
|
@ -186,6 +206,8 @@ handle_data:
|
|||
UClientImage_Base::setRequestProcessed();
|
||||
}
|
||||
|
||||
if (command == U_NULLPTR) on_message(U_DPAGE_CLOSE);
|
||||
|
||||
U_RETURN(U_PLUGIN_HANDLER_PROCESSED);
|
||||
}
|
||||
|
||||
|
@ -197,8 +219,10 @@ handle_data:
|
|||
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
|
||||
const char* UWebSocketPlugIn::dump(bool reset) const
|
||||
{
|
||||
*UObjectIO::os << "on_message " << (void*)on_message << '\n'
|
||||
<< "command (UCommand " << (void*)command << ')';
|
||||
*UObjectIO::os << "fd_stderr " << fd_stderr << '\n'
|
||||
<< "on_message " << (void*)on_message << '\n'
|
||||
<< "command (UCommand " << (void*)command << ")\n"
|
||||
<< "penvironment (UString " << (void*)penvironment << ')';
|
||||
|
||||
if (reset)
|
||||
{
|
||||
|
|
|
@ -111,9 +111,7 @@ int UStreamPlugIn::handlerInit()
|
|||
|
||||
bool result = command->execute(U_NULLPTR, (UString*)-1, -1, fd_stderr);
|
||||
|
||||
#ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(command->getCommand(), true);
|
||||
#endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(*command, false);
|
||||
|
||||
if (result == false)
|
||||
{
|
||||
|
|
|
@ -100,9 +100,7 @@ int UTsaPlugIn::handlerRequest()
|
|||
UHTTP::setResponse(*UString::str_ctype_tsa, &body);
|
||||
}
|
||||
|
||||
# ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(command->getCommand(), true);
|
||||
# endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(*command, true);
|
||||
|
||||
U_RETURN(U_PLUGIN_HANDLER_PROCESSED);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,87 @@
|
|||
<!--#code
|
||||
if (UWebSocket::sendData(UWebSocket::message_type, (const unsigned char*)U_STRING_TO_PARAM(*UClientImage_Base::wbuffer)) == false) U_http_info.nResponseCode = HTTP_INTERNAL_ERROR;
|
||||
<!--#
|
||||
prototype for Victor Stewart
|
||||
-->
|
||||
<!--#declaration
|
||||
static UWebSocketClient* wsclient;
|
||||
static vPFi message_for_another_usp;
|
||||
|
||||
static void usp_init_modsocket()
|
||||
{
|
||||
U_TRACE_NO_PARAM(5, "::usp_init_modsocket()")
|
||||
|
||||
U_NEW(UWebSocketClient, wsclient, UWebSocketClient());
|
||||
}
|
||||
|
||||
static void usp_end_modsocket()
|
||||
{
|
||||
U_TRACE_NO_PARAM(5, "::usp_end_modsocket()")
|
||||
|
||||
#ifdef DEBUG
|
||||
U_DELETE(wsclient)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void usp_open_modsocket()
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "::usp_open_modsocket()")
|
||||
|
||||
U_DEBUG("usp_open_modsocket(): called");
|
||||
}
|
||||
|
||||
static void usp_close_modsocket()
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "::usp_close_modsocket()")
|
||||
|
||||
U_DEBUG("usp_close_modsocket(): called");
|
||||
}
|
||||
|
||||
static bool isMessageForAnotherUSP(const UString& msg)
|
||||
{
|
||||
U_TRACE(5, "::isMessageForAnotherUSP(%V)", msg.rep)
|
||||
|
||||
// TODO
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
static bool isMessageForAnotherWebSocket(const UString& msg)
|
||||
{
|
||||
U_TRACE(5, "::isMessageForAnotherWebSocket(%V)", msg.rep)
|
||||
|
||||
// TODO
|
||||
|
||||
U_RETURN(true);
|
||||
}
|
||||
-->
|
||||
|
||||
<!--#code
|
||||
U_DEBUG("modsocket(): message %V", UWebSocket::message->rep);
|
||||
|
||||
if (isMessageForAnotherUSP(*UWebSocket::message))
|
||||
{
|
||||
if (message_for_another_usp == U_NULLPTR)
|
||||
{
|
||||
(void) UHTTP::getUSP(U_CONSTANT_TO_PARAM("another_usp"));
|
||||
|
||||
U_INTERNAL_ASSERT_POINTER(UHTTP::usp->runDynamicPage)
|
||||
|
||||
message_for_another_usp = UHTTP::usp->runDynamicPage;
|
||||
}
|
||||
|
||||
message_for_another_usp(0);
|
||||
|
||||
// ...
|
||||
}
|
||||
else if (isMessageForAnotherWebSocket(*UWebSocket::message))
|
||||
{
|
||||
if (wsclient->connectServer(U_STRING_FROM_CONSTANT("ws://localhost:8888/websocket"))) (void) wsclient->sendMessage(*UWebSocket::message);
|
||||
|
||||
// ...
|
||||
}
|
||||
else
|
||||
{
|
||||
// echo
|
||||
|
||||
if (UWebSocket::sendData(UServer_Base::csocket, UWebSocket::message_type, *UWebSocket::message) == false) U_http_info.nResponseCode = HTTP_INTERNAL_ERROR;
|
||||
}
|
||||
-->
|
||||
|
|
|
@ -712,37 +712,56 @@ loop: distance = t.getDistance();
|
|||
|
||||
U_INTERNAL_DUMP("declaration = %V", declaration.rep)
|
||||
|
||||
bool binit, // usp_init (Server-wide hooks)...
|
||||
/**
|
||||
* Server-wide hooks
|
||||
*
|
||||
* enum DynamicPageType {
|
||||
* U_DPAGE_INIT = -1,
|
||||
* U_DPAGE_RESET = -2,
|
||||
* U_DPAGE_DESTROY = -3,
|
||||
* U_DPAGE_SIGHUP = -4,
|
||||
* U_DPAGE_FORK = -5,
|
||||
* U_DPAGE_OPEN = -6,
|
||||
* U_DPAGE_CLOSE = -7 };
|
||||
*/
|
||||
|
||||
bool binit, // usp_init
|
||||
breset, // usp_reset
|
||||
bend, // usp_end
|
||||
bsighup, // usp_sighup
|
||||
bfork; // usp_fork
|
||||
bfork, // usp_fork
|
||||
bopen, // usp_open
|
||||
bclose; // usp_close
|
||||
|
||||
char ptr1[100] = { '\0' };
|
||||
char ptr2[100] = { '\0' };
|
||||
char ptr3[100] = { '\0' };
|
||||
char ptr4[100] = { '\0' };
|
||||
char ptr5[100] = { '\0' };
|
||||
const char* ptr6 = "";
|
||||
const char* ptr7 = "";
|
||||
char ptr6[100] = { '\0' };
|
||||
char ptr7[100] = { '\0' };
|
||||
const char* ptr8 = "";
|
||||
|
||||
# ifndef U_CACHE_REQUEST_DISABLE
|
||||
if (usp.c_char(4) == '#' &&
|
||||
u__isspace(usp.c_char(5)) &&
|
||||
u_get_unalignedp32(usp.data()) == U_MULTICHAR_CONSTANT32('<','!','-','-')) // <!--# --> (comment)
|
||||
{
|
||||
ptr7 = "\n\tUClientImage_Base::setRequestNoCache();\n\t\n";
|
||||
ptr8 = "\n\tUClientImage_Base::setRequestNoCache();\n\t\n";
|
||||
}
|
||||
# endif
|
||||
|
||||
if (declaration)
|
||||
{
|
||||
binit = (U_STRING_FIND(declaration, 0, "static void usp_init_") != U_NOT_FOUND);
|
||||
breset = (U_STRING_FIND(declaration, 0, "static void usp_reset_") != U_NOT_FOUND);
|
||||
bend = (U_STRING_FIND(declaration, 0, "static void usp_end_") != U_NOT_FOUND);
|
||||
bsighup = (U_STRING_FIND(declaration, 0, "static void usp_sighup_") != U_NOT_FOUND);
|
||||
bfork = (U_STRING_FIND(declaration, 0, "static void usp_fork_") != U_NOT_FOUND);
|
||||
bopen = (U_STRING_FIND(declaration, 0, "static void usp_open_") != U_NOT_FOUND);
|
||||
bclose = (U_STRING_FIND(declaration, 0, "static void usp_close_") != U_NOT_FOUND);
|
||||
|
||||
if (bfork) (void) u__snprintf(ptr5, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_FORK) { usp_fork_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
if (bsighup) (void) u__snprintf(ptr4, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_SIGHUP) { usp_sighup_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
if (breset) (void) u__snprintf(ptr2, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_RESET) { usp_reset_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
|
||||
if (bend)
|
||||
{
|
||||
|
@ -752,16 +771,24 @@ loop: distance = t.getDistance();
|
|||
# endif
|
||||
(void) u__snprintf(ptr3, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_DESTROY) { usp_end_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
}
|
||||
|
||||
if (bsighup) (void) u__snprintf(ptr4, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_SIGHUP) { usp_sighup_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
if (bfork) (void) u__snprintf(ptr5, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_FORK) { usp_fork_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
if (bopen) (void) u__snprintf(ptr6, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_OPEN) { usp_open_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
if (bclose) (void) u__snprintf(ptr7, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_CLOSE) { usp_close_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
binit =
|
||||
breset =
|
||||
bend =
|
||||
bsighup =
|
||||
bfork = false;
|
||||
bfork =
|
||||
bopen =
|
||||
bclose = false;
|
||||
}
|
||||
|
||||
U_INTERNAL_DUMP("binit = %b bend = %b bsighup = %b bfork = %b", binit, bend, bsighup, bfork)
|
||||
U_INTERNAL_DUMP("binit = %b breset = %b bend = %b bsighup = %b bfork = %b bopen = %b bclose = %b", binit, breset, bend, bsighup, bfork, bopen, bclose)
|
||||
|
||||
if (binit == false &&
|
||||
(bsession || bstorage))
|
||||
|
@ -787,15 +814,6 @@ loop: distance = t.getDistance();
|
|||
|
||||
if (binit) (void) u__snprintf(ptr1, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_INIT) { usp_init_%.*s(); return; }\n"), basename_sz, basename_ptr);
|
||||
|
||||
if (binit == false ||
|
||||
bend == false ||
|
||||
bsighup == false ||
|
||||
bfork == false)
|
||||
{
|
||||
ptr6 = (bfork ? "\n\t\tif (param > U_DPAGE_FORK) return;\n"
|
||||
: "\n\t\tif (param >= U_DPAGE_FORK) return;\n");
|
||||
}
|
||||
|
||||
if (bvar)
|
||||
{
|
||||
(void) vars.append(U_CONSTANT_TO_PARAM("\n\tuint32_t usp_sz = 0;"
|
||||
|
@ -837,6 +855,8 @@ loop: distance = t.getDistance();
|
|||
"%s"
|
||||
"%s"
|
||||
"%s"
|
||||
"%s"
|
||||
"\t\treturn;\n"
|
||||
"\t\t}\n"
|
||||
"\t\n"
|
||||
"%v"
|
||||
|
@ -863,12 +883,13 @@ loop: distance = t.getDistance();
|
|||
ptr4,
|
||||
ptr5,
|
||||
ptr6,
|
||||
ptr7,
|
||||
vcode.rep,
|
||||
http_header.rep,
|
||||
output0.rep,
|
||||
output1.rep,
|
||||
output2.rep,
|
||||
ptr7);
|
||||
ptr8);
|
||||
|
||||
UString name(200U);
|
||||
|
||||
|
|
|
@ -3676,7 +3676,9 @@ U_NO_EXPORT void UServer_Base::manageCommand(const char* format, uint32_t fmt_si
|
|||
|
||||
UString output = UCommand::outputCommand(cmd, U_NULLPTR, -1, fd_stderr);
|
||||
|
||||
logCommandMsgError(cmd.data(), true);
|
||||
#ifdef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(cmd.data(), true);
|
||||
#endif
|
||||
|
||||
if (UCommand::exit_value) U_WARNING("command failed: EXIT_VALUE=%d OUTPUT=%V", UCommand::exit_value, output.rep);
|
||||
|
||||
|
|
|
@ -198,9 +198,7 @@ int UServices::askToLDAP(UString* pinput, UHashMap<UString>* ptable, const char*
|
|||
|
||||
bool result = cmd.execute(pinput, &output, -1, _fd_stderr);
|
||||
|
||||
#ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(cmd.getCommand(), false);
|
||||
#endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(cmd, false);
|
||||
|
||||
if (pinput == U_NULLPTR) ptable->clear();
|
||||
|
||||
|
|
|
@ -3101,6 +3101,7 @@ U_NO_EXPORT bool UHTTP::checkRequestForHeader()
|
|||
}
|
||||
# endif
|
||||
}
|
||||
# if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL)
|
||||
else if (pn[17] == ':') // "If-Modified-Since|Sec-WebSocket-Key:"
|
||||
{
|
||||
pn += 17;
|
||||
|
@ -3127,6 +3128,7 @@ U_NO_EXPORT bool UHTTP::checkRequestForHeader()
|
|||
goto next;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
# ifndef U_LOG_DISABLE
|
||||
else if (pn[22] == ':') // "X-Http-X-Forwarded-For:"
|
||||
{
|
||||
|
@ -4622,12 +4624,12 @@ from_cache:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef U_SERVER_CAPTIVE_PORTAL
|
||||
#if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL)
|
||||
U_INTERNAL_DUMP("U_http_websocket_len = %u", U_http_websocket_len)
|
||||
|
||||
if (U_http_websocket_len)
|
||||
{
|
||||
if (UWebSocket::sendAccept() == false)
|
||||
if (UWebSocket::sendAccept(UServer_Base::csocket) == false)
|
||||
{
|
||||
setBadRequest();
|
||||
|
||||
|
@ -4635,6 +4637,8 @@ from_cache:
|
|||
}
|
||||
|
||||
UClientImage_Base::setRequestNoCache();
|
||||
|
||||
if (UServer_Base::startParallelization()) U_RETURN(U_PLUGIN_HANDLER_OK); // parent
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -10630,9 +10634,7 @@ bool UHTTP::processCGIRequest(UCommand* cmd, UHTTP::ucgi* cgi)
|
|||
|
||||
if (cgi) (void) UFile::chdir(U_NULLPTR, true);
|
||||
|
||||
#ifndef U_LOG_DISABLE
|
||||
UServer_Base::logCommandMsgError(cmd->getCommand(), false);
|
||||
#endif
|
||||
U_SRV_LOG_CMD_MSG_ERR(*cmd, false);
|
||||
|
||||
cmd->reset(UClientImage_Base::environment);
|
||||
|
||||
|
|
|
@ -16,88 +16,40 @@
|
|||
#include <ulib/utility/websocket.h>
|
||||
#include <ulib/net/server/server.h>
|
||||
|
||||
#define OPCODE_CONTINUATION 0x0
|
||||
#define OPCODE_TEXT 0x1
|
||||
#define OPCODE_BINARY 0x2
|
||||
#define OPCODE_CLOSE 0x8
|
||||
#define OPCODE_PING 0x9
|
||||
#define OPCODE_PONG 0xA
|
||||
#define U_WS_DATA_FRAMING_MASK 0
|
||||
#define U_WS_DATA_FRAMING_START 1
|
||||
#define U_WS_DATA_FRAMING_PAYLOAD_LENGTH 2
|
||||
#define U_WS_DATA_FRAMING_PAYLOAD_LENGTH_EXT 3
|
||||
#define U_WS_DATA_FRAMING_EXTENSION_DATA 4
|
||||
#define U_WS_DATA_FRAMING_APPLICATION_DATA 5
|
||||
#define U_WS_DATA_FRAMING_CLOSE 6
|
||||
|
||||
#define DATA_FRAMING_MASK 0
|
||||
#define DATA_FRAMING_START 1
|
||||
#define DATA_FRAMING_PAYLOAD_LENGTH 2
|
||||
#define DATA_FRAMING_PAYLOAD_LENGTH_EXT 3
|
||||
#define DATA_FRAMING_EXTENSION_DATA 4
|
||||
#define DATA_FRAMING_APPLICATION_DATA 5
|
||||
#define DATA_FRAMING_CLOSE 6
|
||||
#define U_WS_FRAME_GET_FIN(BYTE) (((BYTE) >> 7) & 0x01)
|
||||
#define U_WS_FRAME_GET_RSV1(BYTE) (((BYTE) >> 6) & 0x01)
|
||||
#define U_WS_FRAME_GET_RSV2(BYTE) (((BYTE) >> 5) & 0x01)
|
||||
#define U_WS_FRAME_GET_RSV3(BYTE) (((BYTE) >> 4) & 0x01)
|
||||
#define U_WS_FRAME_GET_OPCODE(BYTE) ( (BYTE) & 0x0F)
|
||||
#define U_WS_FRAME_GET_MASK(BYTE) (((BYTE) >> 7) & 0x01)
|
||||
#define U_WS_FRAME_GET_PAYLOAD_LEN(BYTE) ( (BYTE) & 0x7F)
|
||||
|
||||
#define FRAME_GET_FIN(BYTE) (((BYTE) >> 7) & 0x01)
|
||||
#define FRAME_GET_RSV1(BYTE) (((BYTE) >> 6) & 0x01)
|
||||
#define FRAME_GET_RSV2(BYTE) (((BYTE) >> 5) & 0x01)
|
||||
#define FRAME_GET_RSV3(BYTE) (((BYTE) >> 4) & 0x01)
|
||||
#define FRAME_GET_OPCODE(BYTE) ( (BYTE) & 0x0F)
|
||||
#define FRAME_GET_MASK(BYTE) (((BYTE) >> 7) & 0x01)
|
||||
#define FRAME_GET_PAYLOAD_LEN(BYTE) ( (BYTE) & 0x7F)
|
||||
#define U_WS_FRAME_SET_FIN(BYTE) (((BYTE) & 0x01) << 7)
|
||||
#define U_WS_FRAME_SET_OPCODE(BYTE) ((BYTE) & 0x0F)
|
||||
#define U_WS_FRAME_SET_MASK(BYTE) (((BYTE) & 0x01) << 7)
|
||||
#define U_WS_FRAME_SET_LENGTH(X64, IDX) (unsigned char)(((uint64_t)(X64) >> ((IDX)*8)) & 0xFF)
|
||||
|
||||
#define FRAME_SET_FIN(BYTE) (((BYTE) & 0x01) << 7)
|
||||
#define FRAME_SET_OPCODE(BYTE) ((BYTE) & 0x0F)
|
||||
#define FRAME_SET_MASK(BYTE) (((BYTE) & 0x01) << 7)
|
||||
#define FRAME_SET_LENGTH(X64, IDX) (unsigned char)(((uint64_t)(X64) >> ((IDX)*8)) & 0xFF)
|
||||
|
||||
#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
#define WEBSOCKET_GUID_LEN 36
|
||||
#define U_WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
#define U_WS_GUID_LEN 36
|
||||
|
||||
int UWebSocket::status_code;
|
||||
int UWebSocket::message_type;
|
||||
UString* UWebSocket::rbuffer;
|
||||
UString* UWebSocket::message;
|
||||
uint32_t UWebSocket::max_message_size;
|
||||
const char* UWebSocket::upgrade_settings;
|
||||
|
||||
UWebSocket::WebSocketFrameData UWebSocket::control_frame = { U_NULLPTR, 0, 1, 8, 0 };
|
||||
UWebSocket::WebSocketFrameData UWebSocket::message_frame = { U_NULLPTR, 0, 1, 0, 0 };
|
||||
|
||||
bool UWebSocket::sendAccept()
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "UWebSocket::sendAccept()")
|
||||
|
||||
U_INTERNAL_ASSERT_MAJOR(U_http_websocket_len, 0)
|
||||
|
||||
// In order to establish a websocket connection, a client (a web browser) sends a HTTP GET request with a number of HTTP headers. Among those
|
||||
// headers there is the Sec-WebSocket-Key header, which contains a handshake key. According to the WebSocket protocol, the server should:
|
||||
//
|
||||
// 1) Concatenate the handshake key with the magic guid {258EAFA5-E914-47DA-95CA-C5AB0DC85B11}
|
||||
// 2) Take the SHA1 hash of the concatenation result
|
||||
// 3) Send the base64 equivalent of the hash in HTTP response to the client
|
||||
|
||||
unsigned char challenge[128];
|
||||
|
||||
U_MEMCPY(challenge, upgrade_settings, U_http_websocket_len);
|
||||
U_MEMCPY(challenge+U_http_websocket_len, WEBSOCKET_GUID, WEBSOCKET_GUID_LEN);
|
||||
|
||||
// SHA1(challenge)
|
||||
|
||||
UString accept(U_CAPACITY);
|
||||
|
||||
UServices::generateDigest(U_HASH_SHA1, 0, challenge, U_http_websocket_len + WEBSOCKET_GUID_LEN, accept, true);
|
||||
|
||||
UClientImage_Base::wbuffer->snprintf(U_CONSTANT_TO_PARAM("HTTP/1.1 101 Switching Protocols\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
"Sec-WebSocket-Accept: %v\r\n\r\n"), accept.rep);
|
||||
|
||||
if (USocketExt::write(UServer_Base::csocket, *UClientImage_Base::wbuffer, UServer_Base::timeoutMS))
|
||||
{
|
||||
status_code = STATUS_CODE_INTERNAL_ERROR;
|
||||
message_type = MESSAGE_TYPE_INVALID;
|
||||
|
||||
if (max_message_size == 0) max_message_size = U_STRING_MAX_SIZE;
|
||||
|
||||
U_RETURN(true);
|
||||
}
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
void UWebSocket::checkForInitialData()
|
||||
{
|
||||
U_TRACE_NO_PARAM(0, "UWebSocket::checkForInitialData()")
|
||||
|
@ -113,22 +65,62 @@ void UWebSocket::checkForInitialData()
|
|||
{
|
||||
// we have read more data than necessary...
|
||||
|
||||
const char* ptr = UClientImage_Base::rbuffer->c_pointer(UClientImage_Base::size_request);
|
||||
|
||||
(void) rbuffer->append(ptr, sz - UClientImage_Base::size_request);
|
||||
(void) rbuffer->append(UClientImage_Base::rbuffer->c_pointer(UClientImage_Base::size_request), sz - UClientImage_Base::size_request);
|
||||
|
||||
U_INTERNAL_DUMP("rbuffer(%u) = %V", rbuffer->size(), rbuffer->rep)
|
||||
}
|
||||
}
|
||||
|
||||
bool UWebSocket::sendAccept(USocket* socket)
|
||||
{
|
||||
U_TRACE(0, "UWebSocket::sendAccept(%p)", socket)
|
||||
|
||||
U_INTERNAL_ASSERT_MAJOR(U_http_websocket_len, 0)
|
||||
|
||||
// In order to establish a websocket connection, a client (a web browser) sends a HTTP GET request with a number of HTTP headers. Among those
|
||||
// headers there is the Sec-WebSocket-Key header, which contains a handshake key. According to the WebSocket protocol, the server should:
|
||||
//
|
||||
// 1) Concatenate the handshake key with the magic guid {258EAFA5-E914-47DA-95CA-C5AB0DC85B11}
|
||||
// 2) Take the SHA1 hash of the concatenation result
|
||||
// 3) Send the base64 equivalent of the hash in HTTP response to the client
|
||||
|
||||
unsigned char challenge[128];
|
||||
|
||||
U_MEMCPY(challenge, upgrade_settings, U_http_websocket_len);
|
||||
U_MEMCPY(challenge+U_http_websocket_len, U_WS_GUID, U_WS_GUID_LEN);
|
||||
|
||||
// SHA1(challenge)
|
||||
|
||||
UString accept(U_CAPACITY), buffer(U_CAPACITY);
|
||||
|
||||
UServices::generateDigest(U_HASH_SHA1, 0, challenge, U_http_websocket_len + U_WS_GUID_LEN, accept, true);
|
||||
|
||||
buffer.snprintf(U_CONSTANT_TO_PARAM("HTTP/1.1 101 Switching Protocols\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
"Sec-WebSocket-Accept: %v\r\n\r\n"), accept.rep);
|
||||
|
||||
if (USocketExt::write(socket, buffer, UServer_Base::timeoutMS))
|
||||
{
|
||||
status_code = U_WS_STATUS_CODE_INTERNAL_ERROR;
|
||||
message_type = U_WS_MESSAGE_TYPE_INVALID;
|
||||
|
||||
if (max_message_size == 0) max_message_size = U_STRING_MAX_SIZE;
|
||||
|
||||
U_RETURN(true);
|
||||
}
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* So, WebSockets presents a sequence of infinitely long byte streams
|
||||
* with a termination indicator (the FIN bit in the frame header) and
|
||||
* not a message based interface as you might initially believe. Given
|
||||
* that a general purpose protocol handler can only work in terms of
|
||||
* partial frames, we effectively have a stream based protocol with
|
||||
* lots of added complexity to provide the illusion of a message based
|
||||
* @see: http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol
|
||||
*
|
||||
* So, WebSockets presents a sequence of infinitely long byte streams with a termination indicator (the FIN bit in the frame header) and
|
||||
* not a message based interface as you might initially believe. Given that a general purpose protocol handler can only work in terms of
|
||||
* partial frames, we effectively have a stream based protocol with lots of added complexity to provide the illusion of a message based
|
||||
* protocol that can actually only ever be dealt with as a stream of bytes
|
||||
*
|
||||
* +-+-+-+-+-------+-+-------------+-------------------------------+
|
||||
* 0 1 2 3 |
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
|
||||
|
@ -159,13 +151,13 @@ int UWebSocket::handleDataFraming(USocket* socket)
|
|||
WebSocketFrameData* frame = &UWebSocket::control_frame;
|
||||
unsigned char fin = 0, opcode = 0xFF, mask[4] = { 0, 0, 0, 0 };
|
||||
int32_t extension_bytes_remaining = 0, payload_length = 0, mask_offset = 0;
|
||||
int framing_state = DATA_FRAMING_START, payload_length_bytes_remaining = 0, mask_index = 0, masking = 0;
|
||||
int framing_state = U_WS_DATA_FRAMING_START, payload_length_bytes_remaining = 0, mask_index = 0, masking = 0;
|
||||
|
||||
loop:
|
||||
if (rbuffer->empty() &&
|
||||
USocketExt::read(socket, *rbuffer, U_SINGLE_READ, UServer_Base::timeoutMS) == false)
|
||||
{
|
||||
status_code = STATUS_CODE_INTERNAL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_INTERNAL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
@ -179,35 +171,35 @@ loop:
|
|||
|
||||
switch (framing_state)
|
||||
{
|
||||
case DATA_FRAMING_START: // 1
|
||||
case U_WS_DATA_FRAMING_START: // 1
|
||||
{
|
||||
// Since we don't currently support any extensions, the reserve bits must be 0
|
||||
|
||||
if ((FRAME_GET_RSV1(block[block_offset]) != 0) ||
|
||||
(FRAME_GET_RSV2(block[block_offset]) != 0) ||
|
||||
(FRAME_GET_RSV3(block[block_offset]) != 0))
|
||||
if ((U_WS_FRAME_GET_RSV1(block[block_offset]) != 0) ||
|
||||
(U_WS_FRAME_GET_RSV2(block[block_offset]) != 0) ||
|
||||
(U_WS_FRAME_GET_RSV3(block[block_offset]) != 0))
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_PROTOCOL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
||||
fin = FRAME_GET_FIN( block[block_offset]);
|
||||
opcode = FRAME_GET_OPCODE(block[block_offset++]);
|
||||
fin = U_WS_FRAME_GET_FIN( block[block_offset]);
|
||||
opcode = U_WS_FRAME_GET_OPCODE(block[block_offset++]);
|
||||
|
||||
U_INTERNAL_DUMP("fin = %d opcode = %X", fin, opcode)
|
||||
|
||||
framing_state = DATA_FRAMING_PAYLOAD_LENGTH; // 2
|
||||
framing_state = U_WS_DATA_FRAMING_PAYLOAD_LENGTH; // 2
|
||||
|
||||
if (opcode >= 0x8) // Control frame
|
||||
{
|
||||
if (fin == 0)
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_PROTOCOL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
@ -224,9 +216,9 @@ loop:
|
|||
{
|
||||
if (frame->fin == 0)
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_PROTOCOL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
@ -237,9 +229,9 @@ loop:
|
|||
else if (frame->fin ||
|
||||
((opcode = frame->opcode) == 0))
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_PROTOCOL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
@ -257,10 +249,10 @@ loop:
|
|||
|
||||
/* FALLTHRU */
|
||||
|
||||
case DATA_FRAMING_PAYLOAD_LENGTH: // 2
|
||||
case U_WS_DATA_FRAMING_PAYLOAD_LENGTH: // 2
|
||||
{
|
||||
payload_length = FRAME_GET_PAYLOAD_LEN(block[block_offset]);
|
||||
masking = FRAME_GET_MASK( block[block_offset++]);
|
||||
payload_length = U_WS_FRAME_GET_PAYLOAD_LEN(block[block_offset]);
|
||||
masking = U_WS_FRAME_GET_MASK( block[block_offset++]);
|
||||
|
||||
U_INTERNAL_DUMP("masking = %d payload_length = %d", masking, payload_length)
|
||||
|
||||
|
@ -283,14 +275,14 @@ loop:
|
|||
((opcode >= 0x8) && // Control opcodes cannot have a payload larger than 125 bytes
|
||||
(payload_length_bytes_remaining != 0)))
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_PROTOCOL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
||||
framing_state = DATA_FRAMING_PAYLOAD_LENGTH_EXT; // 3
|
||||
framing_state = U_WS_DATA_FRAMING_PAYLOAD_LENGTH_EXT; // 3
|
||||
|
||||
if (block_offset >= block_size) goto next;
|
||||
|
||||
|
@ -299,7 +291,7 @@ loop:
|
|||
|
||||
/* FALLTHRU */
|
||||
|
||||
case DATA_FRAMING_PAYLOAD_LENGTH_EXT: // 3
|
||||
case U_WS_DATA_FRAMING_PAYLOAD_LENGTH_EXT: // 3
|
||||
{
|
||||
while ((payload_length_bytes_remaining > 0) &&
|
||||
(block_offset < block_size))
|
||||
|
@ -317,21 +309,21 @@ loop:
|
|||
{
|
||||
U_SRV_LOG_WITH_ADDR("Got frame with payload greater than maximum frame buffer size: (%u > %u) from", payload_length, max_message_size);
|
||||
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_MESSAGE_TOO_LARGE; // Invalid payload length
|
||||
status_code = U_WS_STATUS_CODE_MESSAGE_TOO_LARGE; // Invalid payload length
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
||||
if (masking == 0)
|
||||
{
|
||||
framing_state = DATA_FRAMING_EXTENSION_DATA; // 4
|
||||
framing_state = U_WS_DATA_FRAMING_EXTENSION_DATA; // 4
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
framing_state = DATA_FRAMING_MASK; // 0
|
||||
framing_state = U_WS_DATA_FRAMING_MASK; // 0
|
||||
}
|
||||
|
||||
if (block_offset >= block_size) goto next;
|
||||
|
@ -341,7 +333,7 @@ loop:
|
|||
|
||||
/* FALLTHRU */
|
||||
|
||||
case DATA_FRAMING_MASK: // 0
|
||||
case U_WS_DATA_FRAMING_MASK: // 0
|
||||
{
|
||||
U_INTERNAL_DUMP("mask_index = %d", mask_index)
|
||||
|
||||
|
@ -353,7 +345,7 @@ loop:
|
|||
|
||||
mask_index = 0;
|
||||
mask_offset = 0;
|
||||
framing_state = DATA_FRAMING_EXTENSION_DATA; // 4
|
||||
framing_state = U_WS_DATA_FRAMING_EXTENSION_DATA; // 4
|
||||
|
||||
if ((mask[0] == 0) &&
|
||||
(mask[1] == 0) &&
|
||||
|
@ -368,7 +360,7 @@ loop:
|
|||
|
||||
/* FALLTHRU */
|
||||
|
||||
case DATA_FRAMING_EXTENSION_DATA: // 4
|
||||
case U_WS_DATA_FRAMING_EXTENSION_DATA: // 4
|
||||
{
|
||||
// Deal with extension data when we support them -- FIXME
|
||||
|
||||
|
@ -378,12 +370,12 @@ loop:
|
|||
{
|
||||
if (payload_length > 0)
|
||||
{
|
||||
(void) UClientImage_Base::wbuffer->reserve(frame->application_data_offset + payload_length);
|
||||
(void) message->setBuffer(frame->application_data_offset + payload_length);
|
||||
|
||||
frame->application_data = (unsigned char*) UClientImage_Base::wbuffer->data();
|
||||
frame->application_data = (unsigned char*) message->data();
|
||||
}
|
||||
|
||||
framing_state = DATA_FRAMING_APPLICATION_DATA; // 5
|
||||
framing_state = U_WS_DATA_FRAMING_APPLICATION_DATA; // 5
|
||||
}
|
||||
|
||||
U_INTERNAL_DUMP("framing_state = %d", framing_state)
|
||||
|
@ -391,7 +383,7 @@ loop:
|
|||
|
||||
/* FALLTHRU */
|
||||
|
||||
case DATA_FRAMING_APPLICATION_DATA: // 5
|
||||
case U_WS_DATA_FRAMING_APPLICATION_DATA: // 5
|
||||
{
|
||||
int32_t block_length = block_size - block_offset,
|
||||
block_data_length = (payload_length > block_length ? block_length
|
||||
|
@ -404,7 +396,7 @@ loop:
|
|||
{
|
||||
int32_t i;
|
||||
|
||||
if (opcode == OPCODE_TEXT)
|
||||
if (opcode == U_WS_OPCODE_TEXT)
|
||||
{
|
||||
unsigned int utf8_state = frame->utf8_state;
|
||||
|
||||
|
@ -440,7 +432,7 @@ loop:
|
|||
{
|
||||
U_MEMCPY(&application_data[application_data_offset], &block[block_offset], block_data_length);
|
||||
|
||||
if (opcode == OPCODE_TEXT)
|
||||
if (opcode == U_WS_OPCODE_TEXT)
|
||||
{
|
||||
unsigned int utf8_state = frame->utf8_state;
|
||||
int32_t i, application_data_end = application_data_offset + block_data_length;
|
||||
|
@ -468,51 +460,56 @@ loop:
|
|||
|
||||
if (payload_length == 0)
|
||||
{
|
||||
message_type = MESSAGE_TYPE_INVALID;
|
||||
message_type = U_WS_MESSAGE_TYPE_INVALID;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case OPCODE_TEXT:
|
||||
case U_WS_OPCODE_TEXT:
|
||||
{
|
||||
if ((fin &&
|
||||
(frame->utf8_state != 0)) ||
|
||||
(frame->utf8_state == 1))
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_INVALID_UTF8;
|
||||
status_code = U_WS_STATUS_CODE_INVALID_UTF8;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
||||
message_type = MESSAGE_TYPE_TEXT;
|
||||
message_type = U_WS_MESSAGE_TYPE_TEXT;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPCODE_BINARY: message_type = MESSAGE_TYPE_BINARY; break;
|
||||
case U_WS_OPCODE_BINARY: message_type = U_WS_MESSAGE_TYPE_BINARY; break;
|
||||
|
||||
case OPCODE_CLOSE:
|
||||
case U_WS_OPCODE_CLOSE:
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_OK;
|
||||
status_code = U_WS_STATUS_CODE_OK;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
||||
case OPCODE_PING:
|
||||
case U_WS_OPCODE_PING:
|
||||
{
|
||||
(void) sendData(MESSAGE_TYPE_PONG, application_data, application_data_offset);
|
||||
if (sendControlFrame(socket, U_WS_OPCODE_PONG, application_data, application_data_offset) == false)
|
||||
{
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OPCODE_PONG: break;
|
||||
case U_WS_OPCODE_PONG: break;
|
||||
|
||||
default:
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_PROTOCOL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
@ -522,17 +519,17 @@ loop:
|
|||
{
|
||||
U_INTERNAL_DUMP("framing_state = %d message_type = %d status_code = %d", framing_state, message_type, status_code)
|
||||
|
||||
if (message_type != MESSAGE_TYPE_INVALID)
|
||||
if (message_type != U_WS_MESSAGE_TYPE_INVALID)
|
||||
{
|
||||
U_INTERNAL_ASSERT_EQUALS(framing_state, DATA_FRAMING_APPLICATION_DATA)
|
||||
U_INTERNAL_ASSERT_EQUALS(framing_state, U_WS_DATA_FRAMING_APPLICATION_DATA)
|
||||
|
||||
UClientImage_Base::wbuffer->size_adjust_force(application_data_offset);
|
||||
message->size_adjust_force(application_data_offset);
|
||||
|
||||
U_SRV_LOG_WITH_ADDR("received websocket data (%u+%u bytes) %V from",
|
||||
ncount - UClientImage_Base::wbuffer->size(),
|
||||
UClientImage_Base::wbuffer->size(), UClientImage_Base::wbuffer->rep)
|
||||
ncount - message->size(),
|
||||
message->size(), message->rep)
|
||||
|
||||
status_code = STATUS_CODE_OK;
|
||||
status_code = U_WS_STATUS_CODE_OK;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
@ -541,20 +538,20 @@ loop:
|
|||
application_data_offset = 0;
|
||||
}
|
||||
|
||||
framing_state = DATA_FRAMING_START; // 1
|
||||
framing_state = U_WS_DATA_FRAMING_START; // 1
|
||||
}
|
||||
|
||||
frame->application_data_offset = application_data_offset;
|
||||
}
|
||||
break;
|
||||
|
||||
// case DATA_FRAMING_CLOSE: block_offset = block_size; break;
|
||||
// case U_WS_DATA_FRAMING_CLOSE: block_offset = block_size; break;
|
||||
|
||||
default:
|
||||
{
|
||||
// framing_state = DATA_FRAMING_CLOSE; // 6
|
||||
// framing_state = U_WS_DATA_FRAMING_CLOSE; // 6
|
||||
|
||||
status_code = STATUS_CODE_PROTOCOL_ERROR;
|
||||
status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR;
|
||||
|
||||
U_RETURN(status_code);
|
||||
}
|
||||
|
@ -564,69 +561,110 @@ loop:
|
|||
|
||||
next:
|
||||
U_INTERNAL_ASSERT(block_offset >= block_size)
|
||||
U_INTERNAL_ASSERT_DIFFERS(framing_state, DATA_FRAMING_CLOSE) // 6
|
||||
U_INTERNAL_ASSERT_DIFFERS(framing_state, U_WS_DATA_FRAMING_CLOSE) // 6
|
||||
|
||||
rbuffer->setEmpty();
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
bool UWebSocket::sendData(int type, const unsigned char* buffer, uint32_t buffer_size)
|
||||
bool UWebSocket::sendData(USocket* socket, int type, const char* data, uint32_t len)
|
||||
{
|
||||
U_TRACE(0, "UWebSocket::sendData(%d,%p,%u)", type, buffer, buffer_size)
|
||||
U_TRACE(0, "UWebSocket::sendData(%p,%d,%.*S,%u)", socket, type, len, data, len)
|
||||
|
||||
uint32_t pos = 0;
|
||||
unsigned char opcode, header[32];
|
||||
uint32_t payload_length = (buffer ? buffer_size : 0);
|
||||
uint8_t opcode, masking_key[4];
|
||||
uint32_t header_length = 6U + (len > 125U ? 2U : 0) + (len > 0xffff ? 8U : 0), ncount = header_length + len;
|
||||
|
||||
UString tmp(ncount);
|
||||
unsigned char* header = (unsigned char*)tmp.data();
|
||||
|
||||
*((uint32_t*)masking_key) = u_get_num_random(0);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MESSAGE_TYPE_TEXT:
|
||||
case MESSAGE_TYPE_INVALID:
|
||||
opcode = OPCODE_TEXT;
|
||||
case U_WS_MESSAGE_TYPE_TEXT:
|
||||
case U_WS_MESSAGE_TYPE_INVALID:
|
||||
opcode = U_WS_OPCODE_TEXT;
|
||||
break;
|
||||
|
||||
case MESSAGE_TYPE_PING: opcode = OPCODE_PING; break;
|
||||
case MESSAGE_TYPE_PONG: opcode = OPCODE_PONG; break;
|
||||
case MESSAGE_TYPE_BINARY: opcode = OPCODE_BINARY; break;
|
||||
case U_WS_MESSAGE_TYPE_PING: opcode = U_WS_OPCODE_PING; break;
|
||||
case U_WS_MESSAGE_TYPE_PONG: opcode = U_WS_OPCODE_PONG; break;
|
||||
case U_WS_MESSAGE_TYPE_BINARY: opcode = U_WS_OPCODE_BINARY; break;
|
||||
|
||||
case MESSAGE_TYPE_CLOSE:
|
||||
case U_WS_MESSAGE_TYPE_CLOSE:
|
||||
default:
|
||||
opcode = OPCODE_CLOSE;
|
||||
opcode = U_WS_OPCODE_CLOSE;
|
||||
break;
|
||||
}
|
||||
|
||||
header[pos++] = FRAME_SET_FIN(1) | FRAME_SET_OPCODE(opcode);
|
||||
header[0] = (opcode | 0x80);
|
||||
|
||||
if (payload_length < 126) header[pos++] = FRAME_SET_MASK(0) | FRAME_SET_LENGTH(payload_length, 0);
|
||||
if (len <= 125)
|
||||
{
|
||||
header[1] = (len | 0x80);
|
||||
|
||||
u_put_unalignedp32(header+2, *((uint32_t*)masking_key));
|
||||
}
|
||||
else if (len > 125 &&
|
||||
len <= 0xffff) // 125 && 65535
|
||||
{
|
||||
header[1] = (126 | 0x80);
|
||||
|
||||
u_put_unalignedp16(header+2, htons(len));
|
||||
u_put_unalignedp32(header+4, *((uint32_t*)masking_key));
|
||||
}
|
||||
else if (len > 0xffff &&
|
||||
len <= 0xffffffff)
|
||||
{
|
||||
header[1] = (127 | 0x80);
|
||||
|
||||
u_put_unalignedp64(header+2, htonl(len));
|
||||
u_put_unalignedp32(header+10, *((uint32_t*)masking_key));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (payload_length < 65536) header[pos++] = FRAME_SET_MASK(0) | 126;
|
||||
else
|
||||
{
|
||||
header[pos++] = FRAME_SET_MASK(0) | 127;
|
||||
header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 7);
|
||||
header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 6);
|
||||
header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 5);
|
||||
header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 4);
|
||||
header[pos++] = FRAME_SET_LENGTH(payload_length, 3);
|
||||
header[pos++] = FRAME_SET_LENGTH(payload_length, 2);
|
||||
}
|
||||
status_code = U_WS_STATUS_CODE_MESSAGE_TOO_LARGE;
|
||||
|
||||
header[pos++] = FRAME_SET_LENGTH(payload_length, 1);
|
||||
header[pos++] = FRAME_SET_LENGTH(payload_length, 0);
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
U_SRV_LOG_WITH_ADDR("send websocket data (%u+%u bytes) %.*S to", pos, buffer_size, buffer_size, buffer)
|
||||
for (uint32_t i = 0; i < len; ++i)
|
||||
{
|
||||
header[6+i] = (data[i] ^ masking_key[i % 4]) & 0xff;
|
||||
}
|
||||
|
||||
struct iovec iov[2] = { { (caddr_t)header, pos },
|
||||
{ (caddr_t)buffer, payload_length } };
|
||||
U_SRV_LOG_WITH_ADDR("send websocket data (%u+%u bytes) %.*S to", header_length, len, len, data)
|
||||
|
||||
int iBytesWrite = (payload_length
|
||||
? (pos += payload_length, USocketExt::writev(UServer_Base::csocket, iov, 2, pos, UServer_Base::timeoutMS))
|
||||
: USocketExt::write( UServer_Base::csocket, (const char*)header, pos, UServer_Base::timeoutMS));
|
||||
|
||||
if (iBytesWrite == (int)pos) U_RETURN(true);
|
||||
if (USocketExt::write(socket, (const char*)header, ncount, UServer_Base::timeoutMS) == ncount) U_RETURN(true);
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
||||
bool UWebSocket::sendControlFrame(USocket* socket, int opcode, const unsigned char* payload, uint32_t payload_length)
|
||||
{
|
||||
U_TRACE(0, "UWebSocket::sendControlFrame(%p,%d,%.*S,%u)", socket, opcode, payload_length, payload, payload_length)
|
||||
|
||||
uint8_t masking_key[4];
|
||||
uint32_t ncount = 6U + payload_length;
|
||||
|
||||
UString tmp(ncount);
|
||||
unsigned char* header = (unsigned char*)tmp.data();
|
||||
|
||||
*((uint32_t*)masking_key) = u_get_num_random(0);
|
||||
|
||||
header[0] = ( opcode | 0x80);
|
||||
header[1] = (payload_length | 0x80);
|
||||
|
||||
u_put_unalignedp32(header+2, *((uint32_t*)masking_key));
|
||||
|
||||
for (uint32_t i = 0; i < payload_length; ++i)
|
||||
{
|
||||
header[6+i] = (payload[i] ^ masking_key[i % 4]) & 0xff;
|
||||
}
|
||||
|
||||
U_SRV_LOG_WITH_ADDR("send control frame(%d) (6+%u bytes) %.*S to", opcode, payload_length, payload_length, payload)
|
||||
|
||||
if (USocketExt::write(socket, (const char*)header, ncount, UServer_Base::timeoutMS) == ncount) U_RETURN(true);
|
||||
|
||||
U_RETURN(false);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ kill_server userver_tcp
|
|||
$SLEEP
|
||||
pkill userver_tcp 2>/dev/null
|
||||
|
||||
cat err/userver_tcp.err >> err/webserver_proxy.err
|
||||
cat err/userver_tcp.err > err/webserver_proxy.err
|
||||
rm err/userver_tcp.err
|
||||
|
||||
# Test against expected output
|
||||
|
|
|
@ -2,44 +2,49 @@
|
|||
|
||||
. ../.function
|
||||
|
||||
rm -f web_socket.log \
|
||||
/tmp/UWebSocketPlugIn.err \
|
||||
out/userver_tcp.out err/userver_tcp.err \
|
||||
trace.*userver_tcp*.[0-9]* object.*userver_tcp*.[0-9]* stack.*userver_tcp*.[0-9]*
|
||||
rm -f /tmp/web_socket.log \
|
||||
/tmp/UWebSocketPlugIn.err \
|
||||
out/web_socket.out err/userver_tcp.err \
|
||||
/tmp/trace.*userver_tcp*.[0-9]* /tmp/object.*userver_tcp*.[0-9]* /tmp/stack.*userver_tcp*.[0-9]*
|
||||
|
||||
UTRACE="0 50M 0"
|
||||
#UOBJDUMP="0 1M 10"
|
||||
UTRACE_SIGNAL="0 50M 0"
|
||||
UTRACE_FOLDER=/tmp
|
||||
TMPDIR=/tmp
|
||||
#UOBJDUMP="0 10M 100"
|
||||
#USIMERR="error.sim"
|
||||
export UTRACE UOBJDUMP USIMERR
|
||||
#UMEMUSAGE=yes
|
||||
export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL UMEMUSAGE UTRACE_FOLDER TMPDIR
|
||||
|
||||
cat <<EOF >web_socket_sh.cfg
|
||||
cat <<EOF >inp/webserver.cfg
|
||||
userver {
|
||||
PORT 8787
|
||||
MAX_KEEP_ALIVE 6
|
||||
RUN_AS_USER apache
|
||||
PID_FILE docroot/web_socket_sh.pid
|
||||
LOG_FILE web_socket.log
|
||||
PID_FILE /tmp/web_socket.pid
|
||||
LOG_FILE /tmp/web_socket.log
|
||||
LOG_FILE_SZ 1M
|
||||
LOG_MSG_SIZE -1
|
||||
PLUGIN "socket http"
|
||||
DOCUMENT_ROOT docroot
|
||||
DOCUMENT_ROOT websocket
|
||||
PLUGIN_DIR ../../../src/ulib/net/server/plugin/.libs
|
||||
ORM_DRIVER_DIR ../../../src/ulib/orm/driver/.libs
|
||||
PREFORK_CHILD 1
|
||||
}
|
||||
socket {
|
||||
COMMAND ../my_websocket.sh
|
||||
}
|
||||
EOF
|
||||
|
||||
(cd websocket; ln -sf ../../../src/ulib/net/server/plugin/usp/.libs/modsocket.so)
|
||||
|
||||
DIR_CMD="../../examples/userver"
|
||||
|
||||
check_for_netcat
|
||||
|
||||
#STRACE=$TRUSS
|
||||
start_prg_background userver_tcp -c web_socket_sh.cfg
|
||||
start_prg_background userver_tcp -c inp/webserver.cfg
|
||||
|
||||
#$SLEEP
|
||||
#kill_prg userver_tcp TERM
|
||||
wait_server_ready localhost 8787
|
||||
$SLEEP
|
||||
send_req $NCAT localhost 8787 inp/http/websocket.req web_socket 3 kill
|
||||
$SLEEP
|
||||
kill_prg userver_tcp TERM
|
||||
|
||||
mv err/userver_tcp.err err/web_socket.err
|
||||
mv err/userver_tcp.err /tmp/web_socket.err
|
||||
|
||||
echo "PID = `cat docroot/web_socket_sh.pid`"
|
||||
#echo "PID = `cat /tmp/web_socket.pid`"
|
||||
|
|
|
@ -2,34 +2,52 @@
|
|||
|
||||
. ../.function
|
||||
|
||||
# set -x
|
||||
|
||||
## web_socket.test -- Test web socket feature
|
||||
|
||||
start_msg web_socket
|
||||
|
||||
DOC_ROOT=websocket
|
||||
|
||||
rm -f $DOC_ROOT/web_socket.log \
|
||||
/tmp/UWebSocketPlugIn.err \
|
||||
out/userver_tcp.out err/userver_tcp.err \
|
||||
rm -f /tmp/web_socket*.log /tmp/UWebSocketPlugIn.err out/userver_tcp.out err/userver_tcp.err \
|
||||
trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \
|
||||
/tmp/trace.*userver_*.[0-9]* /tmp/object.*userver_*.[0-9]* /tmp/stack.*userver_*.[0-9]* /tmp/mempool.*userver_*.[0-9]* \
|
||||
$DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]*
|
||||
|
||||
#UTRACE="0 50M 0"
|
||||
#UOBJDUMP="0 50M 1000"
|
||||
#UTRACE="0 100M 0"
|
||||
UTRACE_FOLDER=/tmp
|
||||
TMPDIR=/tmp
|
||||
#UOBJDUMP="0 10M 100"
|
||||
#USIMERR="error.sim"
|
||||
export UTRACE UOBJDUMP USIMERR
|
||||
#UMEMUSAGE=yes
|
||||
export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL UMEMUSAGE UTRACE_FOLDER TMPDIR
|
||||
|
||||
cat <<EOF >inp/webserver.cfg
|
||||
userver {
|
||||
PORT 8787
|
||||
RUN_AS_USER apache
|
||||
MAX_KEEP_ALIVE 6
|
||||
LOG_FILE web_socket.log
|
||||
LOG_FILE /tmp/web_socket.log
|
||||
LOG_FILE_SZ 1M
|
||||
LOG_MSG_SIZE -1
|
||||
PID_FILE /tmp/userver_tcp.pid
|
||||
PLUGIN "socket http"
|
||||
DOCUMENT_ROOT websocket
|
||||
PLUGIN_DIR ../../../src/ulib/net/server/plugin/.libs
|
||||
ORM_DRIVER_DIR ../../../src/ulib/orm/driver/.libs
|
||||
PREFORK_CHILD 1
|
||||
}
|
||||
EOF
|
||||
|
||||
cat <<EOF >inp/webserver_proxy.cfg
|
||||
userver {
|
||||
PORT 8888
|
||||
LOG_FILE /tmp/webserver_proxy.log
|
||||
LOG_FILE_SZ 10M
|
||||
LOG_MSG_SIZE -1
|
||||
PID_FILE /tmp/userver_tcp_proxy.pid
|
||||
PREFORK_CHILD 0
|
||||
DOCUMENT_ROOT python
|
||||
PLUGIN "socket http"
|
||||
PLUGIN_DIR ../../../src/ulib/net/server/plugin/.libs
|
||||
}
|
||||
socket {
|
||||
COMMAND ../my_websocket.sh
|
||||
|
@ -42,14 +60,21 @@ check_for_netcat
|
|||
|
||||
#STRACE=$TRUSS
|
||||
start_prg_background userver_tcp -c inp/webserver.cfg
|
||||
|
||||
wait_server_ready localhost 8787
|
||||
start_prg_background userver_tcp -c inp/webserver_proxy.cfg
|
||||
wait_server_ready localhost 8888
|
||||
|
||||
sync
|
||||
#echo "PID1 = `cat /tmp/userver_tcp.pid`"
|
||||
#echo "PID2 = `cat /tmp/userver_tcp_proxy.pid`"
|
||||
|
||||
send_req $NCAT localhost 8787 inp/http/websocket.req web_socket 3 kill
|
||||
$SLEEP
|
||||
kill_prg userver_tcp TERM
|
||||
|
||||
mv err/userver_tcp.err err/web_socket.err
|
||||
kill_prg userver_tcp TERM
|
||||
$SLEEP
|
||||
pkill userver_tcp 2>/dev/null
|
||||
|
||||
mv err/userver_tcp.err err/websocket.err
|
||||
|
||||
# Test against expected output
|
||||
test_output_wc l web_socket
|
||||
|
|
Loading…
Reference in New Issue
Block a user