add system calls to map the user-level socket library to LwIP sockets

This commit is contained in:
Stefan Lankes 2011-08-10 08:15:53 +02:00
parent 8e317a5a20
commit 5d9f361174
4 changed files with 156 additions and 5 deletions

View file

@ -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;

View file

@ -24,6 +24,27 @@
#include <metalsvm/errno.h>
#include <metalsvm/spinlock.h>
#include <metalsvm/time.h>
#include <lwip/opt.h>
#if defined(CONFIG_LWIP) && LWIP_SOCKET
#include <lwip/mem.h>
#include <lwip/raw.h>
#include <lwip/icmp.h>
#include <lwip/netif.h>
#include <lwip/sys.h>
#include <lwip/timers.h>
#include <lwip/inet_chksum.h>
#include <lwip/ip.h>
#include <lwip/sockets.h>
#include <lwip/inet.h>
#include <lwip/err.h>
/*
* 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;

View file

@ -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);

View file

@ -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;
}