#include "pcdefs.h"
#include "funcdef.h"
#include "../defs.h"
#include "../funcs.h"
#include "config.h"

#include "mbuf.h"

extern struct mbuf _near *mbfree, _near *mbprocess, _near * _near *mbnext;
extern struct mbuf mb[NMBUFS];
extern struct ebuf eb[NEBUFS+1];
extern int slip_mode;

char _far *environ;

int _near errno;
int _near neterrno;
char net_inited = 0;

char _near shared_buf[4096];

struct tcp_func {
	int (_fastcall *proc)(short _far *);
} _near tcp_funcs[] = {
	0,
	tcp_init,		/*  1 */
	tcp_shutdown,		/*  2 */
	tcp_socket,		/*  3 */
	tcp_info,		/*  4 */
	tcp_accept,		/*  5 */
	tcp_drain,		/*  6 */
	tcp_release,		/*  7 */
	tcp_eof,		/*  8 */
	tcp_read,		/*  9 */
	tcp_write,		/* 10 */
	tcp_recv,		/* 11 */
	tcp_sendto,		/* 12 */
	tcp_select,		/* 13 */
	0
};

#define n_funcs (sizeof (tcp_funcs) / sizeof (tcp_funcs[0]))

int
rpc_entry(buf, size)
short _far *buf;
int size;
{
    struct tcp_func near *nfp;
    int i;

    if (net_inited)
	netsleep();
    i = buf[0];
    nfp = &tcp_funcs[i];
    if ((unsigned)i >= n_funcs || !nfp->proc) {
	buf[0] = -1;
	buf[1] = i;
	buf[2] = NETERR_BADCALL;
	return 6;
    }
/*
if (nfp->proc != tcp_select) {
printd(i);
}
*/
    i = (nfp->proc)(buf);
    if (i < 0) {
	buf[0] = i;
	buf[1] = errno;
	buf[2] = neterrno;
/*
dfputs(":");
*/
	return 6;
    }
/*
if (nfp->proc != tcp_select)
dfputs(";");
*/
    return i;
}

char wattcp[] = "WATTCP.CFG";

int _fastcall
tcp_init(buf)
short _far *buf;
{
    char far *cp;

    dfputs("StarNet TCP/IP transport layer version 1.1\r\n");

    cp = getenv("CONFIG.TEL");
    if (!cp)
	cp = getenv("CONFIGTEL");
    if (cp) {
	if (Sconfigure(cp, 0) < 0)
	    return -1;
    } else {
	cp = getenv(wattcp);
	if (!cp)
	    cp = wattcp;
	if (Sconfigure(cp, 1) < 0)
	    return -1;
    }
    /* If user didn't specify rarp or give an IP address, then assume BOOTP */
    if ((Scon.flags & (H_MYIP|H_BOOTP|H_RARP)) == 0)
	Scon.flags |= H_BOOTP;

    if (pkopen(Scon.address, Scon.ioaddr, Scon.flags) < 0)
	return -1;

    intr_init();
    if (Scon.flags & H_BOOTP) {
	if (!Scon.broadcast)
	    Scon.broadcast = 0xffffffff;
	protinit();
	if (bootp_process()) {
	    pkclose();
	    intr_exit();
	    neterrno = NETERR_TIMEOUT;
	    return -1;
	}
	Scon.flags &= ~H_BOOTP;
	if (Scon.broadcast == 0xffffffff)
	    Scon.broadcast = 0;
    }
    if (Scon.flags & H_RARP) {
	if (slip_mode) {
	    pkclose();
	    intr_exit();
	    neterrno = NETERR_BADARGS;
	    return -1;
	}
	arpinit();
	if (rarp_process()) {
	    pkclose();
	    intr_exit();
	    neterrno = NETERR_TIMEOUT;
	    return -1;
	}
	Scon.flags &= ~H_RARP;
    }
    protinit();
    arpinit();
    net_inited++;

    buf[0] = 0;
    buf[2] = (u_short)(u_long)(char _far *)shared_buf;
    buf[3] = (u_short)((u_long)(char _far *)shared_buf >> 16);
    buf[4] = sizeof shared_buf;
    return 10;
}

int _fastcall
tcp_info(buf)
short _far *buf;
{
    buf[0] = 0;
    ((struct net_info _far *)&buf[1])->ip_address = Scon.myip;
    ((struct net_info _far *)&buf[1])->ip_broadcast = Scon.broadcast;
    return sizeof (struct net_info) + sizeof (short);
}
