emulate old yap socket (thanks to Jan code).

This commit is contained in:
Vítor Santos Costa 2012-07-26 16:16:26 -04:00
parent 9d48e0ed79
commit e7551b106a
4 changed files with 140 additions and 11 deletions

View File

@ -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.

View File

@ -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 \

105
library/sockets.yap Normal file
View File

@ -0,0 +1,105 @@
/** uses SWI code
<module> 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].

View File

@ -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)