mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 13:48:21 +00:00
socket: getname, getpeername, setopt
This commit is contained in:
@@ -92,6 +92,7 @@ typedef struct {
|
||||
|
||||
#define SO_BROADCAST 6
|
||||
#define SO_BINDTODEVICE 25
|
||||
#define SO_KEEPALIVE 9
|
||||
|
||||
#define SOL_SOCKET 1
|
||||
|
||||
|
||||
@@ -37,8 +37,11 @@ typedef struct socketops_t {
|
||||
int (*connect)(socket_t *socket, sockaddr_t *addr, uintmax_t data);
|
||||
int (*listen)(socket_t *socket, int backlog);
|
||||
int (*accept)(socket_t *server, socket_t *client, sockaddr_t *addr, uintmax_t flags);
|
||||
int (*getname)(socket_t *socket, sockaddr_t *addr);
|
||||
int (*getpeername)(socket_t *socket, sockaddr_t *addr);
|
||||
size_t (*datacount)(socket_t *socket);
|
||||
void (*destroy)(socket_t *socket);
|
||||
int (*setopt)(socket_t *socket, int optname, void *buffer, size_t len);
|
||||
} socketops_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -117,6 +120,7 @@ static inline void sock_freemsghdr(msghdr_t *hdr) {
|
||||
}
|
||||
|
||||
void localsock_leavebinding(vnode_t *vnode);
|
||||
int localsock_pair(socket_t **ret1, socket_t **ret2);
|
||||
socket_t *localsock_createsocket();
|
||||
socket_t *udp_createsocket();
|
||||
socket_t *tcp_createsocket();
|
||||
|
||||
@@ -11,7 +11,6 @@ struct localpair_t;
|
||||
struct binding_t;
|
||||
typedef struct {
|
||||
socket_t socket;
|
||||
char *bindpath;
|
||||
ringbuffer_t ringbuffer; // shared with pair
|
||||
// client/connected server
|
||||
struct localpair_t *pair;
|
||||
@@ -21,6 +20,7 @@ typedef struct {
|
||||
int backlogsize; // shared with binding
|
||||
uintmax_t backlogcurrentwrite; // shared with binding
|
||||
uintmax_t backlogcurrentread; // shared with binding
|
||||
char *bindpath;
|
||||
} localsocket_t;
|
||||
|
||||
// created by the client socket
|
||||
@@ -689,6 +689,7 @@ static int localsock_bind(socket_t *socket, sockaddr_t *addr) {
|
||||
vnode->socketbinding = binding;
|
||||
VOP_UNLOCK(vnode);
|
||||
localsocket->binding = binding;
|
||||
localsocket->bindpath = path;
|
||||
|
||||
cleanup:
|
||||
if (error) {
|
||||
@@ -738,6 +739,52 @@ void localsock_leavebinding(vnode_t *vnode) {
|
||||
vnode->socketbinding = NULL;
|
||||
}
|
||||
|
||||
int localsock_pair(socket_t **ret1, socket_t **ret2) {
|
||||
socket_t *socket1 = socket_create(SOCKET_TYPE_LOCAL);
|
||||
if (socket1 == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
socket_t *socket2 = socket_create(SOCKET_TYPE_LOCAL);
|
||||
if (socket2 == NULL) {
|
||||
localsock_destroy(socket1);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
localpair_t *pair = alloc(sizeof(localpair_t));
|
||||
if (pair == NULL) {
|
||||
localsock_destroy(socket1);
|
||||
localsock_destroy(socket2);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
MUTEX_INIT(&pair->mutex);
|
||||
pair->server = (localsocket_t *)socket1;
|
||||
pair->client = (localsocket_t *)socket2;
|
||||
((localsocket_t *)socket1)->pair = pair;
|
||||
((localsocket_t *)socket2)->pair = pair;
|
||||
|
||||
*ret1 = socket1;
|
||||
*ret2 = socket2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int localsock_getname(socket_t *socket, sockaddr_t *addr) {
|
||||
localsocket_t *localsocket = (localsocket_t *)socket;
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
if (localsocket->bindpath)
|
||||
strcpy(addr->path, localsocket->bindpath);
|
||||
else
|
||||
addr->path[0] = '\0';
|
||||
|
||||
MUTEX_RELEASE(&socket->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int localsock_getpeername(socket_t *socket, sockaddr_t *addr) {
|
||||
addr->path[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static socketops_t socketops = {
|
||||
.bind = localsock_bind,
|
||||
.listen = localsock_listen,
|
||||
@@ -747,7 +794,9 @@ static socketops_t socketops = {
|
||||
.recv = localsock_recv,
|
||||
.destroy = localsock_destroy,
|
||||
.poll = localsock_poll,
|
||||
.datacount = localsocket_datacount
|
||||
.datacount = localsocket_datacount,
|
||||
.getname = localsock_getname,
|
||||
.getpeername = localsock_getpeername
|
||||
};
|
||||
|
||||
socket_t *localsock_createsocket() {
|
||||
|
||||
+69
-6
@@ -5,7 +5,7 @@
|
||||
#include <kernel/timekeeper.h>
|
||||
#include <kernel/interrupt.h>
|
||||
|
||||
#define WORKER_COUNT 8
|
||||
#define WORKER_COUNT 12
|
||||
#define WORKER_BUFFER_SIZE (64 * 1024)
|
||||
#define WORKER_INTERNAL_BUFFER_SIZE 2048
|
||||
// MSS will be min(_MSS_LIMIT, mtu - sizeof(ipv4header_t) - sizeof(tcpheader_t))
|
||||
@@ -414,19 +414,16 @@ void tcp_process(netdev_t *netdev, void *buffer, ipv4frame_t *ipv4frame) {
|
||||
};
|
||||
|
||||
if (checksum(&ipv4pseudoheader, buffer) != 0) {
|
||||
printf("tcp: bad checksum\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (be_to_cpu_w(ipv4pseudoheader.length) > WORKER_INTERNAL_BUFFER_SIZE) {
|
||||
printf("tcp: packet too big for internal buffer size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int tasktype = TASK_TYPE_PACKET;
|
||||
tcpworker_t *worker = getworker(ipv4pseudoheader.length, tasktype);
|
||||
if (worker == NULL) {
|
||||
printf("tcp: no free workers to handle packet\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1413,7 +1410,9 @@ static int tcp_poll(socket_t *socket, polldata_t *data, int events) {
|
||||
|
||||
static int tcp_bind(socket_t *socket, sockaddr_t *addr) {
|
||||
tcpsocket_t *tcpsocket = (tcpsocket_t *)socket;
|
||||
__assert(addr->ipv4addr.addr == 0);
|
||||
if (addr->ipv4addr.addr != 0) {
|
||||
printf("tcp: bind tried to bind to non zero address %x\n", addr->ipv4addr.addr);
|
||||
}
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
tcb_t *tcb = tcpsocket->tcb;
|
||||
if (tcb == NULL) {
|
||||
@@ -1741,6 +1740,67 @@ static void tcp_destroy(socket_t *socket) {
|
||||
free(socket);
|
||||
}
|
||||
|
||||
static int tcp_getname(socket_t *socket, sockaddr_t *addr) {
|
||||
tcpsocket_t *tcpsocket = (tcpsocket_t *)socket;
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
tcb_t *tcb = tcpsocket->tcb;
|
||||
|
||||
if (tcb) {
|
||||
MUTEX_ACQUIRE(&tcb->mutex, false);
|
||||
|
||||
addr->ipv4addr.addr = 0;
|
||||
addr->ipv4addr.port = tcb->port;
|
||||
|
||||
MUTEX_RELEASE(&tcb->mutex);
|
||||
} else {
|
||||
addr->ipv4addr.addr = 0;
|
||||
addr->ipv4addr.port = 0;
|
||||
}
|
||||
|
||||
MUTEX_RELEASE(&socket->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcp_getpeername(socket_t *socket, sockaddr_t *addr) {
|
||||
tcpsocket_t *tcpsocket = (tcpsocket_t *)socket;
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
tcb_t *tcb = tcpsocket->tcb;
|
||||
|
||||
if (tcb) {
|
||||
MUTEX_ACQUIRE(&tcb->mutex, false);
|
||||
|
||||
addr->ipv4addr.addr = tcb->key.peer;
|
||||
addr->ipv4addr.port = tcb->key.peerport;
|
||||
|
||||
MUTEX_RELEASE(&tcb->mutex);
|
||||
} else {
|
||||
addr->ipv4addr.addr = 0;
|
||||
addr->ipv4addr.port = 0;
|
||||
}
|
||||
|
||||
MUTEX_RELEASE(&socket->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// called with socket locked
|
||||
static int tcp_setopt(socket_t *socket, int optname, void *buffer, size_t len) {
|
||||
tcpsocket_t *tcpsocket = (tcpsocket_t *)socket;
|
||||
tcb_t *tcb = tcpsocket->tcb;
|
||||
|
||||
if (tcb) {
|
||||
MUTEX_ACQUIRE(&tcb->mutex, false);
|
||||
|
||||
switch (optname) {
|
||||
case SO_KEEPALIVE:
|
||||
// TODO this one
|
||||
break;
|
||||
}
|
||||
|
||||
MUTEX_RELEASE(&tcb->mutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static socketops_t socketops = {
|
||||
.bind = tcp_bind,
|
||||
.send = tcp_send,
|
||||
@@ -1750,7 +1810,10 @@ static socketops_t socketops = {
|
||||
.listen = tcp_listen,
|
||||
.accept = tcp_accept,
|
||||
.datacount = tcp_datacount,
|
||||
.destroy = tcp_destroy
|
||||
.destroy = tcp_destroy,
|
||||
.getname = tcp_getname,
|
||||
.getpeername = tcp_getpeername,
|
||||
.setopt = tcp_setopt
|
||||
};
|
||||
|
||||
socket_t *tcp_createsocket() {
|
||||
|
||||
+22
-1
@@ -293,6 +293,24 @@ static void udp_destroy(socket_t *socket) {
|
||||
free(socket);
|
||||
}
|
||||
|
||||
static int udp_getname(socket_t *socket, sockaddr_t *addr) {
|
||||
udpsocket_t *udpsocket = (udpsocket_t *)socket;
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
addr->ipv4addr.addr = udpsocket->address;
|
||||
addr->ipv4addr.port = udpsocket->port;
|
||||
MUTEX_RELEASE(&socket->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int udp_getpeername(socket_t *socket, sockaddr_t *addr) {
|
||||
udpsocket_t *udpsocket = (udpsocket_t *)socket;
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
addr->ipv4addr.addr = udpsocket->peeraddress;
|
||||
addr->ipv4addr.port = udpsocket->peerport;
|
||||
MUTEX_RELEASE(&socket->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int udp_poll(socket_t *socket, polldata_t *data, int events) {
|
||||
int revents = 0;
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
@@ -308,7 +326,9 @@ static socketops_t socketops = {
|
||||
.send = udp_send,
|
||||
.recv = udp_recv,
|
||||
.destroy = udp_destroy,
|
||||
.poll = udp_poll
|
||||
.poll = udp_poll,
|
||||
.getname = udp_getname,
|
||||
.getpeername = udp_getpeername
|
||||
};
|
||||
|
||||
socket_t *udp_createsocket() {
|
||||
@@ -321,6 +341,7 @@ socket_t *udp_createsocket() {
|
||||
free(socket);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPINLOCK_INIT(socket->ringbufferlock);
|
||||
socket->socket.ops = &socketops;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi
|
||||
|
||||
MUTEX_ACQUIRE(&socket->mutex, false);
|
||||
switch (optname) {
|
||||
case SO_BINDTODEVICE:
|
||||
case SO_BINDTODEVICE: {
|
||||
if (val) {
|
||||
socket->netdev = netdev_getdev(val);
|
||||
ret.errno = socket->netdev ? 0 : ENODEV;
|
||||
@@ -49,7 +49,8 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi
|
||||
socket->netdev = NULL;
|
||||
}
|
||||
break;
|
||||
case SO_BROADCAST:
|
||||
}
|
||||
case SO_BROADCAST: {
|
||||
if (val == NULL) {
|
||||
ret.errno = EFAULT;
|
||||
} else {
|
||||
@@ -57,6 +58,14 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi
|
||||
ret.errno = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SO_KEEPALIVE: {
|
||||
if (val == NULL)
|
||||
ret.errno = EFAULT;
|
||||
else
|
||||
ret.errno = socket->ops->setopt ? socket->ops->setopt(socket, optname, buffer, len) : ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret.errno = ENOPROTOOPT;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user