diff options
author | Loïc Hoguin <[email protected]> | 2013-03-06 14:29:28 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2013-03-06 17:43:04 +0100 |
commit | a930f4ab267064a6316e8914355a4ab4ebd8990c (patch) | |
tree | dcd9388db28d3a740b9c184f6db963bee0e3bf17 /src/cowboy_protocol.erl | |
parent | 233cf43ab9c6c16d22e14039a79606fc935693d6 (diff) | |
download | cowboy-a930f4ab267064a6316e8914355a4ab4ebd8990c.tar.gz cowboy-a930f4ab267064a6316e8914355a4ab4ebd8990c.tar.bz2 cowboy-a930f4ab267064a6316e8914355a4ab4ebd8990c.zip |
Stop using binary:match in cowboy_protocol
It's been found slower than a custom equivalent to what we were
using it for. As this is the critical path we prefer the custom
solution.
Diffstat (limited to 'src/cowboy_protocol.erl')
-rw-r--r-- | src/cowboy_protocol.erl | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/cowboy_protocol.erl b/src/cowboy_protocol.erl index 621be8f..78e3b78 100644 --- a/src/cowboy_protocol.erl +++ b/src/cowboy_protocol.erl @@ -171,20 +171,27 @@ parse_request(<< $\n, _/binary >>, State, _) -> %% reading from the socket and eventually crashing. parse_request(Buffer, State=#state{max_request_line_length=MaxLength, max_empty_lines=MaxEmpty}, ReqEmpty) -> - case binary:match(Buffer, <<"\n">>) of + case match_eol(Buffer, 0) of nomatch when byte_size(Buffer) > MaxLength -> error_terminate(414, State); nomatch -> wait_request(Buffer, State, ReqEmpty); - {1, _} when ReqEmpty =:= MaxEmpty -> + 1 when ReqEmpty =:= MaxEmpty -> error_terminate(400, State); - {1, _} -> + 1 -> << _:16, Rest/binary >> = Buffer, parse_request(Rest, State, ReqEmpty + 1); - {_, _} -> + _ -> parse_method(Buffer, State, <<>>) end. +match_eol(<< $\n, _/bits >>, N) -> + N; +match_eol(<< _, Rest/bits >>, N) -> + match_eol(Rest, N + 1); +match_eol(_, _) -> + nomatch. + parse_method(<< C, Rest/bits >>, State, SoFar) -> case C of $\r -> error_terminate(400, State); @@ -261,15 +268,22 @@ parse_header(<< $\r, $\n, Rest/bits >>, S, M, P, Q, F, V, Headers) -> request(Rest, S, M, P, Q, F, V, lists:reverse(Headers)); parse_header(Buffer, State=#state{max_header_name_length=MaxLength}, M, P, Q, F, V, H) -> - case binary:match(Buffer, <<":">>) of + case match_colon(Buffer, 0) of nomatch when byte_size(Buffer) > MaxLength -> error_terminate(400, State); nomatch -> wait_header(Buffer, State, M, P, Q, F, V, H); - {_, _} -> + _ -> parse_hd_name(Buffer, State, M, P, Q, F, V, H, <<>>) end. +match_colon(<< $:, _/bits >>, N) -> + N; +match_colon(<< _, Rest/bits >>, N) -> + match_colon(Rest, N + 1); +match_colon(_, _) -> + nomatch. + %% I know, this isn't exactly pretty. But this is the most critical %% code path and as such needs to be optimized to death. %% @@ -336,12 +350,12 @@ parse_hd_before_value(<< $\t, Rest/bits >>, S, M, P, Q, F, V, H, N) -> parse_hd_before_value(Rest, S, M, P, Q, F, V, H, N); parse_hd_before_value(Buffer, State=#state{ max_header_value_length=MaxLength}, M, P, Q, F, V, H, N) -> - case binary:match(Buffer, <<"\n">>) of + case match_eol(Buffer, 0) of nomatch when byte_size(Buffer) > MaxLength -> error_terminate(400, State); nomatch -> wait_hd_before_value(Buffer, State, M, P, Q, F, V, H, N); - {_, _} -> + _ -> parse_hd_value(Buffer, State, M, P, Q, F, V, H, N, <<>>) end. |