171 lines
4.4 KiB
C
171 lines
4.4 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, uint16_t port, 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;
|
|
|
|
uint16_t port_be = short_be(port);
|
|
struct pico_ip4 inaddr_any = {0};
|
|
pico_socket_bind(netsock->picosock, &inaddr_any, &port_be);
|
|
|
|
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;
|
|
}
|
|
|
|
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);
|
|
}
|