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