aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2013-06-03 19:10:03 +0200
committerLoïc Hoguin <[email protected]>2013-06-03 19:10:03 +0200
commit1fc69977da8f57d5d3fa48cd68280aa2c0b1d78b (patch)
tree4498bedb4f940a83a8f9b04dfb539efcc1115f43 /src
parente50f7e40862e42feee227acbd3135657d2ea8ee2 (diff)
downloadcowboy-1fc69977da8f57d5d3fa48cd68280aa2c0b1d78b.tar.gz
cowboy-1fc69977da8f57d5d3fa48cd68280aa2c0b1d78b.tar.bz2
cowboy-1fc69977da8f57d5d3fa48cd68280aa2c0b1d78b.zip
Add sendfile support to SPDY, enabling cowboy_static use
Diffstat (limited to 'src')
-rw-r--r--src/cowboy_spdy.erl38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/cowboy_spdy.erl b/src/cowboy_spdy.erl
index ba02706..d605331 100644
--- a/src/cowboy_spdy.erl
+++ b/src/cowboy_spdy.erl
@@ -42,6 +42,7 @@
%% Internal transport functions.
-export([name/0]).
-export([send/2]).
+-export([sendfile/2]).
-record(child, {
streamid :: non_neg_integer(),
@@ -174,6 +175,14 @@ loop(State=#state{parent=Parent, socket=Socket, transport=Transport,
Children2 = lists:keyreplace(StreamID,
#child.streamid, Children, Child#child{output=fin}),
loop(State#state{children=Children2});
+ {sendfile, {Pid, StreamID}, Filepath}
+ when Pid =:= self() ->
+ Child = #child{output=nofin} = lists:keyfind(StreamID,
+ #child.streamid, Children),
+ data_from_file(State, StreamID, Filepath),
+ Children2 = lists:keyreplace(StreamID,
+ #child.streamid, Children, Child#child{output=fin}),
+ loop(State#state{children=Children2});
{'EXIT', Parent, Reason} ->
exit(Reason);
{'EXIT', Pid, _} ->
@@ -430,6 +439,27 @@ data(#state{socket=Socket, transport=Transport}, IsFin, StreamID, Data) ->
<< 0:1, StreamID:31, Flags:8, Len:24 >>,
Data]).
+data_from_file(#state{socket=Socket, transport=Transport},
+ StreamID, Filepath) ->
+ {ok, IoDevice} = file:open(Filepath, [read, binary, raw]),
+ data_from_file(Socket, Transport, StreamID, IoDevice).
+
+data_from_file(Socket, Transport, StreamID, IoDevice) ->
+ case file:read(IoDevice, 16#1fff) of
+ eof ->
+ _ = Transport:send(Socket, << 0:1, StreamID:31, 1:8, 0:24 >>),
+ ok;
+ {ok, Data} ->
+ Len = byte_size(Data),
+ Data2 = [<< 0:1, StreamID:31, 0:8, Len:24 >>, Data],
+ case Transport:send(Socket, Data2) of
+ ok ->
+ data_from_file(Socket, Transport, StreamID, IoDevice);
+ {error, _} ->
+ ok
+ end
+ end.
+
%% Request process.
request_init(Parent, StreamID, Peer,
@@ -535,10 +565,16 @@ stream_close(Socket = {Pid, _}) ->
ok.
%% Internal transport functions.
-%% @todo recv, sendfile
+%% @todo recv
name() ->
spdy.
send(Socket, Data) ->
stream_data(Socket, Data).
+
+%% We don't wait for the result of the actual sendfile call,
+%% therefore we can't know how much was actually sent.
+sendfile(Socket = {Pid, _}, Filepath) ->
+ _ = Pid ! {sendfile, Socket, Filepath},
+ {ok, undefined}.