You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@trafficserver.apache.org by James Peach <jp...@apache.org> on 2014/02/04 02:30:47 UTC
Re: [1/2] git commit: [TS-2541] Add WebSocket Support
On Feb 3, 2014, at 11:11 AM, briang@apache.org wrote:
> Updated Branches:
> refs/heads/master f0f9cb9c3 -> 60ec95053
>
>
> [TS-2541] Add WebSocket Support
Nice; were you planning to update the docs?
>
>
> 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 <br...@apache.org>
> Authored: Mon Feb 3 11:10:44 2014 -0800
> Committer: Brian Geffon <br...@apache.org>
> 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) {
>