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
This commit is contained in:
Tomas Hruby 2012-02-24 18:02:32 +00:00
parent 199e9c1907
commit fb31513b00
13 changed files with 276 additions and 319 deletions

View file

@ -138,7 +138,7 @@ start)
done done
if [ X`/bin/sysenv lwip` = Xyes ] if [ X`/bin/sysenv lwip` = Xyes ]
then 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 else
up inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE up inet -script /etc/rs.inet -dev /dev/ip -devstyle STYLE_CLONE
fi fi

View file

@ -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/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/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/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 \ 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 \ net/gen/eth_hdr.h net/gen/eth_io.h net/gen/icmp.h \

View file

@ -1,11 +1,16 @@
#ifndef __LWIP_SERVER_SOCKET_H__ #ifndef __NET_SERVER_SOCKET_H__
#define __LWIP_SERVER_SOCKET_H__ #define __NET_SERVER_SOCKET_H__
#include <stdlib.h>
#include <minix/ipc.h> #include <minix/ipc.h>
#include <minix/endpoint.h> #include <minix/endpoint.h>
#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_IP 0
#define SOCK_TYPE_TCP 1 #define SOCK_TYPE_TCP 1
@ -15,14 +20,15 @@
struct socket; struct socket;
typedef void (* sock_op_t)(struct socket *, message *); 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 *); typedef int (* sock_op_open_t)(struct socket *, message *);
struct sock_ops { struct sock_ops {
sock_op_open_t open; sock_op_open_t open;
sock_op_t close; sock_op_t close;
sock_op_t read; sock_op_io_t read;
sock_op_t write; sock_op_io_t write;
sock_op_t ioctl; sock_op_io_t ioctl;
sock_op_t select; sock_op_t select;
sock_op_t select_reply; sock_op_t select_reply;
}; };
@ -33,8 +39,7 @@ struct recv_q {
}; };
#define SOCK_FLG_OP_PENDING 0x1 #define SOCK_FLG_OP_PENDING 0x1
#define SOCK_FLG_OP_REVIVING 0x2 #define SOCK_FLG_OP_IOCTL 0x10
#define SOCK_FLG_OP_SUSPENDED 0x4 /* set when processing a suspended op */
#define SOCK_FLG_OP_LISTENING 0x100 /* tcp socket is in a listening mode */ #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_CONNECTING 0x200 /* set when waiting for a connect */
#define SOCK_FLG_OP_READING 0x400 /* reading operation in progress */ #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_WRITE 0x100000
#define SOCK_FLG_SEL_READ 0x200000 #define SOCK_FLG_SEL_READ 0x200000
#define SOCK_FLG_SEL_ERROR 0x400000 #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 | \ #define sock_select_set(sock) ((sock)->flags & (SOCK_FLG_SEL_WRITE | \
SOCK_FLG_SEL_READ | SOCK_FLG_SEL_ERROR)) 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 | \ #define sock_select_rw_set(sock) ((sock)->flags & (SOCK_FLG_SEL_READ | \
SOCK_FLG_SEL_WRITE)) SOCK_FLG_SEL_WRITE))
#define sock_select_error_set(sock) ((sock)->flags & SOCK_FLG_SEL_ERROR) #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 { \ #define sock_clear_select(sock) do { \
(sock)->flags &= ~(SOCK_FLG_SEL_READ | SOCK_FLG_SEL_WRITE | \ (sock)->flags &= ~(SOCK_FLG_SEL_READ | SOCK_FLG_SEL_WRITE | \
SOCK_FLG_SEL_ERROR | SOCK_FLG_SEL_CHECK); \ SOCK_FLG_SEL_ERROR); \
} while (0) } while (0)
struct socket { struct socket {
@ -71,6 +74,8 @@ struct socket {
message mess; /* store the message which initiated the message mess; /* store the message which initiated the
last operation on this socket in case last operation on this socket in case
we have to suspend the operation */ we have to suspend the operation */
void * shm;
size_t shm_size;
endpoint_t select_ep; endpoint_t select_ep;
struct recv_q * recv_head; struct recv_q * recv_head;
struct recv_q * recv_tail; struct recv_q * recv_tail;
@ -78,9 +83,11 @@ struct socket {
void * data; void * data;
}; };
extern struct sock_ops sock_udp_ops; /*
extern struct sock_ops sock_tcp_ops; * Each component needs to provide a method how to initially open a socket.
extern struct sock_ops sock_raw_ip_ops; * The rest is handled byt the socket library.
*/
void socket_open(message * m);
#define get_sock_num(x) ((long int) ((x) - socket)) #define get_sock_num(x) ((long int) ((x) - socket))
#define is_valid_sock_num(x) (x < MAX_SOCKETS) #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); struct socket * get_nic_sock(unsigned dev);
void send_reply(message * m, int status); 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_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 *); 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(struct socket * sock, message * m);
void generic_op_select_reply(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__ */

View file

@ -5,7 +5,8 @@ SUBDIR= csu libcompat_minix libc libblockdriver libchardriver \
libl libhgfs libz libfetch libvtreefs libaudiodriver libmthread \ libl libhgfs libz libfetch libvtreefs libaudiodriver libmthread \
libexec libdevman libusb libminlib libasyn \ libexec libdevman libusb libminlib libasyn \
libddekit libminixfs libbdev libelf libminc libcrypt libterminfo \ 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 SUBDIR+= ../external/public-domain/xz/lib

9
lib/libnetsock/Makefile Normal file
View file

@ -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 <bsd.lib.mk>

View file

@ -10,25 +10,37 @@
#include <minix/com.h> #include <minix/com.h>
#include <minix/callnr.h> #include <minix/callnr.h>
#include <minix/sysutil.h> #include <minix/sysutil.h>
#include <minix/netsock.h>
#include <lwip/tcp.h> #include <lwip/tcp.h>
#include <sys/ioc_net.h> #include <sys/ioc_net.h>
#include "inet_config.h" char * netsock_user_name = NULL;
#include "proto.h" #define NETSOCK_USER_NAME (netsock_user_name ? netsock_user_name : "NETSOCK")
#include "socket.h"
#define debug_print(str, ...) printf("%s : %s:%d : " str "\n", \
NETSOCK_USER_NAME, __func__, __LINE__, ##__VA_ARGS__)
#if 0 #if 0
#define debug_sock_print(str, ...) printf("LWIP %s:%d : " str "\n", \ #define debug_sock_print(...) debug_print(__VA_ARGS__)
__func__, __LINE__, ##__VA_ARGS__)
#else #else
#define debug_sock_print(...) debug_print(__VA_ARGS__) #define debug_sock_print(...)
#endif #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]; struct socket socket[MAX_SOCKETS];
static int notified;
#define recv_q_alloc() debug_malloc(sizeof(struct recv_q)) #define recv_q_alloc() debug_malloc(sizeof(struct recv_q))
#define recv_q_free debug_free #define recv_q_free debug_free
@ -44,7 +56,7 @@ struct mq {
static struct mq * mq_head, *mq_tail; static struct mq * mq_head, *mq_tail;
static int mq_enqueue(message * m) int mq_enqueue(message * m)
{ {
struct mq * mq; struct mq * mq;
@ -121,8 +133,10 @@ static int mq_cancel(message * m)
} }
} }
mq_dequeue(mq); if (mq) {
mq_free(mq); mq_dequeue(mq);
mq_free(mq);
}
return 1; return 1;
} }
@ -189,102 +203,99 @@ static void set_reply_msg(message * m, int status)
m->REP_IO_GRANT= ref; m->REP_IO_GRANT= ref;
} }
void send_reply(message * m, int status) void send_reply_type(message * m, int type, int status)
{ {
int result; int result;
debug_sock_print("status %d", status);
set_reply_msg(m, status); set_reply_msg(m, status);
m->m_type = TASK_REPLY; m->m_type = type;
result = send(m->m_source, m); result = send(m->m_source, m);
if (result != OK) 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; int result;
message msg;
assert(!(sock->flags & SOCK_FLG_OP_REVIVING)); debug_sock_select_print("selops %d", selops);
assert(sock->flags & (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_SUSPENDED));
if (notified) { msg.m_type = DEV_SEL_REPL1;
debug_sock_print("already notified"); msg.DEV_MINOR = get_sock_num(sock);
return; msg.DEV_SEL_OPS = selops;
}
else {
assert(sock->mess.m_type != DEV_REVIVE);
notified = 1;
}
debug_sock_print("socket num %ld, status %d", result = send(sock->select_ep, &msg);
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) if (result != OK)
panic("LWIP : unable to notify (err %d)", result); netsock_panic("unable to send (err %d)", result);
sock->flags |= SOCK_FLG_OP_REVIVING;
} }
void sock_select_notify(struct socket * sock) void sock_select_notify(struct socket * sock)
{ {
int result; 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); assert(sock->select_ep != NONE);
sock->flags |= SOCK_FLG_SEL_CHECK; msg.DEV_SEL_OPS = 0;
if (notified) { sock->ops->select_reply(sock, &msg);
debug_sock_print("already notified"); 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; 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) if (result != OK)
panic("LWIP : unable to notify (err %d)", result); netsock_panic("unable to send (err %d)", result);
sock_clear_select(sock);
sock->select_ep = NONE;
}
static void sock_reply_type(struct socket * sock, int type, int status)
{
sock->mess.m_type = type;
send_reply_type(&sock->mess, type, status);
}
void sock_reply_close(struct socket * sock, int status)
{
debug_sock_print("sock %ld status %d", get_sock_num(sock), status);
sock_reply_type(sock, DEV_CLOSE_REPL, status);
} }
void sock_reply(struct socket * sock, int status) void sock_reply(struct socket * sock, int status)
{ {
debug_sock_print("socket num %ld status %d type %d", debug_sock_print("sock %ld status %d", get_sock_num(sock), status);
get_sock_num(sock), status, sock->mess.m_type); sock_reply_type(sock, DEV_REVIVE, status);
/*
* 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);
} }
struct socket * get_unused_sock(void) struct socket * get_unused_sock(void)
@ -302,157 +313,31 @@ struct socket * get_unused_sock(void)
return NULL; return NULL;
} }
struct socket * get_nic_sock(unsigned dev)
{
if (dev < MAX_DEVS)
return &socket[dev + SOCK_TYPES];
else
return NULL;
}
static 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(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);
}
}
static void do_status(message * m)
{
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;
}
}
}
}
debug_sock_print("no status");
m->m_type = DEV_NO_STATUS;
send(m->m_source, m);
}
static void socket_request_socket(struct socket * sock, message * m) static void socket_request_socket(struct socket * sock, message * m)
{ {
int blocking = m->FLAGS & FLG_OP_NONBLOCK ? 0 : 1;
switch (m->m_type) { switch (m->m_type) {
case DEV_READ_S: case DEV_READ_S:
if (sock && sock->ops && sock->ops->read) if (sock && sock->ops && sock->ops->read)
sock->ops->read(sock, m); sock->ops->read(sock, m, blocking);
else else
send_reply(m, EINVAL); send_reply(m, EINVAL);
return; return;
case DEV_WRITE_S: case DEV_WRITE_S:
if (sock && sock->ops && sock->ops->write) if (sock && sock->ops && sock->ops->write)
sock->ops->write(sock, m); sock->ops->write(sock, m, blocking);
else else
send_reply(m, EINVAL); send_reply(m, EINVAL);
return; return;
case DEV_IOCTL_S: case DEV_IOCTL_S:
if (sock && sock->ops && sock->ops->ioctl) if (sock && sock->ops && sock->ops->ioctl)
sock->ops->ioctl(sock, m); sock->ops->ioctl(sock, m, blocking);
else else
send_reply(m, EINVAL); send_reply(m, EINVAL);
return; return;
default: default:
panic("LWIP : cannot happen!"); netsock_panic("cannot happen!");
} }
} }
@ -460,6 +345,7 @@ void socket_request(message * m)
{ {
struct socket * sock; struct socket * sock;
debug_sock_print("request %d", m->m_type);
switch (m->m_type) { switch (m->m_type) {
case DEV_OPEN: case DEV_OPEN:
socket_open(m); socket_open(m);
@ -471,7 +357,7 @@ void socket_request(message * m)
sock->mess = *m; sock->mess = *m;
sock->ops->close(sock, m); sock->ops->close(sock, m);
} else } else
send_reply(m, EINVAL); send_reply_close(m, EINVAL);
return; return;
case DEV_READ_S: case DEV_READ_S:
case DEV_WRITE_S: case DEV_WRITE_S:
@ -485,7 +371,7 @@ void socket_request(message * m)
* If an operation is pending (blocking operation) or writing is * If an operation is pending (blocking operation) or writing is
* still going and we want to read, suspend the new operation * 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 && (m->m_type == DEV_READ_S &&
sock->flags & SOCK_FLG_OP_WRITING)) { sock->flags & SOCK_FLG_OP_WRITING)) {
char * o = "\0"; char * o = "\0";
@ -495,11 +381,9 @@ void socket_request(message * m)
o = "WRITE"; o = "WRITE";
else else
o = "non R/W op"; o = "non R/W op";
debug_sock_print("socket %ld is busy by %s\n", debug_sock_print("socket %ld is busy by %s flgs 0x%x\n",
get_sock_num(sock), o); get_sock_num(sock), o, sock->flags);
if (mq_enqueue(m) == 0) { if (mq_enqueue(m) != 0) {
send_reply(m, SUSPEND);
} else {
debug_sock_print("Enqueuing suspended " debug_sock_print("Enqueuing suspended "
"call failed"); "call failed");
send_reply(m, ENOMEM); send_reply(m, ENOMEM);
@ -511,6 +395,7 @@ void socket_request(message * m)
return; return;
case CANCEL: case CANCEL:
sock = get_sock(m->DEVICE); sock = get_sock(m->DEVICE);
printf("socket num %ld\n", get_sock_num(sock));
debug_sock_print("socket num %ld", get_sock_num(sock)); debug_sock_print("socket num %ld", get_sock_num(sock));
/* Cancel the last operation in the queue */ /* Cancel the last operation in the queue */
if (mq_cancel(m)) { if (mq_cancel(m)) {
@ -522,15 +407,8 @@ void socket_request(message * m)
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
send_reply(m, EINTR); send_reply(m, EINTR);
return; 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 } else
panic("LWIP : no operation to cancel"); netsock_panic("no operation to cancel");
return; return;
case DEV_SELECT: case DEV_SELECT:
@ -542,17 +420,15 @@ void socket_request(message * m)
assert(sock->select_ep == NONE || sock->select_ep == m->m_source); assert(sock->select_ep == NONE || sock->select_ep == m->m_source);
if (sock && sock->ops && sock->ops->select) { if (sock && sock->ops && sock->ops->select) {
sock->select_ep = m->m_source;
sock->ops->select(sock, m); sock->ops->select(sock, m);
if (sock_select_set(sock)) if (!sock_select_set(sock))
sock->select_ep = m->m_source; sock->select_ep = NONE;
} else } else
send_reply(m, EINVAL); send_reply(m, EINVAL);
return; return;
case DEV_STATUS:
do_status(m);
return;
default: default:
printf("LWIP : unknown message from VFS, type %d\n", netsock_error("unknown message from VFS, type %d\n",
m->m_type); m->m_type);
} }
send_reply(m, EGENERIC); send_reply(m, EGENERIC);
@ -569,11 +445,9 @@ void mq_process(void)
struct mq * next = mq->next; struct mq * next = mq->next;
sock = get_sock(mq->m.DEVICE); sock = get_sock(mq->m.DEVICE);
if (!(sock->flags & if (!(sock->flags & SOCK_FLG_OP_PENDING) &&
(SOCK_FLG_OP_PENDING | SOCK_FLG_OP_REVIVING)) &&
!(mq->m.m_type == DEV_READ_S && !(mq->m.m_type == DEV_READ_S &&
sock->flags & SOCK_FLG_OP_WRITING)) { sock->flags & SOCK_FLG_OP_WRITING)) {
sock->flags = SOCK_FLG_OP_SUSPENDED;
debug_sock_print("resuming op on sock %ld\n", debug_sock_print("resuming op on sock %ld\n",
get_sock_num(sock)); get_sock_num(sock));
sock->mess = mq->m; sock->mess = mq->m;
@ -591,7 +465,7 @@ void generic_op_select(struct socket * sock, message * m)
{ {
int retsel = 0, sel; 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; sel = m->USER_ENDPT;
@ -604,7 +478,7 @@ void generic_op_select(struct socket * sock, message * m)
sock->flags |= SOCK_FLG_SEL_WRITE; sock->flags |= SOCK_FLG_SEL_WRITE;
/* FIXME we do not monitor error */ /* FIXME we do not monitor error */
} }
send_reply(m, 0); sock_reply_select(sock, 0);
return; return;
} }
@ -619,19 +493,19 @@ void generic_op_select(struct socket * sock, message * m)
retsel |= SEL_WR; retsel |= SEL_WR;
/* FIXME SEL_ERR is ignored, we do not generate exceptions */ /* 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) void generic_op_select_reply(struct socket * sock, __unused message * m)
{ {
assert(sock->select_ep != NONE); 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() */ /* unused for generic packet socket, see generic_op_select() */
assert((sock->flags & (SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_ERROR)) == 0); assert((sock->flags & (SOCK_FLG_SEL_WRITE | SOCK_FLG_SEL_ERROR)) == 0);
if (sock->flags & (SOCK_FLG_OP_PENDING | SOCK_FLG_OP_REVIVING)) { if (sock->flags & SOCK_FLG_OP_PENDING) {
debug_print("WARNING socket still blocking!"); debug_sock_print("WARNING socket still blocking!");
return; return;
} }

View file

@ -1,7 +1,6 @@
# Makefile for inet. # Makefile for inet.
PROG= lwip PROG= lwip
SRCS= lwip.c \ SRCS= lwip.c \
socket.c \
driver.c \ driver.c \
udp.c \ udp.c \
tcp.c \ tcp.c \
@ -11,8 +10,8 @@ SRCS= lwip.c \
.PATH: ${.CURDIR}/generic .PATH: ${.CURDIR}/generic
DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBTIMERS} ${LIBLWIP} DPADD+= ${LIBCHARDRIVER} ${LIBSYS} ${LIBTIMERS} ${LIBLWIP} ${LIBNETSOCK}
LDADD+= -lchardriver -lsys -ltimers -llwip LDADD+= -lchardriver -lsys -ltimers -llwip -lnetsock
MAN= MAN=

View file

@ -9,6 +9,7 @@
#include <minix/com.h> #include <minix/com.h>
#include <minix/sysutil.h> #include <minix/sysutil.h>
#include <minix/safecopies.h> #include <minix/safecopies.h>
#include <minix/netsock.h>
#include <sys/ioc_net.h> #include <sys/ioc_net.h>
#include <net/gen/in.h> #include <net/gen/in.h>
@ -22,7 +23,6 @@
#include <netif/etharp.h> #include <netif/etharp.h>
#include "proto.h" #include "proto.h"
#include "socket.h"
#include "driver.h" #include "driver.h"
#if 0 #if 0
@ -303,11 +303,11 @@ int raw_socket_input(struct pbuf * pbuf, struct nic * nic)
ret = raw_receive(&sock->mess, pbuf); ret = raw_receive(&sock->mess, pbuf);
if (ret > 0) { if (ret > 0) {
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
return 0; return 0;
} else { } else {
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~SOCK_FLG_OP_PENDING; 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); 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, 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); 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); 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)); 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); pbuf_free(pbuf);
} }
sock_reply(sock, ret); sock_reply(sock, ret);
} else { } else if (!blk)
send_reply(m, EAGAIN);
else {
/* store the message so we know how to reply */ /* store the message so we know how to reply */
sock->mess = *m; sock->mess = *m;
/* operation is being processes */ /* operation is being processes */
sock->flags |= SOCK_FLG_OP_PENDING; sock->flags |= SOCK_FLG_OP_PENDING;
debug_print("no data to read, suspending"); 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; int ret;
struct pbuf * pbuf; struct pbuf * pbuf;
@ -730,7 +731,7 @@ void nic_open(message *m)
debug_print("device %d", m->DEVICE); debug_print("device %d", m->DEVICE);
if (m->DEVICE > MAX_DEVS || devices[m->DEVICE].drv_ep == NONE) { if (m->DEVICE > MAX_DEVS || devices[m->DEVICE].drv_ep == NONE) {
send_reply(m, ENODEV); send_reply_open(m, ENODEV);
return; return;
} }
@ -750,7 +751,7 @@ void nic_open(message *m)
sock->recv_data_size = 0; sock->recv_data_size = 0;
sock->data = &devices[m->DEVICE]; 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, static int driver_pkt_enqueue(struct packet_q ** head,

View file

@ -25,7 +25,7 @@ Copyright 1995 Philip Homburg
#include "inet_config.h" #include "inet_config.h"
#include "proto.h" #include "proto.h"
#include "socket.h" #include <minix/netsock.h>
struct eth_conf eth_conf[IP_PORT_MAX]; struct eth_conf eth_conf[IP_PORT_MAX];

View file

@ -12,9 +12,9 @@
#include <minix/syslib.h> #include <minix/syslib.h>
#include <minix/sysutil.h> #include <minix/sysutil.h>
#include <minix/timers.h> #include <minix/timers.h>
#include <minix/netsock.h>
#include "proto.h" #include "proto.h"
#include "socket.h"
#include <lwip/mem.h> #include <lwip/mem.h>
#include <lwip/pbuf.h> #include <lwip/pbuf.h>
@ -30,6 +30,10 @@ static int arp_ticks, tcp_fticks, tcp_sticks;
static struct netif * netif_lo; 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) void sys_init(void)
{ {
} }
@ -198,6 +202,56 @@ static void netif_poll_lo(void)
netif_poll(netif_lo); 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) int main(__unused int argc, __unused char ** argv)
{ {
sef_local_startup(); sef_local_startup();

View file

@ -7,7 +7,7 @@
#include <lwip/raw.h> #include <lwip/raw.h>
#include <lwip/ip_addr.h> #include <lwip/ip_addr.h>
#include "socket.h" #include <minix/netsock.h>
#include "proto.h" #include "proto.h"
#define RAW_IP_BUF_SIZE (32 << 10) #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); raw_ip_close(sock);
sock_reply(sock, OK); sock_reply_close(sock, OK);
} }
static int raw_ip_do_receive(message * m, 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); ret = raw_ip_do_receive(&sock->mess, pbuf);
if (ret > 0) { if (ret > 0) {
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
if (sock->usr_flags & NWIO_EXCL) { if (sock->usr_flags & NWIO_EXCL) {
pbuf_free(pbuf); pbuf_free(pbuf);
@ -119,7 +119,7 @@ static u8_t raw_ip_op_receive(void *arg,
} else } else
return 0; return 0;
} else { } else {
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
} }
} }
@ -170,7 +170,7 @@ static u8_t raw_ip_op_receive(void *arg,
return ret; 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)); 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); raw_ip_recv_free(data);
} }
sock_reply(sock, ret); sock_reply(sock, ret);
} else { } else if (!blk)
sock_reply(sock, EAGAIN);
else {
/* store the message so we know how to reply */ /* store the message so we know how to reply */
sock->mess = *m; sock->mess = *m;
/* operation is being processes */ /* operation is being processes */
sock->flags |= SOCK_FLG_OP_PENDING; sock->flags |= SOCK_FLG_OP_PENDING;
debug_print("no data to read, suspending"); 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; int ret;
struct pbuf * pbuf; struct pbuf * pbuf;
@ -332,7 +333,7 @@ static void raw_ip_get_opt(struct socket * sock, message * m)
sock_reply(sock, OK); 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", debug_print("socket num %ld req %c %d %d",
get_sock_num(sock), get_sock_num(sock),

View file

@ -11,7 +11,7 @@
#include <lwip/tcp_impl.h> #include <lwip/tcp_impl.h>
#include <lwip/ip_addr.h> #include <lwip/ip_addr.h>
#include "socket.h" #include <minix/netsock.h>
#include "proto.h" #include "proto.h"
#define TCP_BUF_SIZE (32 << 10) #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) { if (sock->flags & SOCK_FLG_OP_PENDING) {
sock_revive(sock, perr); sock_reply(sock, perr);
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
} else if (sock_select_set(sock)) } else if (sock_select_set(sock))
sock_select_notify(sock); sock_select_notify(sock);
@ -173,7 +173,7 @@ static void tcp_op_close(struct socket * sock, __unused message * m)
} }
debug_tcp_print("freed TX data"); debug_tcp_print("freed TX data");
sock_reply(sock, OK); sock_reply_close(sock, OK);
debug_tcp_print("socket unused"); debug_tcp_print("socket unused");
/* mark it as unused */ /* mark it as unused */
@ -290,7 +290,7 @@ cp_error:
return EFAULT; 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)); 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); sock_reply(sock, 0);
return; return;
} }
if (!blk) {
debug_tcp_print("reading would block -> EAGAIN");
sock_reply(sock, EAGAIN);
return;
}
/* operation is being processed */ /* operation is being processed */
debug_tcp_print("no data to read, suspending"); debug_tcp_print("no data to read, suspending");
sock_reply(sock, SUSPEND);
sock->flags |= SOCK_FLG_OP_PENDING | SOCK_FLG_OP_READING; 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; 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; int ret;
struct wbuf * wbuf; struct wbuf * wbuf;
@ -620,9 +624,8 @@ static err_t tcp_recv_callback(void *arg,
/* wake up the reader and report EOF */ /* wake up the reader and report EOF */
if (sock->flags & SOCK_FLG_OP_PENDING && if (sock->flags & SOCK_FLG_OP_PENDING &&
sock->flags & SOCK_FLG_OP_READING && sock->flags & SOCK_FLG_OP_READING) {
!(sock->flags & SOCK_FLG_OP_REVIVING)) { sock_reply(sock, 0);
sock_revive(sock, 0);
sock->flags &= ~(SOCK_FLG_OP_PENDING | sock->flags &= ~(SOCK_FLG_OP_PENDING |
SOCK_FLG_OP_READING); SOCK_FLG_OP_READING);
} }
@ -652,7 +655,7 @@ static err_t tcp_recv_callback(void *arg,
if (sock->flags & SOCK_FLG_OP_READING) { if (sock->flags & SOCK_FLG_OP_READING) {
ret = read_from_tcp(sock, &sock->mess); ret = read_from_tcp(sock, &sock->mess);
debug_tcp_print("read op finished"); debug_tcp_print("read op finished");
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~(SOCK_FLG_OP_PENDING | sock->flags &= ~(SOCK_FLG_OP_PENDING |
SOCK_FLG_OP_READING); SOCK_FLG_OP_READING);
} }
@ -792,7 +795,7 @@ static err_t tcp_connected_callback(void *arg,
tcp_sent(tpcb, tcp_sent_callback); tcp_sent(tpcb, tcp_sent_callback);
tcp_recv(tpcb, tcp_recv_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); sock->flags &= ~(SOCK_FLG_OP_PENDING | SOCK_FLG_OP_CONNECTING);
/* revive does the sock_select_notify() for us */ /* 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 * Connecting is going to send some packets. Unless an immediate error
* occurs this operation is going to block * occurs this operation is going to block
*/ */
sock_reply(sock, SUSPEND);
sock->flags |= SOCK_FLG_OP_PENDING | SOCK_FLG_OP_CONNECTING; sock->flags |= SOCK_FLG_OP_PENDING | SOCK_FLG_OP_CONNECTING;
/* try to connect now */ /* 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; int ret;
ret = tcp_do_accept(sock, &sock->mess, newpcb); ret = tcp_do_accept(sock, &sock->mess, newpcb);
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
if (ret == OK) { if (ret == OK) {
return ERR_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"); debug_tcp_print("no ready connection, suspending\n");
sock_reply(sock, SUSPEND);
sock->flags |= SOCK_FLG_OP_PENDING; sock->flags |= SOCK_FLG_OP_PENDING;
} }
@ -1040,7 +1041,7 @@ static void tcp_set_opt(struct socket * sock, message * m)
sock_reply(sock, OK); 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) { if (!sock->pcb) {
sock_reply(sock, ENOTCONN); sock_reply(sock, ENOTCONN);
@ -1109,7 +1110,7 @@ static void tcp_op_select(struct socket * sock, __unused message * m)
if (sel & SEL_ERR) if (sel & SEL_ERR)
sock->flags |= SOCK_FLG_SEL_ERROR; sock->flags |= SOCK_FLG_SEL_ERROR;
} }
send_reply(m, 0); sock_reply_select(sock, 0);
return; return;
} }
@ -1155,7 +1156,7 @@ static void tcp_op_select(struct socket * sock, __unused message * m)
if (sel & SEL_ERR && sel & SEL_NOTIFY) if (sel & SEL_ERR && sel & SEL_NOTIFY)
sock->flags |= SOCK_FLG_SEL_ERROR; 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) 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)); 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!"); debug_tcp_print("WARNING socket still blocking!");
return; return;
} }

View file

@ -11,7 +11,7 @@
#include <lwip/udp.h> #include <lwip/udp.h>
#include <lwip/ip_addr.h> #include <lwip/ip_addr.h>
#include "socket.h" #include <minix/netsock.h>
#include "proto.h" #include "proto.h"
#define UDP_BUF_SIZE (4 << 10) #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 */ /* mark it as unused */
sock->ops = NULL; sock->ops = NULL;
sock_reply(sock, OK); sock_reply_close(sock, OK);
} }
static int udp_do_receive(struct socket * sock, static int udp_do_receive(struct socket * sock,
@ -151,11 +151,11 @@ static void udp_recv_callback(void *arg,
if (ret > 0) { if (ret > 0) {
pbuf_free(pbuf); pbuf_free(pbuf);
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
return; return;
} else { } else {
sock_revive(sock, ret); sock_reply(sock, ret);
sock->flags &= ~SOCK_FLG_OP_PENDING; sock->flags &= ~SOCK_FLG_OP_PENDING;
} }
} }
@ -193,7 +193,7 @@ static void udp_recv_callback(void *arg,
sock_select_notify(sock); 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)); 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); udp_recv_free(data);
} }
sock_reply(sock, ret); sock_reply(sock, ret);
} else { } else if (!blk)
sock_reply(sock, EAGAIN);
else {
/* store the message so we know how to reply */ /* store the message so we know how to reply */
sock->mess = *m; sock->mess = *m;
/* operation is being processes */ /* operation is being processes */
sock->flags |= SOCK_FLG_OP_PENDING; sock->flags |= SOCK_FLG_OP_PENDING;
debug_udp_print("no data to read, suspending\n"); 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; int ret;
struct pbuf * pbuf; struct pbuf * pbuf;
@ -385,7 +386,7 @@ static void udp_get_opt(struct socket * sock, message * m)
sock_reply(sock, OK); 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", debug_udp_print("socket num %ld req %c %d %d",
get_sock_num(sock), get_sock_num(sock),