From 77acb473d8f056f6f534395f131c6e45693797f0 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 4 Nov 2015 15:14:21 +0100 Subject: inets: Terminate gracfully when an invalid chunked length header is encountered Also use integer_to_list/2 and list_to_integer/2 instead of reimplementing it. --- lib/inets/src/http_lib/http_chunk.erl | 8 ++-- lib/inets/src/http_lib/http_util.erl | 69 ++--------------------------------- 2 files changed, 9 insertions(+), 68 deletions(-) (limited to 'lib/inets/src/http_lib') diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl index 9476ea9f5f..c17ff6cce5 100644 --- a/lib/inets/src/http_lib/http_chunk.erl +++ b/lib/inets/src/http_lib/http_chunk.erl @@ -143,20 +143,22 @@ decode_size(Data = <>, HexList, {MaxBodySize, Body, AccLength, MaxHeaderSize}) -> - ChunkSize = http_util:hexlist_to_integer(lists:reverse(HexList)), - case ChunkSize of + try http_util:hexlist_to_integer(lists:reverse(HexList)) of 0 -> % Last chunk, there was no data ignore_extensions(Data, {?MODULE, decode_trailer, [<<>>, [],[], MaxHeaderSize, Body, integer_to_list(AccLength)]}); - _ -> + ChunkSize -> %% Note decode_data may call decode_size again if there %% is more than one chunk, hence here is where the last parameter %% to this function comes in. decode_data(ChunkSize, ChunkRest, {MaxBodySize, Body, ChunkSize + AccLength , MaxHeaderSize}) + catch + _:_ -> + throw({error, {chunk_size, HexList}}) end; decode_size(<<";", Rest/binary>>, HexList, Info) -> %% Note ignore_extensions will call decode_size/1 again when diff --git a/lib/inets/src/http_lib/http_util.erl b/lib/inets/src/http_lib/http_util.erl index 0d07231302..aafa97afee 100644 --- a/lib/inets/src/http_lib/http_util.erl +++ b/lib/inets/src/http_lib/http_util.erl @@ -152,27 +152,11 @@ convert_netscapecookie_date([_D,_A,_Y, _SP, Sec=list_to_integer([S1,S2]), {{Year,Month,Day},{Hour,Min,Sec}}. -hexlist_to_integer([]) -> - empty; -%%When the string only contains one value its eaasy done. -%% 0-9 -hexlist_to_integer([Size]) when (Size >= 48) andalso (Size =< 57) -> - Size - 48; -%% A-F -hexlist_to_integer([Size]) when (Size >= 65) andalso (Size =< 70) -> - Size - 55; -%% a-f -hexlist_to_integer([Size]) when (Size >= 97) andalso (Size =< 102) -> - Size - 87; -hexlist_to_integer([_Size]) -> - not_a_num; +hexlist_to_integer(List) -> + list_to_integer(List, 16). -hexlist_to_integer(Size) -> - Len = string:span(Size, "1234567890abcdefABCDEF"), - hexlist_to_integer2(Size, 16 bsl (4 *(Len-2)),0). - -integer_to_hexlist(Num)-> - integer_to_hexlist(Num, get_size(Num), []). +integer_to_hexlist(Int) -> + integer_to_list(Int, 16). convert_month("Jan") -> 1; convert_month("Feb") -> 2; @@ -213,51 +197,6 @@ html_encode(Chars) -> %%%======================================================================== %%% Internal functions %%%======================================================================== -hexlist_to_integer2([],_Pos,Sum)-> - Sum; -hexlist_to_integer2([HexVal | HexString], Pos, Sum) - when HexVal >= 48, HexVal =< 57 -> - hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-48) * Pos)); - -hexlist_to_integer2([HexVal | HexString], Pos, Sum) - when HexVal >= 65, HexVal =<70 -> - hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-55) * Pos)); - -hexlist_to_integer2([HexVal | HexString], Pos, Sum) - when HexVal>=97, HexVal=<102 -> - hexlist_to_integer2(HexString, Pos bsr 4, Sum + ((HexVal-87) * Pos)); - -hexlist_to_integer2(_AfterHexString, _Pos, Sum)-> - Sum. - -integer_to_hexlist(Num, Pot, Res) when Pot < 0 -> - convert_to_ascii([Num | Res]); - -integer_to_hexlist(Num,Pot,Res) -> - Position = (16 bsl (Pot*4)), - PosVal = Num div Position, - integer_to_hexlist(Num - (PosVal*Position), Pot-1, [PosVal | Res]). - -get_size(Num)-> - get_size(Num, 0). - -get_size(Num, Pot) when Num < (16 bsl(Pot *4)) -> - Pot-1; - -get_size(Num, Pot) -> - get_size(Num, Pot+1). - -convert_to_ascii(RevesedNum) -> - convert_to_ascii(RevesedNum, []). - -convert_to_ascii([], Num)-> - Num; -convert_to_ascii([Num | Reversed], Number) - when (Num > -1) andalso (Num < 10) -> - convert_to_ascii(Reversed, [Num + 48 | Number]); -convert_to_ascii([Num | Reversed], Number) - when (Num > 9) andalso (Num < 16) -> - convert_to_ascii(Reversed, [Num + 55 | Number]). char_to_html_entity(Char, Reserved) -> case sets:is_element(Char, Reserved) of -- cgit v1.2.3 From 1545eae1470c0183bacbf1786d6f1c0366138157 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 5 Nov 2015 09:53:26 +0100 Subject: inets: Improve max header size handling The chunked length header should be checked as well as headers present in the chunk trailer part, ignored extensions are counted as header bytes. Also the decode trailer function will stop as soon as the header size is exceed, when that happens. --- lib/inets/src/http_lib/http_chunk.erl | 163 ++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 76 deletions(-) (limited to 'lib/inets/src/http_lib') diff --git a/lib/inets/src/http_lib/http_chunk.erl b/lib/inets/src/http_lib/http_chunk.erl index c17ff6cce5..2f8476a49d 100644 --- a/lib/inets/src/http_lib/http_chunk.erl +++ b/lib/inets/src/http_lib/http_chunk.erl @@ -57,7 +57,7 @@ %%------------------------------------------------------------------------- decode(ChunkedBody, MaxBodySize, MaxHeaderSize) -> %% Note decode_size will call decode_data. - decode_size([ChunkedBody, <<>>, [], + decode_size([ChunkedBody, <<>>, [], 0, {MaxBodySize, <<>>, 0, MaxHeaderSize}]). %%------------------------------------------------------------------------- @@ -120,67 +120,80 @@ handle_headers(ResponseHeaderRecord = #http_response_h{}, ChunkedHeaders) -> %% Functions that may be returned during the decoding process %% if the input data is incompleate. -decode_size([Bin, Rest, HexList, Info]) -> - decode_size(<>, HexList, Info). +decode_size([Bin, Rest, HexList, AccSize, Info]) -> + decode_size(<>, HexList, AccSize, Info). -ignore_extensions([Bin, Rest, NextFunction]) -> - ignore_extensions(<>, NextFunction). +ignore_extensions([Bin, Rest, RemainingSize, TotalMaxHeaderSize, NextFunction]) -> + ignore_extensions(<>, RemainingSize, TotalMaxHeaderSize, NextFunction). decode_data([Bin, ChunkSize, TotalChunk, Info]) -> decode_data(ChunkSize, <>, Info). -decode_trailer([Bin, Rest, Header, Headers, MaxHeaderSize, Body, - BodyLength]) -> +decode_trailer([Bin, Rest, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]) -> decode_trailer(<>, - Header, Headers, MaxHeaderSize, Body, BodyLength). + Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize). %%%======================================================================== %%% Internal functions %%%======================================================================== -decode_size(<<>>, HexList, Info) -> - {?MODULE, decode_size, [<<>>, HexList, Info]}; -decode_size(Data = <>, HexList, +decode_size(_, _, AccHeaderSize, {_,_,_, MaxHeaderSize}) when + AccHeaderSize > MaxHeaderSize -> + throw({error, {header_too_long, {max, MaxHeaderSize}}}); + +decode_size(<<>>, HexList, AccHeaderSize, Info) -> + {?MODULE, decode_size, [<<>>, HexList, AccHeaderSize, Info]}; +decode_size(Data = <>, HexList, AccHeaderSize, {MaxBodySize, Body, AccLength, MaxHeaderSize}) -> try http_util:hexlist_to_integer(lists:reverse(HexList)) of 0 -> % Last chunk, there was no data - ignore_extensions(Data, {?MODULE, decode_trailer, - [<<>>, [],[], MaxHeaderSize, - Body, - integer_to_list(AccLength)]}); + ignore_extensions(Data, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize, + {?MODULE, decode_trailer, + [<<>>, [],[], + Body, + integer_to_list(AccLength)]}); ChunkSize -> %% Note decode_data may call decode_size again if there %% is more than one chunk, hence here is where the last parameter %% to this function comes in. decode_data(ChunkSize, ChunkRest, {MaxBodySize, Body, - ChunkSize + AccLength , + ChunkSize + AccLength, MaxHeaderSize}) catch _:_ -> - throw({error, {chunk_size, HexList}}) + throw({error, {chunk_size, lists:reverse(HexList)}}) end; -decode_size(<<";", Rest/binary>>, HexList, Info) -> +decode_size(<<";", Rest/binary>>, HexList, AccHeaderSize, {_,_,_, MaxHeaderSize} = Info) -> %% Note ignore_extensions will call decode_size/1 again when %% it ignored all extensions. - ignore_extensions(Rest, {?MODULE, decode_size, [<<>>, HexList, Info]}); -decode_size(<> = Data, HexList, Info) -> - {?MODULE, decode_size, [Data, HexList, Info]}; -decode_size(<>, HexList, Info) -> - decode_size(Rest, [Octet | HexList], Info). + ignore_extensions(Rest, remaing_size(MaxHeaderSize, AccHeaderSize), MaxHeaderSize, + {?MODULE, decode_size, [<<>>, HexList, AccHeaderSize, Info]}); +decode_size(<> = Data, HexList, AccHeaderSize, Info) -> + {?MODULE, decode_size, [Data, HexList, AccHeaderSize, Info]}; +decode_size(<>, HexList, AccHeaderSize, Info) -> + decode_size(Rest, [Octet | HexList], AccHeaderSize + 1, Info). %% "All applications MUST ignore chunk-extension extensions they %% do not understand.", see RFC 2616 Section 3.6.1 We don't %% understand any extension... -ignore_extensions(<<>>, NextFunction) -> - {?MODULE, ignore_extensions, [<<>>, NextFunction]}; -ignore_extensions(Data = <>, +ignore_extensions(_, 0, TotalMaxHeaderSize, _) -> + throw({error, {header_too_long, {max, TotalMaxHeaderSize}}}); +ignore_extensions(<<>>, RemainingSize, TotalMaxHeaderSize, NextFunction) -> + {?MODULE, ignore_extensions, [<<>>, RemainingSize, TotalMaxHeaderSize, NextFunction]}; +ignore_extensions(Data = <>, RemainingSize, TotalMaxHeaderSize, {Module, Function, Args}) -> - Module:Function([Data | Args]); -ignore_extensions(<> = Data, NextFunction) -> - {?MODULE, ignore_extensions, [Data, NextFunction]}; -ignore_extensions(<<_Octet, Rest/binary>>, NextFunction) -> - ignore_extensions(Rest, NextFunction). + case Function of + decode_trailer -> + Module:Function([Data | Args ++ [RemainingSize, TotalMaxHeaderSize]]); + _ -> + Module:Function([Data | Args]) + end; +ignore_extensions(<> = Data, RemainingSize, TotalMaxHeaderSize, NextFunction) -> + {?MODULE, ignore_extensions, [Data, RemainingSize, TotalMaxHeaderSize, NextFunction]}; +ignore_extensions(<<_Octet, Rest/binary>>, RemainingSize, TotalMaxHeaderSize, NextFunction) -> + ignore_extensions(Rest, remaing_size(RemainingSize, 1), TotalMaxHeaderSize, NextFunction). decode_data(ChunkSize, TotalChunk, Info = {MaxBodySize, BodySoFar, AccLength, MaxHeaderSize}) @@ -192,83 +205,81 @@ decode_data(ChunkSize, TotalChunk, %% once it ignored all extensions. {?MODULE, ignore_extensions, [<<>>, - {?MODULE, decode_trailer, [<<>>, [],[], MaxHeaderSize, + {?MODULE, decode_trailer, [<<>>, [],[], <>, integer_to_list(AccLength)]}]}; <> -> %% Note ignore_extensions will call decode_trailer/1 %% once it ignored all extensions. - ignore_extensions(Rest, {?MODULE, decode_trailer, - [<<>>, [],[], MaxHeaderSize, + ignore_extensions(Rest, MaxHeaderSize, MaxHeaderSize, + {?MODULE, decode_trailer, + [<<>>, [],[], <>, integer_to_list(AccLength)]}); <> -> - {?MODULE, decode_trailer, [<>, [],[], MaxHeaderSize, + {?MODULE, decode_trailer, [<>, [],[], <>, - integer_to_list(AccLength)]}; + integer_to_list(AccLength), MaxHeaderSize, MaxHeaderSize]}; <> -> - decode_trailer(<>, [],[], MaxHeaderSize, + decode_trailer(<>, [],[], <>, - integer_to_list(AccLength)); - %% There are more chunks, so here we go agin... + integer_to_list(AccLength), MaxHeaderSize, MaxHeaderSize); + %% There are more chunks, so here we go again... <> -> NewBody = <>, - {?MODULE, decode_size, [<<>>, [], {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}; + {?MODULE, decode_size, [<<>>, [], 0, {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}; <> when (AccLength < MaxBodySize) or (MaxBodySize == nolimit) -> - decode_size(Rest, [], + decode_size(Rest, [], 0, {MaxBodySize, <>, AccLength, MaxHeaderSize}); <<_:ChunkSize/binary, ?CR, ?LF, _/binary>> -> - throw({error, body_too_big}); + throw({error, {body_too_big, {max, MaxBodySize}}}); _ -> {?MODULE, decode_data, [ChunkSize, TotalChunk, Info]} end; decode_data(ChunkSize, TotalChunk, Info) -> {?MODULE, decode_data, [ChunkSize, TotalChunk, Info]}. -decode_trailer(<<>>, Header, Headers, MaxHeaderSize, Body, BodyLength) -> - {?MODULE, decode_trailer, [<<>>, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; - +decode_trailer(_,_,_,_,_, 0, TotalMaxHeaderSize) -> + throw({error, {header_too_long, {max, TotalMaxHeaderSize}}}); +decode_trailer(<<>>, Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [<<>>, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; %% Note: If Bin is not empty it is part of a pipelined request/response. -decode_trailer(<>, [], [], _, Body, BodyLength) -> +decode_trailer(<>, [], [], Body, BodyLength, _, _) -> {ok, {["content-length:" ++ BodyLength], <>}}; decode_trailer(<>, - Header, Headers, MaxHeaderSize, Body, BodyLength) -> + Header, Headers, Body, BodyLength, _, _) -> NewHeaders = case Header of [] -> Headers; _ -> [lists:reverse(Header) | Headers] end, - Length = length(NewHeaders), - case Length > MaxHeaderSize of - true -> - throw({error, {header_too_long, MaxHeaderSize, - MaxHeaderSize-Length}}); - false -> - {ok, {["content-length:" ++ BodyLength | NewHeaders], - <>}} - end; -decode_trailer(<> = Data, Header, Headers, MaxHeaderSize, - Body, BodyLength) -> - {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; -decode_trailer(<> = Data, Header, Headers, MaxHeaderSize, - Body, BodyLength) -> - {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; -decode_trailer(<> = Data, Header, Headers, MaxHeaderSize, - Body, BodyLength) -> - {?MODULE, decode_trailer, [Data, Header, Headers, MaxHeaderSize, Body, - BodyLength]}; -decode_trailer(<>, Header, Headers, - MaxHeaderSize, Body, BodyLength) -> + {ok, {["content-length:" ++ BodyLength | NewHeaders], + <>}}; +decode_trailer(<> = Data, Header, Headers, + Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [Data, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; +decode_trailer(<> = Data, Header, Headers, + Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [Data, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; +decode_trailer(<> = Data, Header, Headers, + Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> + {?MODULE, decode_trailer, [Data, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize]}; +decode_trailer(<>, Header, Headers, Body, BodyLength, RemainingSize, TotalMaxHeaderSize) -> decode_trailer(Rest, [], [lists:reverse(Header) | Headers], - MaxHeaderSize, Body, BodyLength); + Body, BodyLength, RemainingSize, TotalMaxHeaderSize); +decode_trailer(<>, Header, Headers, Body, + BodyLength, RemainingSize, TotalMaxHeaderSize) -> + decode_trailer(Rest, [Octet | Header], Headers, + Body, BodyLength, RemainingSize - 1, TotalMaxHeaderSize). -decode_trailer(<>, Header, Headers, MaxHeaderSize, Body, - BodyLength) -> - decode_trailer(Rest, [Octet | Header], Headers, MaxHeaderSize, - Body, BodyLength). +remaing_size(nolimit, _) -> + nolimit; +remaing_size(Total, Consumed) -> + Total - Consumed. -- cgit v1.2.3 From f05f7ae5e8ea4b19be5fa49681ad6efb01daae6d Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 9 Nov 2015 15:08:35 +0100 Subject: inets: Remove debug macros that mimic call trace --- lib/inets/src/http_lib/http_transport.erl | 44 ++++++------------------------- 1 file changed, 8 insertions(+), 36 deletions(-) (limited to 'lib/inets/src/http_lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index 719dc4c425..484e07cd84 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -40,12 +40,6 @@ -include_lib("inets/src/inets_app/inets_internal.hrl"). -include("http_internal.hrl"). --define(SERVICE, httpl). --define(hlri(Label, Content), ?report_important(Label, ?SERVICE, Content)). --define(hlrv(Label, Content), ?report_verbose(Label, ?SERVICE, Content)). --define(hlrd(Label, Content), ?report_debug(Label, ?SERVICE, Content)). --define(hlrt(Label, Content), ?report_trace(Label, ?SERVICE, Content)). - %%%========================================================================= %%% Internal application API @@ -107,8 +101,6 @@ connect(SocketType, Address, Opts) -> connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout) when is_list(Opts0) -> Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0], - ?hlrt("connect using gen_tcp", - [{host, Host}, {port, Port}, {opts, Opts}, {timeout, Timeout}]), try gen_tcp:connect(Host, Port, Opts, Timeout) of {ok, _} = OK -> OK; @@ -127,11 +119,6 @@ connect({ssl, SslConfig}, Address, Opts, Timeout) -> connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) -> Opts = [binary, {active, false}, {ssl_imp, new} | Opts0] ++ SslConfig, - ?hlrt("connect using essl", - [{host, Host}, - {port, Port}, - {ssl_config, SslConfig}, - {timeout, Timeout}]), case (catch ssl:connect(Host, Port, Opts, Timeout)) of {'EXIT', Reason} -> {error, {eoptions, Reason}}; @@ -156,29 +143,23 @@ connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) -> %% reason for this to enable a HTTP-server not running as root to use %% port 80. %%------------------------------------------------------------------------- -listen(ip_comm = _SocketType, Addr, Port, Fd, IpFamily) -> - listen_ip_comm(Addr, Port, Fd, IpFamily); - +listen(ip_comm, Addr, Port, Fd, IpFamily) -> + listen_ip_comm(Addr, Port, [], Fd, IpFamily); + +listen({ip_comm, SockOpts}, Addr, Port, Fd, IpFamily) -> + listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily); + listen({essl, SSLConfig}, Addr, Port, Fd, IpFamily) -> listen_ssl(Addr, Port, Fd, SSLConfig, IpFamily, []). -listen(ip_comm = _SocketType, Addr, Port, IpFamily) -> - listen_ip_comm(Addr, Port, undefined, IpFamily); +listen(ip_comm, Addr, Port, IpFamily) -> + listen_ip_comm(Addr, Port, [], undefined, IpFamily); %% Wrapper for backaward compatibillity listen({ssl, SSLConfig}, Addr, Port, IpFamily) -> - ?hlrt("listen (wrapper)", - [{addr, Addr}, - {port, Port}, - {ssl_config, SSLConfig}]), listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port, IpFamily); - listen({essl, SSLConfig}, Addr, Port, IpFamily) -> - ?hlrt("listen (essl)", - [{addr, Addr}, - {port, Port}, - {ssl_config, SSLConfig}]), {SSLConfig2, ExtraOpts} = case proplists:get_value(log_alert, SSLConfig, undefined) of undefined -> {SSLConfig, []}; @@ -325,7 +306,6 @@ controlling_process({essl, _}, Socket, NewOwner) -> %% gen_tcp or ssl. %%------------------------------------------------------------------------- setopts(ip_comm, Socket, Options) -> - ?hlrt("ip_comm setopts", [{socket, Socket}, {options, Options}]), inet:setopts(Socket, Options); %% Wrapper for backaward compatibillity @@ -351,7 +331,6 @@ getopts(SocketType, Socket) -> getopts(SocketType, Socket, Opts). getopts(ip_comm, Socket, Options) -> - ?hlrt("ip_comm getopts", [{socket, Socket}, {options, Options}]), case inet:getopts(Socket, Options) of {ok, SocketOpts} -> SocketOpts; @@ -364,7 +343,6 @@ getopts({ssl, SSLConfig}, Socket, Options) -> getopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options); getopts({essl, _}, Socket, Options) -> - ?hlrt("essl getopts", [{socket, Socket}, {options, Options}]), getopts_ssl(Socket, Options). getopts_ssl(Socket, Options) -> @@ -384,7 +362,6 @@ getopts_ssl(Socket, Options) -> %% Description: Gets the socket stats values for the socket %%------------------------------------------------------------------------- getstat(ip_comm = _SocketType, Socket) -> - ?hlrt("ip_comm getstat", [{socket, Socket}]), case inet:getstat(Socket) of {ok, Stats} -> Stats; @@ -555,22 +532,17 @@ sock_opts(Opts) -> %% -- negotiate -- negotiate(ip_comm,_,_) -> - ?hlrt("negotiate(ip_comm)", []), ok; negotiate({ssl, SSLConfig}, Socket, Timeout) -> - ?hlrt("negotiate(ssl)", []), negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout); negotiate({essl, _}, Socket, Timeout) -> - ?hlrt("negotiate(essl)", []), negotiate_ssl(Socket, Timeout). negotiate_ssl(Socket, Timeout) -> - ?hlrt("negotiate_ssl", [{socket, Socket}, {timeout, Timeout}]), case ssl:ssl_accept(Socket, Timeout) of ok -> ok; {error, Reason} -> - ?hlrd("negotiate_ssl - accept failed", [{reason, Reason}]), %% Look for "valid" error reasons ValidReasons = [timeout, econnreset, esslaccept, esslerrssl], case lists:member(Reason, ValidReasons) of -- cgit v1.2.3 From 4b7be97512d6fc62b337e810f697a6bb0db1773c Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 9 Nov 2015 15:09:40 +0100 Subject: inets: httpd - Add possibility to specify socket options for HTTP Was already possible for HTTPS. Also remove use of legacy option inet6fb4. IPv6 standard moved away from beeing able to fallback to IPv4 so this option makes little sense, will use inet (Ipv4) as default instead of inet6fb4. --- lib/inets/src/http_lib/http_transport.erl | 116 ++++++++++-------------------- 1 file changed, 38 insertions(+), 78 deletions(-) (limited to 'lib/inets/src/http_lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index 484e07cd84..e3d7382043 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -53,7 +53,8 @@ %%------------------------------------------------------------------------- start(ip_comm) -> do_start_ip_comm(); - +start({ip_comm, _}) -> + do_start_ip_comm(); %% This is just for backward compatibillity start({ssl, _}) -> do_start_ssl(); @@ -97,10 +98,8 @@ do_start_ssl() -> connect(SocketType, Address, Opts) -> connect(SocketType, Address, Opts, infinity). - -connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout) - when is_list(Opts0) -> - Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0], +connect(ip_comm, {Host, Port}, Opts0, Timeout) -> + Opts = [binary, {packet, 0}, {active, false}, {reuseaddr, true} | Opts0 ], try gen_tcp:connect(Host, Port, Opts, Timeout) of {ok, _} = OK -> OK; @@ -168,83 +167,30 @@ listen({essl, SSLConfig}, Addr, Port, IpFamily) -> end, listen_ssl(Addr, Port, undefined, SSLConfig2, IpFamily, ExtraOpts). -listen_ip_comm(Addr, Port, Fd, IpFamily) -> - case (catch do_listen_ip_comm(Addr, Port, Fd, IpFamily)) of +listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily) -> + case (catch do_listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily)) of {'EXIT', Reason} -> {error, {exit, Reason}}; Else -> Else end. -do_listen_ip_comm(Addr, Port, Fd, IpFamily) -> - {NewPort, Opts} = get_socket_info(Addr, Port, Fd), - case IpFamily of - inet6fb4 -> - Opts2 = [inet6 | Opts], - ?hlrt("try ipv6 listen", [{port, NewPort}, {opts, Opts2}]), - case (catch gen_tcp:listen(NewPort, Opts2)) of - {error, Reason} when ((Reason =:= nxdomain) orelse - (Reason =:= eafnosupport)) -> - Opts3 = [inet | Opts], - ?hlrt("ipv6 listen failed - try ipv4 instead", - [{reason, Reason}, {port, NewPort}, {opts, Opts3}]), - gen_tcp:listen(NewPort, Opts3); - - %% This is when a given hostname has resolved to a - %% IPv4-address. The inet6-option together with a - %% {ip, IPv4} option results in badarg - {'EXIT', Reason} -> - Opts3 = [inet | Opts], - ?hlrt("ipv6 listen exit - try ipv4 instead", - [{reason, Reason}, {port, NewPort}, {opts, Opts3}]), - gen_tcp:listen(NewPort, Opts3); - - Other -> - ?hlrt("ipv6 listen done", [{other, Other}]), - Other - end; - _ -> - Opts2 = [IpFamily | Opts], - ?hlrt("listen", [{port, NewPort}, {opts, Opts2}]), - gen_tcp:listen(NewPort, Opts2) - end. +do_listen_ip_comm(Addr, Port, SockOpts, Fd, IpFamily) -> + Backlog = proplists:get_value(backlog, SockOpts, 128), + {NewPort, Opts} = get_socket_info(Addr, Port, Fd, + [{backlog, Backlog}, {reuseaddr, true} | SockOpts]), + Opts2 = [IpFamily | Opts], + gen_tcp:listen(NewPort, Opts2). listen_ssl(Addr, Port, Fd, Opts0, IpFamily, ExtraOpts) -> - {NewPort, SockOpt} = get_socket_info(Addr, Port, Fd), + Backlog = proplists:get_value(backlog, Opts0, 128), + {NewPort, SockOpt} = get_socket_info(Addr, Port, Fd, + [{backlog, Backlog}, {reuseaddr, true}]), Opts = SockOpt ++ Opts0, - case IpFamily of - inet6fb4 -> - Opts2 = [inet6 | Opts] ++ ExtraOpts, - ?hlrt("try ipv6 listen", [{opts, Opts2}]), - case (catch ssl:listen(Port, Opts2)) of - {error, Reason} when ((Reason =:= nxdomain) orelse - (Reason =:= eafnosupport)) -> - Opts3 = [inet | Opts] ++ ExtraOpts, - ?hlrt("ipv6 listen failed - try ipv4 instead", - [{reason, Reason}, {opts, Opts3}]), - ssl:listen(NewPort, Opts3); - - {'EXIT', Reason} -> - Opts3 = [inet | Opts] ++ ExtraOpts, - ?hlrt("ipv6 listen exit - try ipv4 instead", - [{reason, Reason}, {opts, Opts3}]), - ssl:listen(NewPort, Opts3); - - Other -> - ?hlrt("ipv6 listen done", [{other, Other}]), - Other - end; - - _ -> - Opts2 = [IpFamily | Opts], - ?hlrt("listen", [{opts, Opts2}]), - ssl:listen(NewPort, Opts2 ++ ExtraOpts) - end. + Opts2 = [IpFamily | Opts], + ssl:listen(NewPort, Opts2 ++ ExtraOpts). - - -get_socket_info(Addr, Port, Fd) -> - BaseOpts = [{backlog, 128}, {reuseaddr, true}], +get_socket_info(Addr, Port, Fd, BaseOpts) -> %% The presence of a file descriptor takes precedence case Fd of undefined -> @@ -269,6 +215,8 @@ accept(SocketType, ListenSocket) -> accept(ip_comm, ListenSocket, Timeout) -> gen_tcp:accept(ListenSocket, Timeout); +accept({ip_comm, _}, ListenSocket, Timeout) -> + gen_tcp:accept(ListenSocket, Timeout); %% Wrapper for backaward compatibillity accept({ssl, SSLConfig}, ListenSocket, Timeout) -> @@ -288,6 +236,8 @@ accept({essl, _SSLConfig}, ListenSocket, Timeout) -> %%------------------------------------------------------------------------- controlling_process(ip_comm, Socket, NewOwner) -> gen_tcp:controlling_process(Socket, NewOwner); +controlling_process({ip_comm, _}, Socket, NewOwner) -> + gen_tcp:controlling_process(Socket, NewOwner); %% Wrapper for backaward compatibillity controlling_process({ssl, SSLConfig}, Socket, NewOwner) -> @@ -307,16 +257,15 @@ controlling_process({essl, _}, Socket, NewOwner) -> %%------------------------------------------------------------------------- setopts(ip_comm, Socket, Options) -> inet:setopts(Socket, Options); +setopts({ip_comm, _}, Socket, Options) -> + inet:setopts(Socket, Options); %% Wrapper for backaward compatibillity setopts({ssl, SSLConfig}, Socket, Options) -> setopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options); setopts({essl, _}, Socket, Options) -> - ?hlrt("[e]ssl setopts", [{socket, Socket}, {options, Options}]), - Reason = (catch ssl:setopts(Socket, Options)), - ?hlrt("[e]ssl setopts result", [{reason, Reason}]), - Reason. + (catch ssl:setopts(Socket, Options)). %%------------------------------------------------------------------------- @@ -330,6 +279,9 @@ getopts(SocketType, Socket) -> Opts = [packet, packet_size, recbuf, sndbuf, priority, tos, send_timeout], getopts(SocketType, Socket, Opts). +getopts({ip_comm, _}, Socket, Options) -> + getopts(ip_comm, Socket, Options); + getopts(ip_comm, Socket, Options) -> case inet:getopts(Socket, Options) of {ok, SocketOpts} -> @@ -386,6 +338,8 @@ getstat({essl, _} = _SocketType, _Socket) -> %%------------------------------------------------------------------------- send(ip_comm, Socket, Message) -> gen_tcp:send(Socket, Message); +send({ip_comm, _}, Socket, Message) -> + gen_tcp:send(Socket, Message); %% Wrapper for backaward compatibillity send({ssl, SSLConfig}, Socket, Message) -> @@ -394,7 +348,6 @@ send({ssl, SSLConfig}, Socket, Message) -> send({essl, _}, Socket, Message) -> ssl:send(Socket, Message). - %%------------------------------------------------------------------------- %% close(SocketType, Socket) -> ok | {error, Reason} %% SocketType = ip_comm | {ssl, _} @@ -404,6 +357,8 @@ send({essl, _}, Socket, Message) -> %%------------------------------------------------------------------------- close(ip_comm, Socket) -> gen_tcp:close(Socket); +close({ip_comm, []}, Socket) -> + gen_tcp:close(Socket); %% Wrapper for backaward compatibillity close({ssl, SSLConfig}, Socket) -> @@ -425,6 +380,8 @@ close({essl, _}, Socket) -> %%------------------------------------------------------------------------- peername(ip_comm, Socket) -> do_peername(inet:peername(Socket)); +peername({ip_comm, _}, Socket) -> + do_peername(inet:peername(Socket)); %% Wrapper for backaward compatibillity peername({ssl, SSLConfig}, Socket) -> @@ -457,7 +414,8 @@ do_peername({error, _}) -> %%------------------------------------------------------------------------- sockname(ip_comm, Socket) -> do_sockname(inet:sockname(Socket)); - +sockname({ip_comm, _}, Socket) -> + do_sockname(inet:sockname(Socket)); %% Wrapper for backaward compatibillity sockname({ssl, SSLConfig}, Socket) -> sockname({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket); @@ -533,6 +491,8 @@ sock_opts(Opts) -> %% -- negotiate -- negotiate(ip_comm,_,_) -> ok; +negotiate({ip_comm, _},_,_) -> + ok; negotiate({ssl, SSLConfig}, Socket, Timeout) -> negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout); negotiate({essl, _}, Socket, Timeout) -> -- cgit v1.2.3 From 51a236b296a07ef488e29e4f1b38ee4d707e8a88 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 9 Nov 2015 15:48:32 +0100 Subject: Inets: Clean up code Remove point less instructions looking for return values, that in most cases no long exist, of which the result would anyhow be ignored --- lib/inets/src/http_lib/http_transport.erl | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'lib/inets/src/http_lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index e3d7382043..ddfd6a030e 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -499,16 +499,4 @@ negotiate({essl, _}, Socket, Timeout) -> negotiate_ssl(Socket, Timeout). negotiate_ssl(Socket, Timeout) -> - case ssl:ssl_accept(Socket, Timeout) of - ok -> - ok; - {error, Reason} -> - %% Look for "valid" error reasons - ValidReasons = [timeout, econnreset, esslaccept, esslerrssl], - case lists:member(Reason, ValidReasons) of - true -> - {error, normal}; - false -> - {error, Reason} - end - end. + ssl:ssl_accept(Socket, Timeout). -- cgit v1.2.3 From ef9d44bdd378d30dd1233dbb89abc97ecc155868 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Wed, 11 Nov 2015 10:30:23 +0100 Subject: inets: Do not use internal or shell convenience functions in application ssl:start/[1,2] is a shell convenience function and should not be called by other applications. inet_db:start is an internal function that we should not have to call. This was done for legacy reasons and is no longer needed. --- lib/inets/src/http_lib/http_transport.erl | 34 ++++++++++--------------------- 1 file changed, 11 insertions(+), 23 deletions(-) (limited to 'lib/inets/src/http_lib') diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index ddfd6a030e..ab6afe9c6c 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -49,39 +49,27 @@ %% start(SocketType) -> ok | {error, Reason} %% SocketType = ip_comm | {ssl, _} %% -%% Description: Makes sure inet_db or ssl is started. +%% Description: Makes sure ssl is started. %%------------------------------------------------------------------------- start(ip_comm) -> - do_start_ip_comm(); + ok; start({ip_comm, _}) -> - do_start_ip_comm(); -%% This is just for backward compatibillity + ok; start({ssl, _}) -> do_start_ssl(); start({essl, _}) -> do_start_ssl(). - -do_start_ip_comm() -> - case inet_db:start() of - {ok, _} -> - ok; - {error, {already_started, _}} -> - ok; - Error -> - Error - end. - do_start_ssl() -> - case ssl:start() of - ok -> - ok; - {error, {already_started,_}} -> - ok; - Error -> - Error + try lists:foreach(fun(App) -> + ok = application:ensure_started(App) + end, + [crypto, asn1, public_key, ssl]) + catch + _:Reason -> + {error, Reason} end. - + %%------------------------------------------------------------------------- %% connect(SocketType, Address, Options, Timeout) -> -- cgit v1.2.3