/*
 * jam 841029-31
 */

#include "../h/param.h"
#include "../h/mbuf.h"
#include "../vnet/vnet.h"
#include "../conn/conn.h"
#include "../rpc/rpc.h"
#include "../s32/kstat.h"
#include "../rpc/rpc_stat.h"

extern connection_t *conn_findByAddress();
extern int rpc_debug;

rpc_input(m)
   struct mbuf *m;
{
	register rpc_header_t *pkt = mtod(m, rpc_header_t *);
	register connection_t *conn;

#ifdef	DEBUG
	if (rpc_debug)
		rpc_printdebug(pkt, 1);
#endif	DEBUG
	RPC_INCSTAT(inputs);
	/*
	 * If the packet is of an incompatible rpc version,
	 * or an unknown or down node,
	 * or from the wrong generation
	 * then just drop it.
	 */
	if (!rpc_versionCompat(pkt->version, RPC_VERSION) ||
	    (conn = conn_findByAddress(&pkt->source)) == NULL ||
	    conn->state != CONN_ACTIVE ||
	    pkt->sourcegen != conn->generation) {
		if (conn != NULL)
			conn_free(conn);
		rpc_freePkt(pkt);
		RPC_INCSTAT(dropped);
		return;
	}
	conn_free(conn);

	switch (pkt->type) {

	/*
	 * Client side.
	 */

	case RPCPKT_CALLACK:
		rpc_callAck(pkt);
		break;

	case RPCPKT_RETURN:
	case RPCPKT_ERROR:
		rpc_returnReceived(pkt);
		break;

	/*
	 * Server side.
	 */

	case RPCPKT_CALL:
		rpc_callReceived(pkt);
		break;

	case RPCPKT_RETURNACK:
		rpc_returnAck(pkt);
		break;

	/*
	 * Drop unknown rpc packet types (and assume
	 * they are from later versions of rpc).
	 */
	default:
		rpc_freePkt(pkt);
		RPC_INCSTAT(badpkts);
		break;
	}
}
