Noux/net: refactoring of Socket_io_channel
The Socket_io_channel class now uses the Io_channel_backend to provide the network related methods. In addition the Socket_io_channel_registry was replaced with a simpler implementation which uses Io_receptors to unblock I/O channels from the callback-function of lwip.
This commit is contained in:
parent
08bd41b1ec
commit
082d8d6623
|
@ -31,8 +31,6 @@
|
||||||
#include <cpu_session_component.h>
|
#include <cpu_session_component.h>
|
||||||
#include <child_policy.h>
|
#include <child_policy.h>
|
||||||
|
|
||||||
extern void (*cleanup_socket_descriptors)();
|
|
||||||
|
|
||||||
namespace Noux {
|
namespace Noux {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,7 +72,6 @@ namespace Noux {
|
||||||
class User_info;
|
class User_info;
|
||||||
User_info *user_info();
|
User_info *user_info();
|
||||||
|
|
||||||
|
|
||||||
class Child;
|
class Child;
|
||||||
|
|
||||||
bool is_init_process(Child *child);
|
bool is_init_process(Child *child);
|
||||||
|
@ -338,10 +335,6 @@ namespace Noux {
|
||||||
|
|
||||||
~Child()
|
~Child()
|
||||||
{
|
{
|
||||||
/* short-cut to close all remaining open sd's if the child exits */
|
|
||||||
if (cleanup_socket_descriptors)
|
|
||||||
cleanup_socket_descriptors();
|
|
||||||
|
|
||||||
_sig_rec->dissolve(&_execve_cleanup_dispatcher);
|
_sig_rec->dissolve(&_execve_cleanup_dispatcher);
|
||||||
_sig_rec->dissolve(&_exit_dispatcher);
|
_sig_rec->dissolve(&_exit_dispatcher);
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,8 @@ namespace Noux {
|
||||||
|
|
||||||
bool is_init_process(Child *child) { return child == init_child; }
|
bool is_init_process(Child *child) { return child == init_child; }
|
||||||
void init_process_exited() { init_child = 0; }
|
void init_process_exited() { init_child = 0; }
|
||||||
};
|
|
||||||
|
|
||||||
extern void (*close_socket)(int);
|
};
|
||||||
|
|
||||||
extern void init_network();
|
extern void init_network();
|
||||||
|
|
||||||
|
@ -230,13 +229,6 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
|
|
||||||
case SYSCALL_CLOSE:
|
case SYSCALL_CLOSE:
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* We have to explicitly close Socket_io_channel fd's because
|
|
||||||
* these are currently handled separately.
|
|
||||||
*/
|
|
||||||
if (close_socket)
|
|
||||||
close_socket(_sysio->close_in.fd);
|
|
||||||
|
|
||||||
remove_io_channel(_sysio->close_in.fd);
|
remove_io_channel(_sysio->close_in.fd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,6 @@
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <child.h>
|
#include <child.h>
|
||||||
|
|
||||||
void (*close_socket)(int) = 0;
|
|
||||||
|
|
||||||
void (*cleanup_socket_descriptors)() = 0;
|
|
||||||
|
|
||||||
void init_network() { }
|
void init_network() { }
|
||||||
|
|
||||||
bool Noux::Child::_syscall_net(Noux::Session::Syscall sc) { return false; }
|
bool Noux::Child::_syscall_net(Noux::Session::Syscall sc) { return false; }
|
||||||
|
|
|
@ -15,14 +15,15 @@
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <cap_session/connection.h>
|
#include <cap_session/connection.h>
|
||||||
#include <dataspace/client.h>
|
#include <dataspace/client.h>
|
||||||
|
#include <base/lock.h>
|
||||||
|
|
||||||
#include <lwip/genode.h>
|
#include <lwip/genode.h>
|
||||||
|
|
||||||
/* Noux includes */
|
/* Noux includes */
|
||||||
#include <child.h>
|
#include <child.h>
|
||||||
#include <socket_descriptor_registry.h>
|
|
||||||
#include <socket_io_channel.h>
|
#include <socket_io_channel.h>
|
||||||
#include <shared_pointer.h>
|
#include <shared_pointer.h>
|
||||||
|
#include <io_receptor_registry.h>
|
||||||
|
|
||||||
/* Libc includes */
|
/* Libc includes */
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
@ -32,79 +33,30 @@
|
||||||
using namespace Noux;
|
using namespace Noux;
|
||||||
|
|
||||||
void (*libc_select_notify)();
|
void (*libc_select_notify)();
|
||||||
void (*close_socket)(int);
|
|
||||||
void (*cleanup_socket_descriptors)();
|
|
||||||
|
|
||||||
/* set select() timeout to lwip's lowest possible value */
|
/* helper macro for casting the backend */
|
||||||
struct timeval timeout = { 0, 10000 };
|
#define GET_SOCKET_IO_CHANNEL_BACKEND(backend, name) \
|
||||||
|
Socket_io_channel_backend *name = \
|
||||||
|
dynamic_cast<Socket_io_channel_backend*>(backend)
|
||||||
|
|
||||||
|
static Genode::Lock _select_notify_lock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This callback function is called from lwip via the libc_select_notify
|
* This callback function is called from lwip via the libc_select_notify
|
||||||
* function pointer if an event occurs.
|
* function pointer if an event occurs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void select_notify()
|
static void select_notify()
|
||||||
{
|
{
|
||||||
fd_set readfds;
|
/*
|
||||||
fd_set writefds;
|
* The function could be called multiple times while actually
|
||||||
fd_set exceptfds;
|
* still running.
|
||||||
int ready;
|
*/
|
||||||
|
Genode::Lock::Guard guard(_select_notify_lock);
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
for (Io_receptor *r = io_receptor_registry()->first();
|
||||||
FD_ZERO(&writefds);
|
r != 0; r = r->next()) {
|
||||||
FD_ZERO(&exceptfds);
|
r->check_and_wakeup();
|
||||||
|
|
||||||
/* for now set each currently used socket descriptor true */
|
|
||||||
for (int sd = 0; sd < MAX_SOCKET_DESCRIPTORS; sd++) {
|
|
||||||
if (Socket_descriptor_registry<Socket_io_channel>::instance()->sd_in_use(sd)) {
|
|
||||||
int real_sd = Socket_descriptor_registry<Socket_io_channel>::instance()->io_channel_by_sd(sd)->get_socket();
|
|
||||||
|
|
||||||
FD_SET(real_sd, &readfds);
|
|
||||||
FD_SET(real_sd, &writefds);
|
|
||||||
FD_SET(real_sd, &exceptfds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ready = ::select(MAX_SOCKET_DESCRIPTORS, &readfds, &writefds, &exceptfds, &timeout);
|
|
||||||
|
|
||||||
/* if any socket is ready for reading */
|
|
||||||
if (ready > 0) {
|
|
||||||
for (int sd = 0; sd < MAX_SOCKET_DESCRIPTORS; sd++) {
|
|
||||||
if (Socket_descriptor_registry<Socket_io_channel>::instance()->sd_in_use(sd)) {
|
|
||||||
int real_sd = Socket_descriptor_registry<Socket_io_channel>::instance()->io_channel_by_sd(sd)->get_socket();
|
|
||||||
|
|
||||||
if (FD_ISSET(real_sd, &readfds)
|
|
||||||
|| FD_ISSET(real_sd, &writefds)
|
|
||||||
|| FD_ISSET(real_sd, &exceptfds)) {
|
|
||||||
Shared_pointer<Socket_io_channel> sio = Socket_descriptor_registry<Socket_io_channel>::instance()->io_channel_by_sd(sd);
|
|
||||||
|
|
||||||
if (FD_ISSET(real_sd, &readfds))
|
|
||||||
sio->set_unblock(true, false, false);
|
|
||||||
if (FD_ISSET(real_sd, &writefds))
|
|
||||||
sio->set_unblock(false, true, false);
|
|
||||||
if (FD_ISSET(real_sd, &exceptfds))
|
|
||||||
sio->set_unblock(false, false, true);
|
|
||||||
|
|
||||||
sio->invoke_all_notifiers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _close_socket(int sd)
|
|
||||||
{
|
|
||||||
if (Socket_descriptor_registry<Socket_io_channel>::instance()->sd_in_use(sd)) {
|
|
||||||
Socket_descriptor_registry<Socket_io_channel>::instance()->remove_io_channel(sd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _cleanup_socket_descriptors()
|
|
||||||
{
|
|
||||||
Socket_descriptor_registry<Socket_io_channel>::instance()->reset_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,23 +79,12 @@ void init_network()
|
||||||
|
|
||||||
if (!libc_select_notify)
|
if (!libc_select_notify)
|
||||||
libc_select_notify = select_notify;
|
libc_select_notify = select_notify;
|
||||||
|
|
||||||
if (!close_socket)
|
|
||||||
close_socket = _close_socket;
|
|
||||||
|
|
||||||
if (!cleanup_socket_descriptors)
|
|
||||||
cleanup_socket_descriptors = _cleanup_socket_descriptors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************
|
/*********************************
|
||||||
** Noux net syscall dispatcher **
|
** Noux net syscall dispatcher **
|
||||||
*********************************/
|
*********************************/
|
||||||
|
|
||||||
#define GET_SOCKET_IO_CHANNEL(fd, handle) \
|
|
||||||
Shared_pointer<Io_channel> io = _lookup_channel(fd); \
|
|
||||||
Shared_pointer<Socket_io_channel> handle = \
|
|
||||||
io.dynamic_pointer_cast<Socket_io_channel>();
|
|
||||||
|
|
||||||
bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
|
bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
|
||||||
{
|
{
|
||||||
switch (sc) {
|
switch (sc) {
|
||||||
|
@ -184,7 +125,9 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
|
||||||
{
|
{
|
||||||
Socket_io_channel *socket_io_channel = new Socket_io_channel();
|
Socket_io_channel *socket_io_channel = new Socket_io_channel();
|
||||||
|
|
||||||
if (!socket_io_channel->socket(_sysio)) {
|
GET_SOCKET_IO_CHANNEL_BACKEND(socket_io_channel->backend(), backend);
|
||||||
|
|
||||||
|
if (!backend->socket(_sysio)) {
|
||||||
delete socket_io_channel;
|
delete socket_io_channel;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -193,155 +136,112 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
|
||||||
|
|
||||||
_sysio->socket_out.fd = add_io_channel(io_channel);
|
_sysio->socket_out.fd = add_io_channel(io_channel);
|
||||||
|
|
||||||
/* add socket to registry */
|
|
||||||
Socket_descriptor_registry<Socket_io_channel>::instance()->add_io_channel(io_channel.dynamic_pointer_cast<Socket_io_channel>(),
|
|
||||||
_sysio->socket_out.fd);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case SYSCALL_GETSOCKOPT:
|
case SYSCALL_GETSOCKOPT:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->getsockopt_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->getsockopt_in.fd);
|
||||||
|
|
||||||
if (!socket_io_channel->getsockopt(_sysio))
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return backend->getsockopt(_sysio);
|
||||||
}
|
}
|
||||||
case SYSCALL_SETSOCKOPT:
|
case SYSCALL_SETSOCKOPT:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->setsockopt_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->setsockopt_in.fd);
|
||||||
|
|
||||||
if (!socket_io_channel->setsockopt(_sysio)) {
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return backend->setsockopt(_sysio);
|
||||||
}
|
}
|
||||||
case SYSCALL_ACCEPT:
|
case SYSCALL_ACCEPT:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->accept_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->accept_in.fd);
|
||||||
|
|
||||||
int new_socket = socket_io_channel->accept(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
if (new_socket == -1)
|
|
||||||
|
int socket = backend->accept(_sysio);
|
||||||
|
if (socket == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Socket_io_channel *new_socket_io_channel = new Socket_io_channel(new_socket);
|
Socket_io_channel *socket_io_channel = new Socket_io_channel(socket);
|
||||||
Shared_pointer<Io_channel> channel(new_socket_io_channel, Genode::env()->heap());
|
Shared_pointer<Io_channel> io_channel(socket_io_channel, Genode::env()->heap());
|
||||||
|
|
||||||
_sysio->accept_out.fd = add_io_channel(channel);
|
_sysio->accept_out.fd = add_io_channel(io_channel);
|
||||||
|
|
||||||
/* add new socket to registry */
|
|
||||||
Socket_descriptor_registry<Socket_io_channel>::instance()->add_io_channel(channel.dynamic_pointer_cast<Socket_io_channel>(),
|
|
||||||
_sysio->accept_out.fd);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case SYSCALL_BIND:
|
case SYSCALL_BIND:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->bind_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->bind_in.fd);
|
||||||
|
|
||||||
if (socket_io_channel->bind(_sysio) == -1)
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return (backend->bind(_sysio) == -1) ? false : true;
|
||||||
}
|
}
|
||||||
case SYSCALL_LISTEN:
|
case SYSCALL_LISTEN:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->listen_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->listen_in.fd);
|
||||||
|
|
||||||
if (socket_io_channel->listen(_sysio) == -1)
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return (backend->listen(_sysio) == -1) ? false : true;
|
||||||
}
|
}
|
||||||
case SYSCALL_SEND:
|
case SYSCALL_SEND:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->send_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->send_in.fd);
|
||||||
|
|
||||||
ssize_t len = socket_io_channel->send(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
|
|
||||||
if (len == -1)
|
return (backend->send(_sysio) == -1) ? false : true;
|
||||||
return false;
|
|
||||||
|
|
||||||
_sysio->send_out.len = len;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case SYSCALL_SENDTO:
|
case SYSCALL_SENDTO:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->sendto_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->sendto_in.fd);
|
||||||
|
|
||||||
ssize_t len = socket_io_channel->sendto(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
|
|
||||||
if (len == -1)
|
return (backend->sendto(_sysio) == -1) ? false : true;
|
||||||
return false;
|
|
||||||
|
|
||||||
_sysio->sendto_out.len = len;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case SYSCALL_RECV:
|
case SYSCALL_RECV:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->recv_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->recv_in.fd);
|
||||||
|
|
||||||
ssize_t len = socket_io_channel->recv(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
|
|
||||||
if (len == -1)
|
return (backend->recv(_sysio) == -1) ? false : true;
|
||||||
return false;
|
|
||||||
|
|
||||||
_sysio->recv_out.len = len;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case SYSCALL_RECVFROM:
|
case SYSCALL_RECVFROM:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->recvfrom_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->recvfrom_in.fd);
|
||||||
|
|
||||||
ssize_t len = socket_io_channel->recvfrom(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
|
|
||||||
if (len == -1)
|
return (backend->recvfrom(_sysio) == -1) ? false : true;
|
||||||
return false;
|
|
||||||
|
|
||||||
_sysio->recvfrom_out.len = len;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case SYSCALL_GETPEERNAME:
|
case SYSCALL_GETPEERNAME:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->getpeername_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->getpeername_in.fd);
|
||||||
|
|
||||||
int res = socket_io_channel->getpeername(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
|
|
||||||
if (res == -1)
|
return (backend->getpeername(_sysio) == -1) ? false : true;
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case SYSCALL_SHUTDOWN:
|
case SYSCALL_SHUTDOWN:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->shutdown_in.fd, socket_io_channel)
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->shutdown_in.fd);
|
||||||
|
|
||||||
int res = socket_io_channel->shutdown(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
|
|
||||||
if (res == -1)
|
return (backend->shutdown(_sysio) == -1) ? false : true;
|
||||||
return false;
|
|
||||||
|
|
||||||
/* remove sd from registry */
|
|
||||||
_close_socket(_sysio->shutdown_in.fd);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case SYSCALL_CONNECT:
|
case SYSCALL_CONNECT:
|
||||||
{
|
{
|
||||||
GET_SOCKET_IO_CHANNEL(_sysio->connect_in.fd, socket_io_channel);
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->connect_in.fd);
|
||||||
|
|
||||||
int res = socket_io_channel->connect(_sysio);
|
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
|
||||||
|
|
||||||
if (res == -1)
|
return (backend->connect(_sysio) == -1) ? false : true;
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* \brief I/O channel for sockets
|
|
||||||
* \author Josef Söntgen
|
|
||||||
* \date 2012-04-12
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2011-2012 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
|
||||||
* under the terms of the GNU General Public License version 2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _NOUX__SOCKET_DESCRIPTOR_REGISTRY_H_
|
|
||||||
#define _NOUX__SOCKET_DESCRIPTOR_REGISTRY_H_
|
|
||||||
|
|
||||||
/* Noux includes */
|
|
||||||
#include <shared_pointer.h>
|
|
||||||
|
|
||||||
namespace Noux {
|
|
||||||
|
|
||||||
enum { MAX_SOCKET_DESCRIPTORS = 64 };
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class Socket_descriptor_registry
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct {
|
|
||||||
bool allocated;
|
|
||||||
Shared_pointer<T> io_channel;
|
|
||||||
} _sds[MAX_SOCKET_DESCRIPTORS];
|
|
||||||
|
|
||||||
void _assign_sd(int sd, Shared_pointer<T> &io_channel)
|
|
||||||
{
|
|
||||||
_sds[sd].io_channel = io_channel;
|
|
||||||
_sds[sd].allocated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _is_valid_sd(int sd) const
|
|
||||||
{
|
|
||||||
return (sd >= 0) && (sd < MAX_SOCKET_DESCRIPTORS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _reset_sd(int sd)
|
|
||||||
{
|
|
||||||
_sds[sd].io_channel = Shared_pointer<T>();
|
|
||||||
_sds[sd].allocated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
Socket_descriptor_registry()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < MAX_SOCKET_DESCRIPTORS; i++)
|
|
||||||
_reset_sd(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset_all()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < MAX_SOCKET_DESCRIPTORS; i++)
|
|
||||||
_reset_sd(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
int add_io_channel(Shared_pointer<T> io_channel, int sd = -1)
|
|
||||||
{
|
|
||||||
if (sd == -1) {
|
|
||||||
PERR("Could not allocate socket descriptor");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_is_valid_sd(sd)) {
|
|
||||||
PERR("Socket descriptor %d is out of range", sd);
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
_assign_sd(sd, io_channel);
|
|
||||||
return sd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_io_channel(int sd)
|
|
||||||
{
|
|
||||||
if (!_is_valid_sd(sd))
|
|
||||||
PERR("Socket descriptor %d is out of range", sd);
|
|
||||||
else
|
|
||||||
_reset_sd(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sd_in_use(int sd) const
|
|
||||||
{
|
|
||||||
return (_is_valid_sd(sd) && _sds[sd].allocated);
|
|
||||||
}
|
|
||||||
|
|
||||||
Shared_pointer<T> io_channel_by_sd(int sd) const
|
|
||||||
{
|
|
||||||
if (!sd_in_use(sd)) {
|
|
||||||
PWRN("Socket descriptor %d is not open", sd);
|
|
||||||
return Shared_pointer<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _sds[sd].io_channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Socket_descriptor_registry<T> *instance()
|
|
||||||
{
|
|
||||||
static Socket_descriptor_registry<T> _sdr;
|
|
||||||
return &_sdr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif /* _NOUX__SOCKET_DESCRIPTOR_REGISTRY_H_ */
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -33,89 +35,39 @@
|
||||||
|
|
||||||
namespace Noux {
|
namespace Noux {
|
||||||
|
|
||||||
class Socket_io_channel : public Io_channel
|
class Socket_io_channel_backend : public Io_channel_backend
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int _socket;
|
int _socket;
|
||||||
|
|
||||||
enum { UNBLOCK_READ = 0x1,
|
|
||||||
UNBLOCK_WRITE = 0x2,
|
|
||||||
UNBLOCK_EXCEPT = 0x4 };
|
|
||||||
|
|
||||||
int _unblock;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Socket_io_channel()
|
Socket_io_channel_backend()
|
||||||
:
|
:
|
||||||
_socket(-1),
|
_socket(-1)
|
||||||
_unblock(0)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Socket_io_channel(int s)
|
Socket_io_channel_backend(int s)
|
||||||
:
|
:
|
||||||
_socket(s),
|
_socket(s)
|
||||||
_unblock(0)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~Socket_io_channel()
|
~Socket_io_channel_backend()
|
||||||
{
|
{
|
||||||
if (_socket != -1)
|
if (_socket != -1) {
|
||||||
::shutdown(_socket, SHUT_RDWR);
|
::shutdown(_socket, SHUT_RDWR);
|
||||||
}
|
::close(_socket);
|
||||||
|
|
||||||
int get_socket() const
|
|
||||||
{
|
|
||||||
return _socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_unblock(bool rd, bool wr, bool ex)
|
|
||||||
{
|
|
||||||
if (rd)
|
|
||||||
_unblock |= UNBLOCK_READ;
|
|
||||||
if (wr)
|
|
||||||
_unblock |= UNBLOCK_WRITE;
|
|
||||||
if (ex)
|
|
||||||
_unblock |= UNBLOCK_EXCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fstat(Sysio *sysio) { return false; }
|
|
||||||
|
|
||||||
bool fcntl(Sysio *sysio)
|
|
||||||
{
|
|
||||||
switch (sysio->fcntl_in.cmd) {
|
|
||||||
|
|
||||||
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS:
|
|
||||||
case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS:
|
|
||||||
{
|
|
||||||
int result = ::fcntl(_socket, sysio->fcntl_in.cmd,
|
|
||||||
sysio->fcntl_in.long_arg);
|
|
||||||
|
|
||||||
sysio->fcntl_out.result = result;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
PWRN("invalid fcntl command: %d", sysio->fcntl_in.cmd);
|
|
||||||
sysio->error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dirent(Sysio *sysio) { return false; }
|
int type() const { return 1; }
|
||||||
|
|
||||||
bool check_unblock(bool rd, bool wr, bool ex) const
|
int socket() const { return _socket; }
|
||||||
{
|
|
||||||
if (_unblock & UNBLOCK_READ)
|
|
||||||
return true;
|
|
||||||
if (_unblock & UNBLOCK_WRITE)
|
|
||||||
return true;
|
|
||||||
if (_unblock & UNBLOCK_EXCEPT)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
/**
|
||||||
}
|
* Io_channel interface implementation (only needed methods)
|
||||||
|
*/
|
||||||
|
|
||||||
bool write(Sysio *sysio, size_t &count)
|
bool write(Sysio *sysio, size_t &count)
|
||||||
{
|
{
|
||||||
|
@ -135,7 +87,8 @@ namespace Noux {
|
||||||
case EINVAL: sysio->error.read = Sysio::READ_ERR_INVALID; break;
|
case EINVAL: sysio->error.read = Sysio::READ_ERR_INVALID; break;
|
||||||
case EIO: sysio->error.read = Sysio::READ_ERR_IO; break;
|
case EIO: sysio->error.read = Sysio::READ_ERR_IO; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -143,9 +96,7 @@ namespace Noux {
|
||||||
|
|
||||||
bool read(Sysio *sysio)
|
bool read(Sysio *sysio)
|
||||||
{
|
{
|
||||||
size_t const max_count =
|
size_t const max_count = Genode::min(sysio->read_in.count, sizeof(sysio->read_out.chunk));
|
||||||
Genode::min(sysio->read_in.count,
|
|
||||||
sizeof(sysio->read_out.chunk));
|
|
||||||
|
|
||||||
ssize_t result = ::read(_socket, sysio->read_out.chunk, max_count);
|
ssize_t result = ::read(_socket, sysio->read_out.chunk, max_count);
|
||||||
|
|
||||||
|
@ -160,56 +111,106 @@ namespace Noux {
|
||||||
case EINVAL: sysio->error.read = Sysio::READ_ERR_INVALID; break;
|
case EINVAL: sysio->error.read = Sysio::READ_ERR_INVALID; break;
|
||||||
case EIO: sysio->error.read = Sysio::READ_ERR_IO; break;
|
case EIO: sysio->error.read = Sysio::READ_ERR_IO; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool socket(Sysio *sysio)
|
bool fcntl(Sysio *sysio)
|
||||||
{
|
{
|
||||||
_socket = ::socket(sysio->socket_in.domain,
|
int cmd = -1;
|
||||||
sysio->socket_in.type,
|
switch (sysio->fcntl_in.cmd) {
|
||||||
sysio->socket_in.protocol);
|
|
||||||
|
|
||||||
return (_socket == -1) ? false : true;
|
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: cmd = F_GETFL; break;
|
||||||
}
|
case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS: cmd = F_SETFL; break;
|
||||||
|
default:
|
||||||
bool getsockopt(Sysio *sysio)
|
PDBG("invalid fcntl command: %d", sysio->fcntl_in.cmd);
|
||||||
{
|
sysio->error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID;
|
||||||
int result = ::getsockopt(_socket, sysio->getsockopt_in.level,
|
return false;
|
||||||
sysio->getsockopt_in.optname,
|
|
||||||
sysio->getsockopt_in.optval,
|
|
||||||
&sysio->getsockopt_in.optlen);
|
|
||||||
|
|
||||||
return (result == -1) ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool setsockopt(Sysio *sysio)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Filter options out because lwip only supports several socket
|
|
||||||
* options. Therefore for now we silently return 0 and notify
|
|
||||||
* the user via debug message.
|
|
||||||
*/
|
|
||||||
switch (sysio->setsockopt_in.optname) {
|
|
||||||
case SO_DEBUG:
|
|
||||||
case SO_LINGER:
|
|
||||||
case SO_REUSEADDR:
|
|
||||||
|
|
||||||
PWRN("SOL_SOCKET option '%d' is currently not supported, however we report success",
|
|
||||||
sysio->setsockopt_in.optname);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = ::setsockopt(_socket, sysio->setsockopt_in.level,
|
int result = ::fcntl(_socket, cmd, sysio->fcntl_in.long_arg);
|
||||||
sysio->setsockopt_in.optname,
|
|
||||||
sysio->setsockopt_in.optval,
|
|
||||||
sysio->setsockopt_in.optlen);
|
|
||||||
|
|
||||||
return (result == -1) ? false : true;
|
sysio->fcntl_out.result = result;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dirent(Sysio *sysio) { return false; }
|
||||||
|
|
||||||
|
bool ioctl(Sysio *sysio)
|
||||||
|
{
|
||||||
|
int request;
|
||||||
|
|
||||||
|
switch (sysio->ioctl_in.request) {
|
||||||
|
|
||||||
|
case Sysio::Ioctl_in::OP_FIONBIO: request = FIONBIO; break;
|
||||||
|
default:
|
||||||
|
PDBG("invalid ioctl request: %d", sysio->ioctl_in.request);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int result = ::ioctl(_socket, request, NULL);
|
||||||
|
|
||||||
|
return result ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_unblock(bool rd, bool wr, bool ex) const
|
||||||
|
{
|
||||||
|
fd_set readfds;
|
||||||
|
fd_set writefds;
|
||||||
|
fd_set exceptfds;
|
||||||
|
int ready;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timeout will be overriden in libc's select() function
|
||||||
|
* but we still need a valid pointer because libc's select()
|
||||||
|
* will block forever otherwise.
|
||||||
|
*/
|
||||||
|
struct timeval timeout = { 0, 0 };
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_ZERO(&writefds);
|
||||||
|
FD_ZERO(&exceptfds);
|
||||||
|
|
||||||
|
FD_SET(_socket, &readfds);
|
||||||
|
FD_SET(_socket, &writefds);
|
||||||
|
FD_SET(_socket, &exceptfds);
|
||||||
|
|
||||||
|
ready = ::select(_socket + 1, &readfds, &writefds, &exceptfds, &timeout);
|
||||||
|
|
||||||
|
if (ready > 0) {
|
||||||
|
if (rd) {
|
||||||
|
if (FD_ISSET(_socket, &readfds))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wr) {
|
||||||
|
if (FD_ISSET(_socket, &writefds))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ex) {
|
||||||
|
if (FD_ISSET(_socket, &exceptfds))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HACK: Since lwip won't mark fds as writable, even if they
|
||||||
|
* are, if asked multiple times we return true in this
|
||||||
|
* case. Hopefully that won't break any time soon.
|
||||||
|
*/
|
||||||
|
if (wr)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Socket methods
|
||||||
|
*/
|
||||||
|
|
||||||
int accept(Sysio *sysio)
|
int accept(Sysio *sysio)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -230,7 +231,8 @@ namespace Noux {
|
||||||
case EOPNOTSUPP: sysio->error.accept = Sysio::ACCEPT_ERR_NOT_SUPPORTED; break;
|
case EOPNOTSUPP: sysio->error.accept = Sysio::ACCEPT_ERR_NOT_SUPPORTED; break;
|
||||||
case EWOULDBLOCK: sysio->error.accept = Sysio::ACCEPT_ERR_WOULD_BLOCK; break;
|
case EWOULDBLOCK: sysio->error.accept = Sysio::ACCEPT_ERR_WOULD_BLOCK; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +251,8 @@ namespace Noux {
|
||||||
case EINVAL: sysio->error.bind = Sysio::BIND_ERR_INVALID; break;
|
case EINVAL: sysio->error.bind = Sysio::BIND_ERR_INVALID; break;
|
||||||
case ENOMEM: sysio->error.bind = Sysio::BIND_ERR_NO_MEMORY; break;
|
case ENOMEM: sysio->error.bind = Sysio::BIND_ERR_NO_MEMORY; break;
|
||||||
default:
|
default:
|
||||||
PERR("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +272,8 @@ namespace Noux {
|
||||||
case EINPROGRESS: sysio->error.connect = Sysio::CONNECT_ERR_IN_PROGRESS; break;
|
case EINPROGRESS: sysio->error.connect = Sysio::CONNECT_ERR_IN_PROGRESS; break;
|
||||||
case EISCONN: sysio->error.connect = Sysio::CONNECT_ERR_IS_CONNECTED; break;
|
case EISCONN: sysio->error.connect = Sysio::CONNECT_ERR_IS_CONNECTED; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,11 +286,14 @@ namespace Noux {
|
||||||
(socklen_t *)&sysio->getpeername_in.addrlen);
|
(socklen_t *)&sysio->getpeername_in.addrlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ioctl(Sysio *sysio)
|
bool getsockopt(Sysio *sysio)
|
||||||
{
|
{
|
||||||
int result = ::ioctl(_socket, sysio->ioctl_in.request, NULL);
|
int result = ::getsockopt(_socket, sysio->getsockopt_in.level,
|
||||||
|
sysio->getsockopt_in.optname,
|
||||||
|
sysio->getsockopt_in.optval,
|
||||||
|
&sysio->getsockopt_in.optlen);
|
||||||
|
|
||||||
return result ? false : true;
|
return (result == -1) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int listen(Sysio *sysio)
|
int listen(Sysio *sysio)
|
||||||
|
@ -298,7 +305,8 @@ namespace Noux {
|
||||||
case EADDRINUSE: sysio->error.listen = Sysio::LISTEN_ERR_ADDR_IN_USE; break;
|
case EADDRINUSE: sysio->error.listen = Sysio::LISTEN_ERR_ADDR_IN_USE; break;
|
||||||
case EOPNOTSUPP: sysio->error.listen = Sysio::LISTEN_ERR_NOT_SUPPORTED; break;
|
case EOPNOTSUPP: sysio->error.listen = Sysio::LISTEN_ERR_NOT_SUPPORTED; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,10 +324,13 @@ namespace Noux {
|
||||||
case EINVAL: sysio->error.recv = Sysio::RECV_ERR_INVALID; break;
|
case EINVAL: sysio->error.recv = Sysio::RECV_ERR_INVALID; break;
|
||||||
case ENOTCONN: sysio->error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break;
|
case ENOTCONN: sysio->error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysio->recv_out.len = result;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,13 +347,39 @@ namespace Noux {
|
||||||
case EINVAL: sysio->error.recv = Sysio::RECV_ERR_INVALID; break;
|
case EINVAL: sysio->error.recv = Sysio::RECV_ERR_INVALID; break;
|
||||||
case ENOTCONN: sysio->error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break;
|
case ENOTCONN: sysio->error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysio->recvfrom_out.len = result;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool setsockopt(Sysio *sysio)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Filter options out because lwip only supports several socket
|
||||||
|
* options. Therefore for now we silently return 0 and notify
|
||||||
|
* the user via debug message.
|
||||||
|
*/
|
||||||
|
switch (sysio->setsockopt_in.optname) {
|
||||||
|
case SO_DEBUG:
|
||||||
|
case SO_LINGER:
|
||||||
|
PWRN("SOL_SOCKET option '%d' is currently not supported, however we report success",
|
||||||
|
sysio->setsockopt_in.optname);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = ::setsockopt(_socket, sysio->setsockopt_in.level,
|
||||||
|
sysio->setsockopt_in.optname,
|
||||||
|
sysio->setsockopt_in.optval,
|
||||||
|
sysio->setsockopt_in.optlen);
|
||||||
|
|
||||||
|
return (result == -1) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t send(Sysio *sysio)
|
ssize_t send(Sysio *sysio)
|
||||||
{
|
{
|
||||||
ssize_t result = ::send(_socket, sysio->send_in.buf, sysio->send_in.len,
|
ssize_t result = ::send(_socket, sysio->send_in.buf, sysio->send_in.len,
|
||||||
|
@ -357,10 +394,13 @@ namespace Noux {
|
||||||
case EISCONN: sysio->error.send = Sysio::SEND_ERR_IS_CONNECTED; break;
|
case EISCONN: sysio->error.send = Sysio::SEND_ERR_IS_CONNECTED; break;
|
||||||
case ENOMEM: sysio->error.send = Sysio::SEND_ERR_NO_MEMORY; break;
|
case ENOMEM: sysio->error.send = Sysio::SEND_ERR_NO_MEMORY; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysio->send_out.len = result;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,10 +420,13 @@ namespace Noux {
|
||||||
case EISCONN: sysio->error.send = Sysio::SEND_ERR_IS_CONNECTED; break;
|
case EISCONN: sysio->error.send = Sysio::SEND_ERR_IS_CONNECTED; break;
|
||||||
case ENOMEM: sysio->error.send = Sysio::SEND_ERR_NO_MEMORY; break;
|
case ENOMEM: sysio->error.send = Sysio::SEND_ERR_NO_MEMORY; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysio->sendto_out.len = result;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,12 +438,80 @@ namespace Noux {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case ENOTCONN: sysio->error.shutdown = Sysio::SHUTDOWN_ERR_NOT_CONNECTED; break;
|
case ENOTCONN: sysio->error.shutdown = Sysio::SHUTDOWN_ERR_NOT_CONNECTED; break;
|
||||||
default:
|
default:
|
||||||
PDBG("unhandled errno: %d", errno); break;
|
PDBG("unhandled errno: %d", errno);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool socket(Sysio *sysio)
|
||||||
|
{
|
||||||
|
_socket = ::socket(sysio->socket_in.domain,
|
||||||
|
sysio->socket_in.type,
|
||||||
|
sysio->socket_in.protocol);
|
||||||
|
|
||||||
|
return (_socket == -1) ? false : true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Socket_io_channel : public Io_channel
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
Socket_io_channel_backend *_backend;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Socket_io_channel()
|
||||||
|
:
|
||||||
|
_backend(new (env()->heap()) Socket_io_channel_backend())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Socket_io_channel(int s)
|
||||||
|
:
|
||||||
|
_backend(new (env()->heap()) Socket_io_channel_backend(s))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Socket_io_channel()
|
||||||
|
{
|
||||||
|
destroy(env()->heap(), _backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Io_channel interface (only needed methods)
|
||||||
|
*/
|
||||||
|
|
||||||
|
Io_channel_backend *backend() { return _backend; }
|
||||||
|
|
||||||
|
bool write(Sysio *sysio, size_t &count)
|
||||||
|
{
|
||||||
|
return _backend->write(sysio, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read(Sysio *sysio)
|
||||||
|
{
|
||||||
|
return _backend->read(sysio);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fcntl(Sysio* sysio)
|
||||||
|
{
|
||||||
|
return _backend->fcntl(sysio);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ioctl(Sysio *sysio)
|
||||||
|
{
|
||||||
|
return _backend->ioctl(sysio);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_unblock(bool rd, bool wr, bool ex) const
|
||||||
|
{
|
||||||
|
return _backend->check_unblock(rd, wr, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user