diff options
Diffstat (limited to 'lib/inets/src')
23 files changed, 495 insertions, 449 deletions
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl index 3028cd800f..560ee55271 100644 --- a/lib/inets/src/ftp/ftp.erl +++ b/lib/inets/src/ftp/ftp.erl @@ -55,9 +55,10 @@ -include("ftp_internal.hrl"). %% Constante used in internal state definition --define(CONNECTION_TIMEOUT, 60*1000). --define(DEFAULT_MODE, passive). --define(PROGRESS_DEFAULT, ignore). +-define(CONNECTION_TIMEOUT, 60*1000). +-define(DATA_ACCEPT_TIMEOUT, infinity). +-define(DEFAULT_MODE, passive). +-define(PROGRESS_DEFAULT, ignore). %% Internal Constants -define(FTP_PORT, 21). @@ -88,7 +89,8 @@ %% data needed further on. caller = undefined, % term() ipfamily, % inet | inet6 | inet6fb4 - progress = ignore % ignore | pid() + progress = ignore, % ignore | pid() + dtimeout = ?DATA_ACCEPT_TIMEOUT % non_neg_integer() | infinity }). @@ -847,6 +849,7 @@ start_options(Options) -> %% host %% port %% timeout +%% dtimeout %% progress open_options(Options) -> ?fcrt("open_options", [{options, Options}]), @@ -875,7 +878,12 @@ open_options(Options) -> (_) -> false end, ValidateTimeout = - fun(Timeout) when is_integer(Timeout) andalso (Timeout > 0) -> true; + fun(Timeout) when is_integer(Timeout) andalso (Timeout >= 0) -> true; + (_) -> false + end, + ValidateDTimeout = + fun(DTimeout) when is_integer(DTimeout) andalso (DTimeout >= 0) -> true; + (infinity) -> true; (_) -> false end, ValidateProgress = @@ -893,6 +901,7 @@ open_options(Options) -> {port, ValidatePort, false, ?FTP_PORT}, {ipfamily, ValidateIpFamily, false, inet}, {timeout, ValidateTimeout, false, ?CONNECTION_TIMEOUT}, + {dtimeout, ValidateDTimeout, false, ?DATA_ACCEPT_TIMEOUT}, {progress, ValidateProgress, false, ?PROGRESS_DEFAULT}], validate_options(Options, ValidOptions, []). @@ -1037,13 +1046,15 @@ handle_call({_, {open, ip_comm, Opts}}, From, State) -> Mode = key_search(mode, Opts, ?DEFAULT_MODE), Port = key_search(port, Opts, ?FTP_PORT), Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT), + DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT), Progress = key_search(progress, Opts, ignore), IpFamily = key_search(ipfamily, Opts, inet), - + State2 = State#state{client = From, mode = Mode, progress = progress(Progress), - ipfamily = IpFamily}, + ipfamily = IpFamily, + dtimeout = DTimeout}, ?fcrd("handle_call(open) -> setup ctrl connection with", [{host, Host}, {port, Port}, {timeout, Timeout}]), @@ -1064,11 +1075,13 @@ handle_call({_, {open, ip_comm, Host, Opts}}, From, State) -> Mode = key_search(mode, Opts, ?DEFAULT_MODE), Port = key_search(port, Opts, ?FTP_PORT), Timeout = key_search(timeout, Opts, ?CONNECTION_TIMEOUT), + DTimeout = key_search(dtimeout, Opts, ?DATA_ACCEPT_TIMEOUT), Progress = key_search(progress, Opts, ignore), State2 = State#state{client = From, mode = Mode, - progress = progress(Progress)}, + progress = progress(Progress), + dtimeout = DTimeout}, case setup_ctrl_connection(Host, Port, Timeout, State2) of {ok, State3, WaitTimeout} -> @@ -1657,9 +1670,19 @@ handle_ctrl_result({pos_compl, Lines}, %%-------------------------------------------------------------------------- %% Directory listing handle_ctrl_result({pos_prel, _}, #state{caller = {dir, Dir}} = State) -> - NewState = accept_data_connection(State), - activate_data_connection(NewState), - {noreply, NewState#state{caller = {handle_dir_result, Dir}}}; + case accept_data_connection(State) of + {ok, NewState} -> + activate_data_connection(NewState), + {noreply, NewState#state{caller = {handle_dir_result, Dir}}}; + {error, _Reason} = ERROR -> + case State#state.client of + undefined -> + {stop, ERROR, State}; + From -> + gen_server:reply(From, ERROR), + {stop, normal, State#state{client = undefined}} + end + end; handle_ctrl_result({pos_compl, _}, #state{caller = {handle_dir_result, Dir, Data}, client = From} @@ -1756,9 +1779,19 @@ handle_ctrl_result({Status, _}, %%-------------------------------------------------------------------------- %% File handling - recv_bin handle_ctrl_result({pos_prel, _}, #state{caller = recv_bin} = State) -> - NewState = accept_data_connection(State), - activate_data_connection(NewState), - {noreply, NewState}; + case accept_data_connection(State) of + {ok, NewState} -> + activate_data_connection(NewState), + {noreply, NewState}; + {error, _Reason} = ERROR -> + case State#state.client of + undefined -> + {stop, ERROR, State}; + From -> + gen_server:reply(From, ERROR), + {stop, normal, State#state{client = undefined}} + end + end; handle_ctrl_result({pos_compl, _}, #state{caller = {recv_bin, Data}, client = From} = State) -> @@ -1780,16 +1813,37 @@ handle_ctrl_result({Status, _}, #state{caller = {recv_bin, _}} = State) -> handle_ctrl_result({pos_prel, _}, #state{client = From, caller = start_chunk_transfer} = State) -> - NewState = accept_data_connection(State), - gen_server:reply(From, ok), - {noreply, NewState#state{chunk = true, client = undefined, - caller = undefined}}; + case accept_data_connection(State) of + {ok, NewState} -> + gen_server:reply(From, ok), + {noreply, NewState#state{chunk = true, client = undefined, + caller = undefined}}; + {error, _Reason} = ERROR -> + case State#state.client of + undefined -> + {stop, ERROR, State}; + From -> + gen_server:reply(From, ERROR), + {stop, normal, State#state{client = undefined}} + end + end; + %%-------------------------------------------------------------------------- %% File handling - recv_file handle_ctrl_result({pos_prel, _}, #state{caller = {recv_file, _}} = State) -> - NewState = accept_data_connection(State), - activate_data_connection(NewState), - {noreply, NewState}; + case accept_data_connection(State) of + {ok, NewState} -> + activate_data_connection(NewState), + {noreply, NewState}; + {error, _Reason} = ERROR -> + case State#state.client of + undefined -> + {stop, ERROR, State}; + From -> + gen_server:reply(From, ERROR), + {stop, normal, State#state{client = undefined}} + end + end; handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) -> file_close(Fd), @@ -1800,17 +1854,38 @@ handle_ctrl_result({Status, _}, #state{caller = {recv_file, Fd}} = State) -> %% File handling - transfer_* handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_file, Fd}} = State) -> - NewState = accept_data_connection(State), - send_file(Fd, NewState); + case accept_data_connection(State) of + {ok, NewState} -> + send_file(Fd, NewState); + {error, _Reason} = ERROR -> + case State#state.client of + undefined -> + {stop, ERROR, State}; + From -> + gen_server:reply(From, ERROR), + {stop, normal, State#state{client = undefined}} + end + end; handle_ctrl_result({pos_prel, _}, #state{caller = {transfer_data, Bin}} = State) -> - NewState = accept_data_connection(State), - send_data_message(NewState, Bin), - close_data_connection(NewState), - activate_ctrl_connection(NewState), - {noreply, NewState#state{caller = transfer_data_second_phase, - dsock = undefined}}; + case accept_data_connection(State) of + {ok, NewState} -> + send_data_message(NewState, Bin), + close_data_connection(NewState), + activate_ctrl_connection(NewState), + {noreply, NewState#state{caller = transfer_data_second_phase, + dsock = undefined}}; + {error, _Reason} = ERROR -> + case State#state.client of + undefined -> + {stop, ERROR, State}; + From -> + gen_server:reply(From, ERROR), + {stop, normal, State#state{client = undefined}} + end + end; + %%-------------------------------------------------------------------------- %% Default handle_ctrl_result({Status, Lines}, #state{client = From} = State) @@ -2006,16 +2081,20 @@ connect2(Host, Port, IpFam, Timeout) -> Error end. - -accept_data_connection(#state{mode = active, - dsock = {lsock, LSock}} = State) -> - {ok, Socket} = gen_tcp:accept(LSock), - gen_tcp:close(LSock), - State#state{dsock = Socket}; +accept_data_connection(#state{mode = active, + dtimeout = DTimeout, + dsock = {lsock, LSock}} = State) -> + case gen_tcp:accept(LSock, DTimeout) of + {ok, Socket} -> + gen_tcp:close(LSock), + {ok, State#state{dsock = Socket}}; + {error, Reason} -> + {error, {data_connect_failed, Reason}} + end; accept_data_connection(#state{mode = passive} = State) -> - State. + {ok, State}. send_ctrl_message(#state{csock = Socket, verbose = Verbose}, Message) -> %% io:format("send control message: ~n~p~n", [lists:flatten(Message)]), diff --git a/lib/inets/src/http_client/Makefile b/lib/inets/src/http_client/Makefile index 0397b48ab2..d490e59929 100644 --- a/lib/inets/src/http_client/Makefile +++ b/lib/inets/src/http_client/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2005-2010. All Rights Reserved. +# Copyright Ericsson AB 2005-2011. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -41,7 +41,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # Target Specs # ---------------------------------------------------- MODULES = \ - http \ httpc \ httpc_cookie \ httpc_handler \ diff --git a/lib/inets/src/http_client/http.erl b/lib/inets/src/http_client/http.erl deleted file mode 100644 index bbe2fec267..0000000000 --- a/lib/inets/src/http_client/http.erl +++ /dev/null @@ -1,132 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% - -%%% Description: OLD API MODULE - USE httpc INSTEAD - --module(http). - --deprecated({request, 1, next_major_release}). --deprecated({request, 2, next_major_release}). --deprecated({request, 4, next_major_release}). --deprecated({request, 5, next_major_release}). --deprecated({cancel_request, 1, next_major_release}). --deprecated({cancel_request, 2, next_major_release}). --deprecated({set_option, 2, next_major_release}). --deprecated({set_option, 3, next_major_release}). --deprecated({set_options, 1, next_major_release}). --deprecated({set_options, 2, next_major_release}). --deprecated({verify_cookies, 2, next_major_release}). --deprecated({verify_cookies, 3, next_major_release}). --deprecated({cookie_header, 1, next_major_release}). --deprecated({cookie_header, 2, next_major_release}). --deprecated({stream_next, 1, next_major_release}). --deprecated({default_profile, 0, next_major_release}). - -%% Deprecated --export([ - request/1, request/2, request/4, request/5, - cancel_request/1, cancel_request/2, - set_option/2, set_option/3, - set_options/1, set_options/2, - verify_cookies/2, verify_cookies/3, - cookie_header/1, cookie_header/2, - stream_next/1, - default_profile/0 - ]). - - -%%%========================================================================= -%%% API -%%%========================================================================= - -%%-------------------------------------------------------------------------- -%% request(Url [, Profile]) -> -%% request(Method, Request, HTTPOptions, Options [, Profile]) -%%-------------------------------------------------------------------------- - -request(Url) -> httpc:request(Url). -request(Url, Profile) -> httpc:request(Url, Profile). - -request(Method, Request, HttpOptions, Options) -> - httpc:request(Method, Request, HttpOptions, Options). -request(Method, Request, HttpOptions, Options, Profile) -> - httpc:request(Method, Request, HttpOptions, Options, Profile). - - -%%-------------------------------------------------------------------------- -%% cancel_request(RequestId [, Profile]) -%%------------------------------------------------------------------------- - -cancel_request(RequestId) -> - httpc:cancel_request(RequestId). -cancel_request(RequestId, Profile) -> - httpc:cancel_request(RequestId, Profile). - - -%%-------------------------------------------------------------------------- -%% set_options(Options [, Profile]) -%% set_option(Key, Value [, Profile]) -%%------------------------------------------------------------------------- - -set_options(Options) -> - httpc:set_options(Options). -set_options(Options, Profile) -> - httpc:set_options(Options, Profile). - -set_option(Key, Value) -> - httpc:set_option(Key, Value). -set_option(Key, Value, Profile) -> - httpc:set_option(Key, Value, Profile). - - -%%-------------------------------------------------------------------------- -%% verify_cookies(SetCookieHeaders, Url [, Profile]) -%%------------------------------------------------------------------------- - -verify_cookies(SetCookieHeaders, Url) -> - httpc:store_cookies(SetCookieHeaders, Url). -verify_cookies(SetCookieHeaders, Url, Profile) -> - httpc:store_cookies(SetCookieHeaders, Url, Profile). - - -%%-------------------------------------------------------------------------- -%% cookie_header(Url [, Profile]) -%%------------------------------------------------------------------------- - -cookie_header(Url) -> - httpc:cookie_header(Url). -cookie_header(Url, Profile) -> - httpc:cookie_header(Url, Profile). - - -%%-------------------------------------------------------------------------- -%% stream_next(Pid) -%%------------------------------------------------------------------------- - -stream_next(Pid) -> - httpc:stream_next(Pid). - - -%%-------------------------------------------------------------------------- -%% default_profile() -%%------------------------------------------------------------------------- - -default_profile() -> - httpc:default_profile(). diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index fe8e93af1f..ae87ceed93 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -34,7 +34,7 @@ set_option/2, set_option/3, set_options/1, set_options/2, store_cookies/2, store_cookies/3, - cookie_header/1, cookie_header/2, + cookie_header/1, cookie_header/2, cookie_header/3, which_cookies/0, which_cookies/1, reset_cookies/0, reset_cookies/1, stream_next/1, @@ -105,7 +105,6 @@ request(Url, Profile) -> %% {ssl, SSLOptions} | {proxy_auth, {User, Password}} %% Ssloptions = ssl_options() | %% {ssl, ssl_options()} | -%% {ossl, ssl_options()} | %% {essl, ssl_options()} %% ssl_options() = [ssl_option()] %% ssl_option() = {verify, code()} | @@ -142,7 +141,9 @@ request(Url, Profile) -> request(Method, Request, HttpOptions, Options) -> request(Method, Request, HttpOptions, Options, default_profile()). -request(Method, {Url, Headers}, HTTPOptions, Options, Profile) +request(Method, + {Url, Headers}, + HTTPOptions, Options, Profile) when (Method =:= options) orelse (Method =:= get) orelse (Method =:= head) orelse @@ -155,15 +156,17 @@ request(Method, {Url, Headers}, HTTPOptions, Options, Profile) {http_options, HTTPOptions}, {options, Options}, {profile, Profile}]), - case http_uri:parse(Url) of + case http_uri:parse(Url, Options) of {error, Reason} -> {error, Reason}; - ParsedUrl -> + {ok, ParsedUrl} -> handle_request(Method, Url, ParsedUrl, Headers, [], [], HTTPOptions, Options, Profile) end; -request(Method, {Url,Headers,ContentType,Body}, HTTPOptions, Options, Profile) +request(Method, + {Url, Headers, ContentType, Body}, + HTTPOptions, Options, Profile) when ((Method =:= post) orelse (Method =:= put)) andalso (is_atom(Profile) orelse is_pid(Profile)) -> ?hcrt("request", [{method, Method}, @@ -174,10 +177,10 @@ request(Method, {Url,Headers,ContentType,Body}, HTTPOptions, Options, Profile) {http_options, HTTPOptions}, {options, Options}, {profile, Profile}]), - case http_uri:parse(Url) of + case http_uri:parse(Url, Options) of {error, Reason} -> {error, Reason}; - ParsedUrl -> + {ok, ParsedUrl} -> handle_request(Method, Url, ParsedUrl, Headers, ContentType, Body, HTTPOptions, Options, Profile) @@ -268,7 +271,10 @@ store_cookies(SetCookieHeaders, Url, Profile) {profile, Profile}]), try begin - {_, _, Host, Port, Path, _} = http_uri:parse(Url), + %% Since the Address part is not actually used + %% by the manager when storing cookies, we dont + %% care about ipv6-host-with-brackets. + {ok, {_, _, Host, Port, Path, _}} = http_uri:parse(Url), Address = {Host, Port}, ProfileName = profile_name(Profile), Cookies = httpc_cookie:cookies(SetCookieHeaders, Path, Host), @@ -284,25 +290,36 @@ store_cookies(SetCookieHeaders, Url, Profile) %%-------------------------------------------------------------------------- -%% cookie_header(Url [, Profile]) -> Header | {error, Reason} -%% +%% cookie_header(Url) -> Header | {error, Reason} +%% cookie_header(Url, Profile) -> Header | {error, Reason} +%% cookie_header(Url, Opts, Profile) -> Header | {error, Reason} +%% %% Description: Returns the cookie header that would be sent when making %% a request to <Url>. %%------------------------------------------------------------------------- cookie_header(Url) -> cookie_header(Url, default_profile()). -cookie_header(Url, Profile) -> +cookie_header(Url, Profile) when is_atom(Profile) orelse is_pid(Profile) -> + cookie_header(Url, [], Profile); +cookie_header(Url, Opts) when is_list(Opts) -> + cookie_header(Url, Opts, default_profile()). + +cookie_header(Url, Opts, Profile) + when (is_list(Opts) andalso (is_atom(Profile) orelse is_pid(Profile))) -> ?hcrt("cookie header", [{url, Url}, + {opts, Opts}, {profile, Profile}]), try begin - httpc_manager:which_cookies(Url, profile_name(Profile)) + httpc_manager:which_cookies(Url, Opts, profile_name(Profile)) end catch exit:{noproc, _} -> {error, {not_started, Profile}} end. + + %%-------------------------------------------------------------------------- @@ -465,6 +482,8 @@ handle_request(Method, Url, HeadersRecord = header_record(NewHeaders, Host2, HTTPOptions), Receiver = proplists:get_value(receiver, Options), SocketOpts = proplists:get_value(socket_opts, Options), + BracketedHost = proplists:get_value(ipv6_host_with_brackets, + Options), MaybeEscPath = maybe_encode_uri(HTTPOptions, Path), MaybeEscQuery = maybe_encode_uri(HTTPOptions, Query), AbsUri = maybe_encode_uri(HTTPOptions, Url), @@ -483,7 +502,8 @@ handle_request(Method, Url, stream = Stream, headers_as_is = headers_as_is(Headers0, Options), socket_opts = SocketOpts, - started = Started}, + started = Started, + ipv6_host_with_brackets = BracketedHost}, case httpc_manager:request(Request, profile_name(Profile)) of {ok, RequestId} -> @@ -644,8 +664,6 @@ http_options_default() -> {ok, {?HTTP_DEFAULT_SSL_KIND, Value}}; ({ssl, SslOptions}) when is_list(SslOptions) -> {ok, {?HTTP_DEFAULT_SSL_KIND, SslOptions}}; - ({ossl, SslOptions}) when is_list(SslOptions) -> - {ok, {ossl, SslOptions}}; ({essl, SslOptions}) when is_list(SslOptions) -> {ok, {essl, SslOptions}}; (_) -> @@ -742,14 +760,17 @@ request_options_defaults() -> error end, + VerifyBrackets = VerifyBoolean, + [ - {sync, true, VerifySync}, - {stream, none, VerifyStream}, - {body_format, string, VerifyBodyFormat}, - {full_result, true, VerifyFullResult}, - {headers_as_is, false, VerifyHeaderAsIs}, - {receiver, self(), VerifyReceiver}, - {socket_opts, undefined, VerifySocketOpts} + {sync, true, VerifySync}, + {stream, none, VerifyStream}, + {body_format, string, VerifyBodyFormat}, + {full_result, true, VerifyFullResult}, + {headers_as_is, false, VerifyHeaderAsIs}, + {receiver, self(), VerifyReceiver}, + {socket_opts, undefined, VerifySocketOpts}, + {ipv6_host_with_brackets, false, VerifyBrackets} ]. request_options(Options) -> diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 7784060a2b..bfe9b14ef6 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -763,7 +763,7 @@ deliver_answer(Request) -> code_change(_, #state{session = OldSession, profile_name = ProfileName} = State, - upgrade_from_pre_5_7_3) -> + upgrade_from_pre_5_8_1) -> case OldSession of {session, Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type} -> @@ -783,7 +783,7 @@ code_change(_, code_change(_, #state{session = OldSession, profile_name = ProfileName} = State, - downgrade_to_pre_5_7_3) -> + downgrade_to_pre_5_8_1) -> case OldSession of #session{id = Id, client_close = ClientClose, diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl index 3261061d61..8af752546c 100644 --- a/lib/inets/src/http_client/httpc_internal.hrl +++ b/lib/inets/src/http_client/httpc_internal.hrl @@ -90,25 +90,28 @@ %%% All data associated to a specific HTTP request -record(request, { - id, % ref() - Request Id - from, % pid() - Caller - redircount = 0,% Number of redirects made for this request - scheme, % http | https - address, % ({Host,Port}) Destination Host and Port - path, % string() - Path of parsed URL - pquery, % string() - Rest of parsed URL - method, % atom() - HTTP request Method - headers, % #http_request_h{} - content, % {ContentType, Body} - Current HTTP request - settings, % #http_options{} - User defined settings - abs_uri, % string() ex: "http://www.erlang.org" - userinfo, % string() - optinal "<userinfo>@<host>:<port>" - stream, % Boolean() - stream async reply? - headers_as_is, % Boolean() - workaround for servers that does - % not honor the http standard, can also be used for testing purposes. - started, % integer() > 0 - When we started processing the request - timer, % undefined | ref() - socket_opts % undefined | [socket_option()] + id, % ref() - Request Id + from, % pid() - Caller + redircount = 0,% Number of redirects made for this request + scheme, % http | https + address, % ({Host,Port}) Destination Host and Port + path, % string() - Path of parsed URL + pquery, % string() - Rest of parsed URL + method, % atom() - HTTP request Method + headers, % #http_request_h{} + content, % {ContentType, Body} - Current HTTP request + settings, % #http_options{} - User defined settings + abs_uri, % string() ex: "http://www.erlang.org" + userinfo, % string() - optinal "<userinfo>@<host>:<port>" + stream, % boolean() - stream async reply? + headers_as_is, % boolean() - workaround for servers that does + % not honor the http standard, can also be used + % for testing purposes. + started, % integer() > 0 - When we started processing the + % request + timer, % undefined | ref() + socket_opts, % undefined | [socket_option()] + ipv6_host_with_brackets % boolean() } ). diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index 3d846c2bff..453081da21 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -38,7 +38,7 @@ delete_session/2, set_options/2, store_cookies/3, - which_cookies/1, which_cookies/2, + which_cookies/1, which_cookies/2, which_cookies/3, reset_cookies/1, session_type/1, info/1 @@ -278,19 +278,29 @@ reset_cookies(ProfileName) -> %%-------------------------------------------------------------------- -%% Function: which_cookies(Url, ProfileName) -> [cookie()] +%% Function: which_cookies(ProfileName) -> [cookie()] +%% which_cookies(Url, ProfileName) -> [cookie()] +%% which_cookies(Url, Options, ProfileName) -> [cookie()] %% %% Url = string() +%% Options = [option()] %% ProfileName = atom() +%% option() = {ipv6_host_with_brackets, boolean()} %% %% Description: Retrieves the cookies that would be sent when %% requesting <Url>. %%-------------------------------------------------------------------- -which_cookies(ProfileName) -> +which_cookies(ProfileName) when is_atom(ProfileName) -> call(ProfileName, which_cookies). -which_cookies(Url, ProfileName) -> - call(ProfileName, {which_cookies, Url}). + +which_cookies(Url, ProfileName) + when is_list(Url) andalso is_atom(ProfileName) -> + which_cookies(Url, [], ProfileName). + +which_cookies(Url, Options, ProfileName) + when is_list(Url) andalso is_list(Options) andalso is_atom(ProfileName) -> + call(ProfileName, {which_cookies, Url, Options}). %%-------------------------------------------------------------------- @@ -417,15 +427,16 @@ handle_call(which_cookies, _, #state{cookie_db = CookieDb} = State) -> CookieHeaders = httpc_cookie:which_cookies(CookieDb), {reply, CookieHeaders, State}; -handle_call({which_cookies, Url}, _, #state{cookie_db = CookieDb} = State) -> - ?hcrv("which cookies", [{url, Url}]), - case http_uri:parse(Url) of - {Scheme, _, Host, Port, Path, _} -> +handle_call({which_cookies, Url, Options}, _, + #state{cookie_db = CookieDb} = State) -> + ?hcrv("which cookies", [{url, Url}, {options, Options}]), + case http_uri:parse(Url, Options) of + {ok, {Scheme, _, Host, Port, Path, _}} -> CookieHeaders = httpc_cookie:header(CookieDb, Scheme, {Host, Port}, Path), {reply, CookieHeaders, State}; - Msg -> - {reply, Msg, State} + {error, _} = ERROR -> + {reply, ERROR, State} end; handle_call(info, _, State) -> @@ -572,7 +583,7 @@ terminate(_, State) -> %%-------------------------------------------------------------------- code_change(_, #state{session_db = SessionDB} = State, - upgrade_from_pre_5_7_3) -> + upgrade_from_pre_5_8_1) -> Upgrade = fun({session, Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type}) -> @@ -591,7 +602,7 @@ code_change(_, code_change(_, #state{session_db = SessionDB} = State, - downgrade_to_pre_5_7_3) -> + downgrade_to_pre_5_8_1) -> Downgrade = fun(#session{id = Id, client_close = ClientClose, diff --git a/lib/inets/src/http_client/httpc_response.erl b/lib/inets/src/http_client/httpc_response.erl index 207b96271c..919115a23a 100644 --- a/lib/inets/src/http_client/httpc_response.erl +++ b/lib/inets/src/http_client/httpc_response.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -340,7 +340,9 @@ redirect(Response = {StatusLine, Headers, Body}, Request) -> undefined -> transparent(Response, Request); RedirUrl -> - case http_uri:parse(RedirUrl) of + UrlParseOpts = [{ipv6_host_with_brackets, + Request#request.ipv6_host_with_brackets}], + case http_uri:parse(RedirUrl, UrlParseOpts) of {error, no_scheme} when (Request#request.settings)#http_options.relaxed -> NewLocation = fix_relative_uri(Request, RedirUrl), @@ -350,10 +352,9 @@ redirect(Response = {StatusLine, Headers, Body}, Request) -> {error, Reason} -> {ok, error(Request, Reason), Data}; %% Automatic redirection - {Scheme, _, Host, Port, Path, Query} -> + {ok, {Scheme, _, Host, Port, Path, Query}} -> NewHeaders = - (Request#request.headers)#http_request_h{host = - Host}, + (Request#request.headers)#http_request_h{host = Host}, NewRequest = Request#request{redircount = Request#request.redircount+1, diff --git a/lib/inets/src/http_lib/http_internal.hrl b/lib/inets/src/http_lib/http_internal.hrl index 2e924667c6..97cf474ab9 100644 --- a/lib/inets/src/http_lib/http_internal.hrl +++ b/lib/inets/src/http_lib/http_internal.hrl @@ -28,7 +28,6 @@ -define(HTTP_MAX_URI_SIZE, nolimit). -ifndef(HTTP_DEFAULT_SSL_KIND). -%% -define(HTTP_DEFAULT_SSL_KIND, ossl). -define(HTTP_DEFAULT_SSL_KIND, essl). -endif. % -ifdef(HTTP_DEFAULT_SSL_KIND). diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl index 9b8190ebed..5eb827032f 100644 --- a/lib/inets/src/http_lib/http_transport.erl +++ b/lib/inets/src/http_lib/http_transport.erl @@ -62,8 +62,6 @@ start(ip_comm) -> %% This is just for backward compatibillity start({ssl, _}) -> do_start_ssl(); -start({ossl, _}) -> - do_start_ssl(); start({essl, _}) -> do_start_ssl(). @@ -126,22 +124,6 @@ connect(ip_comm = _SocketType, {Host, Port}, Opts0, Timeout) connect({ssl, SslConfig}, Address, Opts, Timeout) -> connect({?HTTP_DEFAULT_SSL_KIND, SslConfig}, Address, Opts, Timeout); -connect({ossl, SslConfig}, {Host, Port}, _, Timeout) -> - Opts = [binary, {active, false}, {ssl_imp, old}] ++ SslConfig, - ?hlrt("connect using ossl", - [{host, Host}, - {port, Port}, - {ssl_config, SslConfig}, - {timeout, Timeout}]), - case (catch ssl:connect(Host, Port, Opts, Timeout)) of - {'EXIT', Reason} -> - {error, {eoptions, Reason}}; - {ok, _} = OK -> - OK; - {error, _} = ERROR -> - ERROR - end; - connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) -> Opts = [binary, {active, false}, {ssl_imp, new} | Opts0] ++ SslConfig, ?hlrt("connect using essl", @@ -187,13 +169,6 @@ listen({ssl, SSLConfig}, Addr, Port) -> {ssl_config, SSLConfig}]), listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port); -listen({ossl, SSLConfig}, Addr, Port) -> - ?hlrt("listen (ossl)", - [{addr, Addr}, - {port, Port}, - {ssl_config, SSLConfig}]), - listen_ssl(Addr, Port, [{ssl_imp, old} | SSLConfig]); - listen({essl, SSLConfig}, Addr, Port) -> ?hlrt("listen (essl)", [{addr, Addr}, @@ -353,8 +328,6 @@ accept(ip_comm, ListenSocket, Timeout) -> accept({ssl, SSLConfig}, ListenSocket, Timeout) -> accept({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, ListenSocket, Timeout); -accept({ossl, _SSLConfig}, ListenSocket, Timeout) -> - ssl:transport_accept(ListenSocket, Timeout); accept({essl, _SSLConfig}, ListenSocket, Timeout) -> ssl:transport_accept(ListenSocket, Timeout). @@ -374,9 +347,6 @@ controlling_process(ip_comm, Socket, NewOwner) -> controlling_process({ssl, SSLConfig}, Socket, NewOwner) -> controlling_process({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, NewOwner); -controlling_process({ossl, _}, Socket, NewOwner) -> - ssl:controlling_process(Socket, NewOwner); - controlling_process({essl, _}, Socket, NewOwner) -> ssl:controlling_process(Socket, NewOwner). @@ -397,13 +367,6 @@ setopts(ip_comm, Socket, Options) -> setopts({ssl, SSLConfig}, Socket, Options) -> setopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options); -setopts({ossl, _}, Socket, Options) -> - ?hlrt("[o]ssl setopts", [{socket, Socket}, {options, Options}]), - Reason = (catch ssl:setopts(Socket, Options)), - ?hlrt("[o]ssl setopts result", [{reason, Reason}]), - Reason; - - setopts({essl, _}, Socket, Options) -> ?hlrt("[e]ssl setopts", [{socket, Socket}, {options, Options}]), Reason = (catch ssl:setopts(Socket, Options)), @@ -435,10 +398,6 @@ getopts(ip_comm, Socket, Options) -> getopts({ssl, SSLConfig}, Socket, Options) -> getopts({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Options); -getopts({ossl, _}, Socket, Options) -> - ?hlrt("ssl getopts", [{socket, Socket}, {options, Options}]), - getopts_ssl(Socket, Options); - getopts({essl, _}, Socket, Options) -> ?hlrt("essl getopts", [{socket, Socket}, {options, Options}]), getopts_ssl(Socket, Options). @@ -472,9 +431,6 @@ getstat(ip_comm = _SocketType, Socket) -> getstat({ssl, SSLConfig}, Socket) -> getstat({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket); -getstat({ossl, _} = _SocketType, _Socket) -> - []; - getstat({essl, _} = _SocketType, _Socket) -> []. @@ -493,9 +449,6 @@ send(ip_comm, Socket, Message) -> send({ssl, SSLConfig}, Socket, Message) -> send({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Message); -send({ossl, _}, Socket, Message) -> - ssl:send(Socket, Message); - send({essl, _}, Socket, Message) -> ssl:send(Socket, Message). @@ -514,9 +467,6 @@ close(ip_comm, Socket) -> close({ssl, SSLConfig}, Socket) -> close({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket); -close({ossl, _}, Socket) -> - ssl:close(Socket); - close({essl, _}, Socket) -> ssl:close(Socket). @@ -538,9 +488,6 @@ peername(ip_comm, Socket) -> peername({ssl, SSLConfig}, Socket) -> peername({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket); -peername({ossl, _}, Socket) -> - do_peername(ssl:peername(Socket)); - peername({essl, _}, Socket) -> do_peername(ssl:peername(Socket)). @@ -573,9 +520,6 @@ sockname(ip_comm, Socket) -> sockname({ssl, SSLConfig}, Socket) -> sockname({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket); -sockname({ossl, _}, Socket) -> - do_sockname(ssl:sockname(Socket)); - sockname({essl, _}, Socket) -> do_sockname(ssl:sockname(Socket)). @@ -651,9 +595,6 @@ negotiate(ip_comm,_,_) -> negotiate({ssl, SSLConfig}, Socket, Timeout) -> ?hlrt("negotiate(ssl)", []), negotiate({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Socket, Timeout); -negotiate({ossl, _}, Socket, Timeout) -> - ?hlrt("negotiate(ossl)", []), - negotiate_ssl(Socket, Timeout); negotiate({essl, _}, Socket, Timeout) -> ?hlrt("negotiate(essl)", []), negotiate_ssl(Socket, Timeout). diff --git a/lib/inets/src/http_lib/http_uri.erl b/lib/inets/src/http_lib/http_uri.erl index 607475c359..32c6305a79 100644 --- a/lib/inets/src/http_lib/http_uri.erl +++ b/lib/inets/src/http_lib/http_uri.erl @@ -16,25 +16,30 @@ %% %% %CopyrightEnd% %% -%% +%% +%% RFC 3986 +%% -module(http_uri). --export([parse/1]). --export([encode/1, decode/1]). +-export([parse/1, parse/2, + encode/1, decode/1]). %%%========================================================================= %%% API %%%========================================================================= parse(AbsURI) -> + parse(AbsURI, []). + +parse(AbsURI, Opts) -> case parse_scheme(AbsURI) of {error, Reason} -> {error, Reason}; {Scheme, Rest} -> - case (catch parse_uri_rest(Scheme, Rest)) of + case (catch parse_uri_rest(Scheme, Rest, Opts)) of {UserInfo, Host, Port, Path, Query} -> - {Scheme, UserInfo, Host, Port, Path, Query}; + {ok, {Scheme, UserInfo, Host, Port, Path, Query}}; _ -> {error, {malformed_url, AbsURI}} end @@ -68,15 +73,14 @@ parse_scheme(AbsURI) -> {error, no_scheme}; {StrScheme, Rest} -> case list_to_atom(http_util:to_lower(StrScheme)) of - Scheme when Scheme == http; Scheme == https -> + Scheme when (Scheme =:= http) orelse (Scheme =:= https) -> {Scheme, Rest}; Scheme -> {error, {not_supported_scheme, Scheme}} end end. -parse_uri_rest(Scheme, "//" ++ URIPart) -> - +parse_uri_rest(Scheme, "//" ++ URIPart, Opts) -> {Authority, PathQuery} = case split_uri(URIPart, "/", URIPart, 1, 0) of Split = {_, _} -> @@ -91,8 +95,8 @@ parse_uri_rest(Scheme, "//" ++ URIPart) -> end, {UserInfo, HostPort} = split_uri(Authority, "@", {"", Authority}, 1, 1), - {Host, Port} = parse_host_port(Scheme, HostPort), - {Path, Query} = parse_path_query(PathQuery), + {Host, Port} = parse_host_port(Scheme, HostPort, Opts), + {Path, Query} = parse_path_query(PathQuery), {UserInfo, Host, Port, Path, Query}. @@ -100,13 +104,14 @@ parse_path_query(PathQuery) -> {Path, Query} = split_uri(PathQuery, "\\?", {PathQuery, ""}, 1, 0), {path(Path), Query}. -parse_host_port(Scheme,"[" ++ HostPort) -> %ipv6 +parse_host_port(Scheme,"[" ++ HostPort, Opts) -> %ipv6 DefaultPort = default_port(Scheme), {Host, ColonPort} = split_uri(HostPort, "\\]", {HostPort, ""}, 1, 1), + Host2 = maybe_ipv6_host_with_brackets(Host, Opts), {_, Port} = split_uri(ColonPort, ":", {"", DefaultPort}, 0, 1), - {Host, int_port(Port)}; + {Host2, int_port(Port)}; -parse_host_port(Scheme, HostPort) -> +parse_host_port(Scheme, HostPort, _Opts) -> DefaultPort = default_port(Scheme), {Host, Port} = split_uri(HostPort, ":", {HostPort, DefaultPort}, 1, 1), {Host, int_port(Port)}. @@ -120,6 +125,14 @@ split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) -> NoMatchResult end. +maybe_ipv6_host_with_brackets(Host, Opts) -> + case lists:keysearch(ipv6_host_with_brackets, 1, Opts) of + {value, {ipv6_host_with_brackets, true}} -> + "[" ++ Host ++ "]"; + _ -> + Host + end. + default_port(http) -> 80; default_port(https) -> diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl index bcebb6a9e3..08ee9ee0d0 100644 --- a/lib/inets/src/http_server/httpd_acceptor.erl +++ b/lib/inets/src/http_server/httpd_acceptor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -139,11 +139,11 @@ acceptor_loop(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout) -> handle_error(Reason, ConfigDb), ?MODULE:acceptor_loop(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout); - {'EXIT', _Reason} = EXIT -> - ?hdri("accept exited", [{reason, _Reason}]), - handle_error(EXIT, ConfigDb), - ?MODULE:acceptor_loop(Manager, SocketType, ListenSocket, - ConfigDb, AcceptTimeout) + {'EXIT', Reason} -> + ?hdri("accept exited", [{reason, Reason}]), + ReasonString = + lists:flatten(io_lib:format("Accept exit: ~p", [Reason])), + accept_failed(ConfigDb, ReasonString) end. @@ -189,15 +189,13 @@ handle_error(esslaccept, _) -> %% not write an error message. ok; -handle_error({'EXIT', Reason}, ConfigDb) -> - String = lists:flatten(io_lib:format("Accept exit: ~p", [Reason])), - accept_failed(ConfigDb, String); - handle_error(Reason, ConfigDb) -> String = lists:flatten(io_lib:format("Accept error: ~p", [Reason])), accept_failed(ConfigDb, String). --spec accept_failed(_, string()) -> no_return(). + +-spec accept_failed(ConfigDB :: term(), + ReasonString :: string()) -> no_return(). accept_failed(ConfigDb, String) -> error_logger:error_report(String), diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl index 5352eb8bb9..7646300409 100644 --- a/lib/inets/src/http_server/httpd_conf.erl +++ b/lib/inets/src/http_server/httpd_conf.erl @@ -219,9 +219,8 @@ load("ServerName " ++ ServerName, []) -> load("SocketType " ++ SocketType, []) -> %% ssl is the same as HTTP_DEFAULT_SSL_KIND - %% ossl is ssl based on OpenSSL (the "old" ssl) %% essl is the pure Erlang-based ssl (the "new" ssl) - case check_enum(clean(SocketType), ["ssl", "ossl", "essl", "ip_comm"]) of + case check_enum(clean(SocketType), ["ssl", "essl", "ip_comm"]) of {ok, ValidSocketType} -> {ok, [], {socket_type, ValidSocketType}}; {error,_} -> @@ -541,7 +540,6 @@ validate_config_params([{server_name, Value} | _]) -> validate_config_params([{socket_type, Value} | Rest]) when (Value =:= ip_comm) orelse (Value =:= ssl) orelse - (Value =:= ossl) orelse (Value =:= essl) -> validate_config_params(Rest); validate_config_params([{socket_type, Value} | _]) -> @@ -811,7 +809,7 @@ lookup_socket_type(ConfigDB) -> case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of ip_comm -> ip_comm; - SSL when (SSL =:= ssl) orelse (SSL =:= ossl) orelse (SSL =:= essl) -> + SSL when (SSL =:= ssl) orelse (SSL =:= essl) -> SSLTag = if (SSL =:= ssl) -> diff --git a/lib/inets/src/http_server/httpd_log.erl b/lib/inets/src/http_server/httpd_log.erl index db1e2c627a..60ab326a20 100644 --- a/lib/inets/src/http_server/httpd_log.erl +++ b/lib/inets/src/http_server/httpd_log.erl @@ -24,68 +24,110 @@ -export([access_entry/8, error_entry/5, error_report_entry/5, security_entry/5]). + %%%========================================================================= %%% Internal Application API %%%========================================================================= -access_entry(Log, NoLog, Info, RFC931, AuthUser, Date, StatusCode, Bytes) -> - ConfigDB = Info#mod.config_db, - case httpd_util:lookup(ConfigDB, Log) of - undefined -> - NoLog; - LogRef -> - {_, RemoteHost} - = (Info#mod.init_data)#init_data.peername, - RequestLine = Info#mod.request_line, - Headers = Info#mod.parsed_header, - Entry = do_access_entry(ConfigDB, Headers, RequestLine, - RemoteHost, RFC931, AuthUser, - Date, StatusCode, Bytes), - {LogRef, Entry} - end. -error_entry(Log, NoLog, Info, Date, Reason) -> - ConfigDB = Info#mod.config_db, - case httpd_util:lookup(ConfigDB, Log) of - undefined -> - NoLog; - LogRef -> - {_, RemoteHost} = - (Info#mod.init_data)#init_data.peername, - URI = Info#mod.request_uri, - Entry = do_error_entry(ConfigDB, RemoteHost, URI, Date, Reason), - {LogRef, Entry} - end. +-spec access_entry(Log :: term(), % Id of the log + NoLog :: term(), % What to return when no log is found + Info :: #mod{}, + RFC931 :: string(), + AuthUser :: string(), + Date :: string(), + StatusCode :: pos_integer(), + Size :: pos_integer() | string()) -> + {Log :: atom() | pid(), Entry :: string()}. + +access_entry(Log, NoLog, Info, RFC931, AuthUser, Date, StatusCode, SizeStr) + when is_list(SizeStr) -> + Size = + case (catch list_to_integer(SizeStr)) of + I when is_integer(I) -> + I; + _ -> + SizeStr % This is better then nothing + end, + access_entry(Log, NoLog, Info, RFC931, AuthUser, Date, StatusCode, Size); +access_entry(Log, NoLog, + #mod{config_db = ConfigDB, + init_data = #init_data{peername = {_, RemoteHost}}, + request_line = RequestLine, + parsed_header = Headers}, + RFC931, AuthUser, Date, StatusCode, Size) -> + MakeEntry = + fun() -> + do_access_entry(ConfigDB, Headers, RequestLine, + RemoteHost, RFC931, AuthUser, + Date, StatusCode, Size) + end, + log_entry(Log, NoLog, ConfigDB, MakeEntry). + + +-spec error_entry(Log :: term(), % Id of the log + NoLog :: term(), % What to return when no log is found + Info :: #mod{}, + Date :: string(), + Reason :: term()) -> + {Log :: atom() | pid(), Entry :: string()}. + +error_entry(Log, NoLog, + #mod{config_db = ConfigDB, + init_data = #init_data{peername = {_, RemoteHost}}, + request_uri = URI}, Date, Reason) -> + MakeEntry = + fun() -> + do_error_entry(ConfigDB, RemoteHost, URI, Date, Reason) + end, + log_entry(Log, NoLog, ConfigDB, MakeEntry). + + +-spec error_report_entry(Log :: term(), + NoLog :: term(), + ConfigDB :: term(), + Date :: string(), + ErrroStr :: string()) -> + {Log :: atom() | pid(), Entry :: string()}. error_report_entry(Log, NoLog, ConfigDb, Date, ErrorStr) -> - case httpd_util:lookup(ConfigDb, Log) of - undefined -> - NoLog; - LogRef -> - Entry = io_lib:format("[~s], ~s~n", [Date, ErrorStr]), - {LogRef, Entry} - end. + MakeEntry = fun() -> io_lib:format("[~s], ~s~n", [Date, ErrorStr]) end, + log_entry(Log, NoLog, ConfigDb, MakeEntry). + -security_entry(Log, NoLog, #mod{config_db = ConfigDb}, Date, Reason) -> +-spec security_entry(Log :: term(), + NoLog :: term(), + ConfigDB :: term(), + Date :: string(), + Reason :: term()) -> + {Log :: atom() | pid(), Entry :: string()}. + +security_entry(Log, NoLog, #mod{config_db = ConfigDB}, Date, Reason) -> + MakeEntry = fun() -> io_lib:format("[~s] ~s~n", [Date, Reason]) end, + log_entry(Log, NoLog, ConfigDB, MakeEntry). + + +log_entry(Log, NoLog, ConfigDb, MakeEntry) when is_function(MakeEntry) -> case httpd_util:lookup(ConfigDb, Log) of undefined -> NoLog; LogRef -> - Entry = io_lib:format("[~s] ~s~n", [Date, Reason]), - {LogRef, Entry} + {LogRef, MakeEntry()} end. - + + %%%======================================================================== %%% Internal functions %%%======================================================================== + do_access_entry(ConfigDB, Headers, RequestLine, - RemoteHost, RFC931, AuthUser, Date, StatusCode, - Bytes) -> + RemoteHost, RFC931, AuthUser, Date, StatusCode, + Size) -> case httpd_util:lookup(ConfigDB, log_format, common) of common -> lists:flatten(io_lib:format("~s ~s ~s [~s] \"~s\" ~w ~w~n", [RemoteHost, RFC931, AuthUser, Date, RequestLine, - StatusCode, Bytes])); + StatusCode, Size])); combined -> Referer = proplists:get_value("referer", Headers, "-"), @@ -94,7 +136,7 @@ do_access_entry(ConfigDB, Headers, RequestLine, Headers, "-"), io_lib:format("~s ~s ~s [~s] \"~s\" ~w ~w ~s ~s~n", [RemoteHost, RFC931, AuthUser, Date, - RequestLine, StatusCode, Bytes, + RequestLine, StatusCode, Size, Referer, UserAgent]) end. diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl index d2f22fce93..b62c10bbc7 100644 --- a/lib/inets/src/http_server/httpd_request_handler.erl +++ b/lib/inets/src/http_server/httpd_request_handler.erl @@ -162,7 +162,14 @@ continue_init(Manager, ConfigDB, SocketType, Socket, TimeOut) -> %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- -handle_call(Request, From, State) -> +handle_call(Request, From, #state{mod = ModData} = State) -> + Error = + lists:flatten( + io_lib:format("Unexpected request: " + "~n~p" + "~nto request handler (~p) from ~p" + "~n", [Request, self(), From])), + error_log(Error, ModData), {stop, {call_api_violation, Request, From}, State}. %%-------------------------------------------------------------------- @@ -171,8 +178,15 @@ handle_call(Request, From, State) -> %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- -handle_cast(Msg, State) -> - {reply, {cast_api_violation, Msg}, State}. +handle_cast(Msg, #state{mod = ModData} = State) -> + Error = + lists:flatten( + io_lib:format("Unexpected message: " + "~n~p" + "~nto request handler (~p)" + "~n", [Msg, self()])), + error_log(Error, ModData), + {noreply, State}. %%-------------------------------------------------------------------- %% handle_info(Info, State) -> {noreply, State} | @@ -253,7 +267,10 @@ handle_info(timeout, #state{mod = ModData} = State) -> %% Default case handle_info(Info, #state{mod = ModData} = State) -> Error = lists:flatten( - io_lib:format("Unexpected message received: ~n~p~n", [Info])), + io_lib:format("Unexpected info: " + "~n~p" + "~nto request handler (~p)" + "~n", [Info, self()])), error_log(Error, ModData), {noreply, State}. diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl index c8a2ec0dc4..a912f5616c 100644 --- a/lib/inets/src/http_server/mod_log.erl +++ b/lib/inets/src/http_server/mod_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -100,7 +100,7 @@ do(Info) -> transfer_log(Info,"-",AuthUser,Date,StatusCode,Size), {proceed,Info#mod.data}; {response, Head, _Body} -> - Size = proplists:get_value(content_length,Head,unknown), + Size = content_length(Head), Code = proplists:get_value(code,Head,unknown), transfer_log(Info, "-", AuthUser, Date, Code, Size), {proceed, Info#mod.data}; @@ -254,4 +254,10 @@ auth_user(Data) -> RemoteUser end. - +content_length(Head) -> + case proplists:get_value(content_length, Head) of + undefined -> + unknown; + Size -> + list_to_integer(Size) + end. diff --git a/lib/inets/src/http_server/mod_responsecontrol.erl b/lib/inets/src/http_server/mod_responsecontrol.erl index 989f45db20..6af5f6211e 100644 --- a/lib/inets/src/http_server/mod_responsecontrol.erl +++ b/lib/inets/src/http_server/mod_responsecontrol.erl @@ -211,7 +211,7 @@ compare_etags(Tag,Etags) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% -%% Control if the file is modificated %% +%% Control if the file is modified %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile index 20e22917e2..d99e33b4ea 100644 --- a/lib/inets/src/inets_app/Makefile +++ b/lib/inets/src/inets_app/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2005-2010. All Rights Reserved. +# Copyright Ericsson AB 2005-2011. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -30,6 +30,7 @@ include ../../vsn.mk VSN = $(INETS_VSN) + # ---------------------------------------------------- # Release directory specification # ---------------------------------------------------- @@ -41,8 +42,8 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # ---------------------------------------------------- MODULES = \ - inets_service \ inets \ + inets_service \ inets_app \ inets_sup \ inets_regexp diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src index cb036157a5..1db7ed2c30 100644 --- a/lib/inets/src/inets_app/inets.app.src +++ b/lib/inets/src/inets_app/inets.app.src @@ -1,7 +1,7 @@ %% This is an -*- erlang -*- file. %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -34,8 +34,7 @@ ftp_sup, %% HTTP client: - http, %% Old client API module - httpc, %% New client API module + httpc, httpc_handler, httpc_handler_sup, httpc_manager, diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index 84217eac78..e80cb2a23b 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -18,91 +18,65 @@ {"%VSN%", [ - {"5.7.2", + {"5.8", [ {load_module, ftp, soft_purge, soft_purge, []}, - {update, httpc_handler, {advanced, upgrade_from_pre_5_7_3}, + {update, httpc_handler, {advanced, upgrade_from_pre_5_8_1}, soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, upgrade_from_pre_5_7_3}, + {update, httpc_manager, {advanced, upgrade_from_pre_5_8_1}, soft_purge, soft_purge, [httpc_handler]} ] }, - {"5.7.1", + {"5.7.2", [ - {load_module, ftp, soft_purge, soft_purge, []}, - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, http_util, soft_purge, soft_purge, []}, - {load_module, httpd_util, soft_purge, soft_purge, [http_util]}, - {load_module, httpd_file, soft_purge, soft_purge, []}, - {load_module, httpd_request, soft_purge, soft_purge, []}, - {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, - {update, httpc_handler, {advanced, upgrade_from_pre_5_7_3}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, upgrade_from_pre_5_7_3}, - soft_purge, soft_purge, [httpc_handler]} + {restart_application, inets} + ] + }, + {"5.7.1", + [ + {restart_application, inets} ] }, {"5.7", [ - {load_module, ftp, soft_purge, soft_purge, []}, - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, httpd_util, soft_purge, soft_purge, [http_util]}, - {load_module, httpd_file, soft_purge, soft_purge, []}, - {load_module, httpd_request, soft_purge, soft_purge, []}, - {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]}, - {load_module, http_util, soft_purge, soft_purge, []}, - {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, - {update, httpc_handler, {advanced, upgrade_from_pre_5_7_3}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, upgrade_from_pre_5_7_3}, - soft_purge, soft_purge, [httpc_handler]} + {restart_application, inets} ] - } + }, + {"5.6", + [ + {restart_application, inets} + ] + } ], [ - {"5.7.2", + {"5.8", [ {load_module, ftp, soft_purge, soft_purge, []}, - {update, httpc_handler, {advanced, downgrade_to_pre_5_7_3}, + {update, httpc_handler, {advanced, upgrade_from_pre_5_8_1}, soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, downgrade_to_pre_5_7_3}, + {update, httpc_manager, {advanced, upgrade_from_pre_5_8_1}, soft_purge, soft_purge, [httpc_handler]} ] }, - {"5.7.1", + {"5.7.2", [ - {load_module, ftp, soft_purge, soft_purge, []}, - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, http_util, soft_purge, soft_purge, []}, - {load_module, httpd_util, soft_purge, soft_purge, [http_util]}, - {load_module, httpd_file, soft_purge, soft_purge, []}, - {load_module, httpd_request, soft_purge, soft_purge, []}, - {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, - {update, httpc_handler, {advanced, downgrade_to_pre_5_7_3}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, downgrade_to_pre_5_7_3}, - soft_purge, soft_purge, [httpc_handler]} + {restart_application, inets} + ] + }, + {"5.7.1", + [ + {restart_application, inets} ] }, {"5.7", - [ - {load_module, ftp, soft_purge, soft_purge, []}, - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, httpd_util, soft_purge, soft_purge, [http_util]}, - {load_module, httpd_file, soft_purge, soft_purge, []}, - {load_module, httpd_request, soft_purge, soft_purge, []}, - {load_module, httpc_cookie, soft_purge, soft_purge, [http_util]}, - {load_module, http_util, soft_purge, soft_purge, []}, - {load_module, mod_responsecontrol, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, [mod_responsecontrol]}, - {update, httpc_handler, {advanced, downgrade_to_pre_5_7_3}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, downgrade_to_pre_5_7_3}, - soft_purge, soft_purge, [httpc_handler]} + [ + {restart_application, inets} + ] + }, + {"5.6", + [ + {restart_application, inets} ] - } + } ] }. diff --git a/lib/inets/src/inets_app/inets.mk b/lib/inets/src/inets_app/inets.mk index b6e9fe1d96..194b4ca2b1 100644 --- a/lib/inets/src/inets_app/inets.mk +++ b/lib/inets/src/inets_app/inets.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2010. All Rights Reserved. +# Copyright Ericsson AB 2010-2011. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -33,6 +33,10 @@ ifeq ($(WARN_UNUSED_WARS), true) ERL_COMPILE_FLAGS += +warn_unused_vars endif +ifeq ($(shell erl -noshell -eval 'io:format("~4s", [erlang:system_info(otp_release)])' -s init stop), R14B) +INETS_ERL_COMPILE_FLAGS += -D'OTP-R14B-COMPILER' +endif + INETS_APP_VSN_COMPILE_FLAGS = \ +'{parse_transform,sys_pre_attributes}' \ +'{attribute,insert,app_vsn,$(APP_VSN)}' diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl index e9eb9892f2..a057a51e2c 100644 --- a/lib/inets/src/inets_app/inets_service.erl +++ b/lib/inets/src/inets_app/inets_service.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% Copyright Ericsson AB 2007-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,24 +20,35 @@ -module(inets_service). +-ifdef('OTP-R14B-COMPILER'). + -export([behaviour_info/1]). behaviour_info(callbacks) -> - [{start_standalone, 1}, - {start_service, 1}, - {stop_service, 1}, - {services, 0}, - {service_info, 1}]; + [{start_standalone, 1}, + {start_service, 1}, + {stop_service, 1}, + {services, 0}, + {service_info, 1}]; behaviour_info(_) -> - undefined. + undefined. + +-else. %% Starts service stand-alone %% start_standalone(Config) -> % {ok, Pid} | {error, Reason} %% <service>:start_link(Config). +-callback start_standalone(Config :: term()) -> + {ok, pid()} | {error, Reason :: term()}. + %% Starts service as part of inets %% start_service(Config) -> % {ok, Pid} | {error, Reason} %% <service_sup>:start_child(Config). + +-callback start_service(Config :: term()) -> + {ok, pid()} | {error, Reason :: term()}. + %% Stop service %% stop_service(Pid) -> % ok | {error, Reason} %% <service_sup>:stop_child(maybe_map_pid_to_other_ref(Pid)). @@ -51,6 +62,9 @@ behaviour_info(_) -> %% Error %% end. +-callback stop_service(Service :: term()) -> + ok | {error, Reason :: term()}. + %% Returns list of running services. Services started as stand alone %% are not listed %% services() -> % [{Service, Pid}] @@ -59,7 +73,14 @@ behaviour_info(_) -> %% [{httpc, Pid} || {_, Pid, _, _} <- %% supervisor:which_children(httpc_profile_sup)]. +-callback services() -> + [{Service :: term(), pid()}]. -%% service_info() -> [{Property, Value}] | {error, Reason} +%% service_info() -> {ok, [{Property, Value}]} | {error, Reason} %% ex: httpc:service_info() -> [{profile, ProfileName}] %% httpd:service_info() -> [{host, Host}, {port, Port}] + +-callback service_info(Service :: term()) -> + {ok, [{Property :: term(), Value :: term()}]} | {error, Reason :: term()}. + +-endif. diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl index bfdb4c0030..0d7ae1a89e 100644 --- a/lib/inets/src/tftp/tftp.erl +++ b/lib/inets/src/tftp/tftp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -215,8 +215,6 @@ start/0 ]). --export([behaviour_info/1]). - %% Application local functions -export([ start_standalone/1, @@ -226,14 +224,67 @@ service_info/1 ]). +-ifdef('OTP-R14B-COMPILER'). + +-export([behaviour_info/1]). behaviour_info(callbacks) -> - [{prepare, 6}, {open, 6}, {read, 1}, {write, 2}, {abort, 3}]; + [{prepare, 6}, + {open, 6}, + {read, 1}, + {write, 2}, + {abort, 3}]; behaviour_info(_) -> undefined. +-else. + +-type peer() :: {PeerType :: inet | inet6, + PeerHost :: inet:ip_address(), + PeerPort :: port()}. + +-type access() :: read | write. + +-type options() :: [{Key :: string(), Value :: string()}]. + +-type error_code() :: undef | enoent | eacces | enospc | + badop | eexist | baduser | badopt | + integer(). + +-callback prepare(Peer :: peer(), + Access :: access(), + Filename :: file:name(), + Mode :: string(), + SuggestedOptions :: options(), + InitialState :: [] | [{root_dir, string()}]) -> + {ok, AcceptedOptions :: options(), NewState :: term()} | + {error, {Code :: error_code(), string()}}. + +-callback open(Peer :: peer(), + Access :: access(), + Filename :: file:name(), + Mode :: string(), + SuggestedOptions :: options(), + State :: [] | [{root_dir, string()}] | term()) -> + {ok, AcceptedOptions :: options(), NewState :: term()} | + {error, {Code :: error_code(), string()}}. + +-callback read(State :: term()) -> {more, binary(), NewState :: term()} | + {last, binary(), integer()} | + {error, {Code :: error_code(), string()}}. + +-callback write(binary(), State :: term()) -> + {more, NewState :: term()} | + {last, FileSize :: integer()} | + {error, {Code :: error_code(), string()}}. + +-callback abort(Code :: error_code(), string(), State :: term()) -> 'ok'. + +-endif. + -include("tftp.hrl"). + %%------------------------------------------------------------------- %% read_file(RemoteFilename, LocalFilename, Options) -> %% {ok, LastCallbackState} | {error, Reason} |