Low-level socket functionalities

Introduced classes

extern class HErrno

socket :: HErrno

Error code of Sys::h_errno
extern class NativeSocket

socket :: NativeSocket

Native C socket
extern class NativeSocketAddrIn

socket :: NativeSocketAddrIn

Socket address in the Internet namespace, pointer to a struct sockaddr_in
extern class NativeSocketHostent

socket :: NativeSocketHostent

Host entry information, a pointer to a struct hostent
extern class NativeSocketOptLevels

socket :: NativeSocketOptLevels

Level on which to set options
extern class NativeSocketOptNames

socket :: NativeSocketOptNames

Options for socket, use with setsockopt
extern class NativeSocketPollValues

socket :: NativeSocketPollValues

Used for the poll function of a socket, mix several Poll values to check for events on more than one type of event
extern class NativeSocketProtocolFamilies

socket :: NativeSocketProtocolFamilies

Socket protocol families
extern class NativeSocketSet

socket :: NativeSocketSet

Structure used to register FDs for a Select
extern class NativeSocketTypes

socket :: NativeSocketTypes

Socket types
extern class NativeTimeval

socket :: NativeTimeval

Time structure, with a microsecond resolution
class PollFD

socket :: PollFD

Wrapper for the data structure used for polling on a socket
class SocketAcceptResult

socket :: SocketAcceptResult

Result of a call to NativeSocket::accept

Redefined classes

redef class Sys

socket :: socket_c $ Sys

The main class of the program.

All class definitions

extern class HErrno

socket $ HErrno

Error code of Sys::h_errno
extern class NativeSocket

socket $ NativeSocket

Native C socket
extern class NativeSocketAddrIn

socket $ NativeSocketAddrIn

Socket address in the Internet namespace, pointer to a struct sockaddr_in
extern class NativeSocketHostent

socket $ NativeSocketHostent

Host entry information, a pointer to a struct hostent
extern class NativeSocketOptLevels

socket $ NativeSocketOptLevels

Level on which to set options
extern class NativeSocketOptNames

socket $ NativeSocketOptNames

Options for socket, use with setsockopt
extern class NativeSocketPollValues

socket $ NativeSocketPollValues

Used for the poll function of a socket, mix several Poll values to check for events on more than one type of event
extern class NativeSocketProtocolFamilies

socket $ NativeSocketProtocolFamilies

Socket protocol families
extern class NativeSocketSet

socket $ NativeSocketSet

Structure used to register FDs for a Select
extern class NativeSocketTypes

socket $ NativeSocketTypes

Socket types
extern class NativeTimeval

socket $ NativeTimeval

Time structure, with a microsecond resolution
class PollFD

socket $ PollFD

Wrapper for the data structure used for polling on a socket
class SocketAcceptResult

socket $ SocketAcceptResult

Result of a call to NativeSocket::accept
redef class Sys

socket :: socket_c $ Sys

The main class of the program.
package_diagram socket::socket_c socket_c core core socket::socket_c->core socket::socket socket socket::socket->socket::socket_c gamnit::common common gamnit::common->socket::socket mpd::mpd mpd mpd::mpd->socket::socket socket::socket_client socket_client socket::socket_client->socket::socket socket::socket_server socket_server socket::socket_server->socket::socket socket::socket_simple_server socket_simple_server socket::socket_simple_server->socket::socket websocket::websocket websocket websocket::websocket->socket::socket gamnit::common... ... gamnit::common...->gamnit::common mpd::mpd... ... mpd::mpd...->mpd::mpd socket::socket_client... ... socket::socket_client...->socket::socket_client socket::socket_server... ... socket::socket_server...->socket::socket_server socket::socket_simple_server... ... socket::socket_simple_server...->socket::socket_simple_server websocket::websocket... ... websocket::websocket...->websocket::websocket

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.

Children

module socket

socket :: socket

Socket services

Descendants

module a_star-m

a_star-m

module client

gamnit :: client

Client-side network services for games and such
module common

gamnit :: common

Services common to the client and server modules
module mpd

mpd :: mpd

Music Player Daemon client library
module network

gamnit :: network

Easy client/server logic for games and simple distributed applications
module server

gamnit :: server

Server-side network services for games and such
module socket_client

socket :: socket_client

Client sample using the Socket module which connect to the server sample.
module socket_server

socket :: socket_server

Server sample using the Socket module which allow client to connect
module socket_simple_server

socket :: socket_simple_server

Simple server example using a non-blocking TCPServer
module websocket

websocket :: websocket

Adds support for a websocket connection in Nit
module websocket_server

websocket :: websocket_server

Sample module for a minimal chat server using Websockets on port 8088
# Low-level socket functionalities
module socket_c

in "C Header" `{
	#include <stdio.h>
	#include <stdlib.h>
	#include <unistd.h>
	#include <string.h>
	#include <sys/socket.h>
	#include <sys/types.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
	#include <netdb.h>
	#include <sys/poll.h>
`}

in "C" `{
	#include <fcntl.h>
	#include <netinet/tcp.h>
`}

# Wrapper for the data structure used for polling on a socket
class PollFD
	super FinalizableOnce

	# The PollFD object
	private var poll_struct: NativeSocketPollFD

	# A collection of the events to be watched
	var events: Array[NativeSocketPollValues]

	# Create a PollFD object from NativePollFD informations
	init from_poll_values(pid: Int, events: Array[NativeSocketPollValues])
	do
		assert events.length >= 1

		var events_in_one = events[0]

		for i in [1 .. events.length - 1] do
			events_in_one += events[i]
		end

		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
	private fun check_response(response: Int): Array[NativeSocketPollValues]
	do
		var resp_array = new Array[NativeSocketPollValues]
		for i in events do
			if c_check_resp(response, i) != 0 then
				resp_array.push(i)
			end
		end
		return resp_array
	end

	# Checks if the poll call has returned true for a particular type of event
	private fun c_check_resp(response: Int, mask: NativeSocketPollValues): Int
	`{
		return response & mask;
	`}

	redef fun finalize_once
	do
		poll_struct.free
	end
end

# Data structure used by the poll function
private extern class NativeSocketPollFD `{ struct pollfd * `}

	# File descriptor
	fun fd: Int `{ return self->fd; `}

	# List of events to be watched
	fun events: Int `{ return self->events; `}

	# List of events received by the last poll function
	fun revents: Int `{  return self->revents; `}

	new (pid: Int, events: NativeSocketPollValues) `{
		struct pollfd *poll = malloc(sizeof(struct pollfd));
		poll->fd = pid;
		poll->events = events;
		return poll;
	`}
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 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

# Result of a call to `NativeSocket::accept`
class SocketAcceptResult

	# Opened socket
	var socket: NativeSocket

	# Address of the remote client
	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;
	`}

	# 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);
	`}

	# 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; `}

	# 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); `}

	# 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): CString `{
		return self->h_aliases[i];
	`}

	# Alternative names for the host
	fun h_aliases: Array[String]
	do
		var res = new Array[String]
		loop
			var ha = native_h_aliases(res.length)
			if ha.address_is_null then break
			res.add ha.to_s
		end
		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;
		tv = malloc(sizeof(struct timeval));
		tv->tv_sec = seconds;
		tv->tv_usec = microseconds;
		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;
		f = malloc(sizeof(fd_set));
		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.
	fun select(max: NativeSocket, reads: nullable NativeSocketSet, write: nullable NativeSocketSet,
			 except: nullable NativeSocketSet, timeout: NativeTimeval): Int `{
		fd_set *rds = NULL,
		       *wts = NULL,
		       *exs = NULL;
		struct timeval *tm = NULL;
		if (reads != NULL) rds = (fd_set*)reads;
		if (write != NULL) wts = (fd_set*)write;
		if (except != NULL) exs = (fd_set*)except;
		if (timeout != NULL) tm = (struct timeval*)timeout;
		return select(*max, rds, wts, exs, tm);
	`}
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 `}
	# Unspecified
	new af_unspec `{ return AF_UNSPEC; `}

	# Local to host (pipes)
	new af_unix `{ return AF_UNIX; `}

	# For backward compatibility
	new af_local `{ return AF_LOCAL; `}

	# Internetwork: UDP, TCP, etc.
	new af_inet `{ return AF_INET; `}

	# IBM SNA
	new af_sna `{ return AF_SNA; `}

	# DECnet
	new af_decnet `{ return AF_DECnet; `}

	# Internal Routing Protocol
	new af_route `{ return AF_ROUTE; `}

	# Novell Internet Protocol
	new af_ipx `{ return AF_IPX; `}

	# 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 `}
	# 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

# Level on which to set options
extern class NativeSocketOptLevels `{ int `}

	# Dummy for IP (As defined in C)
	new ip `{ return IPPROTO_IP;`}

	# Control message protocol
	new icmp `{ return IPPROTO_ICMP;`}

	# Use TCP
	new tcp `{ return IPPROTO_TCP; `}

	# Socket level options
	new socket `{ return SOL_SOCKET; `}
end

# Options for socket, use with setsockopt
extern class NativeSocketOptNames `{ int `}

	# Enables debugging information
	new debug `{ return SO_DEBUG; `}

	# Authorizes the broadcasting of messages
	new broadcast `{ return SO_BROADCAST; `}

	# Authorizes the reuse of the local address
	new reuseaddr `{ return SO_REUSEADDR; `}

	# Authorizes the use of keep-alive packets in a connection
	new keepalive `{ return SO_KEEPALIVE; `}

	# Disable the Nagle algorithm and send data as soon as possible, in smaller packets
	new tcp_nodelay `{ return TCP_NODELAY; `}
end

# Used for the poll function of a socket, mix several Poll values to check for events on more than one type of event
extern class NativeSocketPollValues `{ int `}

	# Data other than high-priority data may be read without blocking.
	new pollin `{ return POLLIN; `}

	# Normal data may be read without blocking.
	new pollrdnorm `{ return POLLRDNORM; `}

	# Priority data may be read without blocking.
	new pollrdband `{ return POLLRDBAND; `}

	# High-priority data may be read without blocking.
	new pollpri `{ return POLLPRI; `}

	# Normal data may be written without blocking.
	new pollout `{ return POLLOUT; `}

	# Equivalent to POLLOUT
	new pollwrnorm `{ return POLLWRNORM; `}

	# Priority data may be written.
	new pollwrband `{ return POLLWRBAND; `}

	# An error has occurred on the device or stream.
	#
	# This flag is only valid in the revents bitmask; it shall be ignored in the events member.
	new pollerr `{ return POLLERR; `}

	# The device has been disconnected.
	#
	# This event and POLLOUT are mutually-exclusive; a stream can never be
	# writable if a hangup has occurred. However, this event and POLLIN,
	# POLLRDNORM, POLLRDBAND, or POLLPRI are not mutually-exclusive.
	#
	# This flag is only valid in the revents bitmask; it shall be ignored in the events member.
	new pollhup `{ return POLLHUP; `}

	# The specified fd value is invalid.
	#
	# This flag is only valid in the revents member; it shall ignored in the events member.
	new pollnval `{ return POLLNVAL; `}

	# Combines two NativeSocketPollValues
	private fun +(other: NativeSocketPollValues): NativeSocketPollValues `{
		return self | other;
	`}
end

redef class Sys
	# Get network host entry
	fun gethostbyname(name: CString): NativeSocketHostent `{
		return gethostbyname(name);
	`}

	# Last error raised by `gethostbyname`
	fun h_errno: HErrno `{ return h_errno; `}
end

# Error code of `Sys::h_errno`
extern class HErrno `{ int `}
	# The specified host is unknown
	fun host_not_found: Bool `{ return self == HOST_NOT_FOUND; `}

	# The requested name is valid but does not have an IP address
	#
	# Same as `no_data`.
	fun no_address: Bool `{ return self == NO_ADDRESS; `}

	# The requested name is valid byt does not have an IP address
	#
	# Same as `no_address`.
	fun no_data: Bool `{ return self == NO_DATA; `}

	# A nonrecoverable name server error occurred
	fun no_recovery: Bool `{ return self == NO_RECOVERY; `}

	# A temporary error occurred on an authoritative name server, try again later
	fun try_again: Bool `{ return self == TRY_AGAIN; `}

	redef fun to_s
	do
		if host_not_found then
			return "The specified host is unknown"
		else if no_address then
			return "The requested name is valid but does not have an IP address"
		else if no_recovery then
			return "A nonrecoverable name server error occurred"
		else if try_again then
			return "A temporary error occurred on an authoritative name server, try again later"
		else
			# This may happen if another call was made to `gethostbyname`
			# before we fetch the error code.
			return "Unknown error on `gethostbyname`"
		end
	end
end
lib/socket/socket_c.nit:17,1--626,3