www.pudn.com > tcpipstack.rar > TINYTC3.C


/* TINYTC3.C - Tiny-TCP source fragment 
	Part 3 of the TCP layer. 
 
 * Copyright (C) 1986, IMAGEN Corporation 
 * "This code may be duplicated in whole or in part provided that [1] there 
 * is no commercial gain involved in the duplication, and [2] that this 
 * copyright notice is preserved on all copies. Any other duplication 
 * requires written notice of the author." 
 
|===================================================================| 
|  The author of this code hereby licenses all duplication and/or   | 
|  modification of this code, in whole or in part, consistent with  | 
|  the terms of the GNU Library General Public License.             | 
|              - Geoffrey H. Cooper 10/29/97                        | 
|===================================================================| 
 
|===================================================================| 
|  My changes can be considered public domain.  Geof's statement    | 
|  will cover everything.                                           | 
|              - Rick Rodman 09/02/97                               | 
|===================================================================| 
 
	941012	rr	split into fragments 
*/ 
 
#include "tinytcp.h" 
 
#include  
 
#ifdef PC 
#include  
#endif 
 
/* ----- globals from tinytcp.c ------------------------------------- */ 
 
extern	IP_Address	local_IP_address;	/* local IP address */ 
 
extern	int		tcp_id;			/* TCP ID, gets incremented */ 
 
extern	struct tcp_Socket *	tcp_allsocs;	/* socket linklist */ 
 
/* ----- retransmitter ---------------------------------------------- */ 
 
/* Retransmitter - called periodically to perform tcp retransmissions */ 
 
Void tcp_Retransmitter( Void ) { 
	S8	struct tcp_Socket *	s; 
	S8	short			x; 
 
	/* Go through all of the open sockets and see if there is 
		anything to send */ 
 
	for( s = tcp_allsocs; s; s = s -> next ) { 
		x = False; 
		if( s -> dataSize > 0 || s -> unhappy ) { 
 
			/* send the data */ 
 
			tcp_Send( s ); 
			x = True; 
		} 
 
		/* anything sent? */ 
 
		if( x || s -> state != TS_ESTAB ) 
			s -> timeout -= tcp_RETRANSMITTIME; 
 
		if( s -> timeout <= 0 ) { 
			if( s -> state == TS_TIMEWT ) { 
 
				printf( "Closed. [222]\n" ); 
 
				s -> state = TS_CLOSED; 
 
				/* cast to Procref removed on following */ 
 
				if( s -> dataHandler != 0 ) 
					( s -> dataHandler )(( void * ) s, 
						( Byte * ) 0, 0 ); 
				else	printf( "got close, no handler\n" ); 
 
				/* Unthread this socket from the linklist */ 
 
				tcp_Unthread( s ); 
			} else { 
				printf( "Timeout, aborting\n" ); 
				tcp_Abort( s ); 
			} 
		} 
	} 
} 
 
/* ----- Unthread a socket from the socket list, if it's there ------ */ 
 
Void tcp_Unthread( ds ) struct tcp_Socket *ds; { 
	S8	struct tcp_Socket *s, **sp; 
 
	if( ds == ( struct tcp_Socket * ) 0 ) return; 
 
	sp = &tcp_allsocs;			/* -> -> socket */ 
	for(;;) { 
		s = *sp;			/* what pointer points to */ 
		if( s == ( struct tcp_Socket * ) 0 ) break;	/* end of list? */ 
		if( s == ds ) {			/* matches one to delete? */ 
			*sp = s -> next;	/* unlink it from the list */ 
			break;			/* all done */ 
		} 
		sp = &s -> next;		/* move to the next one */ 
	} 
 
	ds -> next = ( struct tcp_Socket * ) 0;	/* clear next pointer */ 
} 
 
/* ----- busy-wait loop for tcp. Also calls an "application proc" --- */ 
 
int tcp( application ) 
#ifdef USE_TYPEDEFS 
	Procrefv application; 
#else 
	Void ( *application ) P(( void )); 
#endif 
{ 
	S8	struct in_Header *	ip; 
	S8	Longword		timeout, start; 
 
	sed_Receive( ( Byte * ) 0 ); 
 
	timeout = 0L; 
 
	/* There was a while( tcp_allsocs ) here. However, if we don't 
		have any open, we still want the program to loop, 
		so I changed it to for(;;). */ 
 
	for(;;) { 
		start = ( Longword ) MsecClock(); 
 
		/* Have we received a packet? */ 
 
		ip = ( struct in_Header * ) sed_IsPacket(); 
		if( ip == ( struct in_Header * ) 0 ) { 
 
			/* No, we haven't. */ 
 
			if( MsecClock() > timeout ) { 
 
				/* Anything to retransmit? */ 
 
				tcp_Retransmitter(); 
 
				/* Set next transmit time */ 
 
				timeout = MsecClock() 
					+ tcp_RETRANSMITTIME; 
			} 
 
			/* There's nothing to do. Let the user enter a 
				command. */ 
 
			application(); 
 
			continue; 
		} 
 
		/* We have received a packet. Process it */ 
 
#ifdef ETHERNET 
		/* ARP protocol is supported on ethernet only */ 
 
		if( sed_CheckPacket( ( Word * ) ip, 0x806 ) == 1 ) { 
 
			/* do arp */ 
 
			sar_CheckPacket( ( struct arp_Header * ) ip ); 
 
		} else 
#endif	/* ethernet */ 
		if( sed_CheckPacket( ( Word * ) ip, 0x800 ) == 1 ) { 
 
			/* do IP */ 
 
			if( rev_longword( ip -> destination ) != 
				local_IP_address ) { 
				printf( "IP address doesn't match\n" ); 
 
				/* But ignore that for now (SLIP) */ 
			} 
 
			if( checksum( ( Word * ) ip, IP_HBYTES( ip )) 
				!= 0xFFFF ) { 
				printf( "Checksum bad\n" ); 
 
				/* But ignore that, too, for now (SLIP) */ 
			} 
 
			if( IP_PROTOCOL( ip ) == 6 )		/* tcp/ip */ 
				tcp_Handler( ip ); 
 
			/* protocol 1 is icmp. the first byte of the data 
				is an 8 for ping (echo) requests; the reply 
				Byte should have a zero */ 
		} 
 
		/* recycle buffer */ 
 
		sed_Receive( ( Byte * ) ip ); 
 
		/* How much time elapsed as we were processing the 
			packet? */ 
		/* rr doesn't see the point of this 
		x = ( int )( MsecClock() - start ); 
		timeout -= ( Longword ) x; 
		rr doesn't see the point of this */ 
	} 
 
	return 1;	/* Actually unreachable, but Microsoft C gives you 
				a 'no return value' error. */ 
} 
 
/* end of tinytc3.c */