_buffer = new CString(1024)
_buffer_pos = 0
native = new NativeSocket.socket(new NativeSocketAddressFamilies.af_inet,
- new NativeSocketTypes.sock_stream, new NativeSocketProtocolFamilies.pf_null)
+ new NativeSocketTypes.sock_stream, new NativeSocketProtocolFamilies.pf_unspec)
if native.address_is_null then
end_reached = true
closed = true
# timeout : Time in milliseconds before stopping listening for events on this socket
private fun pollin(event_types: Array[NativeSocketPollValues], timeout: Int): Array[NativeSocketPollValues] do
if end_reached then return new Array[NativeSocketPollValues]
- return native.socket_poll(new PollFD(native.descriptor, event_types), timeout)
+ return native.socket_poll(new PollFD.from_poll_values(native.descriptor, event_types), timeout)
end
# Easier use of pollin to check for something to read on all channels of any priority
native.write(ns, len)
end
+ # Write `msg`, with a trailing `\n`
fun write_ln(msg: Text)
do
if closed then return
_buffer_pos = 0
end
+ # Enlarge `_buffer` to at least `len` bytes
fun enlarge(len: Int) do
if _buffer_capacity >= len then return
_buffer_capacity = len
init
do
native = new NativeSocket.socket(new NativeSocketAddressFamilies.af_inet,
- new NativeSocketTypes.sock_stream, new NativeSocketProtocolFamilies.pf_null)
+ new NativeSocketTypes.sock_stream, new NativeSocketProtocolFamilies.pf_unspec)
assert not native.address_is_null
if not native.setsockopt(new NativeSocketOptLevels.socket, new NativeSocketOptNames.reuseaddr, 1) then
closed = true
class SocketObserver
private var native = new NativeSocketObserver
+ # Set of file descriptors on which to watch read events
var read_set: nullable SocketSet = null
+ # Set of file descriptors on which to watch write events
var write_set: nullable SocketSet = null
+ # Set of file descriptors on which to watch exception events
var except_set: nullable SocketSet = null
- init(read: Bool, write: Bool, except: Bool)
- is old_style_init do
+ # Initialize a socket observer
+ init with_sets(read: Bool, write: Bool, except: Bool) do
if read then read_set = new SocketSet
if write then write_set = new SocketSet
if except then except_set = new SocketSet
end
+ # Watch for changes in the states of several sockets.
fun select(max: Socket, seconds: Int, microseconds: Int): Bool
do
# FIXME this implementation (see the call to nullable attributes below) and
# `NativeSockectObserver::select` is not stable.
var timeval = new NativeTimeval(seconds, microseconds)
- return native.select(max.native, read_set.native, write_set.native, except_set.native, timeval) > 0
+ var rd = if read_set != null then read_set.as(not null).native else null
+ var wrt = if write_set != null then write_set.as(not null).native else null
+ var expt = if except_set != null then except_set.as(not null).native else null
+ return native.select(max.native, rd, wrt, expt, timeval) > 0
end
end
init do native = new NativeSocket.socket(
new NativeSocketAddressFamilies.af_inet,
new NativeSocketTypes.sock_dgram,
- new NativeSocketProtocolFamilies.pf_null)
+ new NativeSocketProtocolFamilies.pf_unspec)
# Bind this socket to an `address`, on `port` (to all addresses if `null`)
#
#include <netinet/tcp.h>
`}
-# Wrapper for the data structure PollFD used for polling on a socket
+# Wrapper for the data structure used for polling on a socket
class PollFD
super FinalizableOnce
# A collection of the events to be watched
var events: Array[NativeSocketPollValues]
- init(pid: Int, events: Array[NativeSocketPollValues])
+ # Create a PollFD object from NativePollFD informations
+ init from_poll_values(pid: Int, events: Array[NativeSocketPollValues])
do
assert events.length >= 1
- self.events = events
var events_in_one = events[0]
- for i in [1 .. events.length-1] do
+ for i in [1 .. events.length - 1] do
events_in_one += events[i]
end
- self.poll_struct = new NativeSocketPollFD(pid, events_in_one)
+ var poll_struct = new NativeSocketPollFD(pid, events_in_one)
+
+ init(poll_struct, events)
end
# Reads the response and returns an array with the type of events that have been found
`}
end
+# Native C socket
extern class NativeSocket `{ int* `}
+ # Create a new C socket
new socket(domain: NativeSocketAddressFamilies, socketType: NativeSocketTypes, protocol: NativeSocketProtocolFamilies) `{
int ds = socket(domain, socketType, protocol);
if(ds == -1){
return d;
`}
+ # Free the socket
fun destroy `{ free(self); `}
+ # Close the socket in both read/write
fun close: Int `{ return close(*self); `}
+ # Get the FD related to `self`
fun descriptor: Int `{ return *self; `}
+ # Connect to another open socket
+ #
+ # SEE: C documentation for more details on the `connect` operation
fun connect(addrIn: NativeSocketAddrIn): Int `{
return connect(*self, (struct sockaddr*)addrIn, sizeof(*addrIn));
`}
return 1;
`}
+ # Bind the socket to a local address
+ #
+ # SEE: C documentation for more details on the bind operation
fun bind(addrIn: NativeSocketAddrIn): Int `{ return bind(*self, (struct sockaddr*)addrIn, sizeof(*addrIn)); `}
+ # Prepare for listening to incoming connections
fun listen(size: Int): Int `{ return listen(*self, size); `}
# Checks if the buffer is ready for any event specified when creating the pollfd structure
return ptr;
`}
+ # Accept a new connection on `self`
+ #
+ # Require the socket to be first bound and listening for connections
fun accept: nullable SocketAcceptResult
do
var addrIn = new NativeSocketAddrIn
return res
end
+ # Host IPv4 address
fun h_addr: CString `{
return (char*)inet_ntoa(*(struct in_addr*)self->h_addr);
`}
+ # Host address type
fun h_addrtype: Int `{ return self->h_addrtype; `}
+ # Length in bytes of the addresses
fun h_length: Int `{ return self->h_length; `}
+ # Host name
fun h_name: CString `{ return self->h_name; `}
end
+# Time structure, with a microsecond resolution
extern class NativeTimeval `{ struct timeval* `}
new (seconds: Int, microseconds: Int) `{
struct timeval* tv = NULL;
return tv;
`}
+ # Number of seconds recorded
fun seconds: Int `{ return self->tv_sec; `}
+ # Number of microseconds recorded
fun microseconds: Int `{ return self->tv_usec; `}
+ # Destory `self`
fun destroy `{ free(self); `}
end
+# Structure used to register FDs for a Select
+#
+# FIXME: This should not be Socket-specific
+# FIXME: This is Unix-specific
extern class NativeSocketSet `{ fd_set* `}
new `{
fd_set *f = NULL;
return f;
`}
+ # Add a file descriptor to the set
fun set(s: NativeSocket) `{ FD_SET(*s, self); `}
+ # Check if `s` is in the set
fun is_set(s: NativeSocket): Bool `{ return FD_ISSET(*s, self); `}
+ # Clear the set
fun zero `{ FD_ZERO(self); `}
+ # Remove `s` from the set
fun clear(s: NativeSocket) `{ FD_CLR(*s, self); `}
+ # Free the set
fun destroy `{ free(self); `}
end
+# Socket observer
class NativeSocketObserver
# FIXME this implementation is broken. `reads`, `write` and `except`
# are boxed objects, passing them to a C function is illegal.
`}
end
+# Socket types
extern class NativeSocketTypes `{ int `}
+ # STREAM socket, used for sequential writes/reads
new sock_stream `{ return SOCK_STREAM; `}
+ # DGRAM socket, used for packet-oriented communication
new sock_dgram `{ return SOCK_DGRAM; `}
+ # RAW socket, access raw data, without it being handled by the IP stack
new sock_raw `{ return SOCK_RAW; `}
+ # SEQPACKET, packet-oriented communication with guarantees in packet order
new sock_seqpacket `{ return SOCK_SEQPACKET; `}
end
+# Socket families
extern class NativeSocketAddressFamilies `{ int `}
- new af_null `{ return 0; `}
-
# Unspecified
new af_unspec `{ return AF_UNSPEC; `}
# IPv6
new af_inet6 `{ return AF_INET6; `}
+ # Maximum identifier for socket families
new af_max `{ return AF_MAX; `}
end
+# Socket protocol families
extern class NativeSocketProtocolFamilies `{ int `}
- new pf_null `{ return 0; `}
+ # Unspecified
new pf_unspec `{ return PF_UNSPEC; `}
+
+ # Local socket
new pf_local `{ return PF_LOCAL; `}
+
+ # Unix socket
new pf_unix `{ return PF_UNIX; `}
+
+ # Internet (IPv4) socket
new pf_inet `{ return PF_INET; `}
+
+ # SNA (IBM) socket
new pf_sna `{ return PF_SNA; `}
+
+ # DECnet socket
new pf_decnet `{ return PF_DECnet; `}
+
+ # Routing tables control
new pf_route `{ return PF_ROUTE; `}
+
+ # Novell internet protocol
new pf_ipx `{ return PF_IPX; `}
+
+ # Key management protocol
new pf_key `{ return PF_KEY; `}
+
+ # Internet (IPv6) socket
new pf_inet6 `{ return PF_INET6; `}
+
+ # Maximum identifier for socket families
new pf_max `{ return PF_MAX; `}
- new ipproto_udp `{ return IPPROTO_UDP; `}
end
# Level on which to set options