diff --git a/kernel/init.c b/kernel/init.c index 444739f4..a29807ac 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -48,6 +48,7 @@ void echo_init(void); void ping_init(void); +void netio_init(void); int test_init(void); /* @@ -158,6 +159,7 @@ int network_init(void) // start echo and ping server echo_init(); //ping_init(); + netio_init(); #endif return 0; diff --git a/kernel/syscall.c b/kernel/syscall.c index d3eba333..6eaecd28 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -24,6 +24,27 @@ #include #include #include +#include + +#if defined(CONFIG_LWIP) && LWIP_SOCKET +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * We set the a bit LWIP_FD_BIT to determine, + * if the descriptor belongs to LwIP or MetalSVM. + */ +#define LWIP_FD_BIT (1 << 28) +#endif static int sys_write(int fildes, const char *buf, size_t len) { @@ -85,15 +106,33 @@ int syscall_handler(uint32_t sys_nr, ...) const char* buf = va_arg(vl, const char*); size_t len = va_arg(vl, size_t); +#if defined(CONFIG_LWIP) && LWIP_SOCKET + if (fildes & LWIP_FD_BIT) { + ret = lwip_write(fildes & ~LWIP_FD_BIT, buf, len); + if (ret < 0) + ret = -errno; + } else ret = sys_write(fildes, buf, len); +#else ret = sys_write(fildes, buf, len); +#endif break; } case __NR_open: ret = 1; break; - case __NR_close: + case __NR_close: { +#if defined(CONFIG_LWIP) && LWIP_SOCKET + int s = va_arg(vl, int); + if (s & LWIP_FD_BIT) { + ret = lwip_close(s & ~LWIP_FD_BIT); + if (ret < 0) + ret = -errno; + } else ret = 0; +#else ret = 0; +#endif break; + } case __NR_sbrk: { int incr = va_arg(vl, int); @@ -127,6 +166,109 @@ int syscall_handler(uint32_t sys_nr, ...) ret = sys_times(buffer, clock); break; } +#if defined(CONFIG_LWIP) && LWIP_SOCKET + case __NR_read: { + int s = va_arg(vl, int); + void* mem = va_arg(vl, void*); + size_t len = va_arg(vl, size_t); + + if (!(s & LWIP_FD_BIT)) { + ret = -ENOTSOCK; + break; + } + + ret = lwip_read(s & ~LWIP_FD_BIT, mem, len); + if (ret < 0) + ret = -errno; + break; + } + case __NR_closesocket: { + int s = va_arg(vl, int); + + if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) { + ret = -ENOTSOCK; + break; + } + + ret = lwip_close(s & ~LWIP_FD_BIT); + if (ret < 0) + ret = -errno; + break; + } + case __NR_socket: { + int domain = va_arg(vl, int); + int type = va_arg(vl, int); + int protocol = va_arg(vl, int); + + ret = lwip_socket(domain, type, protocol); + if (ret >= 0) + ret |= LWIP_FD_BIT; + else + ret = -errno; + break; + } + case __NR_connect: { + int s = va_arg(vl, int); + const struct sockaddr* name = va_arg(vl, const struct sockaddr*); + socklen_t namelen = va_arg(vl, socklen_t); + + if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) { + ret = -ENOTSOCK; + break; + } + + ret = lwip_connect(s & ~LWIP_FD_BIT, name, namelen); + if (ret < 0) + ret = -errno; + break; + } + case __NR_bind: { + int s = va_arg(vl, int); + const struct sockaddr* name = va_arg(vl, const struct sockaddr*); + socklen_t namelen = va_arg(vl, socklen_t); + + if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) { + ret = -ENOTSOCK; + break; + } + + ret = lwip_bind(s & ~LWIP_FD_BIT, name, namelen); + if (ret < 0) + ret = -errno; + break; + } + case __NR_listen:{ + int s = va_arg(vl, int); + int backlog = va_arg(vl, int); + + if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) { + ret = -ENOTSOCK; + break; + } + + ret = lwip_listen(s & ~LWIP_FD_BIT, backlog); + if (ret < 0) + ret = -errno; + break; + } + case __NR_accept: { + int s = va_arg(vl, int); + struct sockaddr* addr = va_arg(vl, struct sockaddr*); + socklen_t* addrlen = va_arg(vl, socklen_t*); + + if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) { + ret = -ENOTSOCK; + break; + } + + ret = lwip_accept(s & ~LWIP_FD_BIT, addr, addrlen); + if (ret >= 0) + ret |= LWIP_FD_BIT; + else + ret = -errno; + break; + } +#endif default: kputs("invalid system call\n"); ret = -ENOSYS; diff --git a/kernel/tasks.c b/kernel/tasks.c index 5813e50a..c941e57e 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -47,8 +47,8 @@ * A task's id will be its position in this array. */ static task_t task_table[MAX_TASKS] = { \ - [0] = {0, TASK_IDLE, 0, 0, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0}, \ - [1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, 0, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0}}; + [0] = {0, TASK_IDLE, 0, 0, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}, \ + [1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, 0, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}}; static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT; DEFINE_PER_CORE(task_t*, current_task, task_table+0); @@ -243,6 +243,7 @@ static int create_task(tid_t* id, internal_entry_point_t ep, void* arg) task_table[i].start_heap = 0; task_table[i].end_heap = 0; + task_table[i].lwip_err = 0; task_table[i].start_tick = get_clock_tick(); break; } @@ -308,6 +309,7 @@ int sys_fork(void) task_table[i].start_tick = get_clock_tick(); task_table[i].start_heap = 0; task_table[i].end_heap = 0; + task_table[i].lwip_err = 0; ret = arch_fork(task_table+i); diff --git a/kernel/tests.c b/kernel/tests.c index 24073e4e..d29e2853 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -253,6 +253,8 @@ void* client_task(void* e) int test_init(void) { char* argv[] = {"/bin/tests", NULL}; + char* server_argv[] = {"/bin/server", "6789", NULL}; + char* client_argv[] = {"/bin/client", "127.0.0.1", "6789", NULL}; sem_init(&producing, 1); sem_init(&consuming, 0); @@ -272,14 +274,17 @@ int test_init(void) #endif create_kernel_task(NULL, foo, "Hello from foo1"); - create_kernel_task(NULL, join_test, NULL); + //create_kernel_task(NULL, join_test, NULL); //create_kernel_task(NULL, producer, NULL); //create_kernel_task(NULL, consumer, NULL); //create_kernel_task(NULL, mail_ping, NULL); - //create_user_task(NULL, "/bin/hello", argv); + create_user_task(NULL, "/bin/hello", argv); create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/jacobi", argv); + create_user_task(NULL, "/bin/server", server_argv); + //sleep(5); + //create_user_task(NULL, "/bin/client", client_argv); return 0; }