socket :: NativeSocket :: defaultinit
# 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 NULL;
}
int *d = malloc(sizeof(int));
memcpy(d, &ds, sizeof(ds));
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));
`}
# Write `length` bytes from `buffer`
fun write(buffer: CString, length: Int): Int `{
return write(*self, buffer, length);
`}
# Write `value` as a single byte
fun write_byte(value: Int): Int `{
unsigned char byt = (unsigned char)value;
return write(*self, &byt, 1);
`}
# 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
#
# Returns `true` on success.
fun setsockopt(level: NativeSocketOptLevels, option_name: NativeSocketOptNames, option_value: Int): Bool `{
int err = setsockopt(*self, level, option_name, &option_value, sizeof(int));
if(err != 0){
return 0;
}
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
fun socket_poll(filedesc: PollFD, timeout: Int): Array[NativeSocketPollValues]
do
var result = native_poll(filedesc.poll_struct, timeout)
assert result != -1
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:
# int poll(struct pollfd fds[], nfds_t nfds, int timeout);
#
# Official documentation of the poll function:
#
# The poll() function provides applications with a mechanism for multiplexing input/output over a set of file descriptors.
# For each member of the array pointed to by fds, poll() shall examine the given file descriptor for the event(s) specified in events.
# The number of pollfd structures in the fds array is specified by nfds.
# The poll() function shall identify those file descriptors on which an application can read or write data, or on which certain events have occurred.
# The fds argument specifies the file descriptors to be examined and the events of interest for each file descriptor.
# It is a pointer to an array with one member for each open file descriptor of interest.
# The array's members are pollfd structures within which fd specifies an open file descriptor and events and revents are bitmasks constructed by
# OR'ing a combination of the pollfd flags.
private fun native_poll(filedesc: NativeSocketPollFD, timeout: Int): Int `{
int poll_return = poll(filedesc, 1, timeout);
return poll_return;
`}
private fun native_accept(addr_in: NativeSocketAddrIn): NativeSocket `{
socklen_t s = sizeof(struct sockaddr);
int socket = accept(*self, (struct sockaddr*)addr_in, &s);
if (socket == -1) return NULL;
int *ptr = malloc(sizeof(int));
*ptr = socket;
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
var s = native_accept(addrIn)
if s.address_is_null then return null
return new SocketAcceptResult(s, addrIn)
end
# Set whether this socket is non blocking
fun non_blocking=(value: Bool) `{
int flags = fcntl(*self, F_GETFL, 0);
if (flags == -1) flags = 0;
if (value) {
flags = flags | O_NONBLOCK;
} else if (flags & O_NONBLOCK) {
flags = flags - O_NONBLOCK;
} else {
return;
}
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
lib/socket/socket_c.nit:108,1--261,3