aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2013-02-06 23:32:31 +0100
committerLoïc Hoguin <[email protected]>2013-02-06 23:32:31 +0100
commitae401f7460664256de588d9a0bfee4c3b1560738 (patch)
tree42035aa85bd9def0a7a9f95931bf4bf8e4491219
parent1541e38d538fc713a71d82764830b0aee563be4b (diff)
downloadcowboy-ae401f7460664256de588d9a0bfee4c3b1560738.tar.gz
cowboy-ae401f7460664256de588d9a0bfee4c3b1560738.tar.bz2
cowboy-ae401f7460664256de588d9a0bfee4c3b1560738.zip
Fix crashes when creating the request
We now obtain the peer address before creating the Req object. If an error occurs, then something went wrong, we close the connection nicely directly.
-rw-r--r--src/cowboy_protocol.erl18
-rw-r--r--src/cowboy_req.erl12
2 files changed, 19 insertions, 11 deletions
diff --git a/src/cowboy_protocol.erl b/src/cowboy_protocol.erl
index b479fa9..caf0806 100644
--- a/src/cowboy_protocol.erl
+++ b/src/cowboy_protocol.erl
@@ -463,10 +463,16 @@ request(Buffer, State=#state{socket=Socket, transport=Transport,
req_keepalive=ReqKeepalive, max_keepalive=MaxKeepalive,
compress=Compress, onresponse=OnResponse},
Method, Path, Query, Fragment, Version, Headers, Host, Port) ->
- Req = cowboy_req:new(Socket, Transport, Method, Path, Query, Fragment,
- Version, Headers, Host, Port, Buffer, ReqKeepalive < MaxKeepalive,
- Compress, OnResponse),
- onrequest(Req, State).
+ case Transport:peername(Socket) of
+ {ok, Peer} ->
+ Req = cowboy_req:new(Socket, Transport, Peer, Method, Path,
+ Query, Fragment, Version, Headers, Host, Port, Buffer,
+ ReqKeepalive < MaxKeepalive, Compress, OnResponse),
+ onrequest(Req, State);
+ {error, _} ->
+ %% Couldn't read the peer address; connection is gone.
+ terminate(State)
+ end.
%% Call the global onrequest callback. The callback can send a reply,
%% in which case we consider the request handled and move on to the next
@@ -562,8 +568,8 @@ error_terminate(Code, State=#state{socket=Socket, transport=Transport,
{cowboy_req, resp_sent} -> ok
after 0 ->
_ = cowboy_req:reply(Code, cowboy_req:new(Socket, Transport,
- <<"GET">>, <<>>, <<>>, <<>>, {1, 1}, [], <<>>, undefined,
- <<>>, false, Compress, OnResponse)),
+ undefined, <<"GET">>, <<>>, <<>>, <<>>, {1, 1}, [], <<>>,
+ undefined, <<>>, false, Compress, OnResponse)),
ok
end,
terminate(State).
diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl
index eb3a939..c807a75 100644
--- a/src/cowboy_req.erl
+++ b/src/cowboy_req.erl
@@ -42,7 +42,7 @@
-module(cowboy_req).
%% Request API.
--export([new/14]).
+-export([new/15]).
-export([method/1]).
-export([version/1]).
-export([peer/1]).
@@ -179,15 +179,16 @@
%%
%% Since we always need to parse the Connection header, we do it
%% in an optimized way and add the parsed value to p_headers' cache.
--spec new(inet:socket(), module(), binary(), binary(), binary(), binary(),
+-spec new(inet:socket(), module(),
+ undefined | {inet:ip_address(), inet:port_number()},
+ binary(), binary(), binary(), binary(),
cowboy_http:version(), cowboy_http:headers(), binary(),
inet:port_number() | undefined, binary(), boolean(), boolean(),
undefined | cowboy_protocol:onresponse_fun())
-> req().
-new(Socket, Transport, Method, Path, Query, Fragment,
+new(Socket, Transport, Peer, Method, Path, Query, Fragment,
Version, Headers, Host, Port, Buffer, CanKeepalive,
Compress, OnResponse) ->
- {ok, Peer} = Transport:peername(Socket),
Req = #http_req{socket=Socket, transport=Transport, pid=self(), peer=Peer,
method=Method, path=Path, qs=Query, fragment=Fragment, version=Version,
headers=Headers, host=Host, port=Port, buffer=Buffer,
@@ -219,7 +220,8 @@ version(Req) ->
%% @doc Return the peer address and port number of the remote host.
-spec peer(Req)
- -> {{inet:ip_address(), inet:port_number()}, Req} when Req::req().
+ -> {undefined | {inet:ip_address(), inet:port_number()}, Req}
+ when Req::req().
peer(Req) ->
{Req#http_req.peer, Req}.