#ifndef net_h
#define net_h

/*
 * eTCP - TCP implementation
 * Copyright (c) 1990, 1999 Erick Engelke
 *
 */
#ifndef byte
typedef unsigned char byte;
#endif
#ifndef word
typedef unsigned int word;
#endif
#ifndef longword
typedef unsigned long longword;
#endif

#if !defined(__TURBOC__) && !defined(__BORLANDC__) && !defined(__DJGPP__)
#error Must have a compiler explicitly defined ... likely #define __DJGPP__
#endif


typedef struct {
#if defined(__TURBOC__)||defined(__BORLANDC__)
    byte undoc[ 4300 ];
#elif defined(__DJGPP__)
    byte undoc[ 4500 ];
#endif
} tcp_Socket;

typedef struct {
    byte undoc[ 2200 ];
} udp_Socket;


typedef struct sockaddr {
    word        s_type;
    word        s_port;
    longword    s_ip;
    byte        s_spares[6];    /* unused in TCP realm */
} sockaddr;

#define sockaddr_in sockaddr

typedef struct in_addr {
    longword    s_addr;
} in_addr;


#define MAX_COOKIES     10
#define MAX_NAMESERVERS 10

#define TCP_MODE_BINARY 0
#define TCP_MODE_ASCII	1
#define UDP_MODE_CHK	0	/*default to checksum */
#define UDP_MODE_NOCHK	2
#define TCP_MODE_NAGLE  0       /* Nagle algorithm */
#define TCP_MODE_NONAGLE 4


/*
 * less general functions
 */
extern longword aton( char *text );
extern int isaddr( char *text );
extern int tcp_cbreak( word mode );
extern longword intel( longword x );
extern word intel16( word x );

#ifdef __DJGPP__
#define usr_init      _w32_usr_init
#define usr_post_init _w32_usr_post_init
#define rip           _w32_rip
#endif

extern void (*usr_init)();
extern void (*usr_post_init)(void);

/*
 * timers
 */
extern void ip_timer_init( void *s , word delayseconds );
extern word ip_timer_expired( void *s );
        /*
         * TCP/IP system variables - do not change these since they
         *      are not necessarily the source variables, instead use
         *      ip_Init function
         */
extern longword my_ip_addr;
extern longword sin_mask;       /* eg.  0xfffffe00L */
extern word sock_delay;


extern int _last_cookie;
extern longword _cookie[MAX_COOKIES];

        /*
         * name domain constants
         */

extern char *def_domain;
extern longword def_nameservers[ MAX_NAMESERVERS ];


extern word wathndlcbrk;
extern word watcbroke;

extern unsigned long set_timeout( unsigned int seconds );
extern unsigned long set_ttimeout( unsigned int ticks );
extern int chk_timeout( unsigned long timeout );

extern void outs( char * string );
extern longword aton( char * string);
extern void _arp_register( longword use, longword instead_of );

/* bsd-similar stuff */

extern int sock_rbsize( void *s );
extern int sock_rbused( void *s );
extern int sock_rbleft( void *s );
extern int sock_tbsize( void *s );
extern int sock_tbused( void *s );
extern int sock_tbleft( void *s );


extern int _chk_socket( tcp_Socket *s );
extern char *inet_ntoa( char *s, longword x );
extern char *psocket( tcp_Socket *s );
extern longword inet_addr( char *s );
extern char *sockerr( tcp_Socket *s );
extern char *sockstate( tcp_Socket *s );
extern int getpeername( tcp_Socket *s, void *dest, int *len );
extern int getsockname(  tcp_Socket *s, void *dest, int *len );
extern longword gethostid( void );
extern longword sethostid( longword ip );
extern char *getdomainname( char *name, int length );
extern char *setdomainname( char *string );

#if defined(__TURBOC__)||defined(__BORLANDC__)
extern char *gethostname( char *name, int length );
#endif

extern char *sethostname( char *string );
extern word ntohs( word a );
extern word htons( word a );
extern longword ntohl( longword x );
extern longword htonl( longword x );

extern void _arp_register( longword use, longword instead_of );
extern int _arp_resolve( longword ina, void *ethap, int nowait );

extern int _survivebootp;
extern int sock_established( tcp_Socket *s);
extern int sock_stats( tcp_Socket *s, word *days, word *inactive, word *cwindow, word *avg, word *sd );
extern int addwattcpd( void (*p)() );
extern int delwattcpd( void (*p)() );
extern int tap_add( void *socket, void *userid );
extern void sock_giveslice( void *s );


#if !defined(ERTOS_NET_CORE)

extern void rt_sock_init( void );
#define sock_init() rt_sock_init()

extern int rt_sock_fastread(void  *s, byte *dp, int len );
#define sock_fastread( s, dp, len ) rt_sock_fastread( s, dp, len )

extern int rt_sock_fastwrite( void *s, byte *dp, int len );
#define sock_fastwrite( s, dp, len ) rt_sock_fastwrite( s, dp, len )

extern int rt_sock_read(void  *s, byte *dp, int len );
#define sock_read( s, dp, len )     rt_sock_read( s, dp, len )

extern int rt_sock_write(void  *s, byte *dp, int len );
#define sock_write( s, dp, len )    rt_sock_write( s, dp, len )

extern void rt_sock_enqueue(void  *s, byte *dp, int len);
#define sock_enqueue( s, dp, len )  rt_sock_enqueue( s, dp, len )

extern int rt_sock_flush( void  *s );
#define sock_flush( s )             rt_sock_flush( s )

extern int rt_sock_flushnext( void  *s);
#define sock_flushnext( s )         rt_sock_flushnext( s )

extern int rt_sock_puts( void  *s, byte *dp );
#define sock_puts( s , dp )         rt_sock_puts( s, dp )

extern word rt_sock_gets( void  *s, byte *dp, int n );
#define sock_gets( s , dp, n)       rt_sock_gets( s, dp, n )

extern byte rt_sock_putc( void  *s, byte c );
#define sock_putc( s, c )           rt_sock_putc( s, c )

extern byte rt_sock_getc( void  *s );
#define sock_getc( s )              rt_sock_getc( s )

extern word rt_sock_dataready( void  *s );
#define sock_dataready( s )         rt_sock_dataready( s )

extern word rt_sock_close( void *s );
#define sock_close( s )             rt_sock_close( s )

extern int rt_sock_abort( void *s );
#define sock_abort( s )             rt_sock_abort( s )

//extern sock_printf( void  *s, char *format, ... );
//extern sock_scanf( void  *s, char *format, ... );

extern int rt_sock_mode( void *s, word mode );
#define sock_mode( s, mode )        rt_sock_mode( s, mode )

/*
 * TCP or UDP specific stuff, must be used for open's and listens, but
 * sock stuff is used for everything else
 */
extern int rt_udp_open(void *s, word lport, longword ina, word port, int (*datahandler)());
#define udp_open( s, l, i, p, d )   rt_udp_open( s, l, i, p, d )

extern int rt_tcp_open(void *s, word lport, longword ina, word port, int (*datahandler)());
#define tcp_open( s, l, i, p, d )   rt_tcp_open( s, l, i, p, d )

extern int rt_tcp_listen(void *s, word lport, longword ina, word port, int (*datahandler)(), word timeout);
#define tcp_listen( s, l, i, p, d, t ) rt_tcp_listen( s, l, i, p, d, t );

extern int rt_tcp_established(void *s);
#define tcp_established( s )        rt_tcp_established( s )

extern longword rt_resolve( char *name);
#define resolve( name )             rt_resolve( name )

extern int rt_reverse_addr_lookup( longword ip, char *name );
#define reverse_addr_lookup( ip, name ) rt_reverse_addr_lookup( ip, name )

extern int rt_tcp_tick( void *s );
#define tcp_tick( s )               rt_tcp_tick( s )

/*
 * recv routines -- pcrecv.c
 */
extern int rt_sock_recv_init( void *s, void *space, word len );
#define sock_recv_init( s, space, len ) rt_sock_recv_init( s, space, len )

extern int rt_sock_recv_from( void *s, long *hisip, word *hisport, char *buffer, int len, word flags );
#define sock_recv_from( s, hi, hp, b, l, f ) rt_sock_recv_from( s, hi, hp, b, l, f )

extern int rt_sock_recv( void *s, char *buffer, int len, word flags );
#define sock_recv( s, b, l, f ) rt_sock_recv( s, b, l, f )

/*
 * sock_wait_... macros
 */
/*
 * sock_wait_established()
 *	- waits then aborts if timeout on s connection
 * sock_wait_input()
 *	- waits for received input on s
 *	- may not be valid input for sock_Gets... check returned length
 * sock_tick()
 *	- do tick and jump on abort
 * sock_wait_closed();
 *	- discards all received data
 *
 * jump to sock_err with contents of *statusptr set to
 *	 1 on closed
 *	-1 on timeout
 *
 */
extern int _rt_ip_delay0( void *s, int seconds, int (*fn)(), void *statusptr );
extern int _rt_ip_delay1( void *s, int seconds, int (*fn)(), void *statusptr );
extern int _rt_ip_delay2( void *s, int seconds, int (*fn)(), void *statusptr );

#define sock_wait_established( s, seconds, fn, statusptr ) \
    if (_rt_ip_delay0( s, seconds, fn, statusptr )) goto sock_err;
#define sock_wait_input( s, seconds, fn , statusptr ) \
    if (_rt_ip_delay1( s, seconds, fn, statusptr )) goto sock_err;
#define sock_tick( s, statusptr ) \
    if ( !rt_tcp_tick(s)) { if (statusptr) *statusptr = 1 ; goto sock_err; }
#define sock_wait_closed(s, seconds, fn, statusptr )\
    if (_rt_ip_delay2( s, seconds, fn, statusptr )) goto sock_err;

extern int _rt_ping( longword host, longword countnum, byte ttl, byte tos, longword *theid );
#define _ping( host, countnum, ttl, tos, theid)      _rt_ping( host, countnum, ttl, tos, theid )

extern longword _rt_chk_ping( longword host , longword *ptr);
#define _chk_ping( host, ptr )      _rt_chk_ping( host, ptr )

extern char *rip( char *s );


#endif // ERTOS_NET_CORE

#endif

