[m-rev.] diff: add network binding to extras
Peter Ross
pro at missioncriticalit.com
Thu Nov 16 15:06:48 AEDT 2006
Hi,
===================================================================
Estimated hours taken: 0.5
Branches: main
extras/README:
Document that streams has been depreceated.
extras/net/net.m:
extras/net/sockets.m:
extras/net/tcp.m:
A network binding to the streams interface.
Index: extras/README
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/README,v
retrieving revision 1.20
diff -U5 -r1.20 README
--- extras/README 10 Nov 2006 03:48:44 -0000 1.20
+++ extras/README 16 Nov 2006 04:00:18 -0000
@@ -60,10 +60,13 @@
Currently you need to write your own lexer to interface
to moose.
morphine A trace analysis system for Mercury.
+net A network library which uses the standard library stream
+ interface.
+
odbc A Mercury interface to ODBC (Open Database Connectivity),
for interfacing to standard relational database packages.
posix A Mercury interface to some of the POSIX
(Portable Operating System Interface) APIs.
@@ -76,10 +79,12 @@
solver_types Contains versions of some standard library modules
adapted to make them suitable for use with solver
types.
stream Generic IO interface using typeclasses.
+ Note this interface has been superceded by the one
+ in standard library.
trailed_update Some library modules that make use of backtrackable
destructive update, including a module which provides
some support for Prolog-style unification constraints.
New File: extras/net/net.m
===================================================================
%---------------------------------------------------------------------------%
% Copyright (C) 2000 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB
%---------------------------------------------------------------------------%
:- module net.
:- interface.
:- pred version(string::out) is det.
:- implementation.
:- import_module sockets, tcp.
version("DEV").
New File: extras/net/sockets.m
===================================================================
%---------------------------------------------------------------------------%
% Copyright (C) 2000 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB
%-----------------------------------------------------------------------------%
%
% Module: sockets
% Main Author: pro at missioncriticalit.com
% (based on code written by pma at missioncriticalit.com)
% Stability: low
%
% Provide a low-level interface to sockets.
% The more declarative interface is provided by the module tcp.
%
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- module sockets.
:- interface.
:- import_module bool.
:- import_module io.
:- type sockets__res(Type)
---> ok(Type)
; error(string).
:- pred sockets__gethostbyname(string::in, string::out, io::di, io::uo)
is det.
:- pred sockets__getservbyname(string::in, string::in, int::out,
io::di, io::uo) is det.
:- pred sockets__socket(int::in, int::in, int::in, int::out, bool::out,
io::di, io::uo) is det.
:- pred sockets__port_address(string::in, int::in, c_pointer::out,
bool::out, io::di, io::uo) is det.
:- pred sockets__service_address(string::in, string::in, c_pointer::out,
bool::out, io::di, io::uo) is det.
:- pred sockets__connect(int::in, c_pointer::in, int::in, bool::out,
io::di, io::uo) is det.
:- pred sockets__bind(int::in, c_pointer::in, int::in, bool::out,
io::di, io::uo) is det.
:- pred sockets__listen(int::in, int::in, bool::out, io::di, io::uo) is det.
:- pred sockets__accept(int::in, c_pointer::in, int::out, bool::out,
io::di, io::uo) is det.
:- pred sockets__close(int::in, io::di, io::uo) is det.
% Why did the socket operation fail?
:- pred sockets__error_message(string::out, io::di, io::uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- pragma c_header_code("
#ifdef MR_WIN32
#include <winsock.h>
#define error() WSAGetLastError
#else
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#define error() errno
#define INVALID_SOCKET -1
#endif
#include \"mercury_string.h\"
").
:- pragma foreign_decl("C", "
/* Save the errno into this variable if a function fails */
static int socket_errno;
").
:- initialise sockets.init/2.
:- pred sockets__init(io::di, io::uo) is det.
:- pragma foreign_proc(c,
sockets__init(_IO0::di, _IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
#ifdef MR_WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
if (!initialiased) {
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup(wVersionRequested, &wsaData);
if ( err != 0 ) {
MR_fatal_error(""Unable to find a ""
""usable winsock.dll\\n"");
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup();
MR_fatal_error(""Unable to find a ""
""usable winsock.dll\\n"");
}
initialiased = MR_TRUE;
}
#endif
}").
% XXX thread safe?
:- pragma foreign_proc(c,
gethostbyname(Name::in, Host::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct hostent *host;
host = gethostbyname(Name);
Host = (MR_String) host->h_name;
}").
% XXX thread safe?
:- pragma foreign_proc(c,
getservbyname(Name::in, Protocol::in, Port::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct servent *service;
service = getservbyname(Name, Protocol);
if (service != NULL) {
Port = (MR_Integer) ntohs(service->s_port);
} else {
Port = -1;
};
}").
% XXX thread safe?
:- pragma foreign_proc(c,
socket(Domain::in, Type::in, Protocol::in, Socket::out, Success::out,
_IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
Socket = socket(Domain, Type, Protocol);
if (Socket == INVALID_SOCKET) {
socket_errno = error();
Success = MR_FALSE;
} else {
Success = MR_TRUE;
}
}").
% XXX thread safe?
:- pragma foreign_proc(c,
port_address(Host::in, Port::in, SA::out, Success::out,
_IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct hostent *host;
struct sockaddr_in *addr;
host = gethostbyname(Host);
if (host == NULL) {
socket_errno = error();
Success = MR_FALSE;
} else {
addr = MR_GC_NEW(struct sockaddr_in);
memcpy(&(addr->sin_addr), host->h_addr, host->h_length);
addr->sin_family = host->h_addrtype;
addr->sin_port = htons(Port);
SA = (MR_Word) addr;
Success = MR_TRUE;
}
}").
% XXX thread safe?
:- pragma foreign_proc(c,
service_address(Service::in, Host::in, SA::out, Success::out,
_IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct hostent *host;
struct servent *service;
struct sockaddr_in *addr;
host = gethostbyname(Host);
if (host == NULL) {
socket_errno = error();
Success = MR_FALSE;
} else {
service = getservbyname(Service,""tcp"");
if (service == NULL) {
socket_errno = error();
Success = MR_FALSE;
} else {
addr = MR_GC_NEW(struct sockaddr_in);
memcpy(&(addr->sin_addr), host->h_addr, host->h_length);
addr->sin_family = host->h_addrtype;
addr->sin_port = service->s_port;
SA = (MR_Word) addr;
Success = MR_TRUE;
}
}
}").
% XXX thread safe?
:- pragma foreign_proc(c,
connect(Fd::in, Addr::in, AddrLen::in, Success::out,
_IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct sockaddr *addr = (struct sockaddr *) Addr;
if (connect(Fd, addr, AddrLen) == INVALID_SOCKET) {
socket_errno = error();
Success = MR_FALSE;
} else {
Success = MR_TRUE;
}
}").
% XXX thread safe?
:- pragma foreign_proc(c,
bind(Fd::in, Addr::in, AddrLen::in, Success::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct sockaddr *addr = (struct sockaddr *) Addr;
if (bind(Fd, addr, AddrLen) == INVALID_SOCKET) {
socket_errno = error();
Success = MR_FALSE;
} else {
Success = MR_TRUE;
}
}").
% XXX thread safe?
:- pragma foreign_proc(c,
listen(Fd::in, BackLog::in, Success::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
if (listen(Fd, BackLog) == INVALID_SOCKET) {
socket_errno = error();
Success = MR_FALSE;
} else {
Success = MR_TRUE;
}
}").
% This code can block, so we make it thread_safe
% so as to avoid other code blocking on the global mutex.
:- pragma foreign_proc(c,
accept(Fd::in, Addr::in, NewSocket::out, Success::out,
_IO0::di, _IO::uo),
[thread_safe, will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct sockaddr *addr = (struct sockaddr *) Addr;
NewSocket = accept(Fd, addr, NULL);
if (NewSocket == INVALID_SOCKET) {
socket_errno = error();
Success = MR_FALSE;
} else {
Success = MR_TRUE;
}
}").
% XXX thread safe?
:- pragma foreign_proc(c,
sockets__close(Fd::in, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
struct linger sockets_linger = { MR_TRUE, 2 };
setsockopt(Fd, SOL_SOCKET, SO_LINGER,
&sockets_linger, sizeof(sockets_linger));
shutdown(Fd, 2);
}").
% XXX thread safe?
:- pragma foreign_proc(c,
error_message(Err::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"{
MR_make_aligned_string_copy(Err, strerror(socket_errno));
}").
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
New File: extras/net/tcp.m
===================================================================
%-----------------------------------------------------------------------------%
% Copyright (C) 2000 The University of Melbourne
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB
%-----------------------------------------------------------------------------%
%
% Module: tcp
% Main Author: peter.ross at miscrit.be (based on code written by pma at miscrit.be)
% Stability: low
%
% An implementation of TCP streams.
%
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- module tcp.
:- interface.
:- import_module io.
:- import_module stream.
:- type tcp.
:- type bound_tcp.
:- type tcp__result(T)
---> ok(T)
; error(string).
:- type host == string. % A hostname ie "localhost"
:- type service == string. % A service ie "www"
:- type protocol == string. % A protocol ie "tcp"
:- type port == int. % A portnumber ie 80 - the webserver
:- pred tcp__connect(host::in, port::in, tcp__result(tcp)::out,
io::di, io::uo) is det.
:- pred tcp__bind(host::in, port::in, tcp__result(bound_tcp)::out,
io::di, io::uo) is det.
:- pred tcp__accept(bound_tcp::in, tcp__result(tcp)::out,
io::di, io::uo) is det.
:- pred tcp__shutdown(tcp::in, io::di, io::uo) is det.
% Accesses the stream to see if there is data available,
% waits for a given period before timeing out
% (use this rather than a failure driven test and
% loop on connects).
:- pred tcp__data_available(bound_tcp,int,int,io,io).
:- mode tcp__data_available(in,in,out,di,uo) is det.
:- func socket_fd(tcp) = int.
:- type error.
:- instance stream(tcp, io.state).
:- instance error(tcp.error).
:- instance input(tcp, io.state, tcp.error).
:- instance reader(tcp, character, io.state, tcp.error).
:- instance output(tcp, io.state).
:- instance writer(tcp, character, io.state).
:- instance writer(tcp, string, io.state).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module bool.
:- import_module char.
:- import_module require.
:- import_module string.
:- type tcp
---> tcp(
name :: string,
handle :: tcp_handle
).
:- type bound_tcp
---> bound_tcp(
int, % socket fd
c_pointer % struct sockaddr
).
%-----------------------------------------------------------------------------%
tcp__connect(Host, Port, Result) -->
handle_connect(Host, Port, Handle, Errno),
{ Errno = 0 ->
Result = ok(tcp(Host, Handle))
;
Result = tcp.error(tcp.error_message(Errno))
}.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
tcp__bind(Host, Port, Result) -->
handle_bind(Host, Port, Socket, Addr, Errno),
{ Errno = 0 ->
Result = ok(bound_tcp(Socket, Addr))
;
Result = tcp.error(tcp.error_message(Errno))
}.
%-----------------------------------------------------------------------------%
tcp__accept(bound_tcp(Socket, Addr), Result) -->
handle_accept(Socket, Addr, Handle, Errno),
{ Errno = 0 ->
Result = ok(tcp("XXX unknown host", Handle))
;
Result = tcp.error(tcp.error_message(Errno))
}.
%-----------------------------------------------------------------------------%
tcp__shutdown(tcp(_, Handle)) -->
handle_shutdown(Handle).
:- pred handle_shutdown(tcp_handle::in, io::di, io::uo) is det.
:- pragma foreign_proc(c,
handle_shutdown(TCP::in, IO0::di, IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
struct linger sockets_linger = { MR_TRUE, 2 };
ML_tcp *sock;
int shutdown_erro = 0;
sock = (ML_tcp *) TCP;
/* setsockopt(sock->socket, SOL_SOCKET, SO_LINGER,
&sockets_linger, sizeof(sockets_linger));*/
errno=0;
if (close(((int)sock->socket)) == SOCKET_ERROR) {
ML_throw_tcp_exception((MR_String) ""tcp__shutdown failed (close)"");
}
IO = IO0;
}").
%-----------------------------------------------------------------------------%
:- type tcp_handle ---> socket(c_pointer).
:- pragma c_header_code("
#ifdef MR_WIN32
#include <windows.h>
#include <winsock.h>
#define ML_error() WSAGetLastError()
#else
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#define ML_error() errno
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#endif
#define ADDRLEN 16
#define BACKLOG 16
#define FULL 2
typedef struct {
int socket;
int error;
MR_bool eof;
} ML_tcp;
void ML_tcp_init(void);
").
:- pragma c_code("
/*
** We must ensure that the socket DLL is initialiased before use under
** Win32.
*/
void ML_tcp_init(void)
{
#ifdef MR_WIN32
static int initialiased = MR_FALSE;
WORD wVersionRequested;
WSADATA wsaData;
int err;
if (!initialiased) {
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup(wVersionRequested, &wsaData);
if ( err != 0 ) {
MR_fatal_error(""Unable to find a ""
""usable winsock.dll\\n"");
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
WSACleanup();
MR_fatal_error(""Unable to find a ""
""usable winsock.dll\\n"");
}
initialiased = MR_TRUE;
}
#endif
}
").
:- pred handle_connect(string::in, port::in, tcp_handle::out, int::out,
io::di, io::uo) is det.
:- pragma foreign_proc(c,
handle_connect(Host::in, Port::in, TCP::out, Errno::out,
IO0::di, IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
ML_tcp *sock;
struct hostent *host;
struct sockaddr_in *addr;
ML_tcp_init();
sock = MR_NEW(ML_tcp);
sock->socket = socket(PF_INET, SOCK_STREAM, 0);
sock->error = 0;
sock->eof = MR_FALSE;
if (sock->socket == INVALID_SOCKET) {
sock->error = ML_error();
} else {
host = gethostbyname(Host);
if (host == NULL) {
sock->error = ML_error();
} else {
addr = MR_NEW(struct sockaddr_in);
memset(addr,0,sizeof(struct sockaddr_in));
memcpy(&(addr->sin_addr), host->h_addr, host->h_length);
addr->sin_family = host->h_addrtype;
addr->sin_port = htons(Port);
/*memset(&addr,0,sizeof(addr));
memcpy((char *)&addr.sin_addr, host->h_addr, host->h_length);
addr.sin_family = host->h_addrtype;
addr.sin_port = htons(Port);*/
if (connect(sock->socket, (struct sockaddr *)addr, ADDRLEN) ==
SOCKET_ERROR)
{
sock->error = ML_error();
}
}
}
Errno = sock->error;
TCP = (MR_Word) sock;
IO = IO0;
}").
socket_fd(Tcp) = socket_fd_c(Tcp ^ handle).
:- func socket_fd_c(tcp_handle) = int.
:- pragma foreign_proc(c, socket_fd_c(Tcp::in) = (FD::out),
[will_not_call_mercury, thread_safe, promise_pure], "
ML_tcp *sock = (ML_tcp *) Tcp;
FD = sock->socket;
").
%-----------------------------------------------------------------------------%
:- pred handle_bind(string::in, port::in, int::out, c_pointer::out, int::out,
io::di, io::uo) is det.
:- pragma foreign_proc(c,
handle_bind(Host::in, Port::in, Socket::out, Addr::out,
Errno::out, IO0::di, IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
struct hostent *host;
struct sockaddr_in *addr = NULL;
ML_tcp_init();
Socket = socket(PF_INET, SOCK_STREAM, 0);
Errno = 0;
if (Socket == INVALID_SOCKET) {
Errno = ML_error();
} else {
host = gethostbyname(Host);
if (host == NULL) {
Errno = ML_error();
} else {
addr = MR_NEW(struct sockaddr_in);
memset(addr,0,sizeof(struct sockaddr_in));
memcpy(&(addr->sin_addr), host->h_addr, host->h_length);
addr->sin_family = host->h_addrtype;
addr->sin_port = htons(Port);
if (bind(Socket, addr, ADDRLEN) == SOCKET_ERROR)
{
Errno = ML_error();
}
else
{
if (listen(Socket, BACKLOG) == SOCKET_ERROR)
{
Errno = ML_error();
}
}
}
}
Addr = (MR_Word) addr;
IO = IO0;
}").
:- pred handle_accept(int::in, c_pointer::in, tcp_handle::out, int::out,
io::di, io::uo) is det.
:- pragma foreign_proc(c,
handle_accept(Socket::in, Addr::in, TCP::out, Errno::out,
IO0::di, IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
ML_tcp *sock;
struct sockaddr *addr;
int size = sizeof(struct sockaddr_in);
sock = MR_NEW(ML_tcp);
addr = (struct sockaddr *) Addr;
sock->socket = accept(Socket, addr, &size);
sock->error = 0;
sock->eof = MR_FALSE;
if (sock->socket == INVALID_SOCKET) {
sock->error = ML_error();
}
TCP = (MR_Word) sock;
Errno = sock->error;
IO = IO0;
}").
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- type error ---> errno(int).
:- instance stream(tcp, io.state) where [
name(TCP, TCP ^ name, !IO)
].
:- instance error(tcp.error) where [
(error_message(E) = S :-
get_error(E, S)
)
].
:- instance input(tcp, io.state, tcp.error) where [].
:- instance reader(tcp, character, io.state, tcp.error) where [
(get(T, Result, !IO) :-
tcp.read_char(T ^ handle, C, B, !IO),
( B = yes,
Result = ok(C)
; B = no,
is_eof(T ^ handle, IsEof, !IO),
( IsEof = yes ->
Result = eof
;
get_errno(T ^ handle, Errno, !IO),
Result = error(Errno)
)
)
)
].
:- instance output(tcp, io) where [
% XXX can one flush a socket?
flush(_, !IO)
].
:- instance writer(tcp, character, io.state) where [
(put(T, C, !IO) :-
tcp.write_char(T ^ handle, C, B, !IO),
( B = yes,
true
; B = no,
get_errno(T ^ handle, Errno, !IO),
get_error(Errno, String),
error("put(char): " ++ String)
)
)
].
:- instance writer(tcp, string, io.state) where [
(put(T, S, !IO) :-
tcp.write_string(T ^ handle, S, B, !IO),
( B = yes,
true
; B = no,
get_errno(T ^ handle, Errno, !IO),
get_error(Errno, String),
error("put(string): " ++ String)
)
)
].
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- pred read_char(tcp_handle::in, char::out, bool::out, io::di, io::uo)
is det.
:- pragma foreign_proc(c,
read_char(Socket::in, Chr::out, Success::out, _IO0::di, _IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
ML_tcp *sock = (ML_tcp *) Socket;
int nchars;
nchars = recv(sock->socket, &Chr, 1, 0);
if (nchars == SOCKET_ERROR) {
sock->error = ML_error();
Success = MR_FALSE;
Chr = 0;
} else if (nchars == 0) {
sock->eof = MR_TRUE;
Success = MR_FALSE;
Chr = 0;
} else {
Success = MR_TRUE;
}
}").
:- pred tcp__write_char(tcp_handle::in, char::in, bool::out,
io::di, io::uo) is det.
:- pragma foreign_proc(c,
tcp__write_char(Socket::in, Chr::in, Success::out, _IO0::di, _IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
ML_tcp *sock = (ML_tcp *) Socket;
if (send(sock->socket, &Chr, 1, 0) == SOCKET_ERROR) {
sock->error = ML_error();
Success = MR_FALSE;
} else {
Success = MR_TRUE;
}
}").
:- pred tcp__write_string(tcp_handle::in, string::in, bool::out,
io::di, io::uo) is det.
:- pragma foreign_proc(c,
tcp__write_string(Socket::in, Str::in, Success::out,
_IO0::di, _IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
ML_tcp *sock = (ML_tcp *) Socket;
if (send(sock->socket, Str, strlen(Str), 0) == SOCKET_ERROR) {
sock->error = ML_error();
Success = MR_FALSE;
} else {
Success = MR_TRUE;
}
}").
:- pred get_errno(tcp_handle::in, tcp.error::out, io::di, io::uo) is det.
:- pragma foreign_proc(c,
get_errno(Socket::in, Errno::out, _IO0::di, _IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
ML_tcp *sock = (ML_tcp *) Socket;
Errno = sock->error;
}").
:- pred tcp__get_error(tcp.error::in, string::out) is det.
:- pragma foreign_proc(c,
tcp__get_error(Errno::in, Msg::out),
[will_not_call_mercury, thread_safe, promise_pure],
"{
MR_save_transient_hp();
MR_make_aligned_string_copy(Msg, strerror(Errno));
MR_restore_transient_hp();
}").
:- pred tcp__is_eof(tcp_handle::in, bool::out, io::di, io::uo) is det.
:- pragma foreign_proc(c,
tcp__is_eof(Socket::in, Success::out, _IO0::di, _IO::uo),
[will_not_call_mercury, thread_safe, promise_pure, tabled_for_io],
"{
ML_tcp *sock = (ML_tcp *) Socket;
Success = sock->eof;
}").
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- pragma foreign_proc(c,
tcp__data_available(Socket::in,Wait::in,Int::out,II::di,IO::uo),
[promise_pure, tabled_for_io],
"{
ML_tcp *sock = (ML_tcp *) Socket;
int selres = 0;
fd_set readfds, writefds, exceptfds;
struct timeval *sockets__timeout;
struct timeval sockets__timeout_struct;
if ( Wait > 0 ) {
sockets__timeout = &sockets__timeout_struct;
sockets__timeout -> tv_sec = ((int)Wait * 60);
sockets__timeout -> tv_usec = 0;
} else {
sockets__timeout = NULL;
};
FD_ZERO(&writefds);
FD_ZERO(&readfds);
FD_ZERO(&exceptfds);
FD_SET(sock->socket,&readfds);
if ( sockets__timeout != NULL ) {
/* Do a select to see if something is available */
selres = select(0,&readfds,&writefds,&exceptfds,sockets__timeout);
if ( selres == 0 ) {
Int = -1;
} else {
if ( selres == SOCKET_ERROR ) {
Int = -2;
} else {
Int = 0;
};
};
} else {
Int = 0;
};
IO = II;
}").
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- func error_message(int) = string.
:- pragma c_code(error_message(Errno::in) = (Err::out),
[will_not_call_mercury], "{
MR_make_aligned_string_copy(Err, strerror(Errno));
}").
:- pred throw_tcp_excption(string::in) is erroneous.
:- pragma export(throw_tcp_excption(in), "ML_throw_tcp_exception").
throw_tcp_excption(S) :-
error(S).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list