aboutsummaryrefslogtreecommitdiffstats
path: root/lib/inets/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/inets/src')
-rw-r--r--lib/inets/src/ftp/ftp.erl4
-rw-r--r--lib/inets/src/ftp/ftp_response.erl3
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl285
-rw-r--r--lib/inets/src/http_lib/http_transport.erl99
-rw-r--r--lib/inets/src/http_server/httpd_acceptor.erl38
-rw-r--r--lib/inets/src/http_server/httpd_acceptor_sup.erl20
-rw-r--r--lib/inets/src/http_server/httpd_conf.erl16
-rw-r--r--lib/inets/src/http_server/httpd_manager.erl8
-rw-r--r--lib/inets/src/http_server/httpd_response.erl6
-rw-r--r--lib/inets/src/http_server/httpd_sup.erl112
10 files changed, 303 insertions, 288 deletions
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index fe25c23316..132a384a49 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -1899,6 +1899,10 @@ ctrl_result_response(pos_compl, #state{client = From} = State, _) ->
gen_server:reply(From, ok),
{noreply, State#state{client = undefined, caller = undefined}};
+ctrl_result_response(enofile, #state{client = From} = State, _) ->
+ gen_server:reply(From, {error, enofile}),
+ {noreply, State#state{client = undefined, caller = undefined}};
+
ctrl_result_response(Status, #state{client = From} = State, _)
when (Status =:= etnospc) orelse
(Status =:= epnospc) orelse
diff --git a/lib/inets/src/ftp/ftp_response.erl b/lib/inets/src/ftp/ftp_response.erl
index faeacb31ab..364f534737 100644
--- a/lib/inets/src/ftp/ftp_response.erl
+++ b/lib/inets/src/ftp/ftp_response.erl
@@ -162,6 +162,7 @@ error_string(epath) -> "No such file or directory, already exists, "
error_string(etype) -> "No such type.";
error_string(euser) -> "User name or password not valid.";
error_string(etnospc) -> "Insufficient storage space in system.";
+error_string(enofile) -> "No files found or file unavailable";
error_string(epnospc) -> "Exceeded storage allocation "
"(for current directory or dataset).";
error_string(efnamena) -> "File name not allowed.";
@@ -180,6 +181,8 @@ interpret_status(?POS_COMPL,_,_) -> pos_compl;
interpret_status(?POS_INTERM,?AUTH_ACC,2) -> pos_interm_acct;
%% Positive Intermediate Reply
interpret_status(?POS_INTERM,_,_) -> pos_interm;
+%% No files found or file not available
+interpret_status(?TRANS_NEG_COMPL,?FILE_SYSTEM,0) -> enofile;
%% No storage area no action taken
interpret_status(?TRANS_NEG_COMPL,?FILE_SYSTEM,2) -> etnospc;
%% Temporary Error, no action taken
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 784a9c0019..857043bae2 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. 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
@@ -257,7 +257,7 @@ handle_call(#request{address = Addr} = Request, _,
session = #session{type = pipeline} = Session,
timers = Timers,
options = #options{proxy = Proxy} = _Options,
- profile_name = ProfileName} = State)
+ profile_name = ProfileName} = State0)
when Status =/= undefined ->
?hcrv("new request on a pipeline session",
@@ -274,18 +274,18 @@ handle_call(#request{address = Addr} = Request, _,
?hcrd("request sent", []),
%% Activate the request time out for the new request
- NewState =
- activate_request_timeout(State#state{request = Request}),
+ State1 =
+ activate_request_timeout(State0#state{request = Request}),
ClientClose =
httpc_request:is_client_closing(Request#request.headers),
- case State#state.request of
- #request{} -> %% Old request not yet finished
+ case State0#state.request of
+ #request{} = OldRequest -> %% Old request not yet finished
?hcrd("old request still not finished", []),
%% Make sure to use the new value of timers in state
- NewTimers = NewState#state.timers,
- NewPipeline = queue:in(Request, State#state.pipeline),
+ NewTimers = State1#state.timers,
+ NewPipeline = queue:in(Request, State1#state.pipeline),
NewSession =
Session#session{queue_length =
%% Queue + current
@@ -293,9 +293,11 @@ handle_call(#request{address = Addr} = Request, _,
client_close = ClientClose},
insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
- {reply, ok, State#state{pipeline = NewPipeline,
- session = NewSession,
- timers = NewTimers}};
+ {reply, ok, State1#state{
+ request = OldRequest,
+ pipeline = NewPipeline,
+ session = NewSession,
+ timers = NewTimers}};
undefined ->
%% Note: tcp-message receiving has already been
%% activated by handle_pipeline/2.
@@ -306,20 +308,15 @@ handle_call(#request{address = Addr} = Request, _,
Session#session{queue_length = 1,
client_close = ClientClose},
httpc_manager:insert_session(NewSession, ProfileName),
- Relaxed =
- (Request#request.settings)#http_options.relaxed,
- MFA = {httpc_response, parse,
- [State#state.max_header_size, Relaxed]},
NewTimers = Timers#timers{queue_timer = undefined},
?hcrd("session created", []),
- {reply, ok, NewState#state{request = Request,
- session = NewSession,
- mfa = MFA,
- timers = NewTimers}}
+ State = init_wait_for_response_state(Request, State1#state{session = NewSession,
+ timers = NewTimers}),
+ {reply, ok, State}
end;
{error, Reason} ->
?hcri("failed sending request", [{reason, Reason}]),
- {reply, {pipeline_failed, Reason}, State}
+ {reply, {pipeline_failed, Reason}, State0}
end;
handle_call(#request{address = Addr} = Request, _,
@@ -327,7 +324,7 @@ handle_call(#request{address = Addr} = Request, _,
session = #session{type = keep_alive} = Session,
timers = Timers,
options = #options{proxy = Proxy} = _Options,
- profile_name = ProfileName} = State)
+ profile_name = ProfileName} = State0)
when Status =/= undefined ->
?hcrv("new request on a keep-alive session",
@@ -335,65 +332,54 @@ handle_call(#request{address = Addr} = Request, _,
{profile, ProfileName},
{status, Status}]),
- Address = handle_proxy(Addr, Proxy),
- case httpc_request:send(Address, Session, Request) of
- ok ->
-
- ?hcrd("request sent", []),
-
- %% Activate the request time out for the new request
- NewState =
- activate_request_timeout(State#state{request = Request}),
-
- ClientClose =
- httpc_request:is_client_closing(Request#request.headers),
-
- case State#state.request of
- #request{} -> %% Old request not yet finished
- %% Make sure to use the new value of timers in state
- ?hcrd("old request still not finished", []),
- NewTimers = NewState#state.timers,
- NewKeepAlive = queue:in(Request, State#state.keep_alive),
- NewSession =
- Session#session{queue_length =
- %% Queue + current
- queue:len(NewKeepAlive) + 1,
- client_close = ClientClose},
- insert_session(NewSession, ProfileName),
- ?hcrd("session updated", []),
- {reply, ok, State#state{keep_alive = NewKeepAlive,
- session = NewSession,
- timers = NewTimers}};
- undefined ->
- %% Note: tcp-message reciving has already been
- %% activated by handle_pipeline/2.
- ?hcrd("no current request", []),
- cancel_timer(Timers#timers.queue_timer,
- timeout_queue),
- NewSession =
- Session#session{queue_length = 1,
- client_close = ClientClose},
- insert_session(NewSession, ProfileName),
- Relaxed =
- (Request#request.settings)#http_options.relaxed,
- MFA = {httpc_response, parse,
- [State#state.max_header_size, Relaxed]},
- {reply, ok, NewState#state{request = Request,
- session = NewSession,
- mfa = MFA}}
- end;
-
- {error, Reason} ->
- ?hcri("failed sending request", [{reason, Reason}]),
- {reply, {request_failed, Reason}, State}
+ ClientClose = httpc_request:is_client_closing(Request#request.headers),
+
+ case State0#state.request of
+ #request{} -> %% Old request not yet finished
+ %% Make sure to use the new value of timers in state
+ ?hcrd("old request still not finished", []),
+ NewKeepAlive = queue:in(Request, State0#state.keep_alive),
+ NewSession =
+ Session#session{queue_length =
+ %% Queue + current
+ queue:len(NewKeepAlive) + 1,
+ client_close = ClientClose},
+ insert_session(NewSession, ProfileName),
+ ?hcrd("session updated", []),
+ {reply, ok, State0#state{keep_alive = NewKeepAlive,
+ session = NewSession}};
+ undefined ->
+ %% Note: tcp-message reciving has already been
+ %% activated by handle_pipeline/2.
+ ?hcrd("no current request", []),
+ cancel_timer(Timers#timers.queue_timer,
+ timeout_queue),
+ Address = handle_proxy(Addr, Proxy),
+ case httpc_request:send(Address, Session, Request) of
+ ok ->
+ ?hcrd("request sent", []),
+
+ %% Activate the request time out for the new request
+ State1 =
+ activate_request_timeout(State0#state{request = Request}),
+ NewTimers = State1#state.timers,
+ NewSession =
+ Session#session{queue_length = 1,
+ client_close = ClientClose},
+ insert_session(NewSession, ProfileName),
+ State = init_wait_for_response_state(Request, State1#state{session = NewSession,
+ timers = NewTimers}),
+ {reply, ok, State};
+ {error, Reason} ->
+ ?hcri("failed sending request", [{reason, Reason}]),
+ {reply, {request_failed, Reason}, State0}
+ end
end;
-
handle_call(info, _, State) ->
Info = handler_info(State),
{reply, Info, State}.
-
%%--------------------------------------------------------------------
%% Function: handle_cast(Msg, State) -> {noreply, State} |
%% {noreply, State, Timeout} |
@@ -1239,8 +1225,7 @@ handle_queue(#state{status = pipeline} = State, Data) ->
handle_pipeline(#state{status = pipeline,
session = Session,
profile_name = ProfileName,
- options = #options{pipeline_timeout = TimeOut}} =
- State,
+ options = #options{pipeline_timeout = TimeOut}} = State,
Data) ->
?hcrd("handle pipeline", [{profile, ProfileName},
@@ -1250,25 +1235,7 @@ handle_pipeline(#state{status = pipeline,
case queue:out(State#state.pipeline) of
{empty, _} ->
?hcrd("pipeline queue empty", []),
-
- %% The server may choose too teminate an idle pipeline
- %% in this case we want to receive the close message
- %% at once and not when trying to pipeline the next
- %% request.
- activate_once(Session),
-
- %% If a pipeline that has been idle for some time is not
- %% closed by the server, the client may want to close it.
- NewState = activate_queue_timeout(TimeOut, State),
- update_session(ProfileName, Session, #session.queue_length, 0),
- %% Note mfa will be initilized when a new request
- %% arrives.
- {noreply,
- NewState#state{request = undefined,
- mfa = undefined,
- status_line = undefined,
- headers = undefined,
- body = undefined}};
+ handle_empty_queue(Session, ProfileName, TimeOut, State);
{{value, NextRequest}, Pipeline} ->
?hcrd("pipeline queue non-empty", []),
case lists:member(NextRequest#request.id,
@@ -1286,38 +1253,17 @@ handle_pipeline(#state{status = pipeline,
Session#session{queue_length =
%% Queue + current
queue:len(Pipeline) + 1},
- insert_session(NewSession, ProfileName),
- Relaxed =
- (NextRequest#request.settings)#http_options.relaxed,
- MFA = {httpc_response,
- parse,
- [State#state.max_header_size, Relaxed]},
- NewState =
- State#state{pipeline = Pipeline,
- request = NextRequest,
- mfa = MFA,
- status_line = undefined,
- headers = undefined,
- body = undefined},
- case Data of
- <<>> ->
- activate_once(Session),
- {noreply, NewState};
- _ ->
- %% If we already received some bytes of
- %% the next response
- handle_info({httpc_handler, dummy, Data},
- NewState)
- end
+ receive_response(NextRequest,
+ NewSession, Data,
+ State#state{pipeline = Pipeline})
end
end.
-handle_keep_alive_queue(
- #state{status = keep_alive,
- session = Session,
- profile_name = ProfileName,
- options = #options{keep_alive_timeout = TimeOut}} = State,
- Data) ->
+handle_keep_alive_queue(#state{status = keep_alive,
+ session = Session,
+ profile_name = ProfileName,
+ options = #options{keep_alive_timeout = TimeOut}} = State,
+ Data) ->
?hcrd("handle keep_alive", [{profile, ProfileName},
{session, Session},
@@ -1326,25 +1272,7 @@ handle_keep_alive_queue(
case queue:out(State#state.keep_alive) of
{empty, _} ->
?hcrd("keep_alive queue empty", []),
- %% The server may choose too terminate an idle keep_alive session
- %% in this case we want to receive the close message
- %% at once and not when trying to send the next
- %% request.
- activate_once(Session),
- %% If a keep_alive session has been idle for some time is not
- %% closed by the server, the client may want to close it.
- NewState = activate_queue_timeout(TimeOut, State),
- update_session(ProfileName, Session, #session.queue_length, 0),
- %% Note mfa will be initilized when a new request
- %% arrives.
- {noreply,
- NewState#state{request = undefined,
- mfa = undefined,
- status_line = undefined,
- headers = undefined,
- body = undefined
- }
- };
+ handle_empty_queue(Session, ProfileName, TimeOut, State);
{{value, NextRequest}, KeepAlive} ->
?hcrd("keep_alive queue non-empty", []),
case lists:member(NextRequest#request.id,
@@ -1355,30 +1283,61 @@ handle_keep_alive_queue(
State#state{keep_alive = KeepAlive}, Data);
false ->
?hcrv("next request", [{request, NextRequest}]),
- Relaxed =
- (NextRequest#request.settings)#http_options.relaxed,
- MFA = {httpc_response, parse,
- [State#state.max_header_size, Relaxed]},
- NewState =
- State#state{request = NextRequest,
- keep_alive = KeepAlive,
- mfa = MFA,
- status_line = undefined,
- headers = undefined,
- body = undefined},
- case Data of
- <<>> ->
- activate_once(Session),
- {noreply, NewState};
- _ ->
- %% If we already received some bytes of
- %% the next response
- handle_info({httpc_handler, dummy, Data},
- NewState)
+ #request{address = Address} = NextRequest,
+ case httpc_request:send(Address, Session, NextRequest) of
+ ok ->
+ receive_response(NextRequest,
+ Session, <<>>,
+ State#state{keep_alive = KeepAlive});
+ {error, Reason} ->
+ {reply, {keep_alive_failed, Reason}, State}
end
end
end.
+handle_empty_queue(Session, ProfileName, TimeOut, State) ->
+ %% The server may choose too terminate an idle pipline| keep_alive session
+ %% in this case we want to receive the close message
+ %% at once and not when trying to send the next
+ %% request.
+ activate_once(Session),
+ %% If a pipline | keep_alive session has been idle for some time is not
+ %% closed by the server, the client may want to close it.
+ NewState = activate_queue_timeout(TimeOut, State),
+ update_session(ProfileName, Session, #session.queue_length, 0),
+ %% Note mfa will be initilized when a new request
+ %% arrives.
+ {noreply,
+ NewState#state{request = undefined,
+ mfa = undefined,
+ status_line = undefined,
+ headers = undefined,
+ body = undefined
+ }
+ }.
+
+receive_response(Request, Session, Data, State) ->
+ NewState = init_wait_for_response_state(Request, State),
+ gather_data(Data, Session, NewState).
+
+init_wait_for_response_state(Request, State) ->
+ Relaxed =
+ (Request#request.settings)#http_options.relaxed,
+ MFA = {httpc_response, parse,
+ [State#state.max_header_size, Relaxed]},
+ State#state{request = Request,
+ mfa = MFA,
+ status_line = undefined,
+ headers = undefined,
+ body = undefined}.
+
+gather_data(<<>>, Session, State) ->
+ activate_once(Session),
+ {noreply, State};
+gather_data(Data, _, State) ->
+ %% If we already received some bytes of
+ %% the next response
+ handle_info({httpc_handler, dummy, Data}, State).
case_insensitive_header(Str) when is_list(Str) ->
http_util:to_lower(Str);
diff --git a/lib/inets/src/http_lib/http_transport.erl b/lib/inets/src/http_lib/http_transport.erl
index 5eb827032f..df58fa1b81 100644
--- a/lib/inets/src/http_lib/http_transport.erl
+++ b/lib/inets/src/http_lib/http_transport.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. 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
@@ -23,7 +23,7 @@
-export([
start/1,
connect/3, connect/4,
- listen/2, listen/3, listen/4,
+ listen/4, listen/5,
accept/2, accept/3,
close/2,
send/3,
@@ -155,41 +155,41 @@ connect({essl, SslConfig}, {Host, Port}, Opts0, Timeout) ->
%% reason for this to enable a HTTP-server not running as root to use
%% port 80.
%%-------------------------------------------------------------------------
-listen(SocketType, Port) ->
- listen(SocketType, undefined, Port).
+listen(ip_comm = _SocketType, Addr, Port, Fd, IpFamily) ->
+ listen_ip_comm(Addr, Port, Fd, IpFamily);
+
+listen({essl, SSLConfig}, Addr, Port, Fd, IpFamily) ->
+ listen_ssl(Addr, Port, Fd, SSLConfig, IpFamily).
-listen(ip_comm = _SocketType, Addr, Port) ->
- listen_ip_comm(Addr, Port, undefined);
+listen(ip_comm = _SocketType, Addr, Port, IpFamily) ->
+ listen_ip_comm(Addr, Port, undefined, IpFamily);
%% Wrapper for backaward compatibillity
-listen({ssl, SSLConfig}, Addr, Port) ->
+listen({ssl, SSLConfig}, Addr, Port, IpFamily) ->
?hlrt("listen (wrapper)",
[{addr, Addr},
{port, Port},
{ssl_config, SSLConfig}]),
- listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port);
+ listen({?HTTP_DEFAULT_SSL_KIND, SSLConfig}, Addr, Port, IpFamily);
-listen({essl, SSLConfig}, Addr, Port) ->
+
+listen({essl, SSLConfig}, Addr, Port, IpFamily) ->
?hlrt("listen (essl)",
[{addr, Addr},
{port, Port},
{ssl_config, SSLConfig}]),
- listen_ssl(Addr, Port, [{ssl_imp, new}, {reuseaddr, true} | SSLConfig]).
-
+ listen_ssl(Addr, Port, undefined, SSLConfig, IpFamily).
-listen(ip_comm, Addr, Port, Fd) ->
- listen_ip_comm(Addr, Port, Fd).
-
-listen_ip_comm(Addr, Port, Fd) ->
- case (catch do_listen_ip_comm(Addr, Port, Fd)) of
+listen_ip_comm(Addr, Port, Fd, IpFamily) ->
+ case (catch do_listen_ip_comm(Addr, Port, Fd, IpFamily)) of
{'EXIT', Reason} ->
{error, {exit, Reason}};
Else ->
Else
end.
-do_listen_ip_comm(Addr, Port, Fd) ->
- {NewPort, Opts, IpFamily} = get_socket_info(Addr, Port, Fd),
+do_listen_ip_comm(Addr, Port, Fd, IpFamily) ->
+ {NewPort, Opts} = get_socket_info(Addr, Port, Fd),
case IpFamily of
inet6fb4 ->
Opts2 = [inet6 | Opts],
@@ -222,10 +222,9 @@ do_listen_ip_comm(Addr, Port, Fd) ->
end.
-listen_ssl(Addr, Port, Opts0) ->
- IpFamily = ipfamily_default(Addr, Port),
- BaseOpts = [{backlog, 128}, {reuseaddr, true} | Opts0],
- Opts = sock_opts(Addr, BaseOpts),
+listen_ssl(Addr, Port, Fd, Opts0, IpFamily) ->
+ {NewPort, SockOpt} = get_socket_info(Addr, Port, Fd),
+ Opts = SockOpt ++ Opts0,
case IpFamily of
inet6fb4 ->
Opts2 = [inet6 | Opts],
@@ -236,13 +235,13 @@ listen_ssl(Addr, Port, Opts0) ->
Opts3 = [inet | Opts],
?hlrt("ipv6 listen failed - try ipv4 instead",
[{reason, Reason}, {opts, Opts3}]),
- ssl:listen(Port, Opts3);
+ ssl:listen(NewPort, Opts3);
{'EXIT', Reason} ->
Opts3 = [inet | Opts],
?hlrt("ipv6 listen exit - try ipv4 instead",
[{reason, Reason}, {opts, Opts3}]),
- ssl:listen(Port, Opts3);
+ ssl:listen(NewPort, Opts3);
Other ->
?hlrt("ipv6 listen done", [{other, Other}]),
@@ -252,61 +251,21 @@ listen_ssl(Addr, Port, Opts0) ->
_ ->
Opts2 = [IpFamily | Opts],
?hlrt("listen", [{opts, Opts2}]),
- ssl:listen(Port, Opts2)
+ ssl:listen(NewPort, Opts2)
end.
-ipfamily_default(Addr, Port) ->
- httpd_conf:lookup(Addr, Port, ipfamily, inet6fb4).
-get_socket_info(Addr, Port, Fd0) ->
+get_socket_info(Addr, Port, Fd) ->
BaseOpts = [{backlog, 128}, {reuseaddr, true}],
- IpFamilyDefault = ipfamily_default(Addr, Port),
%% The presence of a file descriptor takes precedence
- case get_fd(Port, Fd0, IpFamilyDefault) of
- {Fd, IpFamily} ->
- {0, sock_opts(Addr, [{fd, Fd} | BaseOpts]), IpFamily};
+ case Fd of
undefined ->
- {Port, sock_opts(Addr, BaseOpts), IpFamilyDefault}
+ {Port, sock_opts(Addr, BaseOpts)};
+ Fd ->
+ {0, sock_opts(Addr, [{fd, Fd} | BaseOpts])}
end.
-get_fd(Port, undefined = _Fd, IpFamilyDefault) ->
- FdKey = list_to_atom("httpd_" ++ integer_to_list(Port)),
- case init:get_argument(FdKey) of
- {ok, [[Value]]} ->
- case string:tokens(Value, [$|]) of
- [FdStr, IpFamilyStr] ->
- {fd_of(FdStr), ip_family_of(IpFamilyStr)};
- [FdStr] ->
- {fd_of(FdStr), IpFamilyDefault};
- _ ->
- throw({error, {bad_descriptor, Value}})
- end;
- error ->
- undefined
- end;
-get_fd(_Port, Fd, IpFamilyDefault) ->
- {Fd, IpFamilyDefault}.
-
-
-fd_of(FdStr) ->
- case (catch list_to_integer(FdStr)) of
- Fd when is_integer(Fd) ->
- Fd;
- _ ->
- throw({error, {bad_descriptor, FdStr}})
- end.
-
-ip_family_of(IpFamilyStr) ->
- IpFamily = list_to_atom(IpFamilyStr),
- case lists:member(IpFamily, [inet, inet6, inet6fb4]) of
- true ->
- IpFamily;
- false ->
- throw({error, {bad_ipfamily, IpFamilyStr}})
- end.
-
-
%%-------------------------------------------------------------------------
%% accept(SocketType, ListenSocket) -> {ok, Socket} | {error, Reason}
%% accept(SocketType, ListenSocket, Timeout) -> ok | {error, Reason}
diff --git a/lib/inets/src/http_server/httpd_acceptor.erl b/lib/inets/src/http_server/httpd_acceptor.erl
index 08ee9ee0d0..1bffcc1f12 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-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -24,10 +24,10 @@
-include("inets_internal.hrl").
%% Internal application API
--export([start_link/5, start_link/6]).
+-export([start_link/6, start_link/7]).
%% Other exports (for spawn's etc.)
--export([acceptor_init/6, acceptor_init/7, acceptor_loop/5]).
+-export([acceptor_init/7, acceptor_init/8, acceptor_loop/6]).
%%
%% External API
@@ -35,27 +35,27 @@
%% start_link
-start_link(Manager, SocketType, Addr, Port, ConfigDb, AcceptTimeout) ->
+start_link(Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) ->
?hdrd("start link",
[{manager, Manager},
{socket_type, SocketType},
{address, Addr},
{port, Port},
{timeout, AcceptTimeout}]),
- Args = [self(), Manager, SocketType, Addr, Port, ConfigDb, AcceptTimeout],
+ Args = [self(), Manager, SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout],
proc_lib:start_link(?MODULE, acceptor_init, Args).
-start_link(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout) ->
+start_link(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) ->
?hdrd("start link",
[{manager, Manager},
{socket_type, SocketType},
{listen_socket, ListenSocket},
{timeout, AcceptTimeout}]),
- Args = [self(), Manager, SocketType, ListenSocket,
+ Args = [self(), Manager, SocketType, ListenSocket, IpFamily,
ConfigDb, AcceptTimeout],
proc_lib:start_link(?MODULE, acceptor_init, Args).
-acceptor_init(Parent, Manager, SocketType, {ListenOwner, ListenSocket},
+acceptor_init(Parent, Manager, SocketType, {ListenOwner, ListenSocket}, IpFamily,
ConfigDb, AcceptTimeout) ->
?hdrd("acceptor init",
[{parent, Parent},
@@ -66,9 +66,9 @@ acceptor_init(Parent, Manager, SocketType, {ListenOwner, ListenSocket},
{timeout, AcceptTimeout}]),
link(ListenOwner),
proc_lib:init_ack(Parent, {ok, self()}),
- acceptor_loop(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout).
+ acceptor_loop(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout).
-acceptor_init(Parent, Manager, SocketType, Addr, Port,
+acceptor_init(Parent, Manager, SocketType, Addr, Port, IpFamily,
ConfigDb, AcceptTimeout) ->
?hdrd("acceptor init",
[{parent, Parent},
@@ -77,20 +77,20 @@ acceptor_init(Parent, Manager, SocketType, Addr, Port,
{address, Addr},
{port, Port},
{timeout, AcceptTimeout}]),
- case (catch do_init(SocketType, Addr, Port)) of
+ case (catch do_init(SocketType, Addr, Port, IpFamily)) of
{ok, ListenSocket} ->
proc_lib:init_ack(Parent, {ok, self()}),
acceptor_loop(Manager, SocketType,
- ListenSocket, ConfigDb, AcceptTimeout);
+ ListenSocket, IpFamily,ConfigDb, AcceptTimeout);
Error ->
proc_lib:init_ack(Parent, Error),
error
end.
-do_init(SocketType, Addr, Port) ->
+do_init(SocketType, Addr, Port, IpFamily) ->
?hdrt("do init", []),
do_socket_start(SocketType),
- ListenSocket = do_socket_listen(SocketType, Addr, Port),
+ ListenSocket = do_socket_listen(SocketType, Addr, Port, IpFamily),
{ok, ListenSocket}.
@@ -105,9 +105,9 @@ do_socket_start(SocketType) ->
end.
-do_socket_listen(SocketType, Addr, Port) ->
+do_socket_listen(SocketType, Addr, Port, IpFamily) ->
?hdrt("do socket listen", []),
- case http_transport:listen(SocketType, Addr, Port) of
+ case http_transport:listen(SocketType, Addr, Port, IpFamily) of
{ok, ListenSocket} ->
ListenSocket;
{error, Reason} ->
@@ -121,7 +121,7 @@ do_socket_listen(SocketType, Addr, Port) ->
%% acceptor
-acceptor_loop(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout) ->
+acceptor_loop(Manager, SocketType, ListenSocket, IpFamily, ConfigDb, AcceptTimeout) ->
?hdrd("awaiting accept",
[{manager, Manager},
{socket_type, SocketType},
@@ -133,12 +133,12 @@ acceptor_loop(Manager, SocketType, ListenSocket, ConfigDb, AcceptTimeout) ->
handle_connection(Manager, ConfigDb, AcceptTimeout,
SocketType, Socket),
?MODULE:acceptor_loop(Manager, SocketType,
- ListenSocket, ConfigDb,AcceptTimeout);
+ ListenSocket, IpFamily, ConfigDb,AcceptTimeout);
{error, Reason} ->
?hdri("accept failed", [{reason, Reason}]),
handle_error(Reason, ConfigDb),
?MODULE:acceptor_loop(Manager, SocketType, ListenSocket,
- ConfigDb, AcceptTimeout);
+ IpFamily, ConfigDb, AcceptTimeout);
{'EXIT', Reason} ->
?hdri("accept exited", [{reason, Reason}]),
ReasonString =
diff --git a/lib/inets/src/http_server/httpd_acceptor_sup.erl b/lib/inets/src/http_server/httpd_acceptor_sup.erl
index 8b1e4b6c4f..df837b5a24 100644
--- a/lib/inets/src/http_server/httpd_acceptor_sup.erl
+++ b/lib/inets/src/http_server/httpd_acceptor_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2013. 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
@@ -27,7 +27,7 @@
-behaviour(supervisor).
%% API
--export([start_link/2, start_acceptor/5, start_acceptor/6, stop_acceptor/2]).
+-export([start_link/2, start_acceptor/6, start_acceptor/7, stop_acceptor/2]).
%% Supervisor callback
-export([init/1]).
@@ -43,11 +43,11 @@ start_link(Addr, Port) ->
%% Function: [start|stop]_acceptor/5
%% Description: Starts/stops an [auth | security] worker (child) process
%%----------------------------------------------------------------------
-start_acceptor(SocketType, Addr, Port, ConfigDb, AcceptTimeout) ->
- start_worker(httpd_acceptor, SocketType, Addr, Port,
+start_acceptor(SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout) ->
+ start_worker(httpd_acceptor, SocketType, Addr, Port, IpFamily,
ConfigDb, AcceptTimeout, self(), []).
-start_acceptor(SocketType, Addr, Port, ConfigDb, AcceptTimeout, ListenSocket) ->
- start_worker(httpd_acceptor, SocketType, Addr, Port,
+start_acceptor(SocketType, Addr, Port, IpFamily, ConfigDb, AcceptTimeout, ListenSocket) ->
+ start_worker(httpd_acceptor, SocketType, Addr, Port, IpFamily,
ConfigDb, AcceptTimeout, ListenSocket, self(), []).
@@ -69,18 +69,18 @@ init(_) ->
make_name(Addr,Port) ->
httpd_util:make_name("httpd_acc_sup", Addr, Port).
-start_worker(M, SocketType, Addr, Port, ConfigDB, AcceptTimeout, Manager, Modules) ->
+start_worker(M, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout, Manager, Modules) ->
SupName = make_name(Addr, Port),
- Args = [Manager, SocketType, Addr, Port, ConfigDB, AcceptTimeout],
+ Args = [Manager, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout],
Spec = {{M, Addr, Port},
{M, start_link, Args},
permanent, timer:seconds(1), worker, [M] ++ Modules},
supervisor:start_child(SupName, Spec).
-start_worker(M, SocketType, Addr, Port, ConfigDB, AcceptTimeout, ListenSocket,
+start_worker(M, SocketType, Addr, Port, IpFamily, ConfigDB, AcceptTimeout, ListenSocket,
Manager, Modules) ->
SupName = make_name(Addr, Port),
- Args = [Manager, SocketType, ListenSocket, ConfigDB, AcceptTimeout],
+ Args = [Manager, SocketType, ListenSocket, IpFamily, ConfigDB, AcceptTimeout],
Spec = {{M, Addr, Port},
{M, start_link, Args},
permanent, timer:seconds(1), worker, [M] ++ Modules},
diff --git a/lib/inets/src/http_server/httpd_conf.erl b/lib/inets/src/http_server/httpd_conf.erl
index a97bbd9b25..d45f3c0048 100644
--- a/lib/inets/src/http_server/httpd_conf.erl
+++ b/lib/inets/src/http_server/httpd_conf.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -582,11 +582,17 @@ validate_config_params([{server_tokens, {private, Value}} | Rest])
validate_config_params([{server_tokens, Value} | _]) ->
throw({server_tokens, Value});
+validate_config_params([{socket_type, ip_comm} | Rest]) ->
+ validate_config_params(Rest);
+
validate_config_params([{socket_type, Value} | Rest])
- when (Value =:= ip_comm) orelse
- (Value =:= ssl) orelse
- (Value =:= essl) ->
+ when Value == ssl; Value == essl ->
validate_config_params(Rest);
+
+validate_config_params([{socket_type, {Value, _}} | Rest])
+ when Value == essl orelse Value == ssl ->
+ validate_config_params(Rest);
+
validate_config_params([{socket_type, Value} | _]) ->
throw({socket_type, Value});
@@ -916,6 +922,8 @@ lookup_socket_type(ConfigDB) ->
case httpd_util:lookup(ConfigDB, socket_type, ip_comm) of
ip_comm ->
ip_comm;
+ {Tag, Conf} ->
+ {Tag, Conf};
SSL when (SSL =:= ssl) orelse (SSL =:= essl) ->
SSLTag =
if
diff --git a/lib/inets/src/http_server/httpd_manager.erl b/lib/inets/src/http_server/httpd_manager.erl
index b44bc77c41..672a70a394 100644
--- a/lib/inets/src/http_server/httpd_manager.erl
+++ b/lib/inets/src/http_server/httpd_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2013. 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
@@ -264,11 +264,12 @@ init([ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo]) ->
end.
do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port) ->
+ IpFamily = proplists:get_value(ipfamily, ConfigList, inet6fb4),
NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile),
ConfigDB = do_initial_store(ConfigList),
SocketType = httpd_conf:lookup_socket_type(ConfigDB),
case httpd_acceptor_sup:start_acceptor(SocketType, Addr,
- Port, ConfigDB, AcceptTimeout) of
+ Port, IpFamily, ConfigDB, AcceptTimeout) of
{ok, _Pid} ->
Status = [{max_conn, 0},
{last_heavy_load, never},
@@ -284,11 +285,12 @@ do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port) ->
end.
do_init(ConfigFile, ConfigList, AcceptTimeout, Addr, Port, ListenInfo) ->
+ IpFamily = proplists:get_value(ipfamily, ConfigList, inet6fb4),
NewConfigFile = proplists:get_value(file, ConfigList, ConfigFile),
ConfigDB = do_initial_store(ConfigList),
SocketType = httpd_conf:lookup_socket_type(ConfigDB),
case httpd_acceptor_sup:start_acceptor(SocketType, Addr,
- Port, ConfigDB,
+ Port, IpFamily, ConfigDB,
AcceptTimeout, ListenInfo) of
{ok, _Pid} ->
Status = [{max_conn,0}, {last_heavy_load,never},
diff --git a/lib/inets/src/http_server/httpd_response.erl b/lib/inets/src/http_server/httpd_response.erl
index 2dedb088e4..6b6532266b 100644
--- a/lib/inets/src/http_server/httpd_response.erl
+++ b/lib/inets/src/http_server/httpd_response.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2013. 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
@@ -35,8 +35,7 @@ generate_and_send_response(#mod{init_data =
#init_data{peername = {_,"unknown"}}}) ->
ok;
generate_and_send_response(#mod{config_db = ConfigDB} = ModData) ->
- Modules = httpd_util:lookup(ConfigDB,modules,
- [mod_get, mod_head, mod_log]),
+ Modules = httpd_util:lookup(ConfigDB,modules, ?DEFAULT_MODS),
case traverse_modules(ModData, Modules) of
done ->
ok;
@@ -71,7 +70,6 @@ traverse_modules(ModData,[Module|Rest]) ->
?hdrd("traverse modules", [{callback_module, Module}]),
case (catch apply(Module, do, [ModData])) of
{'EXIT', Reason} ->
- ?hdrd("traverse modules - exit", [{reason, Reason}]),
String =
lists:flatten(
io_lib:format("traverse exit from apply: ~p:do => ~n~p",
diff --git a/lib/inets/src/http_server/httpd_sup.erl b/lib/inets/src/http_server/httpd_sup.erl
index 8f3e8f9500..3b1e16cf78 100644
--- a/lib/inets/src/http_server/httpd_sup.erl
+++ b/lib/inets/src/http_server/httpd_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. 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
@@ -196,7 +196,8 @@ httpd_child_spec(ConfigFile, AcceptTimeoutDef, DebugDef) ->
end.
httpd_child_spec(Config, AcceptTimeout, Debug, Addr, Port) ->
- case (Port =:= 0) orelse proplists:is_defined(fd, Config) of
+ Fd = proplists:get_value(fd, Config, undefined),
+ case Port == 0 orelse Fd =/= undefined of
true ->
httpd_child_spec_listen(Config, AcceptTimeout, Debug, Addr, Port);
false ->
@@ -242,21 +243,27 @@ error_msg(F, A) ->
error_logger:error_msg(F ++ "~n", A).
listen(Address, Port, Config) ->
- SocketType = proplists:get_value(socket_type, Config, ip_comm),
- case http_transport:start(SocketType) of
- ok ->
- Fd = proplists:get_value(fd, Config),
- case http_transport:listen(SocketType, Address, Port, Fd) of
- {ok, ListenSocket} ->
- NewConfig = proplists:delete(port, Config),
- {ok, NewPort} = inet:port(ListenSocket),
- {NewPort, [{port, NewPort} | NewConfig], ListenSocket};
+ try socket_type(Config) of
+ SocketType ->
+ case http_transport:start(SocketType) of
+ ok ->
+ Fd = proplists:get_value(fd, Config),
+ IpFamily = proplists:get_value(ipfamily, Config, inet6fb4),
+ case http_transport:listen(SocketType, Address, Port, Fd, IpFamily) of
+ {ok, ListenSocket} ->
+ NewConfig = proplists:delete(port, Config),
+ {NewPort, _} = http_transport:sockname(SocketType, ListenSocket),
+ {NewPort, [{port, NewPort} | NewConfig], ListenSocket};
+ {error, Reason} ->
+ {error, {listen, Reason}}
+ end;
{error, Reason} ->
- {error, {listen, Reason}}
- end;
- {error, Reason} ->
+ {error, {socket_start_failed, Reason}}
+ end
+ catch
+ _:Reason ->
{error, {socket_start_failed, Reason}}
- end.
+ end.
start_listen(Address, Port, Config) ->
Pid = listen_owner(Address, Port, Config),
@@ -280,7 +287,82 @@ listen_loop() ->
ok
end.
+socket_type(Config) ->
+ SocketType = proplists:get_value(socket_type, Config, ip_comm),
+ socket_type(SocketType, Config).
+
+socket_type(ip_comm = SocketType, _) ->
+ SocketType;
+socket_type({essl, _} = SocketType, _) ->
+ SocketType;
+socket_type(_, Config) ->
+ {essl, ssl_config(Config)}.
+
+%%% Backwards compatibility
+ssl_config(Config) ->
+ ssl_certificate_key_file(Config) ++
+ ssl_verify_client(Config) ++
+ ssl_ciphers(Config) ++
+ ssl_password(Config) ++
+ ssl_verify_depth(Config) ++
+ ssl_ca_certificate_file(Config).
+
+ssl_certificate_key_file(Config) ->
+ case proplists:get_value(ssl_certificate_key_file, Config) of
+ undefined ->
+ [];
+ SSLCertificateKeyFile ->
+ [{keyfile,SSLCertificateKeyFile}]
+ end.
+ssl_verify_client(Config) ->
+ case proplists:get_value(ssl_verify_client, Config) of
+ undefined ->
+ [];
+ SSLVerifyClient ->
+ [{verify,SSLVerifyClient}]
+ end.
+ssl_ciphers(Config) ->
+ case proplists:get_value(ssl_ciphers, Config) of
+ undefined ->
+ [];
+ Ciphers ->
+ [{ciphers, Ciphers}]
+ end.
+ssl_password(Config) ->
+ case proplists:get_value(ssl_password_callback_module, Config) of
+ undefined ->
+ [];
+ Module ->
+ case proplists:get_value(ssl_password_callback_function, Config) of
+ undefined ->
+ [];
+ Function ->
+ Args = case proplists:get_value(ssl_password_callback_arguments, Config) of
+ undefined ->
+ [];
+ Arguments ->
+ [Arguments]
+ end,
+ Password = apply(Module, Function, Args),
+ [{password, Password}]
+ end
+ end.
+ssl_verify_depth(Config) ->
+ case proplists:get_value(ssl_verify_client_depth, Config) of
+ undefined ->
+ [];
+ Depth ->
+ [{depth, Depth}]
+ end.
+
+ssl_ca_certificate_file(Config) ->
+ case proplists:get_value(ssl_ca_certificate_file, Config) of
+ undefined ->
+ [];
+ File ->
+ [{cacertfile, File}]
+ end.