diff options
-rw-r--r-- | guide/http.md | 13 | ||||
-rw-r--r-- | guide/protocols.md | 6 | ||||
-rw-r--r-- | src/gun_spdy.erl | 27 |
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}) -> |