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:
		
							parent
							
								
									199e9c1907
								
							
						
					
					
						commit
						fb31513b00
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -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 \
 | 
			
		||||
 | 
			
		||||
@ -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 <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <minix/ipc.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_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__ */
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								lib/libnetsock/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								lib/libnetsock/Makefile
									
									
									
									
									
										Normal 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>
 | 
			
		||||
@ -10,25 +10,37 @@
 | 
			
		||||
#include <minix/com.h>
 | 
			
		||||
#include <minix/callnr.h>
 | 
			
		||||
#include <minix/sysutil.h>
 | 
			
		||||
#include <minix/netsock.h>
 | 
			
		||||
 | 
			
		||||
#include <lwip/tcp.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/ioc_net.h>
 | 
			
		||||
 | 
			
		||||
#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,102 +203,99 @@ 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);
 | 
			
		||||
	msg.m_type = DEV_SEL_REPL1;
 | 
			
		||||
	msg.DEV_MINOR = get_sock_num(sock);
 | 
			
		||||
	msg.DEV_SEL_OPS = selops;
 | 
			
		||||
 | 
			
		||||
	sock->mess.m_type = DEV_REVIVE;
 | 
			
		||||
	set_reply_msg(&sock->mess, status);
 | 
			
		||||
	
 | 
			
		||||
	result = notify(sock->mess.m_source);
 | 
			
		||||
	result = send(sock->select_ep, &msg);
 | 
			
		||||
	if (result != OK)
 | 
			
		||||
		panic("LWIP : unable to notify (err %d)", result);
 | 
			
		||||
 | 
			
		||||
	sock->flags |= SOCK_FLG_OP_REVIVING;
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
	debug_sock_print("sock %ld status %d", get_sock_num(sock), status);
 | 
			
		||||
	sock_reply_type(sock, DEV_REVIVE, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct socket * get_unused_sock(void)
 | 
			
		||||
@ -302,157 +313,31 @@ struct socket * get_unused_sock(void)
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
@ -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=
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@
 | 
			
		||||
#include <minix/com.h>
 | 
			
		||||
#include <minix/sysutil.h>
 | 
			
		||||
#include <minix/safecopies.h>
 | 
			
		||||
#include <minix/netsock.h>
 | 
			
		||||
 | 
			
		||||
#include <sys/ioc_net.h>
 | 
			
		||||
#include <net/gen/in.h>
 | 
			
		||||
@ -22,7 +23,6 @@
 | 
			
		||||
#include <netif/etharp.h>
 | 
			
		||||
 | 
			
		||||
#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,
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ Copyright 1995 Philip Homburg
 | 
			
		||||
#include "inet_config.h"
 | 
			
		||||
 | 
			
		||||
#include "proto.h"
 | 
			
		||||
#include "socket.h"
 | 
			
		||||
#include <minix/netsock.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct eth_conf eth_conf[IP_PORT_MAX];
 | 
			
		||||
 | 
			
		||||
@ -12,9 +12,9 @@
 | 
			
		||||
#include <minix/syslib.h>
 | 
			
		||||
#include <minix/sysutil.h>
 | 
			
		||||
#include <minix/timers.h>
 | 
			
		||||
#include <minix/netsock.h>
 | 
			
		||||
 | 
			
		||||
#include "proto.h"
 | 
			
		||||
#include "socket.h"
 | 
			
		||||
 | 
			
		||||
#include <lwip/mem.h>
 | 
			
		||||
#include <lwip/pbuf.h>
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
#include <lwip/raw.h>
 | 
			
		||||
#include <lwip/ip_addr.h>
 | 
			
		||||
 | 
			
		||||
#include "socket.h"
 | 
			
		||||
#include <minix/netsock.h>
 | 
			
		||||
#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),
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
#include <lwip/tcp_impl.h>
 | 
			
		||||
#include <lwip/ip_addr.h>
 | 
			
		||||
 | 
			
		||||
#include "socket.h"
 | 
			
		||||
#include <minix/netsock.h>
 | 
			
		||||
#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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
#include <lwip/udp.h>
 | 
			
		||||
#include <lwip/ip_addr.h>
 | 
			
		||||
 | 
			
		||||
#include "socket.h"
 | 
			
		||||
#include <minix/netsock.h>
 | 
			
		||||
#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),
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user