Files
my-os-project2/kernel/ipc/netsock/netsock.c

179 lines
4.6 KiB
C

#include <stdint.h>
#include <stddef.h>
#include "hal/hal.h"
#include "spinlock/spinlock.h"
#include "netsock.h"
#include "errors.h"
#include "pico_socket.h"
#include "dlmalloc/malloc.h"
#include "util/util.h"
#include "sysdefs/ipcnetsock.h"
#include "kprintf.h"
#include "proc/proc.h"
IpcNetSocks IPC_NETSOCKS;
void ipc_netsockinit(void) {
hal_memset(&IPC_NETSOCKS, 0, sizeof(IPC_NETSOCKS));
spinlock_init(&IPC_NETSOCKS.spinlock);
}
void ipc_netsock_event(uint16_t ev, struct pico_socket *sock1) {
IpcNetSock *netsock, *netsocktmp;
spinlock_acquire(&IPC_NETSOCKS.spinlock);
LL_FOREACH_SAFE(IPC_NETSOCKS.netsocks, netsock, netsocktmp) {
if (netsock->picosock == sock1)
break;
}
spinlock_release(&IPC_NETSOCKS.spinlock);
if (netsock == NULL) {
return;
}
spinlock_acquire(&netsock->spinlock);
/* if (ev & PICO_SOCK_EV_RD) { */
/* uint8_t *buf = dlmalloc(IPC_PIPE_MAX); */
/* int32_t len = 0; */
/* int32_t read; */
/* do { */
/* read = pico_socket_read(netsock->picosock, buf + len, IPC_PIPE_MAX - len); */
/* if (read > 0) { */
/* len += read; */
/* } */
/* } while(read > 0); */
/* ipc_pipewrite(netsock->datapipe, buf, len); */
/* dlfree(buf); */
/* } */
/* if (ev & PICO_SOCK_EV_WR) { */
/* uint8_t *buf = dlmalloc(IPC_PIPE_MAX); */
/* int32_t read = ipc_piperead(netsock->datapipe, buf, IPC_PIPE_MAX); */
/* if (read > 0) { */
/* pico_socket_write(netsock->picosock, buf, read); */
/* } */
/* dlfree(buf); */
/* } */
/* if (ev & PICO_SOCK_EV_FIN) { */
/* // normal close */
/* } */
/* if (ev & PICO_SOCK_EV_CLOSE) { */
/* pico_socket_shutdown(netsock->picosock, PICO_SHUT_WR); */
/* } */
rbuft_push(&netsock->eventbuffer, &ev);
spinlock_release(&netsock->spinlock);
}
IpcNetSock *ipc_netsockmake(uint16_t net, uint16_t proto, uint64_t pid) {
IpcNetSock *netsock = dlmalloc(sizeof(*netsock));
if (netsock == NULL) {
return NULL;
}
netsock->picosock = pico_socket_open(net, proto, &ipc_netsock_event);
if (netsock->picosock == NULL) {
goto err_sock_open;
}
spinlock_init(&netsock->spinlock);
netsock->datapipe = dlmalloc(sizeof(*netsock->datapipe));
ipc_pipeinit(netsock->datapipe, (uint64_t)-1);
uint8_t *eventbuffer = dlmalloc(sizeof(IpcNetSockEventBuffer) * IPC_NETSOCK_EVENTBUFFER_MAX);
rbuft_init(&netsock->eventbuffer, eventbuffer, sizeof(IpcNetSockEventBuffer), IPC_NETSOCK_EVENTBUFFER_MAX);
netsock->ownerpid = pid;
spinlock_acquire(&IPC_NETSOCKS.spinlock);
LL_APPEND(IPC_NETSOCKS.netsocks, netsock);
spinlock_release(&IPC_NETSOCKS.spinlock);
return netsock;
err_sock_open:
dlfree(netsock);
return NULL;
}
int32_t ipc_netsocklisten(IpcNetSock *netsock, size_t maxlisteners) {
spinlock_acquire(&netsock->spinlock);
int32_t r = pico_socket_listen(netsock->picosock, (int)maxlisteners);
spinlock_release(&netsock->spinlock);
return r == 0 ? E_OK : E_NETSOCKLISTEN;
}
int32_t ipc_netsockdelete_nolock(IpcNetSock *netsock) {
LL_REMOVE(IPC_NETSOCKS.netsocks, netsock);
spinlock_acquire(&netsock->spinlock);
pico_socket_del(netsock->picosock);
ipc_pipefree(netsock->datapipe);
dlfree(netsock->datapipe);
dlfree(netsock->eventbuffer.buffer);
spinlock_release(&netsock->spinlock);
dlfree(netsock);
return E_OK;
}
int32_t ipc_netsockdelete(IpcNetSock *netsock) {
spinlock_acquire(&IPC_NETSOCKS.spinlock);
LL_REMOVE(IPC_NETSOCKS.netsocks, netsock);
spinlock_release(&IPC_NETSOCKS.spinlock);
spinlock_acquire(&netsock->spinlock);
pico_socket_del(netsock->picosock);
ipc_pipefree(netsock->datapipe);
dlfree(netsock->datapipe);
dlfree(netsock->eventbuffer.buffer);
spinlock_release(&netsock->spinlock);
dlfree(netsock);
return E_OK;
}
int32_t ipc_netsockbindport(IpcNetSock *netsock, uint16_t port) {
uint16_t port_be = short_be(port);
struct pico_ip4 inaddr_any = {0};
spinlock_acquire(&netsock->spinlock);
int32_t r = pico_socket_bind(netsock->picosock, &inaddr_any, &port_be);
spinlock_release(&netsock->spinlock);
if (r != 0) {
return E_NETSOCKBIND;
}
return E_OK;
}
void ipc_netsock_cleanup_dangling(void) {
IpcNetSock *ns, *nstmp;
spinlock_acquire(&IPC_NETSOCKS.spinlock);
spinlock_acquire(&PROCS.spinlock);
LL_FOREACH_SAFE(IPC_NETSOCKS.netsocks, ns, nstmp) {
bool foundowner = false;
Proc *proc, *proctmp;
LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) {
if (ns->ownerpid == proc->pid) {
foundowner = true;
break;
}
}
if (!foundowner) {
ipc_netsockdelete_nolock(ns);
}
}
spinlock_release(&PROCS.spinlock);
spinlock_release(&IPC_NETSOCKS.spinlock);
}