/* 1645, Wed 28 Jan 97 */

#ifdef __unix__
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/* this nasty thang assumes that caller assigned the result of
 * tcp_open() or tcp_listen() to *statusptr just before calling us
 */
#define sock_wait_established( s, seconds, fn, statusptr ) \
    if( statusptr && !*statusptr ) goto sock_err;

#define inet_ntoa_unsafe(addr_struct) inet_ntoa(addr_struct)
#define inet_ntoa(buf,addr) inet_ntoa_safe(buf,addr)
/* Joel has redfined inet_ntoa() so as to provide a debugging hook -
   ignore the 'inet_ntoa redfined' warnings you may see */
#define tcp_set_debug_state(x)
#define sock_close(s) close(*s)
#define sock_dataready(s) dataready(*s)
#define sock_read(s,dp,len) read(*s,dp,len)
#define sock_write(s,dp,len) write(*s,dp,len)
#define sock_mode(s,newmode) the_tcp_mode=newmode
#define sock_yield(s,fn)
#define sock_abort(s) sock_close(s)

#define TCP_MODE_ASCII 1
#define TCP_MODE_BINARY 0
#define tcp_Socket int
extern int the_tcp_mode;

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Typedefs and constants
 */
typedef Bit8 byte;
typedef Bit16 word;
typedef Bit32 longword;

#define TCP_MODE_BINARY 0
#define TCP_MODE_ASCII  1

extern void sock_init( void );
extern int tcp_tick( void *s );
extern longword sock_set_rx_buf(void *s, byte *dp, longword len );
extern longword sock_set_tx_buf(void *s, byte *dp, longword len );
extern longword sock_gets( void  *s, byte *dp, longword n );
extern longword sock_puts( void  *s, byte *dp );
extern int tcp_open( void *s, word lport );
extern int tcp_listen(void *s, longword ina, word port, int (*datahandler)(), word timeout);
extern int tcp_connect(void *s, longword ina, word port, int (*datahandler)());
extern longword resolve( char *name);
extern char *inet_ntoa( char *s, longword x );
extern unsigned long set_timeout( unsigned int seconds );
extern unsigned long set_ttimeout( unsigned int ticks );
extern int chk_timeout( unsigned long timeout );

#ifdef __cplusplus
}        /* extern "C" { */
#endif

#else    /* !defined( __unix__ ) */
/*
 * Waterloo TCP
 *
 * Copyright (c) 1990, 1991, 1992, 1993 Erick Engelke
 *
 * Portions copyright others, see copyright.h for details.
 *
 * This library is free software; you can use it or redistribute under
 * the terms of the license included in LICENSE.H.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * file LICENSE.H for more details.
 *
 */
#ifndef WTCP_VER

/* handle some early dumb naming conventions */
#define dbuginit()      dbug_init()

/* Kernal version (major major minor minor) */
#define WTCP_VER 0x0102

#ifdef __cplusplus
#include "..\intel\timestmp.h"

extern "C" {
#endif

/*
 * Typedefs and constants
 */

#ifndef byte
typedef unsigned char byte;         /*  8 bits */
#endif  byte
#ifndef word
typedef unsigned short word;        /* 16 bits */
#endif  word
#ifndef longword
typedef unsigned long longword;     /* 32 bits */
#endif  longword

/*
 * Basic system type definitions, taken from the BSD file sys/types.h.
 */
typedef unsigned char   u_char;
typedef unsigned short  u_short;
typedef unsigned int    u_int;
typedef unsigned long   u_long;

typedef struct {
//  byte undoc[ 4300 ];         // actually 4238 w/2048 window
//  byte undoc[ 8400 ];         // actually 8334   4096
//  byte undoc[ 16600 ];        // actually 16384  16535
//  byte undoc[ 33000 ];        // actually 32915  32911  32910
//  byte undoc[ 270000 ];       // actually 262295
//  byte undoc[ 66000 ];        // actually 65687

//  byte undoc_tcp_h[16538];    // 8192-byte rx and tx buffers
//  byte undoc_tcp_h[16554];    // 8192-byte rx and tx buffers
//  byte undoc_tcp_h[16558];    // 8192-byte rx and tx buffers
//  byte undoc_tcp_h[16570];    // 8192-byte rx and tx buffers
    byte undoc_tcp_h[16568];    // 8192-byte rx and tx buffers
} tcp_Socket;

typedef struct {
//  byte undoc[ 2200 ];         // actually 2121 w/2048 window
//  byte undoc[ 4200 ];         // actually 4169   4096
//  byte undoc[ 16500 ];        // actually 16462  16458  16457  16384
//  byte undoc[ 1600 ];         // actually 1544 1552

//  byte undoc_tcp_h[1538];     // 1x single-packet rx buffer
//  byte undoc_tcp_h[1544];     // 1x single-packet rx buffer
    byte undoc_tcp_h[1548];     // 1x single-packet rx buffer
} udp_Socket;


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

#define sockaddr_in sockaddr

typedef struct in_addr {
    longword    s_addr;
};


/*
 * Constants and structures defined by the internet system,
 * Per RFC 790, September 1981, taken from the BSD file netinet/in.h.
 */

/*
 * Protocols
 */
#define IPPROTO_IP              0               /* dummy for IP */
#define IPPROTO_ICMP            1               /* control message protocol */
#define IPPROTO_GGP             2               /* gateway^2 (deprecated) */
#define IPPROTO_TCP             6               /* tcp */
#define IPPROTO_PUP             12              /* pup */
#define IPPROTO_UDP             17              /* user datagram protocol */
#define IPPROTO_IDP             22              /* xns idp */
#define IPPROTO_ND              77              /* UNOFFICIAL net disk proto */

#define IPPROTO_RAW             255             /* raw IP packet */
#define IPPROTO_MAX             256




#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

extern void sock_init( void );

/*
 *   s is the pointer to a udp or tcp socket
 */
extern void sock_yield( tcp_Socket *s, void (*fn)());
extern longword sock_read(void  *s, byte *dp, longword len );
extern longword sock_fastread(void  *s, byte *dp, longword len );
extern longword sock_write(void  *s, byte *dp, longword len);
extern longword sock_fastwrite(void *s, byte *dp, longword len );
extern longword sock_set_rx_buf(void *s, byte *dp, longword len );
extern longword sock_set_tx_buf(void *s, byte *dp, longword len );
extern sock_noflush( void  *s );
extern sock_flush( void  *s );
extern sock_flushnext( void  *s);
extern longword sock_puts( void  *s, byte *dp );
extern longword sock_gets( void  *s, byte *dp, longword n );
extern byte sock_putc( void  *s, byte c );
extern byte sock_getc( void  *s );
extern longword sock_dataready( void  *s );
extern void sock_close( void *s );
extern void sock_abort( void *s );
extern int sock_printf( void  *s, char *format, ... );
extern int sock_scanf( void  *s, char *format, ... );
extern longword sock_tunnel( void *s, longword tunneladdr );
extern byte sock_ttl( void *s, byte ttl );
extern word sock_mode( void *s, word mode );        /* see TCP_MODE_... */
extern longword sock_get_2msl_timeout( void *s );
extern void db_write( char *msg );
extern void dbug_init();
extern void dbug_printf(char *,... );

/*
 * TCP or UDP specific stuff, must be used for open's and listens, but
 * sock stuff is used for everything else
 */
extern int udp_open(void *s, word lport, longword ina, word port, int (*datahandler)());
extern int tcp_open(void *s, word lport);
extern int tcp_listen(void *s, longword ina, word port, int (*datahandler)(), word timeout);
extern int tcp_connect(void *s, longword ina, word port, int (*datahandler)());
extern char *rip( char *s );
extern longword resolve( char *name);

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

/*
 * 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;

        /*
         * tcp_init/tcp_shutdown
         *      - init/kill all tcp and lower services
         *      - only call if you do not use sock_init
         * (NOT RECOMMENDED)
         */
extern tcp_shutdown();
extern tcp_Init();

/*
 * things you probably won't need to know about
 */
    /*
     * sock_debugdump
     *  - dump some socket control block parameters
     * used for testing the kernal, not recommended
     */
extern sock_debugdump( void *s);
        /*
         * tcp_config - read a configuration file
         *            - if special path desired, call after sock_init()
         *            - null reads path from executable
         * see sock_init();
         */
extern tcp_config( char *path );
        /*
         * tcp_tick - called periodically by user application in sock_wait_...
         *          - returns 1 when our socket closes
         */
extern tcp_tick( void *s );
        /*
         * Retransmitter - called periodically to perform tcp retransmissions
         *          - normally called from tcp_tick, you have to be pretty
         *            low down to use this one
         */
extern tcp_Retransmitter();
        /*
         * tcp_set_debug_state - set 1 or reset 0 - depends on what I have done
         */
extern tcp_set_debug_state( word x );


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;
/*
 * 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 _ip_delay0( void *s, int seconds, int (*fn)(void *), void *statusptr );
extern int _ip_delay1( void *s, int seconds, int (*fn)(void *), void *statusptr );
extern int _ip_delay2( void *s, int seconds, int (*fn)(void *), void *statusptr );

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



extern int tcp_tick( void *s );

#define sock_wait_established( s, seconds, fn, statusptr ) \
    if (_ip_delay0( s, seconds, fn, statusptr )) goto sock_err;
#define sock_wait_input( s, seconds, fn , statusptr ) \
    if (_ip_delay1( s, seconds, fn, statusptr )) goto sock_err;
#define sock_tick( s, statusptr ) \
    if ( !tcp_tick(s)) { if (statusptr) *statusptr = 1 ; goto sock_err; }
#define sock_wait_closed(s, seconds, fn, statusptr )\
    if (_ip_delay2( s, seconds, fn, statusptr )) goto sock_err;

/* user initialization file */
extern void (*usr_init)();

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



extern void _eth_init();
extern byte *_eth_formatpacket( void *eth_dest, word eth_type );
extern void _eth_send( word len);
extern void _eth_free( void *buf);
extern byte *_eth_arrived( word *type_ptr);
extern void _eth_release();



/* bsd-similar stuff */

/* in pcbuf.c */
extern longword sock_rbsize( void *s );
extern longword sock_rbused( void *s );
extern longword sock_rbleft( void *s );
extern longword sock_tbsize( void *s );
extern longword sock_tbused( void *s );
extern longword sock_tbleft( void *s );
extern longword sock_preread( void *s, byte *dp, longword len );

/* in pcbsd.c */
extern _chk_socket( tcp_Socket *s );
extern char *sockerr( tcp_Socket *s );
extern char *sockstate( tcp_Socket *s );
extern char *gethostname( char *name, int length );
extern char *sethostname( char *string );

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

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

extern _survivebootp;
extern int sock_established( tcp_Socket *s);
extern 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 );

/* Nevil's extra routines*/

char *strmov(char *to,char *from);  /* Copy chars, return updated to */
int p_open(char *name,int oflags);  /* Open file on path */

#ifdef __cplusplus
}

/* these functions only work in C++ code
 * because they use C++ datatypes
 */
extern int _ping( longword host, word identifier, word sequence );
extern int _chk_ping( longword host, word *identifier, word *sequence, PentiumClock *delta_when );
#endif

#endif      // not included yet
#endif      /* not unix */
