Updated Branches: refs/heads/master f0f9cb9c3 -> 60ec95053
[TS-2541] Add WebSocket Support Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/cca82f1b Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/cca82f1b Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/cca82f1b Branch: refs/heads/master Commit: cca82f1b910dfea6903e05602b06df53e4979b9b Parents: 70f8e10 Author: Brian Geffon <[email protected]> Authored: Mon Feb 3 11:10:44 2014 -0800 Committer: Brian Geffon <[email protected]> Committed: Mon Feb 3 11:10:44 2014 -0800 ---------------------------------------------------------------------- CHANGES | 2 + proxy/config/remap.config.default | 8 + proxy/hdrs/HdrToken.cc | 18 +++ proxy/hdrs/HdrToken.h | 8 +- proxy/hdrs/MIME.cc | 20 ++- proxy/hdrs/MIME.h | 8 + proxy/hdrs/URL.cc | 14 ++ proxy/hdrs/URL.h | 6 + proxy/http/HttpClientSession.cc | 1 + proxy/http/HttpConfig.cc | 5 + proxy/http/HttpConfig.h | 1 + proxy/http/HttpDebugNames.cc | 3 +- proxy/http/HttpSM.cc | 23 ++- proxy/http/HttpTransact.cc | 284 ++++++++++++++++++++++++++++----- proxy/http/HttpTransact.h | 33 +++- proxy/http/HttpTransactHeaders.cc | 7 +- proxy/http/remap/RemapConfig.cc | 17 +- 17 files changed, 406 insertions(+), 52 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index be006e8..fab65c0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes with Apache Traffic Server 4.2.0 + *) [TS-2541] Add WebSocket support + *) [TS-2550] Add inline configuration overrised to the conf_remap plugin. *) [TS-2546] Move xptr and _xstrdup to ink_memory.{h,cc}. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/config/remap.config.default ---------------------------------------------------------------------- diff --git a/proxy/config/remap.config.default b/proxy/config/remap.config.default index e0cd89a..2198ee4 100644 --- a/proxy/config/remap.config.default +++ b/proxy/config/remap.config.default @@ -149,6 +149,14 @@ # Example: # map http://foo.cow.com/ http://bar.cow.com @src_ip=10.72.118.51-10.72.118.62 @method=GET @method=DELETE @src_ip=192.168.0.1-192.168.0.254 @action=allow @method=PUT # +# Traffic Server supports WebSockets but it must be enabled via remap. WebSocket upgrades are automatically +# detected when there exists a remap rule containing a ws:// scheme. +# +# Example: +# map ws://bar.com/ ws://foo.com/ +# +# Explaination: When a request comes in with the appropriate upgrade headers, Traffic Server will use this +# remap rule in an attempt to establish and maintain a websocket connection. # # Named filters can be created and applied to blocks of mappings # using the .definefilter, .activatefilter, and .deactivatefilter http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/hdrs/HdrToken.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HdrToken.cc b/proxy/hdrs/HdrToken.cc index 72bbbe1..7977b67 100644 --- a/proxy/hdrs/HdrToken.cc +++ b/proxy/hdrs/HdrToken.cc @@ -145,6 +145,11 @@ static const char *_hdrtoken_strs[] = { "chunked", "close", + // WS + "websocket", + "Sec-WebSocket-Key", + "Sec-WebSocket-Version", + // URL schemes "file", "ftp", @@ -164,6 +169,8 @@ static const char *_hdrtoken_strs[] = { "mmsu", "mmst", "mms", + "wss", + "ws", // HTTP methods "CONNECT", @@ -203,6 +210,8 @@ static HdrTokenTypeBinding _hdrtoken_strs_type_initializers[] = { {"mms", HDRTOKEN_TYPE_SCHEME}, {"mmsu", HDRTOKEN_TYPE_SCHEME}, {"mmst", HDRTOKEN_TYPE_SCHEME}, + {"wss", HDRTOKEN_TYPE_SCHEME}, + {"ws", HDRTOKEN_TYPE_SCHEME}, {"CONNECT", HDRTOKEN_TYPE_METHOD}, {"DELETE", HDRTOKEN_TYPE_METHOD}, @@ -309,6 +318,8 @@ static HdrTokenFieldInfo _hdrtoken_strs_field_initializers[] = { {"@DataInfo", MIME_SLOTID_NONE, MIME_PRESENCE_INT_DATA_INFO, HTIF_NONE}, {"X-ID", MIME_SLOTID_NONE, MIME_PRESENCE_NONE, (HTIF_COMMAS | HTIF_MULTVALS | HTIF_HOPBYHOP)}, {"X-Forwarded-For", MIME_SLOTID_NONE, MIME_PRESENCE_NONE, (HTIF_COMMAS | HTIF_MULTVALS)}, + {"Sec-WebSocket-Key", MIME_SLOTID_NONE, MIME_PRESENCE_NONE, HTIF_NONE}, + {"Sec-WebSocket-Version", MIME_SLOTID_NONE, MIME_PRESENCE_NONE, HTIF_NONE}, {NULL, 0, 0, 0} }; @@ -473,6 +484,11 @@ static const char *_hdrtoken_commonly_tokenized_strs[] = { "chunked", "close", + // WS + "websocket", + "Sec-WebSocket-Key", + "Sec-WebSocket-Version", + // URL schemes "file", "ftp", @@ -492,6 +508,8 @@ static const char *_hdrtoken_commonly_tokenized_strs[] = { "mmsu", "mmst", "mms", + "wss", + "ws", // HTTP methods "CONNECT", http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/hdrs/HdrToken.h ---------------------------------------------------------------------- diff --git a/proxy/hdrs/HdrToken.h b/proxy/hdrs/HdrToken.h index 052753a..95dc95c 100644 --- a/proxy/hdrs/HdrToken.h +++ b/proxy/hdrs/HdrToken.h @@ -373,11 +373,11 @@ hdrtoken_wks_to_flags(const char *wks) // bits 56-60 were used for a benchmark hack, but are now free to be used // for something else -#define MIME_PRESENCE_UNUSED_1 (TOK_64_CONST(1) << 56) -#define MIME_PRESENCE_UNUSED_2 (TOK_64_CONST(1) << 57) +#define MIME_PRESENCE_UNUSED_1 (TOK_64_CONST(1) << 56) +#define MIME_PRESENCE_UNUSED_2 (TOK_64_CONST(1) << 57) #define MIME_PRESENCE_UNUSED_3 (TOK_64_CONST(1) << 58) -#define MIME_PRESENCE_UNUSED_4 (TOK_64_CONST(1) << 59) -#define MIME_PRESENCE_UNUSED_5 (TOK_64_CONST(1) << 60) +#define MIME_PRESENCE_UNUSED_4 (TOK_64_CONST(1) << 59) +#define MIME_PRESENCE_UNUSED_5 (TOK_64_CONST(1) << 60) #define MIME_PRESENCE_XREF (TOK_64_CONST(1) << 61) #define MIME_PRESENCE_INT_DATA_INFO (TOK_64_CONST(1) << 62) http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/hdrs/MIME.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/MIME.cc b/proxy/hdrs/MIME.cc index 0313314..0de0db2 100644 --- a/proxy/hdrs/MIME.cc +++ b/proxy/hdrs/MIME.cc @@ -156,6 +156,8 @@ const char *MIME_FIELD_XREF; const char *MIME_FIELD_INT_DATA_INFO; const char *MIME_FIELD_X_ID; const char *MIME_FIELD_X_FORWARDED_FOR; +const char *MIME_FIELD_SEC_WEBSOCKET_KEY; +const char *MIME_FIELD_SEC_WEBSOCKET_VERSION; const char *MIME_VALUE_BYTES; const char *MIME_VALUE_CHUNKED; @@ -179,6 +181,8 @@ const char *MIME_VALUE_PROXY_REVALIDATE; const char *MIME_VALUE_PUBLIC; const char *MIME_VALUE_S_MAXAGE; const char *MIME_VALUE_NEED_REVALIDATE_ONCE; +const char *MIME_VALUE_WEBSOCKET; + // Cache-control: extension "need-revalidate-once" is used internally by T.S. // to invalidate a document, and it is not returned/forwarded. // If a cached document has this extension set (ie, is invalidated), @@ -265,6 +269,8 @@ int MIME_LEN_XREF; int MIME_LEN_INT_DATA_INFO; int MIME_LEN_X_ID; int MIME_LEN_X_FORWARDED_FOR; +int MIME_LEN_SEC_WEBSOCKET_KEY; +int MIME_LEN_SEC_WEBSOCKET_VERSION; int MIME_WKSIDX_ACCEPT; int MIME_WKSIDX_ACCEPT_CHARSET; @@ -340,7 +346,8 @@ int MIME_WKSIDX_XREF; int MIME_WKSIDX_INT_DATA_INFO; int MIME_WKSIDX_X_ID; int MIME_WKSIDX_X_FORWARDED_FOR; - +int MIME_WKSIDX_SEC_WEBSOCKET_KEY; +int MIME_WKSIDX_SEC_WEBSOCKET_VERSION; /*********************************************************************** * * @@ -684,6 +691,9 @@ mime_init() MIME_FIELD_X_ID = hdrtoken_string_to_wks("X-ID"); MIME_FIELD_X_FORWARDED_FOR = hdrtoken_string_to_wks("X-Forwarded-For"); + MIME_FIELD_SEC_WEBSOCKET_KEY = hdrtoken_string_to_wks("Sec-WebSocket-Key"); + MIME_FIELD_SEC_WEBSOCKET_VERSION = hdrtoken_string_to_wks("Sec-WebSocket-Version"); + MIME_LEN_ACCEPT = hdrtoken_wks_to_length(MIME_FIELD_ACCEPT); MIME_LEN_ACCEPT_CHARSET = hdrtoken_wks_to_length(MIME_FIELD_ACCEPT_CHARSET); @@ -760,6 +770,10 @@ mime_init() MIME_LEN_X_ID = hdrtoken_wks_to_length(MIME_FIELD_X_ID); MIME_LEN_X_FORWARDED_FOR = hdrtoken_wks_to_length(MIME_FIELD_X_FORWARDED_FOR); + MIME_LEN_SEC_WEBSOCKET_KEY = hdrtoken_wks_to_length(MIME_FIELD_SEC_WEBSOCKET_KEY); + MIME_LEN_SEC_WEBSOCKET_VERSION = hdrtoken_wks_to_length(MIME_FIELD_SEC_WEBSOCKET_VERSION); + + MIME_WKSIDX_ACCEPT = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT); MIME_WKSIDX_ACCEPT_CHARSET = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT_CHARSET); MIME_WKSIDX_ACCEPT_ENCODING = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT_ENCODING); @@ -833,6 +847,8 @@ mime_init() MIME_WKSIDX_XREF = hdrtoken_wks_to_index(MIME_FIELD_XREF); MIME_WKSIDX_X_ID = hdrtoken_wks_to_index(MIME_FIELD_X_ID); MIME_WKSIDX_X_FORWARDED_FOR = hdrtoken_wks_to_index(MIME_FIELD_X_FORWARDED_FOR); + MIME_WKSIDX_SEC_WEBSOCKET_KEY = hdrtoken_wks_to_index(MIME_FIELD_SEC_WEBSOCKET_KEY); + MIME_WKSIDX_SEC_WEBSOCKET_VERSION = hdrtoken_wks_to_index(MIME_FIELD_SEC_WEBSOCKET_VERSION); MIME_VALUE_BYTES = hdrtoken_string_to_wks("bytes"); MIME_VALUE_CHUNKED = hdrtoken_string_to_wks("chunked"); @@ -856,6 +872,8 @@ mime_init() MIME_VALUE_PUBLIC = hdrtoken_string_to_wks("public"); MIME_VALUE_S_MAXAGE = hdrtoken_string_to_wks("s-maxage"); MIME_VALUE_NEED_REVALIDATE_ONCE = hdrtoken_string_to_wks("need-revalidate-once"); + MIME_VALUE_WEBSOCKET = hdrtoken_string_to_wks("websocket"); + mime_init_date_format_table(); mime_init_cache_control_cooking_masks(); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/hdrs/MIME.h ---------------------------------------------------------------------- diff --git a/proxy/hdrs/MIME.h b/proxy/hdrs/MIME.h index a75e56a..9c7b721 100644 --- a/proxy/hdrs/MIME.h +++ b/proxy/hdrs/MIME.h @@ -367,6 +367,8 @@ extern const char *MIME_FIELD_XREF; extern const char *MIME_FIELD_INT_DATA_INFO; extern const char *MIME_FIELD_X_ID; extern const char *MIME_FIELD_X_FORWARDED_FOR; +extern const char *MIME_FIELD_SEC_WEBSOCKET_KEY; +extern const char *MIME_FIELD_SEC_WEBSOCKET_VERSION; extern const char *MIME_VALUE_BYTES; extern const char *MIME_VALUE_CHUNKED; @@ -390,6 +392,7 @@ extern const char *MIME_VALUE_PROXY_REVALIDATE; extern const char *MIME_VALUE_PUBLIC; extern const char *MIME_VALUE_S_MAXAGE; extern const char *MIME_VALUE_NEED_REVALIDATE_ONCE; +extern const char *MIME_VALUE_WEBSOCKET; extern int MIME_LEN_ACCEPT; extern int MIME_LEN_ACCEPT_CHARSET; @@ -489,6 +492,9 @@ extern int MIME_LEN_PUBLIC; extern int MIME_LEN_S_MAXAGE; extern int MIME_LEN_NEED_REVALIDATE_ONCE; +extern int MIME_LEN_SEC_WEBSOCKET_KEY; +extern int MIME_LEN_SEC_WEBSOCKET_VERSION; + extern int MIME_WKSIDX_ACCEPT; extern int MIME_WKSIDX_ACCEPT_CHARSET; extern int MIME_WKSIDX_ACCEPT_ENCODING; @@ -562,6 +568,8 @@ extern int MIME_WKSIDX_WWW_AUTHENTICATE; extern int MIME_WKSIDX_XREF; extern int MIME_WKSIDX_INT_DATA_INFO; extern int MIME_WKSIDX_X_ID; +extern int MIME_WKSIDX_SEC_WEBSOCKET_KEY; +extern int MIME_WKSIDX_SEC_WEBSOCKET_VERSION; /*********************************************************************** * * http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/hdrs/URL.cc ---------------------------------------------------------------------- diff --git a/proxy/hdrs/URL.cc b/proxy/hdrs/URL.cc index 976a9c4..2dea36f 100644 --- a/proxy/hdrs/URL.cc +++ b/proxy/hdrs/URL.cc @@ -33,6 +33,8 @@ const char *URL_SCHEME_FTP; const char *URL_SCHEME_GOPHER; const char *URL_SCHEME_HTTP; const char *URL_SCHEME_HTTPS; +const char *URL_SCHEME_WSS; +const char *URL_SCHEME_WS; const char *URL_SCHEME_MAILTO; const char *URL_SCHEME_NEWS; const char *URL_SCHEME_NNTP; @@ -52,6 +54,8 @@ int URL_WKSIDX_FTP; int URL_WKSIDX_GOPHER; int URL_WKSIDX_HTTP; int URL_WKSIDX_HTTPS; +int URL_WKSIDX_WS; +int URL_WKSIDX_WSS; int URL_WKSIDX_MAILTO; int URL_WKSIDX_NEWS; int URL_WKSIDX_NNTP; @@ -71,6 +75,8 @@ int URL_LEN_FTP; int URL_LEN_GOPHER; int URL_LEN_HTTP; int URL_LEN_HTTPS; +int URL_LEN_WS; +int URL_LEN_WSS; int URL_LEN_MAILTO; int URL_LEN_NEWS; int URL_LEN_NNTP; @@ -106,6 +112,8 @@ url_init() URL_SCHEME_GOPHER = hdrtoken_string_to_wks("gopher"); URL_SCHEME_HTTP = hdrtoken_string_to_wks("http"); URL_SCHEME_HTTPS = hdrtoken_string_to_wks("https"); + URL_SCHEME_WSS = hdrtoken_string_to_wks("wss"); + URL_SCHEME_WS = hdrtoken_string_to_wks("ws"); URL_SCHEME_MAILTO = hdrtoken_string_to_wks("mailto"); URL_SCHEME_NEWS = hdrtoken_string_to_wks("news"); URL_SCHEME_NNTP = hdrtoken_string_to_wks("nntp"); @@ -125,6 +133,8 @@ url_init() URL_SCHEME_GOPHER && URL_SCHEME_HTTP && URL_SCHEME_HTTPS && + URL_SCHEME_WS && + URL_SCHEME_WSS && URL_SCHEME_MAILTO && URL_SCHEME_NEWS && URL_SCHEME_NNTP && @@ -145,6 +155,8 @@ url_init() URL_WKSIDX_GOPHER = hdrtoken_wks_to_index(URL_SCHEME_GOPHER); URL_WKSIDX_HTTP = hdrtoken_wks_to_index(URL_SCHEME_HTTP); URL_WKSIDX_HTTPS = hdrtoken_wks_to_index(URL_SCHEME_HTTPS); + URL_WKSIDX_WS = hdrtoken_wks_to_index(URL_SCHEME_WS); + URL_WKSIDX_WSS = hdrtoken_wks_to_index(URL_SCHEME_WSS); URL_WKSIDX_MAILTO = hdrtoken_wks_to_index(URL_SCHEME_MAILTO); URL_WKSIDX_NEWS = hdrtoken_wks_to_index(URL_SCHEME_NEWS); URL_WKSIDX_NNTP = hdrtoken_wks_to_index(URL_SCHEME_NNTP); @@ -164,6 +176,8 @@ url_init() URL_LEN_GOPHER = hdrtoken_wks_to_length(URL_SCHEME_GOPHER); URL_LEN_HTTP = hdrtoken_wks_to_length(URL_SCHEME_HTTP); URL_LEN_HTTPS = hdrtoken_wks_to_length(URL_SCHEME_HTTPS); + URL_LEN_WS = hdrtoken_wks_to_length(URL_SCHEME_WS); + URL_LEN_WSS = hdrtoken_wks_to_length(URL_SCHEME_WSS); URL_LEN_MAILTO = hdrtoken_wks_to_length(URL_SCHEME_MAILTO); URL_LEN_NEWS = hdrtoken_wks_to_length(URL_SCHEME_NEWS); URL_LEN_NNTP = hdrtoken_wks_to_length(URL_SCHEME_NNTP); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/hdrs/URL.h ---------------------------------------------------------------------- diff --git a/proxy/hdrs/URL.h b/proxy/hdrs/URL.h index 30f1711..c60d1c2 100644 --- a/proxy/hdrs/URL.h +++ b/proxy/hdrs/URL.h @@ -91,6 +91,8 @@ extern const char *URL_SCHEME_FTP; extern const char *URL_SCHEME_GOPHER; extern const char *URL_SCHEME_HTTP; extern const char *URL_SCHEME_HTTPS; +extern const char *URL_SCHEME_WS; +extern const char *URL_SCHEME_WSS; extern const char *URL_SCHEME_MAILTO; extern const char *URL_SCHEME_NEWS; extern const char *URL_SCHEME_NNTP; @@ -110,6 +112,8 @@ extern int URL_WKSIDX_FTP; extern int URL_WKSIDX_GOPHER; extern int URL_WKSIDX_HTTP; extern int URL_WKSIDX_HTTPS; +extern int URL_WKSIDX_WS; +extern int URL_WKSIDX_WSS; extern int URL_WKSIDX_MAILTO; extern int URL_WKSIDX_NEWS; extern int URL_WKSIDX_NNTP; @@ -129,6 +133,8 @@ extern int URL_LEN_FTP; extern int URL_LEN_GOPHER; extern int URL_LEN_HTTP; extern int URL_LEN_HTTPS; +extern int URL_LEN_WS; +extern int URL_LEN_WSS; extern int URL_LEN_MAILTO; extern int URL_LEN_NEWS; extern int URL_LEN_NNTP; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpClientSession.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpClientSession.cc b/proxy/http/HttpClientSession.cc index 5db6275..c518044 100644 --- a/proxy/http/HttpClientSession.cc +++ b/proxy/http/HttpClientSession.cc @@ -285,6 +285,7 @@ HttpClientSession::do_io_close(int alerrno) HTTP_DECREMENT_DYN_STAT(http_current_active_client_connections_stat); } } + // Prevent double closing ink_release_assert(read_state != HCS_CLOSED); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpConfig.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc index 61ba66b..419de41 100644 --- a/proxy/http/HttpConfig.cc +++ b/proxy/http/HttpConfig.cc @@ -140,6 +140,11 @@ register_stat_callbacks() RECD_INT, RECP_NON_PERSISTENT, (int) http_current_active_client_connections_stat, RecRawStatSyncSum); HTTP_CLEAR_DYN_STAT(http_current_active_client_connections_stat); + RecRegisterRawStat(http_rsb, RECT_PROCESS, + "proxy.process.http.websocket.current_active_client_connections", + RECD_INT, RECP_NON_PERSISTENT, + (int) http_websocket_current_active_client_connections_stat, RecRawStatSyncSum); + HTTP_CLEAR_DYN_STAT(http_websocket_current_active_client_connections_stat); // Current Transaction Stats RecRegisterRawStat(http_rsb, RECT_PROCESS, "proxy.process.http.current_client_transactions", http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpConfig.h ---------------------------------------------------------------------- diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h index e4790a9..54cf273 100644 --- a/proxy/http/HttpConfig.h +++ b/proxy/http/HttpConfig.h @@ -66,6 +66,7 @@ enum http_background_fill_current_count_stat, http_current_client_connections_stat, http_current_active_client_connections_stat, + http_websocket_current_active_client_connections_stat, http_current_client_transactions_stat, http_total_incoming_connections_stat, http_current_parent_proxy_transactions_stat, http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpDebugNames.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpDebugNames.cc b/proxy/http/HttpDebugNames.cc index c5a3728..0211294 100644 --- a/proxy/http/HttpDebugNames.cc +++ b/proxy/http/HttpDebugNames.cc @@ -396,7 +396,8 @@ HttpDebugNames::get_action_name(HttpTransact::StateMachineAction_t e) return ("HTTP_API_POST_REMAP"); case HttpTransact::HTTP_POST_REMAP_SKIP: return ("HTTP_POST_REMAP_SKIP"); - + case HttpTransact::HTTP_POST_REMAP_UPGRADE: + return ("HTTP_POST_REMAP_UPGRADE"); } return ("unknown state name"); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpSM.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 41f8cf1..8618728 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -1583,9 +1583,19 @@ HttpSM::handle_api_return() } case HttpTransact::SERVER_READ: { - setup_server_transfer(); - perform_cache_write_action(); - tunnel.tunnel_run(); + if (unlikely(t_state.did_upgrade_succeed)) { + // We've sucessfully handled the upgrade, let's now setup + // a blind tunnel. + if(t_state.is_websocket) { + HTTP_INCREMENT_DYN_STAT(http_websocket_current_active_client_connections_stat); + } + + setup_blind_tunnel(true); + } else { + setup_server_transfer(); + perform_cache_write_action(); + tunnel.tunnel_run(); + } break; } case HttpTransact::SERVE_FROM_CACHE: @@ -2739,6 +2749,11 @@ HttpSM::tunnel_handler(int event, void *data) ink_assert(data == &tunnel); // The tunnel calls this when it is done terminate_sm = true; + + if (unlikely(t_state.is_websocket)) { + HTTP_DECREMENT_DYN_STAT(http_websocket_current_active_client_connections_stat); + } + return 0; } @@ -6136,6 +6151,7 @@ HttpSM::setup_server_transfer_to_cache_only() void HttpSM::setup_server_transfer() { + DebugSM("http", "Setup Server Transfer"); int64_t alloc_index, hdr_size; int64_t nbytes; @@ -6806,6 +6822,7 @@ HttpSM::set_next_state() break; } + case HttpTransact::HTTP_POST_REMAP_UPGRADE: case HttpTransact::HTTP_POST_REMAP_SKIP: { call_transact_and_set_next_state(NULL); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpTransact.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index a3187b2..9692d99 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -757,6 +757,11 @@ HttpTransact::StartRemapRequest(State* s) if (s->api_skip_all_remapping) { Debug ("http_trans", "API request to skip remapping"); + + if (s->is_upgrade_request && s->post_remap_upgrade_return_point) { + TRANSACT_RETURN(HTTP_POST_REMAP_SKIP, s->post_remap_upgrade_return_point); + } + TRANSACT_RETURN(HTTP_POST_REMAP_SKIP, HttpTransact::HandleRequest); } @@ -965,12 +970,150 @@ done: } else { s->hdr_info.client_response.clear(); //anything previously set is invalid from this point forward DebugTxn("http_trans", "END HttpTransact::EndRemapRequest"); + + if (s->is_upgrade_request && s->post_remap_upgrade_return_point) { + TRANSACT_RETURN(HTTP_API_POST_REMAP, s->post_remap_upgrade_return_point); + } + TRANSACT_RETURN(HTTP_API_POST_REMAP, HttpTransact::HandleRequest); } ink_assert(!"not reached"); } +bool HttpTransact::handle_upgrade_request(State *s) { + // Quickest way to determine that this is defintely not an upgrade. + /* RFC 6455 The method of the request MUST be GET, and the HTTP version MUST + be at least 1.1. */ + if (!s->hdr_info.client_request.presence(MIME_PRESENCE_UPGRADE) || + !s->hdr_info.client_request.presence(MIME_PRESENCE_CONNECTION) || + s->method != HTTP_WKSIDX_GET || + s->hdr_info.client_request.version_get() < HTTPVersion(1, 1)) { + return false; + } + + MIMEField *upgrade_hdr = s->hdr_info.client_request.field_find(MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE); + MIMEField *connection_hdr = s->hdr_info.client_request.field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION); + + StrList connection_hdr_vals; + const char *upgrade_hdr_val = NULL; + int upgrade_hdr_val_len = 0; + + if ( !upgrade_hdr || + !connection_hdr || + connection_hdr->value_get_comma_list(&connection_hdr_vals) == 0 || + (upgrade_hdr_val = upgrade_hdr->value_get(&upgrade_hdr_val_len)) == NULL) { + DebugTxn("http_trans_upgrade", "Transaction wasn't a valid upgrade request, proceeding as a normal HTTP request."); + return false; + } + + /* + * In order for this request to be treated as a normal upgrade request we must have a Connection: Upgrade header + * and a Upgrade: header, with a non-empty value, otherwise we just assume it's not an Upgrade Request, after + * we've verified that, we will try to match this upgrade to a known upgrade type such as Websockets. + */ + bool connection_contains_upgrade = false; + // Next, let's validate that the Connection header contains an Upgrade key + for(int i = 0; i < connection_hdr_vals.count; ++i) { + Str *val = connection_hdr_vals.get_idx(i); + if (ptr_len_casecmp(val->str, val->len, MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE) == 0) { + connection_contains_upgrade = true; + break; + } + } + + if (!connection_contains_upgrade) { + DebugTxn("http_trans_upgrade", "Transaction wasn't a valid upgrade request, proceeding as a normal HTTP request, missing Connection upgrade header."); + return false; + } + + + // Mark this request as an upgrade request. + s->is_upgrade_request = true; + + /* + RFC 6455 + The request MUST contain an |Upgrade| header field whose value + MUST include the "websocket" keyword. + The request MUST contain a |Connection| header field whose value + MUST include the "Upgrade" token. // Checked Above + The request MUST include a header field with the name + |Sec-WebSocket-Key|. + The request MUST include a header field with the name + |Sec-WebSocket-Version|. The value of this header field MUST be + 13. + */ + if (hdrtoken_tokenize(upgrade_hdr_val, upgrade_hdr_val_len, &s->upgrade_token_wks) >= 0) { + if (s->upgrade_token_wks == MIME_VALUE_WEBSOCKET) { + MIMEField *sec_websocket_key = s->hdr_info.client_request.field_find(MIME_FIELD_SEC_WEBSOCKET_KEY, MIME_LEN_SEC_WEBSOCKET_KEY); + MIMEField *sec_websocket_ver = s->hdr_info.client_request.field_find(MIME_FIELD_SEC_WEBSOCKET_VERSION, MIME_LEN_SEC_WEBSOCKET_VERSION); + + if (sec_websocket_key && + sec_websocket_ver && + sec_websocket_ver->value_get_int() == 13) { + DebugTxn("http_trans_upgrade", "Transaction wants upgrade to websockets"); + handle_websocket_upgrade_pre_remap(s); + return true; + } else { + DebugTxn("http_trans_upgrade", "Unable to upgrade connection to websockets, invalid headers (RFC 6455)."); + } + } + } else { + DebugTxn("http_trans_upgrade", "Transaction requested upgrade for unknown protocol: %s", upgrade_hdr_val); + } + + build_error_response(s, HTTP_STATUS_BAD_REQUEST, "Invalid Upgrade Request", "request#syntax_error", + "Invalid Upgrade Request"); + + // we want our modify_request method to just return while we fail out from here. + // this seems like the preferred option because the user wanted to do an upgrade but sent a bad protocol. + TRANSACT_RETURN_VAL(PROXY_SEND_ERROR_CACHE_NOOP, NULL, true); +} + +void +HttpTransact::handle_websocket_upgrade_pre_remap(State *s) { + DebugTxn("http_trans_websocket_upgrade_pre_remap", "Prepping transaction before remap."); + + /* + * We will use this opportunity to set everything up so that during the remap stage we can deal with + * ws:// and wss:// remap rules, and then we will take over again post remap. + */ + s->is_websocket = true; + s->post_remap_upgrade_return_point = HttpTransact::handle_websocket_upgrade_post_remap; + + /* let's modify the url scheme to be wss or ws, so remapping will happen as expected */ + URL *url = s->hdr_info.client_request.url_get(); + if (url->scheme_get_wksidx() == URL_WKSIDX_HTTP) { + DebugTxn("http_trans_websocket_upgrade_pre_remap", "Changing scheme to WS for remapping."); + url->scheme_set(URL_SCHEME_WS, URL_LEN_WS); + } else if (url->scheme_get_wksidx() == URL_WKSIDX_HTTPS) { + DebugTxn("http_trans_websocket_upgrade_pre_remap", "Changing scheme to WSS for remapping."); + url->scheme_set(URL_SCHEME_WSS, URL_LEN_WSS); + } else { + DebugTxn("http_trans_websocket_upgrade_pre_remap", "Invalid scheme for websocket upgrade"); + build_error_response(s, HTTP_STATUS_BAD_REQUEST, "Invalid Upgrade Request", "request#syntax_error", + "Invalid Upgrade Request"); + TRANSACT_RETURN(PROXY_SEND_ERROR_CACHE_NOOP, NULL); + } + + TRANSACT_RETURN(HTTP_API_READ_REQUEST_HDR, HttpTransact::StartRemapRequest); +} + +void +HttpTransact::handle_websocket_upgrade_post_remap(State *s) { + DebugTxn("http_trans_websocket_upgrade_post_remap", "Remap is complete, start websocket upgrade"); + + TRANSACT_RETURN(HTTP_API_POST_REMAP, HttpTransact::handle_websocket_connection); +} + +void +HttpTransact::handle_websocket_connection(State *s) { + DebugTxn("http_trans_websocket", "START handle_websocket_connection"); + + HandleRequest(s); +} + + void HttpTransact::ModifyRequest(State* s) { @@ -1078,6 +1221,13 @@ HttpTransact::ModifyRequest(State* s) DebugTxn("http_trans", "END HttpTransact::ModifyRequest"); + DebugTxn("http_trans", "Checking if transaction wants to upgrade"); + if(handle_upgrade_request(s)) { + // everything should be handled by the upgrade handler. + DebugTxn("http_trans", "Transaction will be upgraded by the appropriate upgrade handler."); + return; + } + TRANSACT_RETURN(HTTP_API_READ_REQUEST_HDR, HttpTransact::StartRemapRequest); } @@ -1129,7 +1279,6 @@ HttpTransact::handleIfRedirect(State *s) return false; } - void HttpTransact::HandleRequest(State* s) { @@ -1158,6 +1307,7 @@ HttpTransact::HandleRequest(State* s) if (is_debug_tag_set("http_chdr_describe")) { obj_describe(s->hdr_info.client_request.m_http, 1); } + // at this point we are guaranteed that the request is good and acceptable. // initialize some state variables from the request (client version, // client keep-alive, cache action, etc. @@ -1251,6 +1401,7 @@ HttpTransact::HandleRequest(State* s) TRANSACT_RETURN(HttpTransact::PROXY_SEND_ERROR_CACHE_NOOP, NULL); } } + // Added to skip the dns if the document is in the cache. // DNS is requested before cache lookup only if there are rules in cache.config , parent.config or // if the newly added varible doc_in_cache_skip_dns is not enabled @@ -5142,7 +5293,8 @@ HttpTransact::RequestError_t HttpTransact::check_request_validity(State* s, HTTP if (!((scheme == URL_WKSIDX_HTTP) && (method == HTTP_WKSIDX_GET))) { if (scheme != URL_WKSIDX_HTTP && scheme != URL_WKSIDX_HTTPS && - method != HTTP_WKSIDX_CONNECT) { + method != HTTP_WKSIDX_CONNECT && + ((scheme == URL_WKSIDX_WS || scheme == URL_WKSIDX_WSS) && !s->is_websocket)) { if (scheme < 0) { return NO_REQUEST_SCHEME; } else { @@ -5471,6 +5623,31 @@ HttpTransact::initialize_state_variables_from_request(State* s, HTTPHdr* obsolet } s->next_hop_scheme = s->scheme = incoming_request->url_get()->scheme_get_wksidx(); + + // With websockets we need to make an outgoing request + // as http or https. + // We switch back to HTTP or HTTPS for the next hop + // I think this is required to properly establish outbound WSS connections, + // you'll need to force the next hop to be https. + if (s->is_websocket) { + if (s->next_hop_scheme == URL_WKSIDX_WS) { + DebugTxn("http_trans", "Switching WS next hop scheme to http."); + s->next_hop_scheme = URL_WKSIDX_HTTP; + s->scheme = URL_WKSIDX_HTTP; + //s->request_data.hdr->url_get()->scheme_set(URL_SCHEME_HTTP, URL_LEN_HTTP); + } else if (s->next_hop_scheme == URL_WKSIDX_WSS) { + DebugTxn("http_trans", "Switching WSS next hop scheme to https."); + s->next_hop_scheme = URL_WKSIDX_HTTPS; + s->scheme = URL_WKSIDX_HTTPS; + //s->request_data.hdr->url_get()->scheme_set(URL_SCHEME_HTTPS, URL_LEN_HTTPS); + } else { + Error("Scheme doesn't match websocket...!"); + } + + s->current.mode = GENERIC_PROXY; + s->cache_info.action = CACHE_DO_NO_ACTION; + } + s->method = incoming_request->method_get_wksidx(); if (s->method == HTTP_WKSIDX_GET) { @@ -5520,6 +5697,7 @@ HttpTransact::initialize_state_variables_from_request(State* s, HTTPHdr* obsolet s->hdr_info.request_content_length = HTTP_UNDEFINED_CL; } s->request_data.hdr = &s->hdr_info.client_request; + s->request_data.hostname_str = s->arena.str_store(host_name, host_len); ats_ip_copy(&s->request_data.src_ip, &s->client_info.addr); memset(&s->request_data.dest_ip, 0, sizeof(s->request_data.dest_ip)); @@ -5570,6 +5748,11 @@ HttpTransact::initialize_state_variables_from_response(State* s, HTTPHdr* incomi s->current.server->keep_alive = is_header_keep_alive(s->hdr_info.server_response.version_get(), s->hdr_info.server_request.version_get(), c_hdr); + // Don't allow an upgrade request to Keep Alive + if (s->is_upgrade_request) { + s->current.server->keep_alive = HTTP_NO_KEEPALIVE; + } + if (s->current.server->keep_alive == HTTP_KEEPALIVE) { if (!s->cop_test_page) DebugTxn("http_hdrs", "[initialize_state_variables_from_response]" "Server is keep-alive."); @@ -6668,44 +6851,53 @@ HttpTransact::handle_request_keep_alive_headers(State* s, HTTPVersion ver, HTTPH // Since connection headers are hop-to-hop, strip the // the ones we received from the user-agent - heads->field_delete(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION); heads->field_delete(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION); + heads->field_delete(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION); - - // Insert K-A headers as necessary - switch (ka_action) { - case KA_CONNECTION: - ink_assert(s->current.server->keep_alive != HTTP_NO_KEEPALIVE); - if (ver == HTTPVersion(1, 0)) { - if (s->current.request_to == PARENT_PROXY || - s->current.request_to == ICP_SUGGESTED_HOST) { - heads->value_set(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION, "keep-alive", 10); - } else { - heads->value_set(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, "keep-alive", 10); + if (!s->is_upgrade_request) { + // Insert K-A headers as necessary + switch (ka_action) { + case KA_CONNECTION: + ink_assert(s->current.server->keep_alive != HTTP_NO_KEEPALIVE); + if (ver == HTTPVersion(1, 0)) { + if (s->current.request_to == PARENT_PROXY || + s->current.request_to == ICP_SUGGESTED_HOST) { + heads->value_set(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION, "keep-alive", 10); + } else { + heads->value_set(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, "keep-alive", 10); + } } - } - // NOTE: if the version is 1.1 we don't need to do - // anything since keep-alive is assumed - break; - case KA_DISABLED: - case KA_CLOSE: - if (s->current.server->keep_alive != HTTP_NO_KEEPALIVE || (ver == HTTPVersion(1, 1))) { - /* Had keep-alive */ - s->current.server->keep_alive = HTTP_NO_KEEPALIVE; - if (s->current.request_to == PARENT_PROXY || - s->current.request_to == ICP_SUGGESTED_HOST) { - heads->value_set(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION, "close", 5); - } else { - heads->value_set(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, "close", 5); + // NOTE: if the version is 1.1 we don't need to do + // anything since keep-alive is assumed + break; + case KA_DISABLED: + case KA_CLOSE: + if (s->current.server->keep_alive != HTTP_NO_KEEPALIVE || (ver == HTTPVersion(1, 1))) { + /* Had keep-alive */ + s->current.server->keep_alive = HTTP_NO_KEEPALIVE; + if (s->current.request_to == PARENT_PROXY || + s->current.request_to == ICP_SUGGESTED_HOST) { + heads->value_set(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION, "close", 5); + } else { + heads->value_set(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, "close", 5); + } } + // Note: if we are 1.1, we always need to send the close + // header since persistant connnections are the default + break; + case KA_UNKNOWN: + default: + ink_assert(0); + break; + } + } else { /* websocket connection */ + s->current.server->keep_alive = HTTP_NO_KEEPALIVE; + s->client_info.keep_alive = HTTP_NO_KEEPALIVE; + heads->value_set(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE); + + if (s->is_websocket) { + heads->value_set(MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE, "websocket", 9); } - // Note: if we are 1.1, we always need to send the close - // header since persistant connnections are the default - break; - case KA_UNKNOWN: - default: - ink_assert(0); - break; } } /* End HttpTransact::handle_request_keep_alive_headers */ @@ -6736,6 +6928,24 @@ HttpTransact::handle_response_keep_alive_headers(State* s, HTTPVersion ver, HTTP heads->field_delete(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION); heads->field_delete(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION); + // Handle the upgrade cases + if (s->is_upgrade_request && + heads->status_get() == HTTP_STATUS_SWITCHING_PROTOCOL && + s->source == SOURCE_HTTP_ORIGIN_SERVER) { + s->client_info.keep_alive = HTTP_NO_KEEPALIVE; + if (s->is_websocket) { + DebugTxn("http_trans", "transaction successfully upgraded to websockets."); + //s->transparent_passthrough = true; + heads->value_set(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE); + heads->value_set(MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE, "websocket", 9); + } + + // We set this state so that we can jump to our blind forwarding state once + // the response is sent to the client. + s->did_upgrade_succeed = true; + return; + } + int c_hdr_field_len; const char *c_hdr_field_str; if (s->client_info.proxy_connect_hdr) { @@ -7585,7 +7795,9 @@ HttpTransact::build_request(State* s, HTTPHdr* base_request, HTTPHdr* outgoing_r } if (s->current.server == &s->server_info && - (s->next_hop_scheme == URL_WKSIDX_HTTP || s->next_hop_scheme == URL_WKSIDX_HTTPS)) { + (s->next_hop_scheme == URL_WKSIDX_HTTP || s->next_hop_scheme == URL_WKSIDX_HTTPS || + s->next_hop_scheme == URL_WKSIDX_WS || s->next_hop_scheme == URL_WKSIDX_WSS)) { + DebugTxn("http_trans", "[build_request] removing host name from url"); HttpTransactHeaders::remove_host_name_from_url(outgoing_request); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpTransact.h ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h index ad3152b..21d8a40 100644 --- a/proxy/http/HttpTransact.h +++ b/proxy/http/HttpTransact.h @@ -79,12 +79,20 @@ } -#define TRANSACT_RETURN(n, r) \ +#define TRANSACT_SETUP_RETURN(n, r) \ s->next_action = n; \ s->transact_return_point = r; \ DebugSpecific((s->state_machine && s->state_machine->debug_on), "http_trans", "Next action %s; %s", #n, #r); \ + +#define TRANSACT_RETURN(n, r) \ +TRANSACT_SETUP_RETURN(n, r) \ return; \ +#define TRANSACT_RETURN_VAL(n, r, v) \ +TRANSACT_SETUP_RETURN(n, r) \ +return v; \ + + #define SET_UNPREPARE_CACHE_ACTION(C) \ { \ if (C.action == HttpTransact::CACHE_PREPARE_TO_DELETE) { \ @@ -499,7 +507,8 @@ public: HTTP_REMAP_REQUEST, HTTP_API_POST_REMAP, HTTP_POST_REMAP_SKIP, - + HTTP_POST_REMAP_UPGRADE, + HTTP_API_OS_DNS, HTTP_API_SEND_REQUEST_HDR, HTTP_API_READ_CACHE_HDR, @@ -894,6 +903,16 @@ public: StateMachineAction_t next_action; // out StateMachineAction_t api_next_action; // out void (*transact_return_point) (HttpTransact::State* s); // out + + // We keep this so we can jump back to the upgrade handler after remap is complete + bool is_upgrade_request; + void (*post_remap_upgrade_return_point) (HttpTransact::State* s); // out + const char *upgrade_token_wks; + + // Some WebSocket state + bool is_websocket; + bool did_upgrade_succeed; + char *internal_msg_buffer; // out char *internal_msg_buffer_type; // out int64_t internal_msg_buffer_size; // out @@ -1031,6 +1050,11 @@ public: next_action(STATE_MACHINE_ACTION_UNDEFINED), api_next_action(STATE_MACHINE_ACTION_UNDEFINED), transact_return_point(NULL), + is_upgrade_request(false), + post_remap_upgrade_return_point(NULL), + upgrade_token_wks(NULL), + is_websocket(false), + did_upgrade_succeed(false), internal_msg_buffer(0), internal_msg_buffer_type(0), internal_msg_buffer_size(0), @@ -1259,6 +1283,10 @@ public: static void merge_warning_header(HTTPHdr* cached_header, HTTPHdr* response_header); static void SetCacheFreshnessLimit(State* s); static void HandleApiErrorJump(State *); + static void handle_websocket_upgrade_pre_remap(State *s); + static void handle_websocket_upgrade_post_remap(State *s); + static bool handle_upgrade_request(State *s); + static void handle_websocket_connection(State *s); static void HandleCacheOpenReadPush(State* s, bool read_successful); static void HandlePushResponseHdr(State* s); @@ -1298,6 +1326,7 @@ public: static bool is_request_cache_lookupable(State* s); static bool is_request_valid(State* s, HTTPHdr* incoming_request); static bool is_request_retryable(State* s); + static bool is_response_cacheable(State* s, HTTPHdr* request, HTTPHdr* response); static bool is_response_valid(State* s, HTTPHdr* incoming_response); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/HttpTransactHeaders.cc ---------------------------------------------------------------------- diff --git a/proxy/http/HttpTransactHeaders.cc b/proxy/http/HttpTransactHeaders.cc index b5ab0fe..0cebb0f 100644 --- a/proxy/http/HttpTransactHeaders.cc +++ b/proxy/http/HttpTransactHeaders.cc @@ -68,9 +68,12 @@ HttpTransactHeaders::is_this_method_supported(int the_scheme, int the_method) { if (the_method == HTTP_WKSIDX_CONNECT) { return true; - } else if (the_scheme == URL_WKSIDX_HTTP || the_scheme == URL_WKSIDX_HTTPS) + } else if (the_scheme == URL_WKSIDX_HTTP || the_scheme == URL_WKSIDX_HTTPS) { return is_this_http_method_supported(the_method); - else + } else if ((the_scheme == URL_WKSIDX_WS || the_scheme == URL_WKSIDX_WSS) && + the_method == HTTP_WKSIDX_GET) { + return true; + } else return false; } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cca82f1b/proxy/http/remap/RemapConfig.cc ---------------------------------------------------------------------- diff --git a/proxy/http/remap/RemapConfig.cc b/proxy/http/remap/RemapConfig.cc index 787fbb0..c138557 100644 --- a/proxy/http/remap/RemapConfig.cc +++ b/proxy/http/remap/RemapConfig.cc @@ -1082,12 +1082,23 @@ remap_parse_config_bti(const char * path, BUILD_TABLE_INFO * bti) // includes support for FILE scheme if ((fromScheme != URL_SCHEME_HTTP && fromScheme != URL_SCHEME_HTTPS && fromScheme != URL_SCHEME_FILE && - fromScheme != URL_SCHEME_TUNNEL) || + fromScheme != URL_SCHEME_TUNNEL && + fromScheme != URL_SCHEME_WS && + fromScheme != URL_SCHEME_WSS) || (toScheme != URL_SCHEME_HTTP && toScheme != URL_SCHEME_HTTPS && - toScheme != URL_SCHEME_TUNNEL)) { - errStr = "Only http, https, and tunnel remappings are supported"; + toScheme != URL_SCHEME_TUNNEL && toScheme != URL_SCHEME_WS && + toScheme != URL_SCHEME_WSS)) { + errStr = "Only http, https, ws, wss, and tunnel remappings are supported"; goto MAP_ERROR; } + + // If mapping from WS or WSS we must map out to WS or WSS + if ( (fromScheme == URL_SCHEME_WSS || fromScheme == URL_SCHEME_WS) && + (toScheme != URL_SCHEME_WSS && toScheme != URL_SCHEME_WS)) { + errStr = "WS or WSS can only be mapped out to WS or WSS."; + goto MAP_ERROR; + } + // Check if a tag is specified. if (bti->paramv[3] != NULL) { if (maptype == FORWARD_MAP_REFERER) {
