1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
19
%%% Description: tcp listen and accept-loop
21
-module(ssh_tcp_wrap).
23
-export([spawn_server/3, server/3]).
24
-export([server_init/4, server_loop/3, accept_loop/4]). %% helper
26
-define(ACCEPT_TIMEOUT, 10000).
28
%% Spawn the server loop
29
spawn_server(Port, Opts, Fun) ->
30
Pid = spawn(?MODULE, server_init, [self(),Port,Opts,Fun]),
31
Ref = erlang:monitor(process, Pid),
33
{'DOWN', Ref, _, _, Reason} ->
36
erlang:demonitor(Ref),
40
server_init(Starter, Port, Opts, Fun) ->
41
case gen_tcp:listen(Port, Opts) of
44
case inet:sockname(Listen) of
46
Starter ! {self(), {ok,self(),Port1}},
47
server_loop(self(), Listen, Fun);
49
gen_tcp:close(Listen),
50
Starter ! {self(), Error}
53
Starter ! {self(), {ok,self(),Port}},
54
server_loop(self(), Listen, Fun)
58
"Failed to listen on port: ~p opts:~p: rsn:~p~n",
60
Starter ! {self(), Error}
64
%% Run the server loop
65
server(Port, Opts, Fun) ->
66
case gen_tcp:listen(Port, Opts) of
68
server_loop(self(), Listen, Fun);
71
"Failed to listen on port: ~p opts:~p: rsn:~p~n",
76
server_loop(User, Listen, Fun) ->
78
?MODULE:accept_loop(User, erlang:monitor(process,User),
81
Ref = erlang:monitor(process, Pid),
83
{'DOWN', Ref, _, _, _Reason} ->
84
?MODULE:server_loop(User, Listen, Fun);
90
erlang:demonitor(Ref),
91
?MODULE:server_loop(User, Listen, Fun)
94
accept_loop(User, Ref, Listen, Fun) ->
95
%% Timeout makes it possible to replace this module
96
%% once every ?ACCEPT_TIMEOUT milliseconds
97
case gen_tcp:accept(Listen, ?ACCEPT_TIMEOUT) of
99
%% poll if 'User' is still alive
101
{'DOWN', Ref, _, _, Reason} ->
109
%% poll if 'User' is still alive
111
{'DOWN', Ref, _, _, Reason} ->
114
?MODULE:accept_loop(User, Ref, Listen, Fun)
117
Listen ! {self(), stop};
119
Listen ! {self(), Error}