From e7551b106a09ea5e8e3577489b0df2dbdb86f138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Thu, 26 Jul 2012 16:16:26 -0400 Subject: [PATCH] emulate old yap socket (thanks to Jan code). --- docs/yap.tex | 25 ++++++----- library/Makefile.in | 1 + library/sockets.yap | 105 ++++++++++++++++++++++++++++++++++++++++++++ pl/yio.yap | 20 +++++++++ 4 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 library/sockets.yap diff --git a/docs/yap.tex b/docs/yap.tex index 5d949d494..d6cb94c95 100644 --- a/docs/yap.tex +++ b/docs/yap.tex @@ -5762,12 +5762,13 @@ interactive control from a pipe or a socket. @node Sockets, , I/O Control, I/O @subsection Using Sockets From YAP -YAP includes a SICStus Prolog compatible socket interface. This -is a low level interface that provides direct access to the major socket -system calls. These calls can be used both to open a new connection in -the network or connect to a networked server. Socket connections are -described as read/write streams, and standard I/O built-ins can be used -to write on or read from sockets. The following calls are available: +YAP includes a SICStus Prolog compatible socket interface. In YAP-6.3 +this uses the @c{clib} package to emulate the old low level interface that +provides direct access to the major socket system calls. These calls +can be used both to open a new connection in the network or connect to +a networked server. Socket connections are described as read/write +streams, and standard I/O built-ins can be used to write on or read +from sockets. The following calls are available: @table @code @@ -5778,13 +5779,15 @@ to write on or read from sockets. The following calls are available: Corresponds to the BSD system call @code{socket}. Create a socket for domain @var{DOMAIN} of type @var{TYPE} and protocol @var{PROTOCOL}. Both @var{DOMAIN} and @var{TYPE} should be atoms, -whereas @var{PROTOCOL} must be an integer. The new socket object is +whereas @var{PROTOCOL} must be an integer. +The new socket object is accessible through a descriptor bound to the variable @var{SOCKET}. -The current implementation of YAP only accepts two socket -domains: @code{'AF_INET'} and @code{'AF_UNIX'}. Socket types depend on the +The current implementation of YAP only accepts one socket +domain: @code{'AF_INET'}. @c and @code{'AF_UNIX'}. +Socket types depend on the underlying operating system, but at least the following types are -supported: @code{'SOCK_STREAM'} and @code{'SOCK_DGRAM'}. +supported: @code{'SOCK_STREAM'} and @code{'SOCK_DGRAM'} (untested in 6.3). @item socket(+@var{DOMAIN},-@var{SOCKET}) @findex socket/2 @@ -5812,7 +5815,7 @@ corresponding stream is closed with @code{close/1} or @code{close/2}. Interface to system call @code{bind}, as used for servers: bind socket to a port. Port information depends on the domain: @table @code -@item 'AF_UNIX'(+@var{FILENAME}) +@item 'AF_UNIX'(+@var{FILENAME}) (unsupported) @item 'AF_FILE'(+@var{FILENAME}) use file name @var{FILENAME} for UNIX or local sockets. diff --git a/library/Makefile.in b/library/Makefile.in index c510d7506..a5bfb5b13 100644 --- a/library/Makefile.in +++ b/library/Makefile.in @@ -60,6 +60,7 @@ PROGRAMS= \ $(srcdir)/rbtrees.yap \ $(srcdir)/regexp.yap \ $(srcdir)/rltree.yap \ + $(srcdir)/sockets.yap \ $(srcdir)/splay.yap \ $(srcdir)/stringutils.yap \ $(srcdir)/system.yap \ diff --git a/library/sockets.yap b/library/sockets.yap new file mode 100644 index 000000000..824bc431b --- /dev/null +++ b/library/sockets.yap @@ -0,0 +1,105 @@ +/** uses SWI code + + SICStus compatible socket library + +@tbd Our implementation does not support AF_UNIX sockets. +@TBD Implement socket_select/5 +@see http://www.sics.se/sicstus/docs/3.7.1/html/sicstus_28.html +*/ + + +:- module(yap_sockets, + [ ip_socket/2, % +Domain, -Socket + ip_socket/4, % +Domain, +Type, +Protocol, -Socket + socket_close/1, % +Socket + socket_bind/2, % +Socket, 'AF_INET'(+Host,+Port) + tcp_socket_connect/3, % +Socket, 'AF_INET'(+Host,+Port), -Stream + socket_listen/2, % +Socket, +Length + socket_accept/2, % +Socket, -Stream + socket_accept/3, % +Socket, -Client, -Stream +% socket_select/5, % +TermsSockets, -NewTermsStreams, + % +TimeOut, +Streams, -ReadStreams + current_host/1, % ?HostName + hostname_address/2 % ?HostName, ?HostAddress + ]). +:- use_module(library(socket)). +:- use_module(library(error)). +:- use_module(library(apply)). + +%socket(+@var{DOMAIN},+@var{TYPE},+@var{PROTOCOL},-@var{SOCKET}) + +ip_socket(Domain, 'SOCK_DGRAM', Protocol, SOCKET) :- + must_be(oneof(['AF_INET']), Domain), + must_be(oneof([0]), Protocol), + udp_socket(SOCKET), + assert(yap_socket(udp, SOCKET)). +ip_socket(Domain, 'SOCK_STREAM', Protocol, SOCKET) :- + must_be(oneof(['AF_INET']), Domain), + must_be(oneof([0]), Protocol), + tcp_socket(SOCKET), + assert(yap_socket(tcp, SOCKET)). + +ip_socket(Domain, SOCK) :- + socket(Domain, 'SOCK_STREAM', 0, SOCK). + +socket_close(Socket) :- + retract(yap_socket(udp, Socket)), !. +socket_close(Socket) :- + retract(yap_socket(tcp, Socket)), !, + tcp_close_socket(Socket). + +socket_bind(Socket, 'AF_INET'(Host,Port)) :- + ( Address = 'AF_INET'(Host, Port) + -> true + ; type_error(socket_address, Address) + ), + ( var(Host) + -> gethostname(Host) + ; true % Warning? + ), + tcp_bind(Socket, Port). + +tcp_socket_connect(Socket, Address, StreamPair) :- + ( Address = 'AF_INET'(Host, Port) + -> true + ; type_error(socket_address, Address) + ), + tcp_connect(Socket, Host:Port), + tcp_open_socket(Socket, Read, Write), + stream_pair(StreamPair, Read, Write). + +socket_listen(SOCKET, BACKLOG) :- + tcp_listen(SOCKET, BACKLOG). + +socket_accept(Socket, Client, StreamPair) :- + tcp_accept(Socket, Socket2, Peer), + peer_to_client(Peer, Client), + tcp_open_socket(Socket2, Read, Write), + stream_pair(StreamPair, Read, Write). + +socket_buffering(STREAM, _, CUR, NEW) :- + stream_property(STREAM, buffer(Prop) ), + translate_buffer(Prop, CUR), + translate_buffer(NProp, NEW), + stream_property(STREAM, buffer(NProp) ). + +translate_buffer(false, unbuf). +translate_buffer(full, fullbuf). + +current_host(Host) :- + gethostname(Host). + +hostname_address(Host, Address) :- + nonvar(Host), !, + tcp_host_to_address(Host, IP), + peer_to_client(IP, Address). + +peer_to_client(ip(A,B,C,D), Client) :- + Parts = [A,B,C,D], + ground(Parts), !, + atomic_list_concat(Parts, '.', Client). +peer_to_client(ip(A,B,C,D), Client) :- + atomic_list_concat(Parts, '.', Client), + maplist(atom_number, Parts, Numbers), + Numbers = [A,B,C,D]. + diff --git a/pl/yio.yap b/pl/yio.yap index 7fabe1286..68498e671 100644 --- a/pl/yio.yap +++ b/pl/yio.yap @@ -78,6 +78,26 @@ '$check_boolean'(X,B,T,G) :- '$do_error'(domain_error(B,T),G). +socket(Domain, Sock) :- + ( + '$undefined'(ip_socket(_,_),yap_sockets) + -> + load_files(library(sockets), [silent(true),if(not_loaded)]) + ; + true + ), + yap_sockets:ip_socket(Domain, Sock). + +socket(Domain, Type, Protocol, Sock) :- + ( + '$undefined'(ip_socket(_,_),yap_sockets) + -> + load_files(library(sockets), [silent(true),if(not_loaded)]) + ; + true + ), + yap_sockets:ip_socket(Domain, Type, Protocol, Sock). + open_pipe_streams(Read, Write) :- ( '$undefined'(pipe(_,_),unix)