mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-28 13:18:22 +00:00
sockets: initial impl
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
#include <kernel/syscalls.h>
|
||||
#include <kernel/socket.h>
|
||||
#include <kernel/fd.h>
|
||||
#include <arch/cls.h>
|
||||
#include <arch/spinlock.h>
|
||||
|
||||
extern fs_t kerneltmpfs;
|
||||
|
||||
syscallret syscall_accept(int sockfd, void* addr, size_t* addrlen){
|
||||
|
||||
syscallret retv;
|
||||
retv.ret = -1;
|
||||
|
||||
if(addr > USER_SPACE_END){
|
||||
retv.errno = EFAULT;
|
||||
return retv;
|
||||
}
|
||||
|
||||
proc_t* proc = arch_getcls()->thread->proc;
|
||||
|
||||
// access sockfd
|
||||
|
||||
fd_t* fd;
|
||||
|
||||
int err = fd_access(&proc->fdtable, &fd, sockfd);
|
||||
|
||||
if(err){
|
||||
retv.errno = err;
|
||||
return retv;
|
||||
}
|
||||
|
||||
if(GETTYPE(fd->mode) != TYPE_SOCKET){
|
||||
retv.errno = ENOTSOCK;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
socket_t* listenersock = fd->node->objdata;
|
||||
|
||||
// create new fd
|
||||
|
||||
fd_t* connfd = NULL;
|
||||
int connifd;
|
||||
|
||||
retv.errno = fd_alloc(&proc->fdtable, &connfd, &connifd, 0);
|
||||
|
||||
if(retv.errno)
|
||||
goto _fail;
|
||||
|
||||
connfd->node = vfs_newnode("SOCKET", &kerneltmpfs, NULL);
|
||||
if(!connfd->node){
|
||||
retv.errno = ENOMEM;
|
||||
goto _fail;
|
||||
}
|
||||
connfd->mode = 0777 | MAKETYPE(TYPE_SOCKET);
|
||||
connfd->node->refcount = 1;
|
||||
connfd->node->st.st_mode = connfd->mode;
|
||||
|
||||
// create socket for new fd
|
||||
|
||||
socket_t* connsock;
|
||||
|
||||
retv.errno = socket_new(&connsock, listenersock->family, listenersock->type, listenersock->protocol);
|
||||
|
||||
// get peer
|
||||
|
||||
socket_t* peer;
|
||||
|
||||
retv.errno = socket_accept(&peer, listenersock, addr, addrlen);
|
||||
|
||||
if(retv.errno)
|
||||
goto _fail;
|
||||
|
||||
connsock->peer = peer;
|
||||
connsock->state = SOCKET_STATE_CONNECTED;
|
||||
|
||||
spinlock_acquire(&peer->lock);
|
||||
|
||||
peer->peer = connsock;
|
||||
|
||||
event_signal(&peer->acceptevent, true);
|
||||
|
||||
spinlock_release(&peer->lock);
|
||||
|
||||
fd_release(fd);
|
||||
|
||||
retv.ret = connifd;
|
||||
|
||||
memcpy(addr, &peer->addr_un, peer->addrlen);
|
||||
*addrlen = peer->addrlen;
|
||||
|
||||
return retv;
|
||||
|
||||
_fail:
|
||||
|
||||
fd_release(fd);
|
||||
|
||||
if(connfd){
|
||||
fd_release(connfd);
|
||||
fd_free(&proc->fdtable, connifd);
|
||||
}
|
||||
|
||||
return retv;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <kernel/syscalls.h>
|
||||
#include <kernel/fd.h>
|
||||
#include <arch/cls.h>
|
||||
#include <errno.h>
|
||||
#include <kernel/vmm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <kernel/socket.h>
|
||||
|
||||
syscallret syscall_bind(int sockfd, void* addr, size_t addrlen){
|
||||
|
||||
syscallret retv;
|
||||
retv.ret = -1;
|
||||
|
||||
if(addr > USER_SPACE_END){
|
||||
retv.errno = EFAULT;
|
||||
return retv;
|
||||
}
|
||||
|
||||
proc_t* proc = arch_getcls()->thread->proc;
|
||||
|
||||
fd_t* fd;
|
||||
|
||||
int err = fd_access(&proc->fdtable, &fd, sockfd);
|
||||
|
||||
if(err){
|
||||
retv.errno = err;
|
||||
return retv;
|
||||
}
|
||||
|
||||
|
||||
if(GETTYPE(fd->mode) != TYPE_SOCKET){
|
||||
retv.errno = ENOTSOCK;
|
||||
goto _ret;
|
||||
}
|
||||
|
||||
retv.errno = socket_bind(fd->node->objdata, addr, addrlen);
|
||||
|
||||
_ret:
|
||||
|
||||
fd_release(fd);
|
||||
|
||||
return retv;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <kernel/syscalls.h>
|
||||
#include <kernel/fd.h>
|
||||
#include <arch/cls.h>
|
||||
#include <errno.h>
|
||||
#include <kernel/vmm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <kernel/socket.h>
|
||||
|
||||
syscallret syscall_connect(int sockfd, void* addr, size_t addrlen){
|
||||
|
||||
syscallret retv;
|
||||
retv.ret = -1;
|
||||
|
||||
if(addr > USER_SPACE_END){
|
||||
retv.errno = EFAULT;
|
||||
return retv;
|
||||
}
|
||||
|
||||
proc_t* proc = arch_getcls()->thread->proc;
|
||||
|
||||
fd_t* fd;
|
||||
|
||||
int err = fd_access(&proc->fdtable, &fd, sockfd);
|
||||
|
||||
if(err){
|
||||
retv.errno = err;
|
||||
return retv;
|
||||
}
|
||||
|
||||
|
||||
if(GETTYPE(fd->mode) != TYPE_SOCKET){
|
||||
retv.errno = ENOTSOCK;
|
||||
goto _ret;
|
||||
}
|
||||
|
||||
retv.errno = socket_connect(fd->node->objdata, addr, addrlen);
|
||||
|
||||
_ret:
|
||||
|
||||
fd_release(fd);
|
||||
|
||||
return retv;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <kernel/syscalls.h>
|
||||
#include <kernel/fd.h>
|
||||
#include <arch/cls.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <kernel/socket.h>
|
||||
|
||||
syscallret syscall_listen(int sockfd, int backlog){
|
||||
|
||||
syscallret retv;
|
||||
retv.ret = -1;
|
||||
|
||||
proc_t* proc = arch_getcls()->thread->proc;
|
||||
|
||||
fd_t* fd;
|
||||
|
||||
int err = fd_access(&proc->fdtable, &fd, sockfd);
|
||||
|
||||
if(err){
|
||||
retv.errno = err;
|
||||
return retv;
|
||||
}
|
||||
|
||||
|
||||
if(GETTYPE(fd->mode) != TYPE_SOCKET){
|
||||
retv.errno = ENOTSOCK;
|
||||
goto _ret;
|
||||
}
|
||||
|
||||
retv.errno = socket_listen(fd->node->objdata, backlog);
|
||||
|
||||
_ret:
|
||||
|
||||
fd_release(fd);
|
||||
|
||||
return retv;
|
||||
|
||||
}
|
||||
@@ -95,6 +95,11 @@ syscallret syscall_openat(int dirfd, const char* pathname, int flags, mode_t mod
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if(GETTYPE(file->st.st_mode) == TYPE_SOCKET){
|
||||
retv.errno = ENXIO;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
|
||||
fd->node = file;
|
||||
fd->mode = file->st.st_mode;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include <kernel/syscalls.h>
|
||||
#include <kernel/socket.h>
|
||||
#include <kernel/fd.h>
|
||||
#include <arch/cls.h>
|
||||
|
||||
extern fs_t kerneltmpfs;
|
||||
|
||||
syscallret syscall_socket(int domain, int type, int protocol){
|
||||
|
||||
syscallret retv;
|
||||
retv.ret = -1;
|
||||
|
||||
proc_t* proc = arch_getcls()->thread->proc;
|
||||
|
||||
fd_t* fd = NULL;
|
||||
int ifd;
|
||||
|
||||
retv.errno = fd_alloc(&proc->fdtable, &fd, &ifd, 0);
|
||||
|
||||
if(retv.errno)
|
||||
return retv;
|
||||
|
||||
fd->node = vfs_newnode("SOCKET", &kerneltmpfs, NULL);
|
||||
if(!fd->node){
|
||||
retv.errno = ENOMEM;
|
||||
goto _fail;
|
||||
}
|
||||
fd->mode = 0777 | MAKETYPE(TYPE_SOCKET);
|
||||
fd->node->refcount = 1;
|
||||
fd->node->st.st_mode = fd->mode;
|
||||
|
||||
socket_t* sock;
|
||||
|
||||
retv.errno = socket_new(&sock, domain, type, protocol);
|
||||
|
||||
if(retv.errno)
|
||||
goto _fail;
|
||||
|
||||
fd->node->objdata = sock;
|
||||
|
||||
fd_release(fd);
|
||||
|
||||
retv.ret = ifd;
|
||||
return retv;
|
||||
|
||||
_fail:
|
||||
|
||||
if(fd){
|
||||
fd_release(fd);
|
||||
fd_free(&proc->fdtable, ifd);
|
||||
}
|
||||
|
||||
return retv;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user