#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));
`}
- fun write(buffer: String): Int
- import String.to_cstring, String.length `{
- return write(*self, (char*)String_to_cstring(buffer), String_length(buffer));
+ # Write `length` bytes from `buffer`
+ fun write(buffer: CString, length: Int): Int `{
+ return write(*self, buffer, length);
`}
# Write `value` as a single byte
return write(*self, &byt, 1);
`}
- fun read: String import NativeString.to_s_with_length, NativeString `{
- char *c = new_NativeString(1024);
- int n = read(*self, c, 1023);
- if(n < 0) {
- return NativeString_to_s_with_length("",0);
- }
- c[n] = 0;
- return NativeString_to_s_with_length(c, n);
+ # Read `length` bytes into `buffer`, returns the number of bytes read
+ fun read(buffer: CString, length: Int): Int `{
+ return read(*self, buffer, length);
`}
# Sets an option for the socket
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 filedesc.check_response(result)
end
+ # Poll this socket with `POLLHUP|POLLERR`
+ #
+ # A return value of 0 means there is no errors.
+ fun poll_hup_err: Int `{
+ struct pollfd fd = {*self, POLLHUP|POLLERR, 0};
+ int res = poll(&fd, 1, 0);
+ return res;
+ `}
+
# Call to the poll function of the C socket
#
# Signature:
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 new SocketAcceptResult(s, addrIn)
end
- # Set wether this socket is non blocking
+ # Set whether this socket is non blocking
fun non_blocking=(value: Bool) `{
int flags = fcntl(*self, F_GETFL, 0);
if (flags == -1) flags = 0;
}
fcntl(*self, F_SETFL, flags);
`}
+
+ # Send `len` bytes from `buf` to `dest_addr`
+ fun sendto(buf: CString, len: Int, flags: Int, dest_addr: NativeSocketAddrIn): Int `{
+ return sendto(*self, buf, len, flags, (struct sockaddr*)dest_addr, sizeof(struct sockaddr_in));
+ `}
+
+ # Receive a message into `buf` of maximum `len` bytes
+ fun recv(buf: CString, len: Int, flags: Int): Int `{
+ return recv(*self, buf, len, flags);
+ `}
+
+ # Receive a message into `buf` of maximum `len` bytes and store sender info into `src_addr`
+ fun recvfrom(buf: CString, len: Int, flags: Int, src_addr: NativeSocketAddrIn): Int `{
+ socklen_t srclen = sizeof(struct sockaddr_in);
+ return recvfrom(*self, buf, len, flags, (struct sockaddr*)src_addr, &srclen);
+ `}
end
# Result of a call to `NativeSocket::accept`
var addr_in: NativeSocketAddrIn
end
+# Socket address in the Internet namespace, pointer to a `struct sockaddr_in`
extern class NativeSocketAddrIn `{ struct sockaddr_in* `}
+
+ # `NULL` pointer
+ new nul `{ return NULL; `}
+
+ # `malloc` a new instance
new `{
struct sockaddr_in *sai = NULL;
sai = malloc(sizeof(struct sockaddr_in));
return sai;
`}
- new with_port(port: Int, family: NativeSocketAddressFamilies) `{
- struct sockaddr_in *sai = NULL;
- sai = malloc(sizeof(struct sockaddr_in));
- sai->sin_family = family;
- sai->sin_port = htons(port);
- sai->sin_addr.s_addr = INADDR_ANY;
- return sai;
+ # Set `address` and `family` from `hostent` (to use with `Sys::gethostbyname`)
+ fun fill_from_hostent(hostent: NativeSocketHostent) `{
+ self->sin_family = hostent->h_addrtype;
+ memcpy((char*)&self->sin_addr.s_addr,
+ (char*)hostent->h_addr,
+ hostent->h_length);
`}
- new with_hostent(hostent: NativeSocketHostent, port: Int) `{
- struct sockaddr_in *sai = NULL;
- sai = malloc(sizeof(struct sockaddr_in));
- sai->sin_family = hostent->h_addrtype;
- sai->sin_port = htons(port);
- memcpy((char*)&sai->sin_addr.s_addr, (char*)hostent->h_addr, hostent->h_length);
- return sai;
- `}
+ # Internet address as then IPV4 numbers-and-dots notation
+ fun address: CString `{ return (char*)inet_ntoa(self->sin_addr); `}
+
+ # Set `address` to `INADDR_ANY`
+ fun address_any `{ self->sin_addr.s_addr = INADDR_ANY; `}
- fun address: String import NativeString.to_s `{ return NativeString_to_s((char*)inet_ntoa(self->sin_addr)); `}
+ # Set `address` to `INADDR_BROADCAST`
+ fun address_broadcast `{ self->sin_addr.s_addr = INADDR_BROADCAST; `}
+ # Address family
fun family: NativeSocketAddressFamilies `{ return self->sin_family; `}
+ # Address family
+ fun family=(value: NativeSocketAddressFamilies) `{ self->sin_family = value; `}
+
+ # Port
fun port: Int `{ return ntohs(self->sin_port); `}
- fun destroy `{ free(self); `}
+ # Port
+ fun port=(value: Int) `{ self->sin_port = htons(value); `}
end
+# Host entry information, a pointer to a `struct hostent`
extern class NativeSocketHostent `{ struct hostent* `}
- private fun native_h_aliases(i: Int): String import NativeString.to_s `{ return NativeString_to_s(self->h_aliases[i]); `}
-
- private fun native_h_aliases_reachable(i: Int): Bool `{ return (self->h_aliases[i] != NULL); `}
+ private fun native_h_aliases(i: Int): CString `{
+ return self->h_aliases[i];
+ `}
+ # Alternative names for the host
fun h_aliases: Array[String]
do
- var i=0
- var d=new Array[String]
+ var res = new Array[String]
loop
- d.add(native_h_aliases(i))
- if native_h_aliases_reachable(i+1) == false then break
- i += 1
+ var ha = native_h_aliases(res.length)
+ if ha.address_is_null then break
+ res.add ha.to_s
end
- return d
+ return res
end
- fun h_addr: String import NativeString.to_s `{ return NativeString_to_s((char*)inet_ntoa(*(struct in_addr*)self->h_addr)); `}
+ # 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; `}
- fun h_name: String import NativeString.to_s `{ return NativeString_to_s(self->h_name); `}
+ # 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; `}
end
redef class Sys
# Get network host entry
- fun gethostbyname(name: NativeString): NativeSocketHostent `{
+ fun gethostbyname(name: CString): NativeSocketHostent `{
return gethostbyname(name);
`}