/*
 * Generic IP driver interface. 
 *
 * The operating system-dependent code must provide
 * a function osipinit(inst), which calls inst() once
 * for each protocol to be installed.
 *
 * Each protocol is described by a Proto structure,
 * containing the file system name (e.g., tcp, udp)
 * and read, write, clone, connect, announce, listen,
 * and close functions.  Hnputl etc. are provided as
 * helpers.
 *
 * The functions are called when the corresponding 
 * Plan 9 events happen on the connections.  That is,
 * announce gets called for a Plan 9 announce message,
 * which is not the same as a BSD announce.
 * 
 * The given functions should error() out when errors
 * happen, returning normally only on success.
 *
 * clone:
 *	called when /net/proto/clone is read,
 * 	should allocate a new conversation.
 *	in BSD lingo, socket().
 *
 * connect:
 *	called when connect addr!port is written
 *	to the conversation's ctl file, should
 *	connect to c->raddr, c->rport.
 *	in BSD lingo, connect().
 *
 * announce:
 *	called when announce addr!port is written
 *	to the conversation's ctl file, should 
 *	announce intent to receive connections to
 * 	c->laddr, c->lport.
 *	in BSD lingo, listen().
 *
 * listen:
 *	called when the conversation's listen file
 *	is read, should return the next call on an
 *	announced port.
 *	in BSD lingo, accept().
 *
 * close:
 *	called when the last reference to a conversation
 *	disappears, should tear down a connection.
 *	in BSD lingo, closesocket().
 *	close must return successfully.
 */


typedef struct Proto	Proto;
typedef struct Conv	Conv;

struct Conv
{
	int	x;
	struct{
		Lock l;
		int ref;
	} r;
	int	ref;
	int	perm;
	char	*owner;
	char*	state;
	ulong	laddr;
	ushort	lport;
	ulong	raddr;
	ushort	rport;
	int	restricted;
	Proto*	p;
	int sfd;
	int cfd;
	int dirno;
};

struct Proto
{
	char	*name;
	long (*read)(Conv*, void*, long);
	long (*write)(Conv*, void*, long);
	void (*clone)(Conv*);
	void (*connect)(Conv*);
	void (*announce)(Conv*);
	void (*listen)(Conv*, Conv*);
	void (*close)(Conv*);
	
	int	maxconv;
	Lock	l;
	int	x;
	int	stype;
	int	nc;
	Conv**	conv;
	Qid	qid;
};

void	pm_ipinit(void (*inst)(Proto*));

void	pm_hnputl(void*, ulong);
ulong	pm_nhgetl(void*);
void	pm_hnputs(void*, ushort);
ushort	pm_nhgets(void*);

#ifndef NODEFINE

#undef  ipinit
#define ipinit			pm_ipinit
#undef  hnputl
#define hnputl			pm_hnputl
#undef  nhgetl
#define nhgetl			pm_nhgetl
#undef  hnputs
#define hnputs			pm_hnputs
#undef  nhgets
#define nhgets			pm_nhgets

#endif
