1:- module(imodule,[
    2              imodule/3,
    3              iuse_module/3
    4          ]).    5
    6:- use_module(library(socket)).    7
    8:- meta_predicate imodule(+,:,+).    9
   10imodule(Port,M,Options) :-
   11    ssl_context(server,SSL,Options),
   12    tcp_socket(Socket),
   13    tcp_bind(Socket,Port),
   14    tcp_listen(Socket,5),
   15    tcp_open_socket(Socket,AcceptFd),
   16
   17    %catch(dispatch(AcceptFd,M),_,true),
   18    %tcp_close_socket(Socket)
   19    thread_create(dispatch(AcceptFd, M, SSL), _,
   20                  [ detached(true)
   21                  ]).
   22
   23dispatch(AcceptFd, M, SSL) :-
   24        tcp_accept(AcceptFd, Socket, Peer),
   25
   26        %process_client(Socket, Peer, M)
   27        thread_create(process_client(Socket, Peer, M, SSL), _,
   28                      [ detached(true)
   29                      ]),
   30        dispatch(AcceptFd, M, SSL).
   31
   32process_client(Socket, _, M, SSL):-
   33    setup_call_cleanup(
   34        tcp_open_socket(Socket, StreamPair),
   35        customer_service(SSL,StreamPair,M),
   36        close(StreamPair)
   37    ).
   38
   39customer_service(SSL,StreamPair,M):-
   40    stream_pair(StreamPair,PlainRead,PlainWrite),
   41    setup_call_cleanup(
   42        ssl_negotiate(SSL,PlainRead,PlainWrite,SSLRead,SSLWrite),
   43        run_server(SSLRead,SSLWrite,M),
   44        (   close(SSLRead),
   45            close(SSLWrite)
   46        )
   47    ).
   48
   49run_server(R,W,Module:M):-
   50    read(R,K),
   51    (   K = list
   52    ->  portray_clause(W,M)
   53    ;   K = run
   54    ->  read(R,F),
   55        functor(F,A,N),
   56        memberchk(A/N,M),
   57        call(Module:F),
   58        portray_clause(W,F)
   59    ;   portray_clause(W,error)
   60    ),
   61    flush_output(W).
   62
   63:- meta_predicate iuse_module(:,+,+).   64
   65iuse_module(Module:URI,Port,Options):-
   66    ssl_context(client,SSL,[host(client)|Options]),
   67    setup_call_cleanup(
   68        tcp_connect(URI:Port, SP, []),
   69        get_predicates(SSL,SP,L),
   70        close(SP)
   71    ),
   72    create_predicates(L,Module,URI:Port,SSL).
   73
   74get_predicates(SSL,SP,L):-
   75    stream_pair(SP,PlainRead,PlainWrite),
   76    setup_call_cleanup(
   77        ssl_negotiate(SSL,PlainRead,PlainWrite,SSLRead,SSLWrite),
   78        (   portray_clause(SSLWrite,list),
   79            flush_output(SSLWrite),
   80            read(SSLRead,L)
   81        ),
   82        (   close(SSLWrite),
   83            close(SSLRead)
   84        )
   85    ).
   86
   87create_predicates([],_,_,_).
   88create_predicates([A/N|H],Module,URI,SSL):-
   89    functor(F,A,N),
   90    Module:abolish(A/N),
   91    Module:dynamic(A/N),
   92    Module:asserta(F:-
   93                   setup_call_cleanup(
   94                       tcp_connect(URI, SP, []),
   95                       (   stream_pair(SP,PlainRead,PlainWrite),
   96                           setup_call_cleanup(
   97                               ssl_negotiate(SSL,PlainRead,PlainWrite,SSLRead,SSLWrite),
   98                               (   portray_clause(SSLWrite,run),
   99                                   portray_clause(SSLWrite,F),
  100                                   flush_output(SSLWrite),
  101                                   read(SSLRead,F)
  102                               ),
  103                               (   close(SSLRead),
  104                                   close(SSLWrite)
  105                               )
  106                           )
  107                       ),
  108                       close(SP)
  109                   )),
  110    Module:compile_predicates([A/N]),
  111    create_predicates(H,Module,URI,SSL)