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.erl7
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl125
-rw-r--r--lib/inets/src/http_client/httpc_internal.hrl36
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl90
-rw-r--r--lib/inets/src/inets_app/inets.appup.src46
5 files changed, 245 insertions, 59 deletions
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index ac72963347..3028cd800f 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -1912,17 +1912,14 @@ setup_ctrl_connection(Host, Port, Timeout, State) ->
setup_data_connection(#state{mode = active,
caller = Caller,
csock = CSock} = State) ->
- IntToString = fun(Element) -> integer_to_list(Element) end,
-
case (catch inet:sockname(CSock)) of
{ok, {{_, _, _, _, _, _, _, _} = IP, _}} ->
{ok, LSock} =
gen_tcp:listen(0, [{ip, IP}, {active, false},
inet6, binary, {packet, 0}]),
{ok, Port} = inet:port(LSock),
- Cmd = mk_cmd("EPRT |2|~s:~s:~s:~s:~s:~s:~s:~s|~s|",
- lists:map(IntToString,
- tuple_to_list(IP) ++ [Port])),
+ IpAddress = inet_parse:ntoa(IP),
+ Cmd = mk_cmd("EPRT |2|~s|~p|", [IpAddress, Port]),
send_ctrl_message(State, Cmd),
activate_ctrl_connection(State),
{noreply, State#state{caller = {setup_data_connection,
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 0f9e039643..7784060a2b 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -288,7 +288,7 @@ handle_call(#request{address = Addr} = Request, _,
%% Queue + current
queue:len(NewPipeline) + 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{pipeline = NewPipeline,
session = NewSession,
@@ -356,7 +356,7 @@ handle_call(#request{address = Addr} = Request, _,
%% Queue + current
queue:len(NewKeepAlive) + 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
?hcrd("session updated", []),
{reply, ok, State#state{keep_alive = NewKeepAlive,
session = NewSession,
@@ -370,7 +370,7 @@ handle_call(#request{address = Addr} = Request, _,
NewSession =
Session#session{queue_length = 1,
client_close = ClientClose},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
Relaxed =
(Request#request.settings)#http_options.relaxed,
MFA = {httpc_response, parse,
@@ -759,23 +759,52 @@ deliver_answer(Request) ->
%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
%% Purpose: Convert process state when code is changed
%%--------------------------------------------------------------------
-%% code_change(_, #state{request = Request, pipeline = Queue} = State,
-%% [{from, '5.0.1'}, {to, '5.0.2'}]) ->
-%% Settings = new_http_options(Request#request.settings),
-%% NewRequest = Request#request{settings = Settings},
-%% NewQueue = new_queue(Queue, fun new_http_options/1),
-%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
-
-%% code_change(_, #state{request = Request, pipeline = Queue} = State,
-%% [{from, '5.0.2'}, {to, '5.0.1'}]) ->
-%% Settings = old_http_options(Request#request.settings),
-%% NewRequest = Request#request{settings = Settings},
-%% NewQueue = new_queue(Queue, fun old_http_options/1),
-%% {ok, State#state{request = NewRequest, pipeline = NewQueue}};
+
+code_change(_,
+ #state{session = OldSession,
+ profile_name = ProfileName} = State,
+ upgrade_from_pre_5_7_3) ->
+ case OldSession of
+ {session,
+ Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type} ->
+ NewSession = #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type},
+ insert_session(NewSession, ProfileName),
+ {ok, State#state{session = NewSession}};
+ _ ->
+ {ok, State}
+ end;
+
+code_change(_,
+ #state{session = OldSession,
+ profile_name = ProfileName} = State,
+ downgrade_to_pre_5_7_3) ->
+ case OldSession of
+ #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type} ->
+ NewSession = {session,
+ Id, ClientClose, Scheme, Socket, SocketType,
+ QueueLen, Type},
+ insert_session(NewSession, ProfileName),
+ {ok, State#state{session = NewSession}};
+ _ ->
+ {ok, State}
+ end;
code_change(_, State, _) ->
{ok, State}.
+
%% new_http_options({http_options, TimeOut, AutoRedirect, SslOpts,
%% Auth, Relaxed}) ->
%% {http_options, "HTTP/1.1", TimeOut, AutoRedirect, SslOpts,
@@ -1174,7 +1203,7 @@ handle_pipeline(#state{status = pipeline,
case queue:out(State#state.pipeline) of
{empty, _} ->
- ?hcrd("epmty pipeline queue", []),
+ ?hcrd("pipeline queue empty", []),
%% The server may choose too teminate an idle pipeline
%% in this case we want to receive the close message
@@ -1184,9 +1213,8 @@ handle_pipeline(#state{status = pipeline,
%% 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),
- NewSession = Session#session{queue_length = 0},
- httpc_manager:insert_session(NewSession, ProfileName),
+ 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,
@@ -1196,6 +1224,7 @@ handle_pipeline(#state{status = pipeline,
headers = undefined,
body = undefined}};
{{value, NextRequest}, Pipeline} ->
+ ?hcrd("pipeline queue non-empty", []),
case lists:member(NextRequest#request.id,
State#state.canceled) of
true ->
@@ -1211,7 +1240,7 @@ handle_pipeline(#state{status = pipeline,
Session#session{queue_length =
%% Queue + current
queue:len(Pipeline) + 1},
- httpc_manager:insert_session(NewSession, ProfileName),
+ insert_session(NewSession, ProfileName),
Relaxed =
(NextRequest#request.settings)#http_options.relaxed,
MFA = {httpc_response,
@@ -1250,7 +1279,7 @@ handle_keep_alive_queue(
case queue:out(State#state.keep_alive) of
{empty, _} ->
- ?hcrd("empty keep_alive queue", []),
+ ?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
@@ -1259,8 +1288,7 @@ handle_keep_alive_queue(
%% 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),
- NewSession = Session#session{queue_length = 0},
- httpc_manager:insert_session(NewSession, ProfileName),
+ update_session(ProfileName, Session, #session.queue_length, 0),
%% Note mfa will be initilized when a new request
%% arrives.
{noreply,
@@ -1272,6 +1300,7 @@ handle_keep_alive_queue(
}
};
{{value, NextRequest}, KeepAlive} ->
+ ?hcrd("keep_alive queue non-empty", []),
case lists:member(NextRequest#request.id,
State#state.canceled) of
true ->
@@ -1381,10 +1410,10 @@ try_to_enable_pipeline_or_keep_alive(
case (is_pipeline_enabled_client(Session) andalso
httpc_request:is_idempotent(Method)) of
true ->
- httpc_manager:insert_session(Session, ProfileName),
+ insert_session(Session, ProfileName),
State#state{status = pipeline};
false ->
- httpc_manager:insert_session(Session, ProfileName),
+ insert_session(Session, ProfileName),
%% Make sure type is keep_alive in session
%% as it in this case might be pipeline
NewSession = Session#session{type = keep_alive},
@@ -1396,7 +1425,9 @@ try_to_enable_pipeline_or_keep_alive(
end.
answer_request(#request{id = RequestId, from = From} = Request, Msg,
- #state{timers = Timers, profile_name = ProfileName} = State) ->
+ #state{session = Session,
+ timers = Timers,
+ profile_name = ProfileName} = State) ->
?hcrt("answer request", [{request, Request}, {msg, Msg}]),
httpc_response:send(From, Msg),
RequestTimers = Timers#timers.request_timers,
@@ -1405,12 +1436,20 @@ answer_request(#request{id = RequestId, from = From} = Request, Msg,
Timer = {RequestId, TimerRef},
cancel_timer(TimerRef, {timeout, Request#request.id}),
httpc_manager:request_done(RequestId, ProfileName),
-
+ NewSession = maybe_make_session_available(ProfileName, Session),
+ Timers2 = Timers#timers{request_timers = lists:delete(Timer,
+ RequestTimers)},
State#state{request = Request#request{from = answer_sent},
- timers =
- Timers#timers{request_timers =
- lists:delete(Timer, RequestTimers)}}.
-
+ session = NewSession,
+ timers = Timers2}.
+
+maybe_make_session_available(ProfileName,
+ #session{available = false} = Session) ->
+ update_session(ProfileName, Session, #session.available, true),
+ Session#session{available = true};
+maybe_make_session_available(_ProfileName, Session) ->
+ Session.
+
cancel_timers(#timers{request_timers = ReqTmrs, queue_timer = QTmr}) ->
cancel_timer(QTmr, timeout_queue),
CancelTimer = fun({_, Timer}) -> cancel_timer(Timer, timeout) end,
@@ -1649,6 +1688,28 @@ send_raw(SocketType, Socket, ProcessBody, Acc) ->
end.
+%% ---------------------------------------------------------------------
+%% Session wrappers
+%% ---------------------------------------------------------------------
+
+insert_session(Session, ProfileName) ->
+ httpc_manager:insert_session(Session, ProfileName).
+
+
+update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) ->
+ try
+ begin
+ httpc_manager:update_session(ProfileName, SessionId, Pos, Value)
+ end
+ catch
+ error:undef -> % This could happen during code upgrade
+ Session2 = erlang:setelement(Pos, Session, Value),
+ insert_session(Session2, ProfileName)
+ end.
+
+
+%% ---------------------------------------------------------------------
+
call(Msg, Pid) ->
Timeout = infinity,
call(Msg, Pid, Timeout).
diff --git a/lib/inets/src/http_client/httpc_internal.hrl b/lib/inets/src/http_client/httpc_internal.hrl
index 1d8a5b6a92..3261061d61 100644
--- a/lib/inets/src/http_client/httpc_internal.hrl
+++ b/lib/inets/src/http_client/httpc_internal.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2012. 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
@@ -112,17 +112,37 @@
}
).
+
-record(session,
{
- id, % {{Host, Port}, HandlerPid}
- client_close, % true | false
- scheme, % http (HTTP/TCP) | https (HTTP/SSL/TCP)
- socket, % Open socket, used by connection
- socket_type, % socket-type, used by connection
- queue_length = 1, % Current length of pipeline or keep-alive queue
- type % pipeline | keep_alive (wait for response before sending new request)
+ %% {{Host, Port}, HandlerPid}
+ id,
+
+ %% true | false
+ client_close,
+
+ %% http (HTTP/TCP) | https (HTTP/SSL/TCP)
+ scheme,
+
+ %% Open socket, used by connection
+ socket,
+
+ %% socket-type, used by connection
+ socket_type,
+
+ %% Current length of pipeline or keep-alive queue
+ queue_length = 1,
+
+ %% pipeline | keep_alive (wait for response before sending new request)
+ type,
+
+ %% true | false
+ %% This will be true, when a response has been received for
+ %% the first request. See type above.
+ available = false
}).
+
-record(http_cookie,
{
domain,
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 9015bf1ce2..3d846c2bff 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2012. 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,6 +34,7 @@
retry_request/2,
redirect_request/2,
insert_session/2,
+ update_session/4,
delete_session/2,
set_options/2,
store_cookies/3,
@@ -193,6 +194,27 @@ insert_session(Session, ProfileName) ->
%%--------------------------------------------------------------------
+%% Function: update_session(ProfileName, SessionId, Pos, Value) -> _
+%% Session - #session{}
+%% ProfileName - atom()
+%%
+%% Description: Update, only one field (Pos) of the session record
+%% identified by the SessionId, the session information
+%% of the httpc manager table <ProfileName>_session_db.
+%% Intended to be called by the httpc request handler process.
+%%--------------------------------------------------------------------
+
+update_session(ProfileName, SessionId, Pos, Value) ->
+ SessionDbName = session_db_name(ProfileName),
+ ?hcrt("update session",
+ [{id, SessionId},
+ {pos, Pos},
+ {value, Value},
+ {profile, ProfileName}]),
+ ets:update_element(SessionDbName, SessionId, {Pos, Value}).
+
+
+%%--------------------------------------------------------------------
%% Function: delete_session(SessionId, ProfileName) -> _
%% SessionId - {{Host, Port}, HandlerPid}
%% ProfileName - atom()
@@ -548,9 +570,70 @@ terminate(_, State) ->
%% Func: code_change(_OldVsn, State, Extra) -> {ok, NewState}
%% Purpose: Convert process state when code is changed
%%--------------------------------------------------------------------
-code_change(_OldVsn, State, _Extra) ->
+code_change(_,
+ #state{session_db = SessionDB} = State,
+ upgrade_from_pre_5_7_3) ->
+ Upgrade =
+ fun({session,
+ Id, ClientClose, Scheme, Socket, SocketType, QueueLen, Type}) ->
+ {ok, #session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type}};
+ (_) -> % Already upgraded (by handler)
+ ignore
+ end,
+ (catch update_session_table(SessionDB, Upgrade)),
+ {ok, State};
+
+code_change(_,
+ #state{session_db = SessionDB} = State,
+ downgrade_to_pre_5_7_3) ->
+ Downgrade =
+ fun(#session{id = Id,
+ client_close = ClientClose,
+ scheme = Scheme,
+ socket = Socket,
+ socket_type = SocketType,
+ queue_length = QueueLen,
+ type = Type}) ->
+ {ok, {session,
+ Id, ClientClose, Scheme, Socket, SocketType,
+ QueueLen, Type}};
+ (_) -> % Already downgraded (by handler)
+ ignore
+ end,
+ (catch update_session_table(SessionDB, Downgrade)),
+ {ok, State};
+
+code_change(_, State, _) ->
{ok, State}.
+%% This function is to catch everything that calls through the cracks...
+update_session_table(SessionDB, Transform) ->
+ ets:safe_fixtable(SessionDB, true),
+ update_session_table(SessionDB, ets:first(SessionDB), Transform),
+ ets:safe_fixtable(SessionDB, false).
+
+update_session_table(_SessionDB, '$end_of_table', _Transform) ->
+ ok;
+update_session_table(SessionDB, Key, Transform) ->
+ case ets:lookup(SessionDB, Key) of
+ [OldSession] ->
+ case Transform(OldSession) of
+ {ok, NewSession} ->
+ ets:insert(SessionDB, NewSession);
+ ignore ->
+ ok
+ end;
+ _ ->
+ ok
+ end,
+ update_session_table(SessionDB, ets:next(SessionDB, Key), Transform).
+
%%--------------------------------------------------------------------
%% Internal functions
@@ -679,6 +762,7 @@ select_session(Method, HostPort, Scheme, SessionType,
scheme = Scheme,
queue_length = '$2',
type = SessionType,
+ available = true,
_ = '_'},
%% {'_', {HostPort, '$1'}, false, Scheme, '_', '$2', SessionTyp},
Candidates = ets:match(SessionDb, Pattern),
@@ -716,7 +800,7 @@ pipeline_or_keep_alive(Request, HandlerPid, State) ->
ets:insert(State#state.handler_db, {Request#request.id,
HandlerPid,
Request#request.from});
- _ -> %timeout pipelining failed
+ _ -> % timeout pipelining failed
start_handler(Request, State)
end.
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 6864558781..84217eac78 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -20,23 +20,32 @@
[
{"5.7.2",
[
- {update, httpc_handler, soft, soft_purge, soft_purge, []}
+ {load_module, ftp, soft_purge, soft_purge, []},
+ {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]}
]
},
{"5.7.1",
[
+ {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, soft, 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]}
]
},
{"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, []},
@@ -44,31 +53,43 @@
{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, soft, 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]}
]
}
],
[
{"5.7.2",
[
- {update, httpc_handler, soft, soft_purge, soft_purge, []}
+ {load_module, ftp, soft_purge, soft_purge, []},
+ {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]}
]
},
{"5.7.1",
[
+ {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, soft, 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]}
]
},
{"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, []},
@@ -76,8 +97,11 @@
{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, soft, 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]}
]
}
]