aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2013-08-26 18:55:41 +0200
committerLoïc Hoguin <[email protected]>2013-08-26 18:56:54 +0200
commit5388696cf95d6c9b4400952bfcf3fb9db215c63c (patch)
treeeb5c52c44e250e1b2699167e11d297f598e310d5
parent0c5a2c3a9097207da803da7ee45cdad2d387a5a4 (diff)
downloadgun-5388696cf95d6c9b4400952bfcf3fb9db215c63c.tar.gz
gun-5388696cf95d6c9b4400952bfcf3fb9db215c63c.tar.bz2
gun-5388696cf95d6c9b4400952bfcf3fb9db215c63c.zip
Fix server pushed streams
-rw-r--r--guide/http.md13
-rw-r--r--guide/protocols.md6
-rw-r--r--src/gun_spdy.erl27
3 files changed, 36 insertions, 10 deletions
diff --git a/guide/http.md b/guide/http.md
index 98a042e..e6b5f64 100644
--- a/guide/http.md
+++ b/guide/http.md
@@ -206,3 +206,16 @@ one for the request this stream is associated with.
Pushed streams typically feature a body. Replying to a pushed
stream is forbidden and Gun will send an error message if
attempted.
+
+Pushed streams can be received like this:
+
+``` erlang
+receive
+ {gun_push, Pid, PushedStreamRef, StreamRef,
+ Method, Host, Path, Headers} ->
+ %% ...
+end
+```
+
+The pushed stream gets a new identifier but you still receive
+the `StreamRef` this stream is associated to.
diff --git a/guide/protocols.md b/guide/protocols.md
index 87ab0cf..c3aef6f 100644
--- a/guide/protocols.md
+++ b/guide/protocols.md
@@ -64,9 +64,9 @@ Messages by protocol
This table lists all messages that can be received depending
on the current protocol.
-| Message | SPDY | HTTP | Websocket |
-| -------------------------------- | ---- | ---- | --------- |
-| {gun_request, ...} | yes | no | no |
+| Message | SPDY | HTTP | Websocket |
+| ------------------------------- | ---- | ---- | --------- |
+| {gun_push, ...} | yes | no | no |
| {gun_response, ...} | yes | yes | no |
| {gun_data, ...} | yes | yes | no |
| {gun_error, _, StreamRef, _} | yes | yes | no |
diff --git a/src/gun_spdy.erl b/src/gun_spdy.erl
index 410ed57..98c538f 100644
--- a/src/gun_spdy.erl
+++ b/src/gun_spdy.erl
@@ -80,20 +80,33 @@ handle_frame(Rest, State=#spdy_state{owner=Owner,
end;
handle_frame(Rest, State=#spdy_state{owner=Owner,
socket=Socket, transport=Transport},
- {syn_stream, StreamID, _, IsFin, IsUnidirectional,
- _, Method, _, Host, Path, Version, Headers}) ->
+ {syn_stream, StreamID, AssocToStreamID, IsFin, IsUnidirectional,
+ _, Method, _, Host, Path, Version, Headers})
+ when AssocToStreamID =/= 0, IsUnidirectional ->
case get_stream_by_id(StreamID, State) of
false ->
- StreamRef = make_ref(),
- Owner ! {gun, request, self(), StreamRef,
- Method, Host, Path, Headers},
- handle_loop(Rest, new_stream(StreamID, StreamRef,
- not IsFin, not IsUnidirectional, Version, State));
+ case get_stream_by_id(AssocToStreamID, State) of
+ #stream{ref=AssocToStreamRef} ->
+ StreamRef = make_ref(),
+ Owner ! {gun_push, self(), StreamRef,
+ AssocToStreamRef, Method, Host, Path, Headers},
+ handle_loop(Rest, new_stream(StreamID, StreamRef,
+ not IsFin, false, Version, State));
+ false ->
+ Transport:send(Socket,
+ cow_spdy:rst_stream(AssocToStreamID, invalid_stream)),
+ handle_loop(Rest, State)
+ end;
#stream{} ->
Transport:send(Socket,
cow_spdy:rst_stream(StreamID, stream_in_use)),
handle_loop(Rest, State)
end;
+handle_frame(Rest, State=#spdy_state{socket=Socket, transport=Transport},
+ {syn_stream, StreamID, _, _, _, _, _, _, _, _, _, _}) ->
+ Transport:send(Socket,
+ cow_spdy:rst_stream(StreamID, protocol_error)),
+ handle_loop(Rest, State);
handle_frame(Rest, State=#spdy_state{owner=Owner,
socket=Socket, transport=Transport},
{syn_reply, StreamID, IsFin, Status, _, Headers}) ->