Clean implementation of socket classes
This commit is contained in:
@@ -105,6 +105,7 @@ OBJS+=$(O)/sys/sys_net.o \
|
||||
$(O)/net/raw.o \
|
||||
$(O)/net/tcp.o \
|
||||
$(O)/net/if.o \
|
||||
$(O)/net/socket.o \
|
||||
$(O)/net/util.o
|
||||
DIRS+=$(O)/net
|
||||
|
||||
|
||||
+2
-5
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "node.h"
|
||||
#include "net/socket.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#define OF_WRITABLE (1 << 0)
|
||||
@@ -19,10 +20,6 @@ struct ofile {
|
||||
size_t pos;
|
||||
void *priv_data;
|
||||
} file;
|
||||
struct {
|
||||
int domain;
|
||||
int type;
|
||||
void *sock;
|
||||
} socket;
|
||||
struct socket socket;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
#include "sys/list.h"
|
||||
|
||||
struct sockaddr;
|
||||
struct socket;
|
||||
|
||||
struct sockops {
|
||||
ssize_t (*recvfrom) (struct socket *, void *, size_t, struct sockaddr *, size_t *);
|
||||
ssize_t (*sendto) (struct socket *, const void *, size_t, struct sockaddr *, size_t);
|
||||
|
||||
int (*open) (struct socket *);
|
||||
void (*close) (struct socket *);
|
||||
|
||||
int (*bind) (struct socket *, struct sockaddr *, size_t);
|
||||
int (*setsockopt) (struct socket *, int, void *, size_t);
|
||||
};
|
||||
|
||||
struct socket_class {
|
||||
const char *name;
|
||||
int domain, type;
|
||||
int (*supports) (int proto);
|
||||
|
||||
struct sockops *ops;
|
||||
|
||||
struct list_head link;
|
||||
};
|
||||
|
||||
void socket_class_register(struct socket_class *cls);
|
||||
@@ -1,10 +1,6 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
|
||||
#define INET_P_ICMP 1
|
||||
#define INET_P_TCP 6
|
||||
#define INET_P_UDP 17
|
||||
|
||||
struct inet_frame {
|
||||
uint8_t ihl:4;
|
||||
uint8_t version:4;
|
||||
|
||||
@@ -1,27 +1,7 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
|
||||
struct sockaddr;
|
||||
struct vfs_ioctx;
|
||||
struct ofile;
|
||||
struct netdev;
|
||||
|
||||
int net_receive(struct netdev *dev, const void *data, size_t len);
|
||||
int net_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto);
|
||||
ssize_t net_sendto(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t salen);
|
||||
ssize_t net_recvfrom(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen);
|
||||
int net_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len);
|
||||
int net_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen);
|
||||
void net_close(struct vfs_ioctx *ioctx, struct ofile *fd);
|
||||
|
||||
void net_daemon_start(void);
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
|
||||
struct vfs_ioctx;
|
||||
struct ofile;
|
||||
struct sockaddr;
|
||||
struct packet;
|
||||
|
||||
int raw_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto);
|
||||
ssize_t raw_socket_send(struct vfs_ioctx *ioctx, struct ofile *fd, const void *buf, size_t lim, struct sockaddr *sa, size_t salen);
|
||||
ssize_t raw_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, size_t lim, struct sockaddr *sa, size_t *salen);
|
||||
int raw_socket_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len);
|
||||
int raw_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen);
|
||||
void raw_socket_close(struct vfs_ioctx *ioctx, struct ofile *fd);
|
||||
|
||||
void raw_packet_handle(struct packet *p);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
|
||||
struct sockaddr;
|
||||
struct vfs_ioctx;
|
||||
struct ofile;
|
||||
struct netdev;
|
||||
|
||||
struct socket {
|
||||
struct sockops *op;
|
||||
struct vfs_ioctx *ioctx;
|
||||
void *data;
|
||||
};
|
||||
|
||||
int net_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto);
|
||||
ssize_t net_sendto(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t salen);
|
||||
ssize_t net_recvfrom(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen);
|
||||
int net_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len);
|
||||
int net_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen);
|
||||
void net_close(struct vfs_ioctx *ioctx, struct ofile *fd);
|
||||
@@ -11,14 +11,5 @@ struct udp_frame {
|
||||
struct eth_frame;
|
||||
struct inet_frame;
|
||||
struct packet;
|
||||
struct vfs_ioctx;
|
||||
struct ofile;
|
||||
struct sockaddr;
|
||||
|
||||
void udp_handle_frame(struct packet *p, struct eth_frame *eth, struct inet_frame *ip, void *data, size_t len);
|
||||
int udp_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto);
|
||||
ssize_t udp_socket_send(struct vfs_ioctx *ioctx, struct ofile *fd, const void *buf, size_t lim, struct sockaddr *sa, size_t salen);
|
||||
ssize_t udp_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, size_t lim, struct sockaddr *sa, size_t *salen);
|
||||
int udp_socket_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len);
|
||||
int udp_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen);
|
||||
void udp_socket_close(struct vfs_ioctx *ioctx, struct ofile *fd);
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
#define INADDR_ANY 0
|
||||
#define INADDR_BROADCAST 0xFFFFFFFF
|
||||
|
||||
#define INET_P_ICMP 1
|
||||
#define INET_P_TCP 6
|
||||
#define INET_P_UDP 17
|
||||
|
||||
#define IPPROTO_ICMP (INET_P_ICMP)
|
||||
#define IPPROTO_UDP (INET_P_UDP)
|
||||
|
||||
struct sockaddr_in {
|
||||
uint16_t sin_family;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "net/packet.h"
|
||||
#include "sys/string.h"
|
||||
#include "user/inet.h"
|
||||
#include "sys/debug.h"
|
||||
#include "net/util.h"
|
||||
#include "net/inet.h"
|
||||
|
||||
@@ -150,144 +150,3 @@ void net_daemon_start(void) {
|
||||
netd_thread.pid = thread_alloc_pid(0);
|
||||
sched_queue(&netd_thread);
|
||||
}
|
||||
|
||||
int net_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto) {
|
||||
_assert(fd);
|
||||
fd->flags = OF_SOCKET;
|
||||
|
||||
switch (dom) {
|
||||
case AF_INET:
|
||||
switch (type) {
|
||||
case SOCK_DGRAM:
|
||||
return udp_socket_open(ioctx, fd, dom, type, proto);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AF_PACKET:
|
||||
switch (type) {
|
||||
case SOCK_RAW:
|
||||
return raw_socket_open(ioctx, fd, dom, type, proto);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void net_close(struct vfs_ioctx *ioctx, struct ofile *fd) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
|
||||
switch (fd->socket.domain) {
|
||||
case AF_INET:
|
||||
switch (fd->socket.type) {
|
||||
case SOCK_DGRAM:
|
||||
udp_socket_close(ioctx, fd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AF_PACKET:
|
||||
switch (fd->socket.type) {
|
||||
case SOCK_RAW:
|
||||
raw_socket_close(ioctx, fd);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t net_sendto(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t salen) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
|
||||
if (fd->socket.domain != AF_INET) {
|
||||
kwarn("Unknown socket family: %d\n", fd->socket.domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fd->socket.type) {
|
||||
case SOCK_DGRAM:
|
||||
return udp_socket_send(ioctx, fd, buf, len, sa, salen);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t net_recvfrom(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
|
||||
switch (fd->socket.domain) {
|
||||
case AF_INET:
|
||||
switch (fd->socket.type) {
|
||||
case SOCK_DGRAM:
|
||||
return udp_socket_recv(ioctx, fd, buf, len, sa, salen);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case AF_PACKET:
|
||||
switch (fd->socket.type) {
|
||||
case SOCK_RAW:
|
||||
return raw_socket_recv(ioctx, fd, buf, len, sa, salen);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
kwarn("Unknown socket family: %d\n", fd->socket.domain);
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int net_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len) {
|
||||
_assert(fd);
|
||||
|
||||
if (fd->socket.domain != AF_INET) {
|
||||
kwarn("Unknown socket family: %d\n", fd->socket.domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fd->socket.type) {
|
||||
case SOCK_DGRAM:
|
||||
return udp_socket_bind(ioctx, fd, sa, len);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int net_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen) {
|
||||
_assert(fd);
|
||||
|
||||
if (fd->socket.domain != AF_INET) {
|
||||
kwarn("Unknown socket family: %d\n", fd->socket.domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fd->socket.type) {
|
||||
case SOCK_DGRAM:
|
||||
return udp_setsockopt(ioctx, fd, optname, optval, optlen);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,46 @@
|
||||
#include "net/packet.h"
|
||||
#include "sys/thread.h"
|
||||
#include "sys/string.h"
|
||||
#include "net/socket.h"
|
||||
#include "net/class.h"
|
||||
#include "sys/sched.h"
|
||||
#include "sys/debug.h"
|
||||
#include "fs/ofile.h"
|
||||
#include "sys/heap.h"
|
||||
#include "sys/attr.h"
|
||||
#include "net/raw.h"
|
||||
|
||||
static int raw_class_supports(int proto) {
|
||||
return proto == 0;
|
||||
}
|
||||
|
||||
static int raw_socket_open(struct socket *s);
|
||||
static ssize_t raw_socket_recvfrom(struct socket *s,
|
||||
void *buf,
|
||||
size_t lim,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen);
|
||||
static void raw_socket_close(struct socket *s);
|
||||
static struct sockops raw_socket_ops = {
|
||||
.open = raw_socket_open,
|
||||
.close = raw_socket_close,
|
||||
|
||||
.sendto = NULL,
|
||||
.recvfrom = raw_socket_recvfrom,
|
||||
|
||||
.bind = NULL,
|
||||
.setsockopt = NULL,
|
||||
};
|
||||
static struct socket_class raw_socket_class = {
|
||||
.name = "raw-packet",
|
||||
.ops = &raw_socket_ops,
|
||||
.domain = AF_PACKET,
|
||||
.type = SOCK_DGRAM,
|
||||
.supports = raw_class_supports,
|
||||
};
|
||||
|
||||
////
|
||||
|
||||
struct raw_socket {
|
||||
struct thread *wait;
|
||||
struct packet_queue queue;
|
||||
@@ -19,7 +53,31 @@ struct raw_socket {
|
||||
static spin_t g_raw_lock = 0;
|
||||
static struct raw_socket *g_raw_sockets = NULL;
|
||||
|
||||
int raw_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto) {
|
||||
void raw_packet_handle(struct packet *p) {
|
||||
// Queue the packet for all the sockets
|
||||
uintptr_t irq;
|
||||
// TODO: too much time spent in spinlocked region?
|
||||
spin_lock_irqsave(&g_raw_lock, &irq);
|
||||
for (struct raw_socket *r = g_raw_sockets; r; r = r->next) {
|
||||
packet_ref(p);
|
||||
packet_queue_push(&r->queue, p);
|
||||
struct thread *w = r->wait;
|
||||
if (w) {
|
||||
r->wait = NULL;
|
||||
sched_queue(w);
|
||||
}
|
||||
}
|
||||
spin_release_irqrestore(&g_raw_lock, &irq);
|
||||
}
|
||||
|
||||
static __init void raw_class_register(void) {
|
||||
socket_class_register(&raw_socket_class);
|
||||
}
|
||||
|
||||
//////////
|
||||
// Socket implementation
|
||||
|
||||
static int raw_socket_open(struct socket *s) {
|
||||
// TODO: check your privilege
|
||||
struct raw_socket *r_sock = kmalloc(sizeof(struct raw_socket));
|
||||
_assert(r_sock);
|
||||
@@ -30,16 +88,17 @@ int raw_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type
|
||||
r_sock->wait = NULL;
|
||||
g_raw_sockets = r_sock;
|
||||
|
||||
fd->flags |= OF_SOCKET;
|
||||
fd->socket.sock = r_sock;
|
||||
fd->socket.domain = PF_PACKET;
|
||||
fd->socket.type = SOCK_RAW;
|
||||
s->data = r_sock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t raw_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, size_t lim, struct sockaddr *sa, size_t *salen) {
|
||||
struct raw_socket *sock = fd->socket.sock;
|
||||
static ssize_t raw_socket_recvfrom(struct socket *s,
|
||||
void *buf,
|
||||
size_t lim,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen) {
|
||||
struct raw_socket *sock = s->data;
|
||||
_assert(sock);
|
||||
struct thread *t = thread_self;
|
||||
_assert(t);
|
||||
@@ -69,9 +128,9 @@ ssize_t raw_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, si
|
||||
return p_size;
|
||||
}
|
||||
|
||||
void raw_socket_close(struct vfs_ioctx *ioctx, struct ofile *fd) {
|
||||
static void raw_socket_close(struct socket *s) {
|
||||
uintptr_t irq;
|
||||
struct raw_socket *r_sock = fd->socket.sock;
|
||||
struct raw_socket *r_sock = s->data;
|
||||
_assert(r_sock);
|
||||
|
||||
spin_lock_irqsave(&g_raw_lock, &irq);
|
||||
@@ -92,21 +151,7 @@ void raw_socket_close(struct vfs_ioctx *ioctx, struct ofile *fd) {
|
||||
struct packet *p = packet_queue_pop(&r_sock->queue);
|
||||
packet_unref(p);
|
||||
}
|
||||
}
|
||||
|
||||
void raw_packet_handle(struct packet *p) {
|
||||
// Queue the packet for all the sockets
|
||||
uintptr_t irq;
|
||||
// TODO: too much time spent in spinlocked region?
|
||||
spin_lock_irqsave(&g_raw_lock, &irq);
|
||||
for (struct raw_socket *r = g_raw_sockets; r; r = r->next) {
|
||||
packet_ref(p);
|
||||
packet_queue_push(&r->queue, p);
|
||||
struct thread *w = r->wait;
|
||||
if (w) {
|
||||
r->wait = NULL;
|
||||
sched_queue(w);
|
||||
}
|
||||
}
|
||||
spin_release_irqrestore(&g_raw_lock, &irq);
|
||||
kfree(r_sock);
|
||||
s->data = NULL;
|
||||
}
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
#include "user/socket.h"
|
||||
#include "user/errno.h"
|
||||
#include "sys/assert.h"
|
||||
#include "user/inet.h"
|
||||
#include "sys/debug.h"
|
||||
#include "net/class.h"
|
||||
#include "fs/ofile.h"
|
||||
|
||||
static LIST_HEAD(g_socket_class_head);
|
||||
|
||||
void socket_class_register(struct socket_class *cls) {
|
||||
list_head_init(&cls->link);
|
||||
list_add(&cls->link, &g_socket_class_head);
|
||||
}
|
||||
|
||||
int net_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto) {
|
||||
struct socket_class *cls, *iter;
|
||||
|
||||
cls = NULL;
|
||||
list_for_each_entry(iter, &g_socket_class_head, link) {
|
||||
if (iter->domain == dom && iter->type == type) {
|
||||
_assert(iter->supports);
|
||||
|
||||
if (iter->supports(proto)) {
|
||||
cls = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cls) {
|
||||
// No support for (dom:type:proto) tuple
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
_assert(cls->ops && cls->ops->open);
|
||||
|
||||
fd->flags = OF_SOCKET;
|
||||
fd->socket.ioctx = ioctx;
|
||||
fd->socket.op = cls->ops;
|
||||
|
||||
return cls->ops->open(&fd->socket);
|
||||
}
|
||||
|
||||
void net_close(struct vfs_ioctx *ioctx, struct ofile *fd) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
_assert(fd->socket.ioctx == ioctx);
|
||||
_assert(fd->socket.op);
|
||||
|
||||
if (fd->socket.op->close) {
|
||||
fd->socket.op->close(&fd->socket);
|
||||
}
|
||||
fd->flags &= ~OF_SOCKET;
|
||||
}
|
||||
|
||||
ssize_t net_sendto(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
const void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t salen) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
_assert(fd->socket.ioctx == ioctx);
|
||||
_assert(fd->socket.op);
|
||||
|
||||
if (fd->socket.op->sendto) {
|
||||
return fd->socket.op->sendto(&fd->socket, buf, len, sa, salen);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t net_recvfrom(struct vfs_ioctx *ioctx,
|
||||
struct ofile *fd,
|
||||
void *buf,
|
||||
size_t len,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
_assert(fd->socket.ioctx == ioctx);
|
||||
_assert(fd->socket.op);
|
||||
|
||||
if (fd->socket.op->recvfrom) {
|
||||
return fd->socket.op->recvfrom(&fd->socket, buf, len, sa, salen);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int net_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
_assert(fd->socket.ioctx == ioctx);
|
||||
_assert(fd->socket.op);
|
||||
|
||||
if (fd->socket.op->bind) {
|
||||
return fd->socket.op->bind(&fd->socket, sa, len);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int net_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen) {
|
||||
_assert(fd);
|
||||
_assert(fd->flags & OF_SOCKET);
|
||||
_assert(fd->socket.ioctx == ioctx);
|
||||
_assert(fd->socket.op);
|
||||
|
||||
if (fd->socket.op->setsockopt) {
|
||||
return fd->socket.op->setsockopt(&fd->socket, optname, optval, optlen);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "net/packet.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/debug.h"
|
||||
#include "user/inet.h"
|
||||
#include "sys/panic.h"
|
||||
#include "net/inet.h"
|
||||
#include "net/util.h"
|
||||
|
||||
@@ -5,17 +5,56 @@
|
||||
#include "net/packet.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/string.h"
|
||||
#include "net/class.h"
|
||||
#include "sys/sched.h"
|
||||
#include "user/inet.h"
|
||||
#include "sys/debug.h"
|
||||
#include "net/util.h"
|
||||
#include "sys/heap.h"
|
||||
#include "sys/attr.h"
|
||||
#include "fs/ofile.h"
|
||||
#include "net/inet.h"
|
||||
#include "net/udp.h"
|
||||
#include "net/eth.h"
|
||||
#include "net/if.h"
|
||||
|
||||
static int udp_class_supports(int proto) {
|
||||
return proto == IPPROTO_UDP || proto == 0;
|
||||
}
|
||||
|
||||
static int udp_socket_open(struct socket *sock);
|
||||
static void udp_socket_close(struct socket *sock);
|
||||
static ssize_t udp_socket_recvfrom(struct socket *s,
|
||||
void *buf,
|
||||
size_t lim,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen);
|
||||
static ssize_t udp_socket_sendto(struct socket *s,
|
||||
const void *buf,
|
||||
size_t lim,
|
||||
struct sockaddr *sa,
|
||||
size_t salen);
|
||||
static int udp_socket_bind(struct socket *s, struct sockaddr *sa, size_t len);
|
||||
static int udp_socket_setsockopt(struct socket *s, int optname, void *optval, size_t optlen);
|
||||
|
||||
static struct sockops udp_socket_ops = {
|
||||
.open = udp_socket_open,
|
||||
.close = udp_socket_close,
|
||||
|
||||
.sendto = udp_socket_sendto,
|
||||
.recvfrom = udp_socket_recvfrom,
|
||||
|
||||
.bind = udp_socket_bind,
|
||||
.setsockopt = udp_socket_setsockopt,
|
||||
};
|
||||
static struct socket_class udp_socket_class = {
|
||||
.name = "udp",
|
||||
.ops = &udp_socket_ops,
|
||||
.domain = AF_INET,
|
||||
.type = SOCK_DGRAM,
|
||||
.supports = udp_class_supports,
|
||||
};
|
||||
|
||||
// Accept any packet (for receiving socket)
|
||||
#define UDP_SOCKET_ANY (1 << 0)
|
||||
// Accept port match (when calling recvfrom)
|
||||
@@ -54,19 +93,57 @@ struct udp_socket *udp_socket_create(void) {
|
||||
return sock;
|
||||
}
|
||||
|
||||
int udp_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto) {
|
||||
struct udp_socket *sock = udp_socket_create();
|
||||
_assert(sock);
|
||||
void udp_handle_frame(struct packet *p, struct eth_frame *eth, struct inet_frame *ip, void *data, size_t len) {
|
||||
struct udp_frame *udp;
|
||||
|
||||
fd->socket.domain = AF_INET;
|
||||
fd->socket.type = SOCK_DGRAM;
|
||||
fd->socket.sock = sock;
|
||||
if (len < sizeof(struct udp_frame)) {
|
||||
return;
|
||||
}
|
||||
|
||||
udp = data;
|
||||
|
||||
uint16_t dpt = ntohs(udp->dst_port);
|
||||
|
||||
if (dpt >= UDP_BIND_START && (dpt - UDP_BIND_START) < UDP_BIND_COUNT) {
|
||||
// Check if it's a packet for one of "listening" sockets
|
||||
struct udp_socket *sock = udp_ports[dpt - UDP_BIND_START];
|
||||
|
||||
if (sock) {
|
||||
// Add "pending" packet for this socket
|
||||
packet_ref(p);
|
||||
packet_queue_push(&sock->pending, p);
|
||||
|
||||
if (sock->flags & UDP_SOCKET_PENDING) {
|
||||
sock->flags &= ~UDP_SOCKET_PENDING;
|
||||
sched_queue(sock->owner);
|
||||
}
|
||||
} else {
|
||||
kdebug("Packet is destined to unbound port: %u\n", dpt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static __init void udp_class_register(void) {
|
||||
socket_class_register(&udp_socket_class);
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Socket impl.
|
||||
|
||||
static int udp_socket_open(struct socket *sock) {
|
||||
struct udp_socket *usock = udp_socket_create();
|
||||
_assert(usock);
|
||||
sock->data = usock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t udp_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, size_t lim, struct sockaddr *sa, size_t *salen) {
|
||||
struct udp_socket *sock = fd->socket.sock;
|
||||
static ssize_t udp_socket_recvfrom(struct socket *s,
|
||||
void *buf,
|
||||
size_t lim,
|
||||
struct sockaddr *sa,
|
||||
size_t *salen) {
|
||||
struct udp_socket *sock = s->data;
|
||||
_assert(sock);
|
||||
struct thread *t = thread_self;
|
||||
struct packet *p;
|
||||
@@ -102,8 +179,12 @@ ssize_t udp_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, si
|
||||
return p_size;
|
||||
}
|
||||
|
||||
ssize_t udp_socket_send(struct vfs_ioctx *ioctx, struct ofile *fd, const void *buf, size_t lim, struct sockaddr *sa, size_t salen) {
|
||||
struct udp_socket *sock = fd->socket.sock;
|
||||
static ssize_t udp_socket_sendto(struct socket *s,
|
||||
const void *buf,
|
||||
size_t lim,
|
||||
struct sockaddr *sa,
|
||||
size_t salen) {
|
||||
struct udp_socket *sock = s->data;
|
||||
struct sockaddr_in *sin;
|
||||
int res;
|
||||
uint16_t port;
|
||||
@@ -148,8 +229,8 @@ ssize_t udp_socket_send(struct vfs_ioctx *ioctx, struct ofile *fd, const void *b
|
||||
return lim;
|
||||
}
|
||||
|
||||
int udp_socket_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len) {
|
||||
struct udp_socket *sock = fd->socket.sock;
|
||||
static int udp_socket_bind(struct socket *s, struct sockaddr *sa, size_t len) {
|
||||
struct udp_socket *sock = s->data;
|
||||
struct sockaddr_in *sin;
|
||||
_assert(sa);
|
||||
_assert(sock);
|
||||
@@ -172,8 +253,8 @@ int udp_socket_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udp_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen) {
|
||||
struct udp_socket *sock = fd->socket.sock;
|
||||
static int udp_socket_setsockopt(struct socket *s, int optname, void *optval, size_t optlen) {
|
||||
struct udp_socket *sock = s->data;
|
||||
_assert(sock);
|
||||
|
||||
switch (optname) {
|
||||
@@ -188,47 +269,16 @@ int udp_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void
|
||||
}
|
||||
}
|
||||
|
||||
void udp_socket_close(struct vfs_ioctx *ioctx, struct ofile *fd) {
|
||||
struct udp_socket *sock = fd->socket.sock;
|
||||
static void udp_socket_close(struct socket *s) {
|
||||
struct udp_socket *sock = s->data;
|
||||
_assert(sock);
|
||||
|
||||
sock->flags &= ~UDP_SOCKET_ANY;
|
||||
|
||||
if (sock->flags & UDP_SOCKET_ANY) {
|
||||
udp_ports[sock->recv_port - UDP_BIND_START] = NULL;
|
||||
}
|
||||
|
||||
sock->flags &= ~UDP_SOCKET_ANY;
|
||||
|
||||
kfree(sock);
|
||||
fd->socket.sock = NULL;
|
||||
fd->flags &= ~OF_SOCKET;
|
||||
}
|
||||
|
||||
void udp_handle_frame(struct packet *p, struct eth_frame *eth, struct inet_frame *ip, void *data, size_t len) {
|
||||
struct udp_frame *udp;
|
||||
|
||||
if (len < sizeof(struct udp_frame)) {
|
||||
return;
|
||||
}
|
||||
|
||||
udp = data;
|
||||
|
||||
uint16_t dpt = ntohs(udp->dst_port);
|
||||
|
||||
if (dpt >= UDP_BIND_START && (dpt - UDP_BIND_START) < UDP_BIND_COUNT) {
|
||||
// Check if it's a packet for one of "listening" sockets
|
||||
struct udp_socket *sock = udp_ports[dpt - UDP_BIND_START];
|
||||
|
||||
if (sock) {
|
||||
// Add "pending" packet for this socket
|
||||
packet_ref(p);
|
||||
packet_queue_push(&sock->pending, p);
|
||||
|
||||
if (sock->flags & UDP_SOCKET_PENDING) {
|
||||
sock->flags &= ~UDP_SOCKET_PENDING;
|
||||
sched_queue(sock->owner);
|
||||
}
|
||||
} else {
|
||||
kdebug("Packet is destined to unbound port: %u\n", dpt);
|
||||
}
|
||||
}
|
||||
s->data = NULL;
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,9 +7,9 @@
|
||||
#include "sys/thread.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/string.h"
|
||||
#include "net/socket.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/heap.h"
|
||||
#include "net/net.h"
|
||||
|
||||
ssize_t sys_read(int fd, void *data, size_t lim) {
|
||||
struct thread *thr = thread_self;
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@
|
||||
#include "sys/sys_net.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/thread.h"
|
||||
#include "net/socket.h"
|
||||
#include "user/errno.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/heap.h"
|
||||
@@ -40,7 +41,7 @@ int sys_socket(int domain, int type, int protocol) {
|
||||
struct ofile *ofile = kmalloc(sizeof(struct ofile));
|
||||
_assert(ofile);
|
||||
|
||||
if ((res = net_socket_open(&thr->ioctx, ofile, domain, type, protocol)) != 0) {
|
||||
if ((res = net_open(&thr->ioctx, ofile, domain, type, protocol)) != 0) {
|
||||
kfree(ofile);
|
||||
return res;
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,6 +5,7 @@
|
||||
#include "arch/amd64/mm/map.h"
|
||||
#include "arch/amd64/cpu.h"
|
||||
#include "sys/binfmt_elf.h"
|
||||
#include "net/socket.h"
|
||||
#include "fs/ofile.h"
|
||||
#include "sys/sys_proc.h"
|
||||
#include "sys/vmalloc.h"
|
||||
@@ -18,7 +19,6 @@
|
||||
#include "sys/sched.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/heap.h"
|
||||
#include "net/net.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
struct sys_fork_frame {
|
||||
|
||||
Reference in New Issue
Block a user