PCTCP.C
资源名称:wattcp.rar [点击查看]
上传用户:better800
上传日期:2022-06-13
资源大小:1853k
文件大小:93k
源码类别:
TCP/IP协议栈
开发平台:
DOS
- /* DEBUG flag may be set for my internal playing */
- /*
- #define DEBUG
- */
- /*
- * PCTCP - the true worker of Waterloo TCP
- * - contains all opens, closes, major read/write routines and
- * basic IP handler for incomming packets
- * - NOTE: much of the TCP/UDP/IP layering is done at the data structure
- * level, not in separate routines or tasks
- *
- */
- #include <copyright.h>
- #include <time.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <string.h>
- #include <mem.h>
- #include <dos.h>
- #include <values.h>
- #include "wattcp.h"
- #include "elib.h"
- static void udp_handler(in_Header *ip);
- static udp_write(udp_Socket *s, byte *datap, int len, word offset);
- static int udp_read(udp_Socket *s, byte *datap, int maxlen);
- static void tcp_Retransmitter(void);
- #define TCP_LOCAL 0x4000
- #define TCP_SAWCR 0x2000 // S. Lawson
- /* statics */
- //static tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len);
- static void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len, // 94.11.19
- tcp_PseudoHeader *ph, word *flags); // S. Lawson
- static char far *mono = (char far *)0xb0000000L;
- static char far *colour = (char far *)0xb8000000L;
- static initialized = 0;
- void (*system_yield)() = NULL; /* 2000.4.14 EE */
- extern int multihomes;
- extern word _pktipofs;
- void (*_dbugxmit)( sock_type *s, in_Header *inp, void *phdr, unsigned line ) = NULL;
- void (*_dbugrecv)( sock_type *s, in_Header *inp, void *phdr, unsigned line ) = NULL;
- void (*wattcpd)(void) = NULL;
- char *_hostname = "012345678901234567890123456789012345678901234567890";
- word _mss = ETH_MSS; // maximum size of *IP DATAGRAM*
- word sock_data_timeout = 120; /* after 2 minutes we give up EE 99.08.23 */
- char *_wattcp = WATTCP_C;
- static void tcp_handler(in_Header *ip);
- static void udp_handler(in_Header *ip);
- static void tcp_unthread(tcp_Socket *ds);
- static void tcp_abort(tcp_Socket *s);
- void tcp_sendsoon(tcp_Socket *s );
- static void tcp_send(tcp_Socket *s, int line);
- static void tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp);
- static udp_close(udp_Socket *ds);
- // AGW
- // unsigned long later than for seq and ack comparisons -- allow for roll over
- #define laterthan(x,y) ((long)((x)-(y))>0)
- /*
- * sock_yield - enable user defined yield function
- */
- int sock_yield( tcp_Socket *s, void (*fn)( void ) )
- {
- if ( s )
- s->usr_yield = fn;
- else
- system_yield = fn;
- return( 0 );
- }
- /*
- * sock_mode - set binary or ascii - affects sock_gets, sock_dataready
- * - set udp checksums
- */
- word sock_mode( sock_type *s, word mode )
- {
- return( s->tcp.sock_mode = (s->tcp.sock_mode & 0xfffc) | mode);
- }
- /*
- * ip user level timer stuff
- * void ip_timer_init( void *s, int delayseconds )
- * int ip_timer_expired( void *s )
- * - 0 if not expired
- */
- static unsigned long far *realclock = (unsigned long far *)0x000046cL;
- #define MAXTICKS 0x1800b0L
- void ip_timer_init( sock_type *s , int delayseconds )
- {
- if (delayseconds)
- s->tcp.usertimer = set_timeout( delayseconds );
- else
- s->tcp.usertimer = 0;
- }
- int ip_timer_expired( sock_type *s )
- {
- if (! s->tcp.usertimer) /* cannot expire */
- return( 0 );
- return( chk_timeout( s->tcp.usertimer));
- }
- longword MsecClock( void )
- {
- return( (*realclock) * 055L);
- }
- static long make_timeout( word timeout )
- {
- if ( timeout ) return( set_timeout( timeout ));
- return( 0 );
- }
- #ifdef NOTUSED /* 94.11.27 -- not used? */
- /*
- * check_timeout - test agains timeout clock - account for overflow
- */
- static int check_timeout( unsigned long timeout )
- {
- if (timeout) return( chk_timeout( timeout ));
- return( 0 );
- }
- #endif
- /*
- * Local IP address
- */
- longword my_ip_addr = 0L; /* for external references */
- longword sin_mask = 0xfffffe00L;
- longword sin_gate = 0x0;
- /*
- * IP identification numbers
- */
- static int ip_id = 0; /* packet number */
- static int next_tcp_port = 1024; /* auto incremented */
- static int next_udp_port = 1024;
- //static
- tcp_Socket *tcp_allsocs = NULL;
- static udp_Socket *udp_allsocs = NULL;
- /* Timer definitions */
- #define RETRAN_STRAT_TIME 1 /* in ticks - how often do we check retransmitter tables*/
- #define tcp_RETRANSMITTIME 3 /* interval at which retransmitter is called */
- #define tcp_LONGTIMEOUT 31 /* timeout for opens */
- #define tcp_TIMEOUT 13 /* timeout during a connection */
- #define LASTACK_TIMEOUT 10 // timeout in the LASTACK state added AGW 5th Jan 2001
- // S. Lawson - define a short TIME_WAIT timeout that can be set in the
- // makefile. It should be from .5 to 4 minutes (2MSL) but it's
- // not really practical for us. 2 secs will hopefully handle the
- // case where ACK must be retransmitted, but can't protect future
- // connections on the same port from old packets.
- #if !defined(TW_TO)
- #define TW_TO 2
- #endif
- word debug_on = 0;
- /*
- * look for bugs
- */
- int tcp_checkfor( sock_type *t )
- {
- tcp_Socket *p;
- for ( p = tcp_allsocs ; p ; p = p->next )
- if ( p == (tcp_Socket *)t ) return( 1 );
- return( 0 );
- }
- /*
- * Shut down the card and all services
- */
- void tcp_shutdown( void )
- {
- while (tcp_allsocs)
- tcp_abort( tcp_allsocs );
- _eth_release();
- initialized = 0;
- }
- // S. Lawson - keep an exiting tcp_init()
- void tcp_init( void )
- {
- int r;
- r=tcp_init_noexit();
- if (r) exit(r);
- }
- /*
- * tcp_init - Initialize the tcp implementation
- * - may be called more than once without hurting
- */
- int tcp_init_noexit( void ) // S. Lawson
- {
- extern int _arp_last_gateway;
- extern int _last_nameserver;
- if (!initialized) {
- /* initialize ethernet interface */
- initialized = 1;
- // S. Lawson _eth_init();
- if (_eth_init()) return 1; // S. Lawson
- /* reset the various tables */
- _arp_last_gateway = 0; /* reset the gateway table */
- _last_nameserver = 0; /* reset the nameserver table */
- _last_cookie = 0; /* eat all remaining crumbs */
- *_hostname = 0; /* reset the host's name */
- _eth_free( 0 );
- next_udp_port = next_tcp_port = 1024 + ((int)(*realclock >> 7 )& 0x1ff);
- }
- return 0; // S. Lawson
- }
- // S. Lawson - initialize the port number counters
- void tcp_set_ports(word tcp_base, word udp_base) {
- if (tcp_base) next_tcp_port=(int) tcp_base;
- if (udp_base) next_udp_port=(int) udp_base;
- }
- // S. Lawson - return current port number counters
- void tcp_get_ports(word *tcp_base, word *udp_base) {
- if (tcp_base) *tcp_base=(word) next_tcp_port;
- if (udp_base) *udp_base=(word) next_udp_port;
- }
- /*
- * Checks for bugs when compiling in large model C compiler
- *
- * Borland C uses a 4K stack by default. In all memory models the
- * stack grows down toward the heap.
- *
- * If you accidentally place tcp_Socket onto the stack (like by making
- * it an automatic variable), then you will have already used up that
- * whole 4K and then some!
- *
- * In large model, this will mess up the data space in a major way
- * because the stack starts at SS:_stklen, or SS:1000, so you will
- * wrap the SP pointer back around to FFFE and start writing over
- * the far heap. Yuck.
- *
- * In small model it usually doesn't kill your application because
- * you would have to be down to your last 4K of memory and this is
- * not as common.
- *
- * The solutions: declare your sockets as static, or put them on the
- * heap, or bump up your stack size by using the global special variable:
- *
- * unsigned _stklen = 16536; // set stack to 16 k
- */
- static void largecheck( void *s, int size )
- {
- #ifdef __TURBOC__
- if ( (word)(FP_OFF(s)) > (word)(-size)) {
- outs("ERROR: user stack size errorn");
- exit( 3 );
- }
- #endif
- }
- /*
- * findfreeport - return unused local port
- * - oldport = 0:normal port, 1:special port (513-1023)
- * - we need not be this picky, but it doesn't hurt
- * S. Lawson - added TCP/UDP flag so we can pick unique ports and
- * avoid reconnecting with a socket in TIME_WAIT (the
- * original "oldport+510" scan needs a rewrite someday)
- */
- static word findfreeport( word oldport, word proto_tcp )
- {
- word temp;
- tcp_Socket *s;
- // S. Lawson - s/b > 1 if (( oldport > 0 ) && (oldport < 0xffff))
- if (( oldport > 1 ) && (oldport < 0xffff)) // S. Lawson
- return( oldport );
- // S. Lawson - start
- // if ( oldport == 0 ) oldport = 1025;
- if ( oldport == 0) {
- if (proto_tcp) {
- if ((oldport=next_tcp_port++)>=32767-510) next_tcp_port=1024;
- } else {
- if ((oldport=next_udp_port++)>=32767-510) next_udp_port=1024;
- }
- }
- // S. Lawson - end
- else oldport = 513;
- for ( temp = oldport ; temp < oldport + 510 ; ++temp ) {
- if (!proto_tcp) { // S. Lawson
- if (( s = (tcp_Socket*)udp_allsocs) != NULL ) {
- while ( s->next && (s->myport != temp))
- s = (tcp_Socket*)s->next;
- if ( s->myport == temp ) continue;
- }
- } else { // S. Lawson
- if ( (s = tcp_allsocs ) != NULL ) {
- while ( s->next && (s->myport != temp ))
- s = s->next;
- if ( s->myport == temp ) continue;
- }
- } // S. Lawson
- break;
- }
- return( temp );
- }
- /* socket, localport, destaddress */
- int udp_open( udp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler )
- {
- udp_close( s );
- largecheck( s, sizeof( udp_Socket ));
- memset( s, 0, sizeof( udp_Socket ));
- s->rdata = s->rddata;
- s->maxrdatalen = tcp_MaxBufSize;
- s->ip_type = UDP_PROTO;
- lport = findfreeport(lport, false); // S. Lawson - added "false"
- s->myport = lport;
- s->myaddr = my_ip_addr;
- /* check for broadcast */
- if ( (long)(ina) == -1 )
- memset( &s->hisethaddr, 0xff, sizeof( eth_address ));
- // EE 2000.9.13
- // handle late binding IP
- else if ( ina == 0 )
- // Changed. EE 2000.9.13 we want this zeroed so udp_writes will arp_resolve
- // once we have bound to a particular IP and
- memset( &s->hisethaddr, 0x00, sizeof( eth_address ));
- else if ( ! _arp_resolve(ina, &s->hisethaddr, 0) )
- return( 0 );
- s->hisaddr = ina;
- s->hisport = port;
- s->dataHandler = datahandler;
- s->usr_yield = system_yield;
- s->safetysig = SAFETYUDP;
- s->next = udp_allsocs;
- udp_allsocs = s;
- return( 1 );
- }
- /*
- * Actively open a TCP connection to a particular destination.
- * - 0 on error
- */
- int tcp_open( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler )
- {
- largecheck( s, sizeof( tcp_Socket )); /* stack space warnings */
- tcp_unthread(s); /* just in case not totally closed */
- memset( s, 0, sizeof( tcp_Socket));
- s->rdata = s->rddata;
- s->maxrdatalen = tcp_MaxBufSize;
- s->ip_type = TCP_PROTO;
- // S. Lawson - _mss is *IP DATAGRAM* size, set TCP MSS here
- // s->mss = _mss;
- s->mss = _mss - sizeof( in_Header ) - sizeof ( tcp_Header );
- s->state = tcp_StateSYNSENT;
- s->timeout = set_timeout( tcp_LONGTIMEOUT );
- s->cwindow = 1;
- s->wwindow = 0; /* slow start VJ algorithm */
- s->vj_sa = 4; /* about 250 ms */
- lport = findfreeport( lport, true ); /* get a nonzero port val (S. Lawson - added true) */
- s->myaddr = my_ip_addr;
- s->myport = lport;
- if ( ina - my_ip_addr <= multihomes ) return( 0 );
- if ( ! _arp_resolve(ina, &s->hisethaddr, 0) )
- return( 0 );
- s->hisaddr = ina;
- s->hisport = port;
- s->seqnum = intel( set_timeout( 1 )) & 0xffff0000uL;
- s->datalen = 0;
- s->flags = tcp_FlagSYN;
- s->unhappy = true;
- s->dataHandler = datahandler;
- s->usr_yield = system_yield;
- s->frag[0]=s->frag[1]=0L; // S. Lawson
- s->safetysig = SAFETYTCP; /* insert into chain */
- s->next = tcp_allsocs;
- tcp_allsocs = s;
- s->rtt_delay = s->rtt_smooth = 18; /* one second startup */
- tcp_send(s, __LINE__ );
- s->rtt_time = set_timeout( 1 );
- return( 1 );
- }
- /*
- * Passive open: listen for a connection on a particular port
- */
- int tcp_listen( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler, word timeout )
- {
- largecheck( s, sizeof( tcp_Socket ));
- tcp_unthread(s); /* just in case not totally closed */
- memset( s, 0, sizeof( tcp_Socket));
- s->rdata = s->rddata;
- s->maxrdatalen = tcp_MaxBufSize;
- s->ip_type = TCP_PROTO;
- // S. Lawson - _mss is *IP DATAGRAM* size, set TCP MSS here
- // s->mss = _mss;
- s->mss = _mss - sizeof( in_Header ) - sizeof ( tcp_Header );
- s->cwindow = 1;
- s->wwindow = 0; /* slow start VJ algorithm */
- /* s->vj_sa = 36; /* about 250 ms */
- /* tcpwinfix -- mdurkin */
- s->vj_sa = 4; /* about 250 ms */ /* was wrong val 95.05.02 */
- s->state = tcp_StateLISTEN;
- if ( !timeout ) s->timeout = 0; /* forever... */
- else s->timeout = set_timeout( timeout );
- lport = findfreeport( lport, true ); /* get a nonzero port val (S. Lawson - added true)*/
- s->myport = lport;
- s->hisport = port;
- s->hisaddr = ina;
- s->seqnum = intel( (word)(s));
- s->datalen = 0;
- s->flags = 0;
- s->unhappy = false;
- s->dataHandler = datahandler;
- s->usr_yield = system_yield;
- s->frag[0]=s->frag[1]=0L; // S. Lawson
- s->safetysig = SAFETYTCP; /* insert into chain */
- s->next = tcp_allsocs;
- tcp_allsocs = s;
- return( 1 );
- }
- static udp_close( udp_Socket *ds )
- {
- udp_Socket *s, **sp;
- sp = &udp_allsocs;
- for (;;) {
- s = *sp;
- if ( s == ds ) {
- *sp = s->next;
- break;
- }
- if ( !s ) break;
- if ( ! s->err_msg ) s->err_msg = "UDP Close called";
- sp = &s->next;
- }
- return( 0 );
- }
- /*
- * Send a FIN on a particular port -- only works if it is open
- * Must still allow receives
- */
- static void tcp_close( tcp_Socket *s )
- {
- if ( s->ip_type != TCP_PROTO )
- return;
- if ( s->state == tcp_StateESTAB ||
- s->state == tcp_StateESTCL ||
- s->state == tcp_StateSYNREC )
- {
- if ( s->datalen ) /* must first flush all data */
- {
- s->flags |= tcp_FlagPUSH | tcp_FlagACK;
- if ( s->state < tcp_StateESTCL )
- {
- s->state = tcp_StateESTCL;
- tcp_sendsoon( s );
- }
- }
- else
- { /* really closing */
- s->flags = tcp_FlagACK | tcp_FlagFIN;
- if (!s->err_msg)
- s->err_msg = "Connection closed normally";
- s->state = tcp_StateFINWT1;
- s->timeout = set_timeout( tcp_TIMEOUT ); /* should be a pretty lengthy time */ /* S. Lawson - make longer */
- tcp_send( s, __LINE__ );
- }
- s->unhappy = true;
- }
- else if (s->state == tcp_StateCLOSWT )
- { /* need to ack the fin and get on with it */
- s->timeout = set_timeout( LASTACK_TIMEOUT ); // Added AGW 6 Jan 2001
- s->state = tcp_StateLASTACK;
- s->flags |= tcp_FlagFIN;
- tcp_send( s, __LINE__ );
- s->unhappy = true;
- // S. Lawson - Added per (10-Jun 1997, GV)
- }
- else if (s->state == tcp_StateSYNSENT)
- {
- s->state = tcp_StateCLOSED;
- tcp_unthread (s); /* unlink failed connect */
- }
- }
- /*
- * Abort a tcp connection
- */
- static void tcp_abort( tcp_Socket *s )
- {
- if (!s->err_msg) s->err_msg = "TCP_ABORT";
- if ( s->state != tcp_StateLISTEN && s->state != tcp_StateCLOSED ) {
- s->flags = tcp_FlagRST | tcp_FlagACK ;
- s->unhappy = true;
- tcp_send(s, __LINE__);
- }
- s->unhappy = false;
- s->datalen = 0;
- s->ip_type = 0;
- s->state = tcp_StateCLOSED;
- /* if (s->dataHandler) s->dataHandler(s, 0, -1); */
- tcp_unthread(s);
- }
- void sock_abort( sock_type *s )
- {
- if ( s->tcp.ip_type == TCP_PROTO )
- tcp_abort( (tcp_Socket *)s );
- else
- udp_close( (udp_Socket *)s );
- }
- /*
- * tcp_sendsoon - schedule a transmission pretty soon
- * - this one has an imperfection at midnight, but it
- * is not significant to the connection performance
- */
- void tcp_sendsoon( tcp_Socket *s )
- {
- longword temp;
- if (s->ip_type == TCP_PROTO ) {
- temp = set_ttimeout( 1 );
- if ( temp == s->rtt_time && s->rto < 2 && s->recent == 0 ) {
- s->karn_count = 0;
- tcp_send( s, __LINE__ );
- s->recent = 1;
- return;
- }
- if ((s->unhappy || s->datalen > 0 || s->karn_count == 1)
- && (s->rtt_time < temp && s->rtt_time != 0)) // S. Lawson - handle 0
- return;
- s->rtt_time = set_ttimeout( 1 + (s->rto >> 4) );
- s->karn_count = 1;
- }
- }
- /*
- * Retransmitter - called periodically to perform tcp retransmissions
- */
- static longword retran_strat = 0L; /* timeout retran strategy */
- static void tcp_Retransmitter( void )
- {
- tcp_Socket *s;
- /* only do this once per RETRAN_STRAT_TIME milliseconds */
- if ( !chk_timeout( retran_strat ))
- return;
- retran_strat = set_ttimeout( RETRAN_STRAT_TIME );
- for ( s = tcp_allsocs; s; s = s->next ) {
- // S. Lawson - possible to be closed but still queued
- if ( s->state==tcp_StateCLOSED ) {
- if ( s->rdatalen == 0) tcp_unthread(s);
- continue;
- }
- if ( s->datalen > 0 || s->unhappy || s->karn_count == 1 ) {
- /* retransmission strategy */
- // S. Lawson - clear the timeout once it fires (thanks GV)
- #ifdef NOTUSED
- if ( chk_timeout( s->rtt_time)) {
- #else
- if ( s->rtt_time && chk_timeout( s->rtt_time )) {
- s->rtt_time = 0;
- #endif
- #ifdef DEBUG
- if(debug_on >1) printf("regular retran TO set unacked back to 0 from %un", s->unacked);
- #endif //DEBUG
- /* strategy handles closed windows J.D. + E.E. */
- if (s->window == 0 && s->karn_count == 2)
- s->window = 1;
- if ( s->karn_count == 0 ) {
- /* if really did timeout */
- s->karn_count = 2;
- s->unacked = 0;
- /* use the backed off rto - implied, no code necessary */
- /* reduce the transmit window */
- s->cwindow = ((s->cwindow + 1) * 3) >> 2;
- if ( s->cwindow == 0 ) s->cwindow = 1;
- s->wwindow = 0;
- }
- if (s->datalen)
- s->flags |= tcp_FlagPUSH | tcp_FlagACK;
- tcp_send(s, __LINE__);
- }
- /* EE 99.08.23 */
- if ( s->datatimer )
- if ( chk_timeout( s->datatimer )) {
- sock_abort( (sock_type *) s );
- }
- }
- /* handle inactive tcp timeouts */
- if ( sock_inactive && s->inactive_to ) {
- if ( chk_timeout( s->inactive_to)) {
- /* this baby has timed out */
- s->err_msg = "Connection timed out - no activity";
- sock_close( (sock_type *) s );
- }
- }
- if ( s->timeout && chk_timeout( s->timeout)) {
- if ( s->state == tcp_StateTIMEWT ) {
- s->state = tcp_StateCLOSED;
- tcp_unthread(s);
- break;
- } else if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL ) {
- s->err_msg = "Timeout, aborting";
- tcp_abort(s);
- break;
- }
- }
- }
- /* do our various daemons */
- if ( wattcpd ) (*wattcpd)();
- }
- /*
- * Unthread a socket from the tcp socket list, if it's there
- */
- static void tcp_unthread( tcp_Socket *ds )
- {
- tcp_Socket *s, **sp;
- if (!ds->rdatalen || (ds->state > tcp_StateESTCL))
- ds->ip_type = 0; /* fail io */
- ds->state = tcp_StateCLOSED; /* tcp_tick needs this */
- sp = &tcp_allsocs;
- for (;;) {
- s = *sp;
- if ( s == ds )
- {
- *sp = s->next;
- continue; /* unthread multiple copies if necessary */
- }
- if ( !s ) break;
- sp = &s->next;
- }
- }
- /*
- * tcp_tick - called periodically by user application
- * - returns 1 when our socket closes (S. Lawson - wrong: 0)
- * - called with socket parameter or NULL
- */
- int tcp_tick( sock_type *s )
- {
- in_Header *ip;
- static longword timeout = 0;
- static longword start = 0;
- extern int dhcp_expired(void); /* S. Lawson - in pcbootp.c */
- /* int x; */
- int packettype;
- /* S. Lawson - handle DHCP lease expiration */
- if (dhcp_expired()) {
- if ( s ) s->udp.err_msg = "DHCP lease expired";
- return 0;
- }
- /* finish off dead sockets */
- if ( s ) {
- if (( s->tcp.ip_type == TCP_PROTO ) &&
- ( s->tcp.state == tcp_StateCLOSED ) &&
- ( s->tcp.rdatalen == 0 )) {
- tcp_unthread( & s->tcp );
- s->tcp.ip_type = 0;
- }
- }
- /* plan our next retransmit */
- if ( !timeout )
- timeout = make_timeout( tcp_RETRANSMITTIME );
- while ( (ip = (in_Header *)_eth_arrived( (word *) &packettype )) != NULL )
- {
- start = *realclock;
- switch ( packettype )
- {
- case /*0x800*/ 0x008 :
- /* do IP */
- if ( checksum(ip, in_GetHdrlenBytes(ip)) == 0xffff ) {
- switch ( ip->proto ) {
- case TCP_PROTO :
- tcp_handler(ip);
- break;
- case UDP_PROTO :
- udp_handler(ip);
- break;
- case ICMP_PROTO :
- icmp_handler(ip);
- break;
- }
- } else {
- #ifdef DEBUG
- if (debug_on) outs("nrIP: Bad Checksumnr"); // R. Whitby
- #endif
- }
- break;
- case /*0x806*/ 0x608 :
- /* do arp */
- _arp_handler( (arp_Header *)ip );
- break;
- }
- if (ip) _eth_free(ip);
- continue;
- }
- /* check for our outstanding packets */
- tcp_Retransmitter();
- // S. Lawson return( s->udp.ip_type );
- return( s ? s->udp.ip_type : 1 ); /* S. Lawson - change CJ01 */
- }
- void tcp_set_debug_state( int x )
- {
- debug_on = x;
- }
- /* returns 1 if connection is established */
- int tcp_established( tcp_Socket *s )
- {
- return( s->state >= tcp_StateESTAB );
- }
- /*
- * udp_write() handles fragmented UDP by assuming it'll be called
- * once for all fragments with no intervening calls. This is
- * the case in sock_write().
- * Handles upto a hair-under 32K datagrams. Could be made to handle
- * upto a hair-under 64K easily... wanna Erick?
- * Might be possible to test 'offset' for non/zero fewer times to be
- * more efficient. Might also be more efficient to use the old
- * UDP checksum() call when more_frags is false in the first frag
- * (i.e., not a fragmented dgram).
- * Uses _mss to decide splits which defaults to 1400. Could pack
- * more into an Ethernet packet.
- */
- #define IP_MF 0x0020 // more fragments, net byte order
- static udp_write( udp_Socket *s, byte *datap, int len, word offset )
- {
- struct { // special pseudo header because need to
- tcp_PseudoHeader ph; // compute checksum in two parts (may not
- word checksum2; // have all of datagram built at once).
- } ph;
- struct _pkt {
- in_Header in;
- udp_Header udp;
- int data;
- /* longword maxsegopt; */
- } *pkt;
- byte *dp;
- in_Header *inp;
- udp_Header *udpp;
- word maxlen;
- int more_frags;
- word origlen = len;
- // S. Lawson - set Ethernet address if not set (possible if we were
- // a passive/broadcast socket
- if (memcmp(&s->hisethaddr, "