1% ----------------------------------------------------------------------
2% BEGIN LICENSE BLOCK
3% Version: CMPL 1.1
4%
5% The contents of this file are subject to the Cisco-style Mozilla Public
6% License Version 1.1 (the "License"); you may not use this file except
7% in compliance with the License.  You may obtain a copy of the License
8% at www.eclipse-clp.org/license.
9%
10% Software distributed under the License is distributed on an "AS IS"
11% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
12% the License for the specific language governing rights and limitations
13% under the License.
14%
15% The Original Code is  The ECLiPSe Constraint Logic Programming System.
16% The Initial Developer of the Original Code is  Cisco Systems, Inc.
17% Portions created by the Initial Developer are
18% Copyright (C) 1998-2006 Cisco Systems, Inc.  All Rights Reserved.
19%
20% Contributor(s): IC-Parc, Imperal College London
21%
22% END LICENSE BLOCK
23%
24% System:	ECLiPSe Constraint Logic Programming System
25% Version:	$Id: sockets.pl,v 1.3 2009/12/22 02:44:23 jschimpf Exp $
26% ----------------------------------------------------------------------
27
28/*
29 * IDENTIFICATION:	sockets.pl
30 *
31 * DESCRIPTION: 	SICStus Prolog compatibility package
32 *
33 *
34 * CONTENTS:
35 *
36 * AUTHOR:               Kish Shen
37 *
38 * DATE:                24 Sept. 1998
39 */
40
41:- module(sockets).
42
43:- comment(categories, ["Compatibility"]).
44:- comment(summary, "Sicstus compatible sockets interface").
45:- comment(author, "Kish Shen, ECRC Munich").
46:- comment(copyright, "Cisco Systems, Inc").
47:- comment(date, "$Date: 2009/12/22 02:44:23 $").
48:- comment(desc, html("
49    Note that ECLiPSe provides its own built-in socket manipulation
50    predicates which provides similar functionality to this library.
51    <P>
52    This library is only provided for compatibility with the socket
53    manipulation predicates of SICStus Prolog. To use these predicates,
54    the sockets library has to be loaded:
55    <PRE>
56    :- use_module(library(sockets)).
57    </PRE>
58    For SICStus 3.0, the sockets predicates are also in a sockets library,
59    so no changes are needed to load the library.  However, for older
60    versions of SICStus, the predicates are available as built-ins, and no
61    library has to be loaded.  So if the code is written for older
62    versions of SICStus, then the above line has to be added.
63    <P>
64    The sockets library can be used independently of the sicstus library.
65    ")).
66:- comment(socket/2, [template:"socket(+Domain, -Socket)",
67    summary:"Create a socket",
68    see_also:[socket/3]]).
69:- comment(socket_bind/2, [template:"socket_bind(+Socket, +Address)",
70    summary:"Bind a socket to an address",
71    see_also:[bind/2]]).
72:- comment(socket_connect/3, [template:"socket_connect(+Socket, +Address, -Stream)",
73    summary:"Connect a socket to an address",
74    see_also:[connect/2]]).
75:- comment(socket_listen/2, [template:"socket_listen(+Socket, +Length)",
76    summary:"Limit the maximum of pending connections",
77    see_also:[listen/2]]).
78:- comment(socket_accept/2, [template:"socket_accept(+Socket, -Stream)",
79    summary:"Extract the first connection to socket",
80    see_also:[accept/3]]).
81:- comment(socket_select/5, [template:"socket_select(+Socket, -NewStream, +TimeOut0, +Streams, -ReadStreams)",
82    summary:"Wait for new connection on Socket, and for data on Streams",
83    see_also:[stream_select/3]]).
84:- comment(current_host/1, [template:"current_host(?HostName)",
85    summary:"Get the host machine name",
86    see_also:[get_flag/2]]).
87
88:- export
89      socket/2,
90      socket_bind/2,
91      socket_connect/3,
92      socket_listen/2,
93      socket_accept/2,
94      socket_select/5,
95      current_host/1,
96      stream_select/3.
97
98:- comment(stream_select/3, [template:"stream_select(+Streams, +TimeOut0, -ReadStreams)",
99    summary:"Wait for data on Streams",
100    see_also:[eclipse_language:stream_select/3,select/3]]).
101
102
103
104socket(Domain, Socket) :-
105    (Domain == 'AF_INET' -> Dom = internet ;
106     Domain == 'AF_UNIX' -> Dom = unix ; error(5, socket(Domain,Socket))
107    ),
108    sepia_kernel:socket(Dom, stream, Socket).
109
110socket_bind(Socket, Address) :-
111    translate_address(Address, Name, socket_bind(Socket,Address)),
112    sepia_kernel:bind(Socket, Name).
113
114socket_connect(Socket, Address, Stream) :-
115    translate_address(Address, Name, socket_connect(Socket,Address,Stream)),
116    Socket = Stream,
117    sepia_kernel:connect(Socket, Name).
118
119socket_listen(Socket, Length) :-
120    sepia_kernel:listen(Socket, Length).
121
122socket_accept(Socket, Stream) :-
123    sepia_kernel: accept(Socket, _, Stream).
124
125socket_select(Socket, NewStream, TimeOut0, Streams, ReadStreams) :-
126   translate_timeout(TimeOut0, TimeOut, socket_select(Socket,NewStream,TimeOut0,Streams,ReadStreams)),
127   sepia_kernel: stream_select([Socket|Streams], TimeOut, ReadStreams0),
128   (delete(Socket, ReadStreams0, ReadStreams) ->
129       sepia_kernel: accept(Socket, _, NewStream) ; ReadStreams = ReadStreams0
130   ).
131
132stream_select(Streams, TimeOut0, ReadStreams) :-
133    translate_timeout(TimeOut0, TimeOut, stream_select(Streams,TimeOut0,ReadStreams)),
134    sepia_kernel:stream_select(Streams, TimeOut, ReadStreams).
135
136current_host(HostName) :-
137	get_flag(hostname, Shostname),
138	atom_string(HostName, Shostname).
139
140
141translate_timeout(S:MS, TimeOut, _Culprit) ?-
142    integer(S),
143    integer(MS),
144    S > 0, MS > 0, !,
145    TimeOut is S + MS/1000000.
146translate_timeout(off, TimeOut, _) ?- !,
147    TimeOut = block.
148translate_timeout(_, _, Culprit) :-
149    error(5,Culprit).
150
151translate_address('AF_UNIX'(Name0), Name, _Culprit) ?-
152    atom(Name0), !, Name = Name0.
153translate_address('AF_INET'(Host,Port), Name, Culprit) ?-
154    (Culprit = socket_bind(_,_) -> true ;
155	/* assume to be socket_connect */
156        nonvar(Host), nonvar(Port)
157    ),
158    !, Name = Host/Port.
159translate_address(_, _, Culprit) :-
160    error(5, Culprit).
161
162
163
164
165