Property definitions

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