File chatterbox-0.8.0-git.patch of Package chatterbox

diff --git a/include/http2.hrl b/include/http2.hrl
index a0183a6..55b6a90 100644
--- a/include/http2.hrl
+++ b/include/http2.hrl
@@ -79,7 +79,7 @@
               | ?FLAG_PADDED
               | ?FLAG_PRIORITY.
 
-%% These are macros because they're used in guards alot
+%% These are macros because they're used in guards a lot
 -define(IS_FLAG(Flags, Flag), Flags band Flag =:= Flag).
 -define(NOT_FLAG(Flags, Flag), Flags band Flag =/= Flag).
 
diff --git a/src/h2_client.erl b/src/h2_client.erl
index 493292d..f0b7233 100644
--- a/src/h2_client.erl
+++ b/src/h2_client.erl
@@ -19,6 +19,7 @@
          start_link/2,
          start_link/3,
          start_link/4,
+         start/4,
          start_ssl_upgrade_link/4,
          stop/1,
          send_request/3,
@@ -108,6 +109,20 @@ start_link(Transport, Host, Port, SSLOptions) ->
            end,
     h2_connection:start_client_link(NewT, Host, Port, SSLOptions, chatterbox:settings(client)).
 
+-spec start(http | https,
+                 string(),
+                 non_neg_integer(),
+                 [ssl:ssl_option()]) ->
+                        {ok, pid()}
+                      | ignore
+                      | {error, term()}.
+start(Transport, Host, Port, SSLOptions) ->
+    NewT = case Transport of
+               http -> gen_tcp;
+               https -> ssl
+           end,
+    h2_connection:start_client(NewT, Host, Port, SSLOptions, chatterbox:settings(client)).
+
 start_ssl_upgrade_link(Host, Port, InitialMessage, SSLOptions) ->
     h2_connection:start_ssl_upgrade_link(Host, Port, InitialMessage, SSLOptions, chatterbox:settings(client)).
 
diff --git a/src/h2_connection.erl b/src/h2_connection.erl
index 6e0018e..856e7c5 100644
--- a/src/h2_connection.erl
+++ b/src/h2_connection.erl
@@ -4,6 +4,9 @@
 
 %% Start/Stop API
 -export([
+         start_client/2,
+         start_client/5,
+         start_client_link/2,
          start_client_link/5,
          start_ssl_upgrade_link/5,
          start_server_link/3,
@@ -121,6 +124,30 @@
 start_client_link(Transport, Host, Port, SSLOptions, Http2Settings) ->
     gen_statem:start_link(?MODULE, {client, Transport, Host, Port, SSLOptions, Http2Settings}, []).
 
+-spec start_client(gen_tcp | ssl,
+                        inet:ip_address() | inet:hostname(),
+                        inet:port_number(),
+                        [ssl:ssl_option()],
+                        settings()
+                       ) ->
+                               {ok, pid()} | ignore | {error, term()}.
+start_client(Transport, Host, Port, SSLOptions, Http2Settings) ->
+    gen_statem:start(?MODULE, {client, Transport, Host, Port, SSLOptions, Http2Settings}, []).
+
+-spec start_client_link(socket(),
+                        settings()
+                       ) ->
+                               {ok, pid()} | ignore | {error, term()}.
+start_client_link({Transport, Socket}, Http2Settings) ->
+    gen_statem:start_link(?MODULE, {client, {Transport, Socket}, Http2Settings}, []).
+
+-spec start_client(socket(),
+                        settings()
+                       ) ->
+                               {ok, pid()} | ignore | {error, term()}.
+start_client({Transport, Socket}, Http2Settings) ->
+    gen_statem:start(?MODULE, {client, {Transport, Socket}, Http2Settings}, []).
+
 -spec start_ssl_upgrade_link(inet:ip_address() | inet:hostname(),
                              inet:port_number(),
                              binary(),
@@ -133,7 +160,7 @@ start_ssl_upgrade_link(Host, Port, InitialMessage, SSLOptions, Http2Settings) ->
 
 -spec start_server_link(socket(),
                         [ssl:ssl_option()],
-                        #settings{}) ->
+                        settings()) ->
                                {ok, pid()} | ignore | {error, term()}.
 start_server_link({Transport, ListenSocket}, SSLOptions, Http2Settings) ->
     gen_statem:start_link(?MODULE, {server, {Transport, ListenSocket}, SSLOptions, Http2Settings}, []).
@@ -149,8 +176,7 @@ become(Socket, Http2Settings) ->
 -spec become(socket(), settings(), maps:map()) -> no_return().
 become({Transport, Socket}, Http2Settings, ConnectionSettings) ->
     ok = sock:setopts({Transport, Socket}, [{packet, raw}, binary]),
-    {_, _, NewState} =
-        start_http2_server(Http2Settings,
+    case start_http2_server(Http2Settings,
                            #connection{
                               stream_callback_mod =
                                   maps:get(stream_callback_mod, ConnectionSettings,
@@ -160,54 +186,47 @@ become({Transport, Socket}, Http2Settings, ConnectionSettings) ->
                                            application:get_env(chatterbox, stream_callback_opts, [])),
                               streams = h2_stream_set:new(server),
                               socket = {Transport, Socket}
-                             }),
-    gen_statem:enter_loop(?MODULE,
-                       [],
-                       handshake,
-                       NewState).
+                             }) of
+        {_, handshake, NewState} ->
+            gen_statem:enter_loop(?MODULE,
+                                  [],
+                                  handshake,
+                                  NewState);
+        {_, closing, _NewState} ->
+            sock:close({Transport, Socket}),
+            exit(invalid_preface)
+    end.
 
 %% Init callback
 init({client, Transport, Host, Port, SSLOptions, Http2Settings}) ->
     case Transport:connect(Host, Port, client_options(Transport, SSLOptions)) of
         {ok, Socket} ->
-            ok = sock:setopts({Transport, Socket}, [{packet, raw}, binary]),
-            Transport:send(Socket, <<?PREFACE>>),
-            InitialState =
-                #connection{
-                   type = client,
-                   streams = h2_stream_set:new(client),
-                   socket = {Transport, Socket},
-                   next_available_stream_id=1,
-                   flow_control=application:get_env(chatterbox, client_flow_control, auto)
-                  },
-            {ok,
-             handshake,
-             send_settings(Http2Settings, InitialState),
-             4500};
+            init({client, {Transport, Socket}, Http2Settings});
         {error, Reason} ->
             {stop, Reason}
     end;
+init({client, {Transport, Socket}, Http2Settings}) ->
+    ok = sock:setopts({Transport, Socket}, [{packet, raw}, binary, {active, once}]),
+    Transport:send(Socket, <<?PREFACE>>),
+    InitialState =
+        #connection{
+           type = client,
+           streams = h2_stream_set:new(client),
+           socket = {Transport, Socket},
+           next_available_stream_id=1,
+           flow_control=application:get_env(chatterbox, client_flow_control, auto)
+          },
+    {ok,
+     handshake,
+     send_settings(Http2Settings, InitialState),
+     4500};
 init({client_ssl_upgrade, Host, Port, InitialMessage, SSLOptions, Http2Settings}) ->
     case gen_tcp:connect(Host, Port, [{active, false}]) of
         {ok, TCP} ->
             gen_tcp:send(TCP, InitialMessage),
             case ssl:connect(TCP, client_options(ssl, SSLOptions)) of
                 {ok, Socket} ->
-                    active_once({ssl, Socket}),
-                    ok = ssl:setopts(Socket, [{packet, raw}, binary]),
-                    ssl:send(Socket, <<?PREFACE>>),
-                    InitialState =
-                        #connection{
-                           type = client,
-                           streams = h2_stream_set:new(client),
-                           socket = {ssl, Socket},
-                           next_available_stream_id=1,
-                           flow_control=application:get_env(chatterbox, client_flow_control, auto)
-                          },
-                    {ok,
-                     handshake,
-                     send_settings(Http2Settings, InitialState),
-                     4500};
+                    init({client, {ssl, Socket}, Http2Settings});
                 {error, Reason} ->
                     {stop, Reason}
             end;
@@ -966,13 +985,15 @@ handle_event(_, {send_headers, StreamId, Headers, Opts},
         closed ->
             {keep_state, Conn}
     end;
-handle_event(_, {send_trailers, StreamId, Headers, _Opts},
+handle_event(_, {send_trailers, StreamId, Headers, Opts},
              #connection{
                 encode_context=EncodeContext,
                 streams = Streams,
                 socket = _Socket
                }=Conn
             ) ->
+    BodyComplete = proplists:get_value(send_end_stream, Opts, true),
+
     Stream = h2_stream_set:get(StreamId, Streams),
     case h2_stream_set:type(Stream) of
         active ->
@@ -990,7 +1011,7 @@ handle_event(_, {send_trailers, StreamId, Headers, _Opts},
                   Conn#connection.send_window_size,
                   (Conn#connection.peer_settings)#settings.max_frame_size,
                   h2_stream_set:upsert(
-                    h2_stream_set:update_data_queue(h2_stream_set:queued_data(Stream), false, NewS),
+                    h2_stream_set:update_data_queue(h2_stream_set:queued_data(Stream), BodyComplete, NewS),
                     Conn#connection.streams)),
 
             send_t(Stream, Headers),
@@ -1036,7 +1057,7 @@ handle_event(_, {send_body, StreamId, Body, Opts},
               }};
         idle ->
             %% Sending DATA frames on an idle stream?  It's a
-            %% Connection level protocol error on reciept, but If we
+            %% Connection level protocol error on receipt, but If we
             %% have no active stream what can we even do?
             {keep_state, Conn};
         closed ->
@@ -1359,7 +1380,7 @@ client_options(Transport, SSLOptions) ->
     ClientSocketOptions = [
                            binary,
                            {packet, raw},
-                           {active, once}
+                           {active, false}
                           ],
     case Transport of
         ssl ->
diff --git a/src/h2_frame.erl b/src/h2_frame.erl
index e07bc14..5c3c772 100644
--- a/src/h2_frame.erl
+++ b/src/h2_frame.erl
@@ -43,7 +43,7 @@
     {ok, payload(), Remainder::binary()}
   | {error, stream_id(), error_code(), binary()}.
 
-%% For io:formating
+%% For io:formatting
 -callback format(payload()) -> iodata().
 
 %% convert payload to binary
diff --git a/src/h2_padding.erl b/src/h2_padding.erl
index f948b2b..10f6557 100644
--- a/src/h2_padding.erl
+++ b/src/h2_padding.erl
@@ -26,8 +26,8 @@ read_possibly_padded_payload(Bin, Header) ->
                          -> binary() | {error, error_code()}.
 read_padded_payload(<<Padding:8,Bytes/bits>>,
                     #frame_header{length=Length}) ->
-    L = Length - Padding,
-    case L > 0 of
+    L = Length - Padding - 1, % Exclude Pad length field (1 byte)
+    case L >= 0 of
         true ->
             <<Data:L/binary,_:Padding/binary>> = Bytes,
             Data;
diff --git a/src/h2_stream_set.erl b/src/h2_stream_set.erl
index 4a2c6a1..6f243a4 100644
--- a/src/h2_stream_set.erl
+++ b/src/h2_stream_set.erl
@@ -78,7 +78,7 @@
      % Data that is in queue to send on this stream, if flow control
      % hasn't allowed it to be sent yet
      queued_data           :: undefined | done | binary(),
-     % Has the body been completely recieved.
+     % Has the body been completely received.
      body_complete = false :: boolean(),
      trailers = undefined  :: [h2_frame:frame()] | undefined
     }).
@@ -86,7 +86,7 @@
 
 %% The closed_stream record is way more important to a client than a
 %% server. It's a way of holding on to a response that has been
-%% recieved, but not processed by the client yet.
+%% received, but not processed by the client yet.
 -record(
    closed_stream, {
      id               :: stream_id(),
@@ -113,7 +113,7 @@
 -type idle_stream() :: #idle_stream{}.
 
 %% So a stream can be any of these things. And it will be something
-%% that you can pass back into serveral functions here in this module.
+%% that you can pass back into several functions here in this module.
 -type stream() :: active_stream()
                 | closed_stream()
                 | idle_stream().
@@ -374,7 +374,7 @@ upsert_peer_subset(
   PeerSubset)
   when Id >= PeerSubset#peer_subset.lowest_stream_id,
        Id < PeerSubset#peer_subset.next_available_stream_id ->
-    OldStream = lists:keyfind(Id, 2, PeerSubset#peer_subset.active),
+    OldStream = get_from_subset(Id, PeerSubset),
     OldType = type(OldStream),
     ActiveDiff =
         case OldType of
@@ -393,7 +393,7 @@ upsert_peer_subset(
               lowest_stream_id=PeerSubset#peer_subset.next_available_stream_id,
               active_count=0,
               active=[]
-              };
+             };
         [NewLowestStream|_] ->
             NewLowest = stream_id(NewLowestStream),
             PeerSubset#peer_subset{
@@ -411,7 +411,7 @@ upsert_peer_subset(
   PeerSubset)
   when Id >= PeerSubset#peer_subset.lowest_stream_id,
        Id < PeerSubset#peer_subset.next_available_stream_id ->
-    OldStream = lists:keyfind(Id, 2, PeerSubset#peer_subset.active),
+    OldStream = get_from_subset(Id, PeerSubset),
     OldType = type(OldStream),
     ActiveDiff =
         case OldType of
@@ -678,7 +678,7 @@ s_send_what_we_can(SWS, MFS, #active_stream{}=Stream) ->
     %% We're coming in here with three numbers we need to look at:
     %% * Connection send window size
     %% * Stream send window size
-    %% * Maximimum frame size
+    %% * Maximum frame size
 
     %% If none of them are zero, we have to send something, so we're
     %% going to figure out what's the biggest number we can send. If
@@ -818,10 +818,30 @@ update_data_queue(_, _, S) ->
 response(#closed_stream{
             response_headers=Headers,
             response_body=Body}) ->
-    {Headers, Body};
+    Encoding = case lists:keyfind(<<"content-encoding">>, 1, Headers) of
+        false -> identity;
+        {_, Encoding0} -> binary_to_atom(Encoding0, 'utf8')
+    end,
+    {Headers, decode_body(Body, Encoding)};
 response(_) ->
     no_response.
 
+decode_body(Body, identity) ->
+    Body;
+decode_body(Body, gzip) ->
+    zlib:gunzip(Body);
+decode_body(Body, zip) ->
+    zlib:unzip(Body);
+decode_body(Body, compress) ->
+    zlib:uncompress(Body);
+decode_body(Body, deflate) ->
+    Z = zlib:open(),
+    ok = zlib:inflateInit(Z, -15),
+    Decompressed = try zlib:inflate(Z, Body) catch E:V -> {E,V} end,
+    ok = zlib:inflateEnd(Z),
+    ok = zlib:close(Z),
+    iolist_to_binary(Decompressed).
+
 recv_window_size(#active_stream{recv_window_size=RWS}) ->
     RWS;
 recv_window_size(_) ->
diff --git a/test/client_server_SUITE_data/css/theme/README.md b/test/client_server_SUITE_data/css/theme/README.md
index 5a6c8fa..1bca121 100644
--- a/test/client_server_SUITE_data/css/theme/README.md
+++ b/test/client_server_SUITE_data/css/theme/README.md
@@ -1,6 +1,6 @@
 ## Dependencies
 
-Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceding: https://github.com/hakimel/reveal.js#full-setup
+Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceeding: https://github.com/hakimel/reveal.js#full-setup
 
 ## Creating a Theme
 
diff --git a/test/client_server_SUITE_data/js/reveal.js b/test/client_server_SUITE_data/js/reveal.js
index d2b2970..2ccfd6a 100644
--- a/test/client_server_SUITE_data/js/reveal.js
+++ b/test/client_server_SUITE_data/js/reveal.js
@@ -121,7 +121,7 @@
 			// Dispatches all reveal.js events to the parent window through postMessage
 			postMessageEvents: false,
 
-			// Focuses body when page changes visiblity to ensure keyboard shortcuts work
+			// Focuses body when page changes visibility to ensure keyboard shortcuts work
 			focusBodyOnPageVisibilityChange: true,
 
 			// Transition style
@@ -4666,7 +4666,7 @@
 			}
 		},
 
-		// Programatically triggers a keyboard event
+		// Programmatically triggers a keyboard event
 		triggerKey: function( keyCode ) {
 			onDocumentKeyDown( { keyCode: keyCode } );
 		}
diff --git a/test/http2c.erl b/test/http2c.erl
index b67890f..5e7151a 100644
--- a/test/http2c.erl
+++ b/test/http2c.erl
@@ -53,7 +53,7 @@ start_link() ->
 
 %% Three API levels:
 %% 1: lowest: Send a frame or set of frames
-%% 2: middle: Here's some hastily constucted frames, do some setup of frame header flags.
+%% 2: middle: Here's some hastily constructed frames, do some setup of frame header flags.
 %% 3: highest: a semantic http request: **NOT IMPLEMENTED HERE*
 
 %% send_binary/2 is the lowest level API. It just puts bits on the
@@ -64,8 +64,8 @@ send_binary(Pid, Binary) ->
 
 %% send_unaltered_frames is the raw version of the middle level. You
 %% can put frames directly as constructed on the wire. This is
-%% desgined for testing error conditions by giving you the freedom to
-%% create bad sets of frames. This will problably only be exported
+%% designed for testing error conditions by giving you the freedom to
+%% create bad sets of frames. This will probably only be exported
 %% ifdef(TEST)
 -spec send_unaltered_frames(pid(), [h2_frame:frame()]) -> ok.
 send_unaltered_frames(Pid, Frames) ->
@@ -142,7 +142,7 @@ init([]) ->
     BinToSend = h2_frame_settings:send(#settings{}, ClientSettings),
     Transport:send(Socket, BinToSend),
 
-    {AH, _PAck} = h2_frame:read({Transport, Socket}, 100),
+    {AH, _PAck} = h2_frame:read({Transport, Socket}, 1000),
     _ = ?IS_FLAG((AH#frame_header.flags), ?FLAG_ACK),
 
     case Transport of
openSUSE Build Service is sponsored by