From: Tomas Hruby Date: Fri, 24 Feb 2012 18:02:32 +0000 (+0000) Subject: LWIP,NETSOCK - lwip uses asynchronous protocol X-Git-Tag: v3.2.1~686 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zpipe.c?a=commitdiff_plain;h=fb31513b002258acd239f8f88592ae4c08b537a5;p=minix.git LWIP,NETSOCK - lwip uses asynchronous protocol - libnetsock - internal implementation of a socket on the lwip server side. it encapsulates the asynchronous protocol - lwip server - uses libnetsock to work with the asynchronous protocol --- diff --git a/etc/usr/rc b/etc/usr/rc index 71042a13c..ed154cbd6 100644 --- a/etc/usr/rc +++ b/etc/usr/rc @@ -138,7 +138,7 @@ start) done if [ X`/bin/sysenv lwip` = Xyes ] then - up lwip -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE + up lwip -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE_A else up inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE fi diff --git a/include/Makefile.minix.inc b/include/Makefile.minix.inc index a9bd5d6e4..03d3cc2e1 100644 --- a/include/Makefile.minix.inc +++ b/include/Makefile.minix.inc @@ -18,7 +18,8 @@ INCS+= minix/acpi.h minix/ansi.h minix/audio_fw.h minix/bitmap.h \ minix/sound.h minix/spin.h minix/sys_config.h minix/sysinfo.h \ minix/syslib.h minix/sysutil.h minix/timers.h minix/type.h \ minix/tty.h minix/u64.h minix/usb.h minix/usb_ch9.h minix/vm.h \ - minix/vfsif.h minix/vtreefs.h minix/libminixfs.h + minix/vfsif.h minix/vtreefs.h minix/libminixfs.h \ + minix/netsock.h INCS+= net/gen/arp_io.h net/gen/dhcp.h net/gen/ether.h \ net/gen/eth_hdr.h net/gen/eth_io.h net/gen/icmp.h \ diff --git a/servers/lwip/socket.h b/include/minix/netsock.h similarity index 76% rename from servers/lwip/socket.h rename to include/minix/netsock.h index bddcd656a..c341cc2fd 100644 --- a/servers/lwip/socket.h +++ b/include/minix/netsock.h @@ -1,11 +1,16 @@ -#ifndef __LWIP_SERVER_SOCKET_H__ -#define __LWIP_SERVER_SOCKET_H__ +#ifndef __NET_SERVER_SOCKET_H__ +#define __NET_SERVER_SOCKET_H__ + +#include #include #include -#include "inet_config.h" -#include "proto.h" +/* + * User can set this variable to make the debugging output differ between + * various users, e.g. "TCP" or "UDP" + */ +extern char * netsock_user_name; #define SOCK_TYPE_IP 0 #define SOCK_TYPE_TCP 1 @@ -15,14 +20,15 @@ struct socket; typedef void (* sock_op_t)(struct socket *, message *); +typedef void (* sock_op_io_t)(struct socket *, message *, int blk); typedef int (* sock_op_open_t)(struct socket *, message *); struct sock_ops { sock_op_open_t open; sock_op_t close; - sock_op_t read; - sock_op_t write; - sock_op_t ioctl; + sock_op_io_t read; + sock_op_io_t write; + sock_op_io_t ioctl; sock_op_t select; sock_op_t select_reply; }; @@ -33,8 +39,7 @@ struct recv_q { }; #define SOCK_FLG_OP_PENDING 0x1 -#define SOCK_FLG_OP_REVIVING 0x2 -#define SOCK_FLG_OP_SUSPENDED 0x4 /* set when processing a suspended op */ +#define SOCK_FLG_OP_IOCTL 0x10 #define SOCK_FLG_OP_LISTENING 0x100 /* tcp socket is in a listening mode */ #define SOCK_FLG_OP_CONNECTING 0x200 /* set when waiting for a connect */ #define SOCK_FLG_OP_READING 0x400 /* reading operation in progress */ @@ -45,7 +50,6 @@ struct recv_q { #define SOCK_FLG_SEL_WRITE 0x100000 #define SOCK_FLG_SEL_READ 0x200000 #define SOCK_FLG_SEL_ERROR 0x400000 -#define SOCK_FLG_SEL_CHECK 0x800000 /* select satisfied, go and check it */ #define sock_select_set(sock) ((sock)->flags & (SOCK_FLG_SEL_WRITE | \ SOCK_FLG_SEL_READ | SOCK_FLG_SEL_ERROR)) @@ -54,10 +58,9 @@ struct recv_q { #define sock_select_rw_set(sock) ((sock)->flags & (SOCK_FLG_SEL_READ | \ SOCK_FLG_SEL_WRITE)) #define sock_select_error_set(sock) ((sock)->flags & SOCK_FLG_SEL_ERROR) -#define sock_select_check_set(sock) ((sock)->flags & SOCK_FLG_SEL_CHECK) #define sock_clear_select(sock) do { \ (sock)->flags &= ~(SOCK_FLG_SEL_READ | SOCK_FLG_SEL_WRITE | \ - SOCK_FLG_SEL_ERROR | SOCK_FLG_SEL_CHECK); \ + SOCK_FLG_SEL_ERROR); \ } while (0) struct socket { @@ -71,6 +74,8 @@ struct socket { message mess; /* store the message which initiated the last operation on this socket in case we have to suspend the operation */ + void * shm; + size_t shm_size; endpoint_t select_ep; struct recv_q * recv_head; struct recv_q * recv_tail; @@ -78,9 +83,11 @@ struct socket { void * data; }; -extern struct sock_ops sock_udp_ops; -extern struct sock_ops sock_tcp_ops; -extern struct sock_ops sock_raw_ip_ops; +/* + * Each component needs to provide a method how to initially open a socket. + * The rest is handled byt the socket library. + */ +void socket_open(message * m); #define get_sock_num(x) ((long int) ((x) - socket)) #define is_valid_sock_num(x) (x < MAX_SOCKETS) @@ -101,8 +108,11 @@ struct socket * get_unused_sock(void); struct socket * get_nic_sock(unsigned dev); void send_reply(message * m, int status); +void send_reply_open(message * m, int status); +void send_reply_close(message * m, int status); void sock_reply(struct socket * sock, int status); -void sock_revive(struct socket * sock, int status); +void sock_reply_close(struct socket * sock, int status); +void sock_reply_select(struct socket * sock, unsigned selops); typedef void (* recv_data_free_fn)(void *); @@ -132,4 +142,9 @@ static inline void * debug_malloc(size_t s) void generic_op_select(struct socket * sock, message * m); void generic_op_select_reply(struct socket * sock, message * m); -#endif /* __LWIP_SERVER_SOCKET_H__ */ +int mq_enqueue(message * m); + +/* a function thr user has to provide to reply to the posix server */ +void posix_reply(endpoint_t ep, message * m); + +#endif /* __NET_SERVER_SOCKET_H__ */ diff --git a/lib/Makefile b/lib/Makefile index 83aa2db6b..93f203dbf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,7 +5,8 @@ SUBDIR= csu libcompat_minix libc libblockdriver libchardriver \ libl libhgfs libz libfetch libvtreefs libaudiodriver libmthread \ libexec libdevman libusb libminlib libasyn \ libddekit libminixfs libbdev libelf libminc libcrypt libterminfo \ - libcurses libvassert libutil libpuffs librefuse libbz2 libarchive libprop + libcurses libvassert libutil libpuffs librefuse libbz2 libarchive libprop \ + libnetsock SUBDIR+= ../external/public-domain/xz/lib diff --git a/lib/libnetsock/Makefile b/lib/libnetsock/Makefile new file mode 100644 index 000000000..4da9229bb --- /dev/null +++ b/lib/libnetsock/Makefile @@ -0,0 +1,9 @@ +LIB = netsock + +CPPFLAGS += -I${.CURDIR}/include/ -D_SYSTEM -D_MINIX +CPPFLAGS+= -I${.CURDIR}/../../lib/liblwip/include +CFLAGS += -Wall -Wextra -std=c99 + +SRCS += socket.c + +.include diff --git a/servers/lwip/socket.c b/lib/libnetsock/socket.c similarity index 54% rename from servers/lwip/socket.c rename to lib/libnetsock/socket.c index 75be4a275..96f0000e7 100644 --- a/servers/lwip/socket.c +++ b/lib/libnetsock/socket.c @@ -10,25 +10,37 @@ #include #include #include +#include #include #include -#include "inet_config.h" -#include "proto.h" -#include "socket.h" +char * netsock_user_name = NULL; +#define NETSOCK_USER_NAME (netsock_user_name ? netsock_user_name : "NETSOCK") + +#define debug_print(str, ...) printf("%s : %s:%d : " str "\n", \ + NETSOCK_USER_NAME, __func__, __LINE__, ##__VA_ARGS__) #if 0 -#define debug_sock_print(str, ...) printf("LWIP %s:%d : " str "\n", \ - __func__, __LINE__, ##__VA_ARGS__) +#define debug_sock_print(...) debug_print(__VA_ARGS__) #else -#define debug_sock_print(...) debug_print(__VA_ARGS__) +#define debug_sock_print(...) #endif +#if 0 +#define debug_sock_select_print(...) debug_print(__VA_ARGS__) +#else +#define debug_sock_select_print(...) debug_sock_print(__VA_ARGS__) +#endif + +#define netsock_panic(str, ...) panic("%s : " str, NETSOCK_USER_NAME, \ + ##__VA_ARGS__) +#define netsock_error(str, ...) printf("%s : " str, NETSOCK_USER_NAME, \ + ##__VA_ARGS__) + struct socket socket[MAX_SOCKETS]; -static int notified; #define recv_q_alloc() debug_malloc(sizeof(struct recv_q)) #define recv_q_free debug_free @@ -44,7 +56,7 @@ struct mq { static struct mq * mq_head, *mq_tail; -static int mq_enqueue(message * m) +int mq_enqueue(message * m) { struct mq * mq; @@ -84,7 +96,7 @@ __unused static struct mq * mq_dequeue_head(void) mq_head->prev = NULL; } else mq_head = mq_tail = NULL; - + debug_sock_print("socket %d\n", ret->m.DEVICE); return ret; @@ -121,8 +133,10 @@ static int mq_cancel(message * m) } } - mq_dequeue(mq); - mq_free(mq); + if (mq) { + mq_dequeue(mq); + mq_free(mq); + } return 1; } @@ -189,270 +203,141 @@ static void set_reply_msg(message * m, int status) m->REP_IO_GRANT= ref; } -void send_reply(message * m, int status) +void send_reply_type(message * m, int type, int status) { int result; - debug_sock_print("status %d", status); set_reply_msg(m, status); - - m->m_type = TASK_REPLY; + + m->m_type = type; result = send(m->m_source, m); if (result != OK) - panic("LWIP : unable to send (err %d)", result); + netsock_panic("unable to send (err %d)", result); } -void sock_revive(struct socket * sock, int status) +void send_reply(message * m, int status) +{ + debug_sock_print("status %d", status); + send_reply_type(m, DEV_REVIVE, status); +} + +void send_reply_open(message * m, int status) +{ + debug_sock_print("status %d", status); + send_reply_type(m, DEV_OPEN_REPL, status); +} + +void send_reply_close(message * m, int status) +{ + debug_sock_print("status %d", status); + send_reply_type(m, DEV_CLOSE_REPL, status); +} + +void sock_reply_select(struct socket * sock, unsigned selops) { int result; + message msg; - assert(!(sock->flags & SOCK_FLG_OP_REVIVING)); - assert(sock->flags & (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_SUSPENDED)); + debug_sock_select_print("selops %d", selops); - if (notified) { - debug_sock_print("already notified"); - return; - } - else { - assert(sock->mess.m_type != DEV_REVIVE); - notified = 1; - } - - debug_sock_print("socket num %ld, status %d", - get_sock_num(sock), status); - - sock->mess.m_type = DEV_REVIVE; - set_reply_msg(&sock->mess, status); - - result = notify(sock->mess.m_source); - if (result != OK) - panic("LWIP : unable to notify (err %d)", result); + msg.m_type = DEV_SEL_REPL1; + msg.DEV_MINOR = get_sock_num(sock); + msg.DEV_SEL_OPS = selops; - sock->flags |= SOCK_FLG_OP_REVIVING; + result = send(sock->select_ep, &msg); + if (result != OK) + netsock_panic("unable to send (err %d)", result); } void sock_select_notify(struct socket * sock) { int result; + message msg; - debug_sock_print("socket num %ld", get_sock_num(sock)); + debug_sock_select_print("socket num %ld", get_sock_num(sock)); assert(sock->select_ep != NONE); - sock->flags |= SOCK_FLG_SEL_CHECK; - if (notified) { - debug_sock_print("already notified"); + msg.DEV_SEL_OPS = 0; + sock->ops->select_reply(sock, &msg); + if (msg.DEV_SEL_OPS == 0) { + debug_sock_select_print("called from %p sflags 0x%x TXsz %d RXsz %d\n", + __builtin_return_address(0), sock->flags, + sock->buf_size, sock->recv_data_size); return; } - else - notified = 1; - - result = notify(sock->select_ep); + + msg.m_type = DEV_SEL_REPL2; + msg.DEV_MINOR = get_sock_num(sock); + + debug_sock_select_print("socket num %d select result 0x%x sent", + msg.DEV_MINOR, msg.DEV_SEL_OPS); + result = send(sock->select_ep, &msg); if (result != OK) - panic("LWIP : unable to notify (err %d)", result); -} + netsock_panic("unable to send (err %d)", result); -void sock_reply(struct socket * sock, int status) -{ - debug_sock_print("socket num %ld status %d type %d", - get_sock_num(sock), status, sock->mess.m_type); - /* - * If the status is SUSPEND send the - * message only if this operation wasn't - * suspended already, e.g. by enqueing the - * message when the socket was busy - * because of another pending message - * - * If there is a pending operation or we a reprocessing a suspended - * operation, revive. - * - * Otherwise send a message straightaway - */ - if (status == SUSPEND) { - if (sock->flags & SOCK_FLG_OP_SUSPENDED) { - debug_sock_print("suspended before"); - sock->flags &= ~SOCK_FLG_OP_SUSPENDED; - return; - } - message m = sock->mess; - debug_sock_print("SUSPEND"); - send_reply(&m, status); - } else if (sock->flags & (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_SUSPENDED)) { - sock_revive(sock, status); - /* - * From now on, we process suspended calls as any other. The - * status is set and will be collected - */ - sock->flags &= ~SOCK_FLG_OP_SUSPENDED; - } else - send_reply(&sock->mess, status); + sock_clear_select(sock); + sock->select_ep = NONE; } -struct socket * get_unused_sock(void) +static void sock_reply_type(struct socket * sock, int type, int status) { - int i; + sock->mess.m_type = type; - for (i = SOCK_TYPES + MAX_DEVS; i < MAX_SOCKETS; i++) { - if (socket[i].ops == NULL) { - /* clear it all */ - memset(&socket[i], 0, sizeof(struct socket)); - return &socket[i]; - } - } - - return NULL; + send_reply_type(&sock->mess, type, status); } -struct socket * get_nic_sock(unsigned dev) +void sock_reply_close(struct socket * sock, int status) { - if (dev < MAX_DEVS) - return &socket[dev + SOCK_TYPES]; - else - return NULL; + debug_sock_print("sock %ld status %d", get_sock_num(sock), status); + sock_reply_type(sock, DEV_CLOSE_REPL, status); } -static void socket_open(message * m) +void sock_reply(struct socket * sock, int status) { - struct sock_ops * ops; - struct socket * sock; - int ret = OK; - - switch (m->DEVICE) { - case SOCK_TYPE_TCP: - ops = &sock_tcp_ops; - break; - case SOCK_TYPE_UDP: - ops = &sock_udp_ops; - break; - case SOCK_TYPE_IP: - ops = &sock_raw_ip_ops; - break; - default: - if (m->DEVICE - SOCK_TYPES < MAX_DEVS) { - m->DEVICE -= SOCK_TYPES; - nic_open(m); - return; - } - printf("LWIP unknown socket type %d\n", m->DEVICE); - send_reply(m, EINVAL); - return; - } - - sock = get_unused_sock(); - if (!sock) { - printf("LWIP : no free socket\n"); - send_reply(m, EAGAIN); - return; - } - - sock->ops = ops; - sock->select_ep = NONE; - sock->recv_data_size = 0; - - if (sock->ops && sock->ops->open) - ret = sock->ops->open(sock, m); - - if (ret == OK) { - debug_sock_print("new socket %ld", get_sock_num(sock)); - send_reply(m, get_sock_num(sock)); - } else { - debug_sock_print("failed %d", ret); - send_reply(m, ret); - } + debug_sock_print("sock %ld status %d", get_sock_num(sock), status); + sock_reply_type(sock, DEV_REVIVE, status); } -static void do_status(message * m) +struct socket * get_unused_sock(void) { int i; - debug_sock_print("called"); - - notified = 0; - - for (i = 0; i < MAX_SOCKETS; i++) { - struct socket * sock = &socket[i]; - if (!sock->ops) { - continue; - } - if (sock->flags & (SOCK_FLG_OP_REVIVING)) { - /* - * We send the reply and we are done with this request - */ - debug_sock_print("status %d ep %d sent sock %ld type %d", - sock->mess.REP_STATUS, - sock->mess.REP_ENDPT, - get_sock_num(sock), - sock->mess.m_type); - send(m->m_source, &sock->mess); - /* - * Remove only the reviving flag, i.e. the status has - * been consumed. SOCK_FLG_OP_PENDING may stay set. For - * instance in case of a TCP write, the application is - * already notified while the process of sending is - * still going on - */ - sock->flags &= ~SOCK_FLG_OP_REVIVING; - return; - } - - /* - * We check select AFTER possible reviving an operation, - * otherwise the select will fail as the socket is still - * blocking - */ - if (sock_select_check_set(sock)) { - if (sock->ops && sock->ops->select_reply) { - message msg; - msg.m_type = DEV_IO_READY; - msg.DEV_MINOR = get_sock_num(sock); - msg.DEV_SEL_OPS = 0; - sock->ops->select_reply(sock, &msg); - if (msg.DEV_SEL_OPS) { - int result; - - debug_sock_print("socket num %d select " - "result 0x%x sent", - msg.DEV_MINOR, - msg.DEV_SEL_OPS); - result = send(sock->select_ep, &msg); - if (result != OK) - panic("LWIP : unable to send " - "(err %d)", result); - sock_clear_select(sock); - sock->select_ep = NONE; - return; - } - } + for (i = SOCK_TYPES + MAX_DEVS; i < MAX_SOCKETS; i++) { + if (socket[i].ops == NULL) { + /* clear it all */ + memset(&socket[i], 0, sizeof(struct socket)); + return &socket[i]; } } - debug_sock_print("no status"); - m->m_type = DEV_NO_STATUS; - send(m->m_source, m); + return NULL; } static void socket_request_socket(struct socket * sock, message * m) { + int blocking = m->FLAGS & FLG_OP_NONBLOCK ? 0 : 1; + switch (m->m_type) { case DEV_READ_S: if (sock && sock->ops && sock->ops->read) - sock->ops->read(sock, m); + sock->ops->read(sock, m, blocking); else send_reply(m, EINVAL); return; case DEV_WRITE_S: if (sock && sock->ops && sock->ops->write) - sock->ops->write(sock, m); + sock->ops->write(sock, m, blocking); else send_reply(m, EINVAL); return; case DEV_IOCTL_S: if (sock && sock->ops && sock->ops->ioctl) - sock->ops->ioctl(sock, m); + sock->ops->ioctl(sock, m, blocking); else send_reply(m, EINVAL); return; default: - panic("LWIP : cannot happen!"); + netsock_panic("cannot happen!"); } } @@ -460,6 +345,7 @@ void socket_request(message * m) { struct socket * sock; + debug_sock_print("request %d", m->m_type); switch (m->m_type) { case DEV_OPEN: socket_open(m); @@ -471,7 +357,7 @@ void socket_request(message * m) sock->mess = *m; sock->ops->close(sock, m); } else - send_reply(m, EINVAL); + send_reply_close(m, EINVAL); return; case DEV_READ_S: case DEV_WRITE_S: @@ -485,7 +371,7 @@ void socket_request(message * m) * If an operation is pending (blocking operation) or writing is * still going and we want to read, suspend the new operation */ - if ((sock->flags & (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_REVIVING)) | + if ((sock->flags & SOCK_FLG_OP_PENDING) || (m->m_type == DEV_READ_S && sock->flags & SOCK_FLG_OP_WRITING)) { char * o = "\0"; @@ -495,11 +381,9 @@ void socket_request(message * m) o = "WRITE"; else o = "non R/W op"; - debug_sock_print("socket %ld is busy by %s\n", - get_sock_num(sock), o); - if (mq_enqueue(m) == 0) { - send_reply(m, SUSPEND); - } else { + debug_sock_print("socket %ld is busy by %s flgs 0x%x\n", + get_sock_num(sock), o, sock->flags); + if (mq_enqueue(m) != 0) { debug_sock_print("Enqueuing suspended " "call failed"); send_reply(m, ENOMEM); @@ -511,6 +395,7 @@ void socket_request(message * m) return; case CANCEL: sock = get_sock(m->DEVICE); + printf("socket num %ld\n", get_sock_num(sock)); debug_sock_print("socket num %ld", get_sock_num(sock)); /* Cancel the last operation in the queue */ if (mq_cancel(m)) { @@ -522,37 +407,28 @@ void socket_request(message * m) sock->flags &= ~SOCK_FLG_OP_PENDING; send_reply(m, EINTR); return; - /* - * .. or return the status of the operation which was finished - * before canceled - */ - } else if (sock->flags & SOCK_FLG_OP_REVIVING) { - sock->flags &= ~SOCK_FLG_OP_REVIVING; - send_reply(m, sock->mess.REP_STATUS); } else - panic("LWIP : no operation to cancel"); + netsock_panic("no operation to cancel"); return; case DEV_SELECT: - /* + /* * Select is always executed immediately and is never suspended. * Although, it sets actions which must be monitored */ sock = get_sock(m->DEVICE); assert(sock->select_ep == NONE || sock->select_ep == m->m_source); - + if (sock && sock->ops && sock->ops->select) { + sock->select_ep = m->m_source; sock->ops->select(sock, m); - if (sock_select_set(sock)) - sock->select_ep = m->m_source; + if (!sock_select_set(sock)) + sock->select_ep = NONE; } else send_reply(m, EINVAL); return; - case DEV_STATUS: - do_status(m); - return; default: - printf("LWIP : unknown message from VFS, type %d\n", + netsock_error("unknown message from VFS, type %d\n", m->m_type); } send_reply(m, EGENERIC); @@ -567,13 +443,11 @@ void mq_process(void) while(mq) { struct mq * next = mq->next; - + sock = get_sock(mq->m.DEVICE); - if (!(sock->flags & - (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_REVIVING)) && + if (!(sock->flags & SOCK_FLG_OP_PENDING) && !(mq->m.m_type == DEV_READ_S && - sock->flags & SOCK_FLG_OP_WRITING)) { - sock->flags = SOCK_FLG_OP_SUSPENDED; + sock->flags & SOCK_FLG_OP_WRITING)) { debug_sock_print("resuming op on sock %ld\n", get_sock_num(sock)); sock->mess = mq->m; @@ -591,7 +465,7 @@ void generic_op_select(struct socket * sock, message * m) { int retsel = 0, sel; - debug_print("socket num %ld 0x%x", get_sock_num(sock), m->USER_ENDPT); + debug_sock_print("socket num %ld 0x%x", get_sock_num(sock), m->USER_ENDPT); sel = m->USER_ENDPT; @@ -604,7 +478,7 @@ void generic_op_select(struct socket * sock, message * m) sock->flags |= SOCK_FLG_SEL_WRITE; /* FIXME we do not monitor error */ } - send_reply(m, 0); + sock_reply_select(sock, 0); return; } @@ -619,26 +493,26 @@ void generic_op_select(struct socket * sock, message * m) retsel |= SEL_WR; /* FIXME SEL_ERR is ignored, we do not generate exceptions */ - send_reply(m, retsel); + sock_reply_select(sock, retsel); } void generic_op_select_reply(struct socket * sock, __unused message * m) { assert(sock->select_ep != NONE); - debug_print("socket num %ld", get_sock_num(sock)); + debug_sock_print("socket num %ld", get_sock_num(sock)); /* unused for generic packet socket, see generic_op_select() */ assert((sock->flags & (SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_ERROR)) == 0); - if (sock->flags & (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_REVIVING)) { - debug_print("WARNING socket still blocking!"); + if (sock->flags & SOCK_FLG_OP_PENDING) { + debug_sock_print("WARNING socket still blocking!"); return; } if (sock->flags & SOCK_FLG_SEL_READ && sock->recv_head) m->DEV_SEL_OPS |= SEL_RD; - - if (m->DEV_SEL_OPS) + + if (m->DEV_SEL_OPS) sock->flags &= ~(SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_READ | SOCK_FLG_SEL_ERROR); } diff --git a/servers/lwip/Makefile b/servers/lwip/Makefile index a188b417e..cc6912496 100644 --- a/servers/lwip/Makefile +++ b/servers/lwip/Makefile @@ -1,7 +1,6 @@ # Makefile for inet. PROG= lwip SRCS= lwip.c \ - socket.c \ driver.c \ udp.c \ tcp.c \ @@ -11,8 +10,8 @@ SRCS= lwip.c \ .PATH: ${.CURDIR}/generic -DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBTIMERS} ${LIBLWIP} -LDADD+= -lchardriver -lsys -ltimers -llwip +DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBTIMERS} ${LIBLWIP} ${LIBNETSOCK} +LDADD+= -lchardriver -lsys -ltimers -llwip -lnetsock MAN= diff --git a/servers/lwip/driver.c b/servers/lwip/driver.c index dd912c584..a1c5a5318 100644 --- a/servers/lwip/driver.c +++ b/servers/lwip/driver.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,6 @@ #include #include "proto.h" -#include "socket.h" #include "driver.h" #if 0 @@ -303,11 +303,11 @@ int raw_socket_input(struct pbuf * pbuf, struct nic * nic) ret = raw_receive(&sock->mess, pbuf); if (ret > 0) { - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~SOCK_FLG_OP_PENDING; return 0; } else { - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~SOCK_FLG_OP_PENDING; } } @@ -456,7 +456,7 @@ static void nic_op_close(struct socket * sock, __unused message * m) debug_drv_print("no active raw sock at %s", nic->name); } - sock_reply(sock, OK); + sock_reply_close(sock, OK); } static void nic_ioctl_set_conf(__unused struct socket * sock, @@ -643,12 +643,12 @@ void nic_default_ioctl(message *m) nic_do_ioctl(NULL, nic, m); } -static void nic_op_ioctl(struct socket * sock, message * m) +static void nic_op_ioctl(struct socket * sock, message * m, __unused int blk) { nic_do_ioctl(sock, (struct nic *)sock->data, m); } -static void nic_op_read(struct socket * sock, message * m) +static void nic_op_read(struct socket * sock, message * m, int blk) { debug_drv_print("sock num %d", get_sock_num(sock)); @@ -668,18 +668,19 @@ static void nic_op_read(struct socket * sock, message * m) pbuf_free(pbuf); } sock_reply(sock, ret); - } else { + } else if (!blk) + send_reply(m, EAGAIN); + else { /* store the message so we know how to reply */ sock->mess = *m; /* operation is being processes */ sock->flags |= SOCK_FLG_OP_PENDING; debug_print("no data to read, suspending"); - sock_reply(sock, SUSPEND); } } -static void nic_op_write(struct socket * sock, message * m) +static void nic_op_write(struct socket * sock, message * m, __unused int blk) { int ret; struct pbuf * pbuf; @@ -730,7 +731,7 @@ void nic_open(message *m) debug_print("device %d", m->DEVICE); if (m->DEVICE > MAX_DEVS || devices[m->DEVICE].drv_ep == NONE) { - send_reply(m, ENODEV); + send_reply_open(m, ENODEV); return; } @@ -750,7 +751,7 @@ void nic_open(message *m) sock->recv_data_size = 0; sock->data = &devices[m->DEVICE]; - send_reply(m, get_sock_num(sock)); + send_reply_open(m, get_sock_num(sock)); } static int driver_pkt_enqueue(struct packet_q ** head, diff --git a/servers/lwip/inet_config.c b/servers/lwip/inet_config.c index 475be3cab..631df1c72 100644 --- a/servers/lwip/inet_config.c +++ b/servers/lwip/inet_config.c @@ -25,7 +25,7 @@ Copyright 1995 Philip Homburg #include "inet_config.h" #include "proto.h" -#include "socket.h" +#include struct eth_conf eth_conf[IP_PORT_MAX]; diff --git a/servers/lwip/lwip.c b/servers/lwip/lwip.c index 39a2487f7..32fa6c417 100644 --- a/servers/lwip/lwip.c +++ b/servers/lwip/lwip.c @@ -12,9 +12,9 @@ #include #include #include +#include #include "proto.h" -#include "socket.h" #include #include @@ -30,6 +30,10 @@ static int arp_ticks, tcp_fticks, tcp_sticks; static struct netif * netif_lo; +extern struct sock_ops sock_udp_ops; +extern struct sock_ops sock_tcp_ops; +extern struct sock_ops sock_raw_ip_ops; + void sys_init(void) { } @@ -198,6 +202,56 @@ static void netif_poll_lo(void) netif_poll(netif_lo); } +void socket_open(message * m) +{ + struct sock_ops * ops; + struct socket * sock; + int ret = OK; + + switch (m->DEVICE) { + case SOCK_TYPE_TCP: + ops = &sock_tcp_ops; + break; + case SOCK_TYPE_UDP: + ops = &sock_udp_ops; + break; + case SOCK_TYPE_IP: + ops = &sock_raw_ip_ops; + break; + default: + if (m->DEVICE - SOCK_TYPES < MAX_DEVS) { + m->DEVICE -= SOCK_TYPES; + nic_open(m); + return; + } + printf("LWIP unknown socket type %d\n", m->DEVICE); + send_reply_open(m, EINVAL); + return; + } + + sock = get_unused_sock(); + if (!sock) { + printf("LWIP : no free socket\n"); + send_reply_open(m, EAGAIN); + return; + } + + sock->ops = ops; + sock->select_ep = NONE; + sock->recv_data_size = 0; + + if (sock->ops && sock->ops->open) + ret = sock->ops->open(sock, m); + + if (ret == OK) { + debug_print("new socket %ld", get_sock_num(sock)); + send_reply_open(m, get_sock_num(sock)); + } else { + debug_print("failed %d", ret); + send_reply_open(m, ret); + } +} + int main(__unused int argc, __unused char ** argv) { sef_local_startup(); diff --git a/servers/lwip/raw_ip.c b/servers/lwip/raw_ip.c index d22abb609..6bf4ead89 100644 --- a/servers/lwip/raw_ip.c +++ b/servers/lwip/raw_ip.c @@ -7,7 +7,7 @@ #include #include -#include "socket.h" +#include #include "proto.h" #define RAW_IP_BUF_SIZE (32 << 10) @@ -62,7 +62,7 @@ static void raw_ip_op_close(struct socket * sock, __unused message * m) raw_ip_close(sock); - sock_reply(sock, OK); + sock_reply_close(sock, OK); } static int raw_ip_do_receive(message * m, @@ -111,7 +111,7 @@ static u8_t raw_ip_op_receive(void *arg, ret = raw_ip_do_receive(&sock->mess, pbuf); if (ret > 0) { - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~SOCK_FLG_OP_PENDING; if (sock->usr_flags & NWIO_EXCL) { pbuf_free(pbuf); @@ -119,7 +119,7 @@ static u8_t raw_ip_op_receive(void *arg, } else return 0; } else { - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~SOCK_FLG_OP_PENDING; } } @@ -170,7 +170,7 @@ static u8_t raw_ip_op_receive(void *arg, return ret; } -static void raw_ip_op_read(struct socket * sock, message * m) +static void raw_ip_op_read(struct socket * sock, message * m, int blk) { debug_print("socket num %ld", get_sock_num(sock)); @@ -195,18 +195,19 @@ static void raw_ip_op_read(struct socket * sock, message * m) raw_ip_recv_free(data); } sock_reply(sock, ret); - } else { + } else if (!blk) + sock_reply(sock, EAGAIN); + else { /* store the message so we know how to reply */ sock->mess = *m; /* operation is being processes */ sock->flags |= SOCK_FLG_OP_PENDING; debug_print("no data to read, suspending"); - sock_reply(sock, SUSPEND); } } -static void raw_ip_op_write(struct socket * sock, message * m) +static void raw_ip_op_write(struct socket * sock, message * m, __unused int blk) { int ret; struct pbuf * pbuf; @@ -332,7 +333,7 @@ static void raw_ip_get_opt(struct socket * sock, message * m) sock_reply(sock, OK); } -static void raw_ip_op_ioctl(struct socket * sock, message * m) +static void raw_ip_op_ioctl(struct socket * sock, message * m, __unused int blk) { debug_print("socket num %ld req %c %d %d", get_sock_num(sock), diff --git a/servers/lwip/tcp.c b/servers/lwip/tcp.c index f38df285e..077b964df 100644 --- a/servers/lwip/tcp.c +++ b/servers/lwip/tcp.c @@ -11,7 +11,7 @@ #include #include -#include "socket.h" +#include #include "proto.h" #define TCP_BUF_SIZE (32 << 10) @@ -67,7 +67,7 @@ static void tcp_error_callback(void *arg, err_t err) } if (sock->flags & SOCK_FLG_OP_PENDING) { - sock_revive(sock, perr); + sock_reply(sock, perr); sock->flags &= ~SOCK_FLG_OP_PENDING; } else if (sock_select_set(sock)) sock_select_notify(sock); @@ -173,9 +173,9 @@ static void tcp_op_close(struct socket * sock, __unused message * m) } debug_tcp_print("freed TX data"); - sock_reply(sock, OK); + sock_reply_close(sock, OK); debug_tcp_print("socket unused"); - + /* mark it as unused */ sock->ops = NULL; } @@ -290,7 +290,7 @@ cp_error: return EFAULT; } -static void tcp_op_read(struct socket * sock, message * m) +static void tcp_op_read(struct socket * sock, message * m, int blk) { debug_tcp_print("socket num %ld", get_sock_num(sock)); @@ -313,9 +313,13 @@ static void tcp_op_read(struct socket * sock, message * m) sock_reply(sock, 0); return; } + if (!blk) { + debug_tcp_print("reading would block -> EAGAIN"); + sock_reply(sock, EAGAIN); + return; + } /* operation is being processed */ debug_tcp_print("no data to read, suspending"); - sock_reply(sock, SUSPEND); sock->flags |= SOCK_FLG_OP_PENDING | SOCK_FLG_OP_READING; } } @@ -383,7 +387,7 @@ static struct wbuf * wbuf_ack_sent(struct socket * sock, unsigned sz) return wc->head; } -static void tcp_op_write(struct socket * sock, message * m) +static void tcp_op_write(struct socket * sock, message * m, __unused int blk) { int ret; struct wbuf * wbuf; @@ -620,9 +624,8 @@ static err_t tcp_recv_callback(void *arg, /* wake up the reader and report EOF */ if (sock->flags & SOCK_FLG_OP_PENDING && - sock->flags & SOCK_FLG_OP_READING && - !(sock->flags & SOCK_FLG_OP_REVIVING)) { - sock_revive(sock, 0); + sock->flags & SOCK_FLG_OP_READING) { + sock_reply(sock, 0); sock->flags &= ~(SOCK_FLG_OP_PENDING | SOCK_FLG_OP_READING); } @@ -652,7 +655,7 @@ static err_t tcp_recv_callback(void *arg, if (sock->flags & SOCK_FLG_OP_READING) { ret = read_from_tcp(sock, &sock->mess); debug_tcp_print("read op finished"); - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~(SOCK_FLG_OP_PENDING | SOCK_FLG_OP_READING); } @@ -792,7 +795,7 @@ static err_t tcp_connected_callback(void *arg, tcp_sent(tpcb, tcp_sent_callback); tcp_recv(tpcb, tcp_recv_callback); - sock_revive(sock, OK); + sock_reply(sock, OK); sock->flags &= ~(SOCK_FLG_OP_PENDING | SOCK_FLG_OP_CONNECTING); /* revive does the sock_select_notify() for us */ @@ -811,7 +814,6 @@ static void tcp_op_connect(struct socket * sock) * Connecting is going to send some packets. Unless an immediate error * occurs this operation is going to block */ - sock_reply(sock, SUSPEND); sock->flags |= SOCK_FLG_OP_PENDING | SOCK_FLG_OP_CONNECTING; /* try to connect now */ @@ -874,7 +876,7 @@ static err_t tcp_accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err) int ret; ret = tcp_do_accept(sock, &sock->mess, newpcb); - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~SOCK_FLG_OP_PENDING; if (ret == OK) { return ERR_OK; @@ -951,7 +953,6 @@ static void tcp_op_accept(struct socket * sock, message * m) debug_tcp_print("no ready connection, suspending\n"); - sock_reply(sock, SUSPEND); sock->flags |= SOCK_FLG_OP_PENDING; } @@ -1040,7 +1041,7 @@ static void tcp_set_opt(struct socket * sock, message * m) sock_reply(sock, OK); } -static void tcp_op_ioctl(struct socket * sock, message * m) +static void tcp_op_ioctl(struct socket * sock, message * m, __unused int blk) { if (!sock->pcb) { sock_reply(sock, ENOTCONN); @@ -1109,7 +1110,7 @@ static void tcp_op_select(struct socket * sock, __unused message * m) if (sel & SEL_ERR) sock->flags |= SOCK_FLG_SEL_ERROR; } - send_reply(m, 0); + sock_reply_select(sock, 0); return; } @@ -1155,7 +1156,7 @@ static void tcp_op_select(struct socket * sock, __unused message * m) if (sel & SEL_ERR && sel & SEL_NOTIFY) sock->flags |= SOCK_FLG_SEL_ERROR; - send_reply(m, retsel); + sock_reply_select(sock, retsel); } static void tcp_op_select_reply(struct socket * sock, message * m) @@ -1164,7 +1165,7 @@ static void tcp_op_select_reply(struct socket * sock, message * m) debug_tcp_print("socket num %ld", get_sock_num(sock)); - if (sock->flags & (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_REVIVING)) { + if (sock->flags & SOCK_FLG_OP_PENDING) { debug_tcp_print("WARNING socket still blocking!"); return; } diff --git a/servers/lwip/udp.c b/servers/lwip/udp.c index fafb0dc58..38ca29ce3 100644 --- a/servers/lwip/udp.c +++ b/servers/lwip/udp.c @@ -11,7 +11,7 @@ #include #include -#include "socket.h" +#include #include "proto.h" #define UDP_BUF_SIZE (4 << 10) @@ -72,7 +72,7 @@ static void udp_op_close(struct socket * sock, __unused message * m) /* mark it as unused */ sock->ops = NULL; - sock_reply(sock, OK); + sock_reply_close(sock, OK); } static int udp_do_receive(struct socket * sock, @@ -151,11 +151,11 @@ static void udp_recv_callback(void *arg, if (ret > 0) { pbuf_free(pbuf); - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~SOCK_FLG_OP_PENDING; return; } else { - sock_revive(sock, ret); + sock_reply(sock, ret); sock->flags &= ~SOCK_FLG_OP_PENDING; } } @@ -193,7 +193,7 @@ static void udp_recv_callback(void *arg, sock_select_notify(sock); } -static void udp_op_read(struct socket * sock, message * m) +static void udp_op_read(struct socket * sock, message * m, int blk) { debug_udp_print("socket num %ld", get_sock_num(sock)); @@ -214,14 +214,15 @@ static void udp_op_read(struct socket * sock, message * m) udp_recv_free(data); } sock_reply(sock, ret); - } else { + } else if (!blk) + sock_reply(sock, EAGAIN); + else { /* store the message so we know how to reply */ sock->mess = *m; /* operation is being processes */ sock->flags |= SOCK_FLG_OP_PENDING; debug_udp_print("no data to read, suspending\n"); - sock_reply(sock, SUSPEND); } } @@ -262,7 +263,7 @@ static int udp_op_sendto(struct socket * sock, struct pbuf * pbuf, message * m) } } -static void udp_op_write(struct socket * sock, message * m) +static void udp_op_write(struct socket * sock, message * m, __unused int blk) { int ret; struct pbuf * pbuf; @@ -385,7 +386,7 @@ static void udp_get_opt(struct socket * sock, message * m) sock_reply(sock, OK); } -static void udp_op_ioctl(struct socket * sock, message * m) +static void udp_op_ioctl(struct socket * sock, message * m, __unused int blk) { debug_udp_print("socket num %ld req %c %d %d", get_sock_num(sock),