Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions ffsocket.nit
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ in "C Header" `{
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/poll.h>
#include <errno.h>

typedef int S_DESCRIPTOR;
Expand All @@ -23,6 +24,24 @@ in "C Header" `{
typedef socklen_t S_LEN;
`}

# Data structure used by the poll function
extern PollFD `{ struct pollfd `}
# File descriptor id
fun fd: Int `{ return recv.fd; `}
# List of events to be watched
fun events: Int `{ return recv.events; `}
# List of events received by the last poll function
fun revents: Int `{ return recv.revents; `}

new (pid: Int, events: FFSocketPollValues)`{
struct pollfd poll;
poll.fd = pid;
poll.events = events;
return poll;
`}

end

extern FFSocket `{ S_DESCRIPTOR* `}

new socket(domain :FFSocketAddressFamilies, socketType :FFSocketTypes, protocol :FFSocketProtocolFamilies) `{
Expand Down Expand Up @@ -60,6 +79,34 @@ extern FFSocket `{ S_DESCRIPTOR* `}
private fun i_listen(size: Int):Int `{ return listen(*recv, size); `}
fun listen(size: Int):Int do return i_listen(size)

# Checks if the buffer is ready for any event specified when creating the pollfd structure
fun socket_poll(filedesc: PollFD, timeout: Int): Bool
do
var result = i_poll(filedesc, timeout)
assert result != -1
if result == 0 then return false
return true
end

# 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 i_poll(filedesc: PollFD, timeout: Int): Int `{
return poll(&filedesc, 1, timeout);
`}

private fun i_accept(addrIn: FFSocketAddrIn):FFSocket `{
S_LEN s = sizeof(S_ADDR);
S_DESCRIPTOR *d = NULL;
Expand Down Expand Up @@ -209,4 +256,19 @@ extern FFSocketProtocolFamilies `{ int `}
new pf_inet6 `{ return PF_INET6; `}
new pf_max `{ return PF_MAX; `}
end
extern FFSocketPollValues `{ int `}
new pollin `{ return POLLIN; `} # Data other than high-priority data may be read without blocking.
new pollrdnorm `{ return POLLRDNORM; `} # Normal data may be read without blocking.
new pollrdband `{ return POLLRDBAND; `} # Priority data may be read without blocking.
new pollpri `{ return POLLPRI; `} # High-priority data may be read without blocking.
new pollout `{ return POLLOUT; `} # Normal data may be written without blocking.
new pollwrnorm `{ return POLLWRNORM; `} # Equivalent to POLLOUT
new pollwrband `{ return POLLWRBAND; `} # Priority data may be written.
new pollerr `{ return POLLERR; `} # 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 pollhup `{ return POLLHUP; `} # 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 pollnval `{ return POLLNVAL; `} # The specified fd value is invalid. This flag is only valid in the revents member; it shall ignored in the events member.

fun +(other: FFSocketPollValues): FFSocketPollValues `{
return recv | other;
`}
end
8 changes: 8 additions & 0 deletions socket.nit
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ class Socket
var port: Int
private var socket: FFSocket
private var addrin: FFSocketAddrIn
# PollFD object, used for the ready_to_read function
private var read_pollFD: PollFD

init streamWithHost(thost: String, tport: Int)
do
socket = new FFSocket.socket( new FFSocketAddressFamilies.af_inet, new FFSocketTypes.sock_stream, new FFSocketProtocolFamilies.pf_null )
self.read_pollFD = new PollFD(socket.descriptor, new FFSocketPollValues.pollin)
var hostname = socket.gethostbyname(thost)
addrin = new FFSocketAddrIn.withHostent(hostname, tport)
address = addrin.address
Expand All @@ -22,6 +25,7 @@ class Socket
init streamWithPort(tport: Int)
do
socket = new FFSocket.socket( new FFSocketAddressFamilies.af_inet, new FFSocketTypes.sock_stream, new FFSocketProtocolFamilies.pf_null )
self.read_pollFD = new PollFD(socket.descriptor, new FFSocketPollValues.pollin)
addrin = new FFSocketAddrIn.with(tport, new FFSocketAddressFamilies.af_inet)
address = addrin.address
port = addrin.port
Expand All @@ -31,6 +35,7 @@ class Socket
init primitiveInit(h: FFSocketAcceptResult)
do
socket = h.socket
self.read_pollFD = new PollFD(socket.descriptor, new FFSocketPollValues.pollin)
addrin = h.addrIn
address = addrin.address
port = addrin.port
Expand All @@ -44,6 +49,9 @@ class Socket
fun bind:Bool do return socket.bind(addrin) >= 0
fun listen(size: Int):Bool do return socket.listen(size) >= 0
fun accept:Socket do return new Socket.primitiveInit(socket.accept)
# Checks if the socket is ready to be read with the read() function without blocking
fun ready_to_read: Bool do return socket.socket_poll(self.read_pollFD, 0)
fun timeout_rdy_to_read(timeout: Int): Bool do return socket.socket_poll(self.read_pollFD, timeout)

fun errno:Int do return socket.errno
end
Expand Down