com_tcp.pl

来自「SRI international 发布的OAA框架软件」· PL 代码 · 共 1,050 行 · 第 1/3 页

PL
1,050
字号


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
code_list_is_local([A,B,C|_Rest]) :-
  name('1', [A]),
  name('2', [B]),
  name('7', [C]).

check_localhost(A, A) :-
  atom_chars(A, List),
  code_list_is_local(List),
  (oaa:oaa_ResolveVariables([
     [cmd('-allow_localhost', UseLocal)],
     [setup(_, 'allow_localhost', UseLocal)]])
  -> UseLocal
  | otherwise -> false).

check_localhost(_, _).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name:    com_ListenAt(+ConnectionId, Params, ?RequestedAddress, 
%                                              -ActualAddress)
% purpose: Given a connection ID and an address, initiate a server connection
% remarks:
%  - if Address is a variable, instantiates the Address by using
%     oaa_ResolveVariables, which looks in a setup file, command line, and
%     environment variables for the required info.
%  - Even if RequestedAddress is fully instantiated, the actual listener 
%     address could be different, because of user input.  Thus, ActualAddress
%     should always be used as the return value (and should be a variable
%     when called).
%     * UNLESS Params includes resolve_vars(false)
%  - stores the connection info for connection ID in com_connection_info/5.
%  - fails if connection can't be made
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
com_ListenAt(ConnectionId, Params, tcp(Host,Port), 
	     tcp(ActualHost,ActualPort)) :-
    com_ListenAt(ConnectionId, Params, tcp(Host,Port), 
	         tcp(ActualHost,ActualPort), 0).

com_ListenAt(ConnectionId, Params, tcp(Host,Port), 
	     tcp(ActualHost,ActualPort), NumAttempts) :-
    ground(ConnectionId),
    (memberchk(resolve_vars(false), Params) ->
       true
    |
       % if variable address, look it up...
       ((var(Host) ; var(Port)) ->
          oaa:oaa_ResolveVariables([
             [cmd('-oaa_connect',tcp(Host,Port))],
             [env('OAA_CONNECT',tcp(Host,Port))],
             [setup(_, default_facilitator, tcp(Host,Port))]
             ])
       | true)
    ),
    ( oaa:oaa_ResolveVariables([[env('HOST', LocalHost)]]) -> true | true ),

    ( oaa:oaa_ResolveVariables([
	[cmd('-oaa_max_connections',MaxConn)],
	[env('OAA_MAX_CONNECTIONS',MaxConn)],
	[setup(_, oaa_max_connections, MaxConn)]
	]) ->
	  retractall(max_connections(_)),
	  assert(max_connections(MaxConn))
    | otherwise ->
        true
    ),

    % Check whether the requested host matches the real host:
    ( ground(Host), ground(LocalHost) ->
        tcp_inet_addr(Host, HostIP),
	 % This is just to get LocalHost IP:
	 tcp_inet_addr(LocalHost, LocalHostIP),
	( HostIP \== LocalHostIP ->
	    format('~w (com_ListenAt): The specified host, ~w, (from commandline,~n  environment, or setup file), isn''t the machine~n  on which I am running (~w)~n',
	           ['WARNING', Host, LocalHost])
	| otherwise ->
	    true
	)
    | otherwise ->
        true
    ),

    ( ground(Host) ->
        com_StandardizeAddress(tcp(Host, Port), tcp(HostIP, Port)),
        check_localhost(ActualHost, HostIP)
    | otherwise ->
        true
    ),

    repeat,
    ( on_exception(E, 
                   tcp_listen_at_port(Port, ActualHost),
		   Exception = E) ->
	true
    | otherwise ->
        Exception = tcp_create_listener_failed
    ),

    ( var(Exception) ->
        tcp_inet_addr(ActualHost, IPNum),
	assert(com_connection_info(ConnectionId, tcp, server,
	       [oaa_address(addr(tcp(IPNum, Port)))
	       ], 
	       connected)),
	ActualPort = Port,
	!
    | oaa:oaa_ResolveVariables([
             [cmd('-on_port_exception', Response)],
             [env('ON_PORT_EXCEPTION', Response)],
             [setup(_, on_port_exception, Response)]
             ]) ->
        NewParams = [resolve_vars(false) | Params],
	format('Currently unable to access ~w port ~w.~n',
	           [LocalHost, Port]),
        ( Response == try_again ->
	    format('Will try again after 5 seconds ...~n', []),
	    com_sleep(5),
	    fail
        | Response = try_again(NumSeconds) ->
	    format('Will try again after ~w seconds ...~n', [NumSeconds]),
	    com_sleep(NumSeconds),
	    fail
	| Response == next_highest ->
	    NewNumAttempts is NumAttempts + 1,
	    ( NewNumAttempts > 100 ->
	        halt
	    | otherwise ->
	        NewPort is Port + 1,
	        com_ListenAt(ConnectionId, NewParams, tcp(ActualHost,NewPort), 
	                     tcp(ActualHost,ActualPort), NewNumAttempts)
            ),
	    !
	| Response = next_highest(MaxAttempts) ->
	    NewNumAttempts is NumAttempts + 1,
	    ( NewNumAttempts > MaxAttempts ->
	        halt
	    | otherwise ->
	        NewPort is Port + 1,
	        com_ListenAt(ConnectionId, NewParams, tcp(ActualHost,NewPort), 
	                     tcp(ActualHost,ActualPort), NewNumAttempts)
            ),
	    !
	| Response == change_port ->
	    com_get_new_port(Port, NewPort),
	    com_ListenAt(ConnectionId, NewParams, tcp(ActualHost,NewPort), 
	                 tcp(ActualHost,ActualPort)),
	    !
	| Response == any_available ->
            % With _NewPort a var, a port will be assigned by the OS.
	    com_ListenAt(ConnectionId, NewParams, tcp(ActualHost,_NewPort), 
	                 tcp(ActualHost,ActualPort)),
	    !
	| otherwise ->
            format('Exiting~n', []),
	    halt
	)
    | otherwise ->
        NewParams = [resolve_vars(false) | Params],
	com_ask_about_tcp_exception(Exception, Port, LocalHost, Response),
        ( Response == try_again ->
	    fail
	| Response == next_highest ->
	    NewPort is Port + 1,
	    com_ListenAt(ConnectionId, NewParams, tcp(ActualHost,NewPort), 
	                 tcp(ActualHost,ActualPort)),
	    !
	| Response == change_port ->
	    com_get_new_port(Port, NewPort),
	    com_ListenAt(ConnectionId, NewParams, tcp(ActualHost,NewPort), 
	                 tcp(ActualHost,ActualPort)),
	    !
	| Response == any_available ->
            % With _NewPort a var, a port will be assigned by the OS.
	    com_ListenAt(ConnectionId, NewParams, tcp(ActualHost,_NewPort), 
	                 tcp(ActualHost,ActualPort)),
	    !
	| otherwise ->
	    halt
	)
    ).

% for backwards compatibility:
com_ListenAt(ConnectionId, Params, tcp(Host,Port)) :-
    com_ListenAt(ConnectionId, Params, tcp(Host,Port), _).

com_ask_about_tcp_exception(Exception, Port, Host, Response) :-
    format('Exception reported:~n  ~p~n~n',[Exception]),
    repeat,
    with_output_to_chars(
        format('Currently unable to access ~w port ~w.  What now?~n  ~w',
	       [Host, Port, '[e)xit, t)ry_again, n)ext_highest, c)hange_port, a)ny_available, h)elp]']),
	Chars),
    name(Prompt, Chars),
    ask_oneof(Prompt, [exit, try_again, next_highest, change_port, any_available, help], Response),
    ( Response == help ->
	com_print_tcp_exception_help,
	fail
    | otherwise ->
        format('~n',[]),
	!
    ).

com_ask_about_connect_exception(Exception, Port, Host, Response) :-
    format('Exception reported:~n  ~p~n~n',[Exception]),
    repeat,
    with_output_to_chars(
        format('Currently unable to connect to ~w port ~w.  What now?~n  ~w',
	       [Host, Port, '[e)xit, t)ry_again, n)ext_highest, c)hange_port, h)elp]']),
	Chars),
    name(Prompt, Chars),
    ask_oneof(Prompt, [exit, try_again, next_highest, change_port, help], Response),
    ( Response == help ->
	com_print_connect_exception_help,
	fail
    | otherwise ->
        format('~n',[]),
	!
    ).

com_get_new_port(Port, NewPort) :-
    ask_number('Enter the new port number:', Port, NewPort).

 
com_print_tcp_exception_help :-
    write('
I''ve just attempted to listen on the specified port, but was unable
to gain control of it.  This could be because there''s already a
Facilitator, or some other program, making use of that port.  Or, it
could be that a Facilitator using that port has just terminated.  In
such cases, the port may be inaccessible for a brief period (usually
only a few seconds, but sometimes more).

If you think the specified port may now be accessible, enter "t" and
I''ll try again.  You may request retry any number of times.

If you want me to try listening on the next highest port, enter "n".
If you wish to specify a different port to try, enter "c", and you
will be prompted for the new port.  If you enter "a", I''ll ask the
operating system for an available port.

If you want me to halt, enter "e", which will cause me to terminate.
Then you may change your port specification (it''s either in a setup
file or an environment variable), and restart me.

One final note: Any of these options (exit, try_again, next_highest,
change_port, any_available) may also be specified in the setup.pl
file, within the on_port_exception functor.  try_again can be
specified with an argument indicating number of times to try, and
next_highest can be specified with an argument indicating number of
seconds to wait between tries.  Examples:

    on_port_exception(any_available).
    on_port_exception(next_highest(50)).
    on_port_exception(try_again(5.0)).

I check in setup.pl before prompting the user for keyboard input.

').

 
com_print_connect_exception_help :-
    write('
I''ve just attempted to connect to the specified port, but was unable
to do so.  This could be because there''s no facilitator listening at
that port.

If you think there is a facilitator listening, or there may be soon,
enter "t" and I''ll try again.  You may request retry any number of
times.

If you want me to try connecting on the next highest port, enter "n".
If you wish to specify a different port to try, enter "c", and you
will be prompted for the new port.

If you want me to halt, enter "e", which will cause me to terminate.
Then you may either start a facilitator or change your port
specification (it''s either in a setup file, environment variable, or
on the command line), and restart me.

One final note: Any of these options (exit, try_again, next_highest,
change_port, any_available) may also be specified in the setup.pl
file, within the on_connect_exception functor.  try_again can be
specified with an argument indicating number of times to try, and
next_highest can be specified with an argument indicating number of
seconds to wait between tries.  Examples:

    on_connect_exception(exit).
    on_connect_exception(next_highest(50)).
    on_connect_exception(try_again(5.0)).

I check in setup.pl before prompting the user for keyboard input.

').




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name:    com_SendData(+ConnectionId, +Data)
% purpose: Sends data to the specified connection ID
% remarks:
%  - Checks format for destination connection
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
com_SendData(ConnectionId, Data) :-
	ground(ConnectionId),
	( com_connection_info(ConnectionId, Type, _ClientServer, InfoList, 
	     connected),
	  (Type = tcp ; Type = unknown), !,
	  memberchk(connection(Dest), InfoList) 
        ;
	  format('~nError: cannot find open connection for ~p!~n',
	     [ConnectionId]),
	  fail
	),
	( memberchk(format(F), InfoList) ->
	    true
	| otherwise ->
	    F = default
	),
	( memberchk(other_version(Version), InfoList) ->
	    true
	| otherwise ->
	    oaa:oaa_LibraryVersion(Version)
	),
	( memberchk(other_language(Language), InfoList) ->
	    true
	| otherwise ->
	    Language = unknown
	),
	( memberchk(other_dialect(Dialect), InfoList) ->
	    true
          % When parent dialect differs from mine, it may be necessary
	  % to specify the parent dialect, so the initial message
	  % comes out right:
%         NOT NEEDED ANY MORE: see 2000/11/15 comment below
%	| ConnectionId == parent,
%          oaa:oaa_ResolveVariables([
%	         [cmd('-parent_dialect', Dialect)],
%	         [env('PARENT_DIALECT', Dialect)],
%	         [setup(_, parent_dialect, Dialect)]
%	       ]) ->
%            true
          % If not specified, assume same as mine:
	| ConnectionId == parent ->
	    oaa:current_prolog(Dialect)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?