www.pudn.com > watsock.zip > WATSOCK.C


#include  
#include  
#include  
#include  
#include  
#include  
#include "tcp.h"      /* must include before watsock.h */ 
#include "watsock.h" 
 
#define MAX_LEN  8192 
static L_SOCKET local_socket[MAX_SOCK];   /* an array of sockets */ 
static int lasterror = 0 ; 
 
extern void sock_exit(void); 
extern int sock_init(void); 
extern void sock_yield(tcp_Socket *s, void(*yield_fn)()); 
extern int sock_preread(void *s, byte *dp, int len); 
extern int sock_recv( void *s, char *buffer, int len ); 
extern sock_recv_init( void *s, void *space, int len ); 
 
/* --- DLL initialization --- */ 
 
int PASCAL FAR LibMain(HANDLE hInstance, WORD wDataSeg, WORD wHeapSize, LPSTR lpCmdLine) 
{ 
    return(1); 
} /* LibMain */ 
 
void free_socket(SOCKET s) 
{ 
  local_socket[s].type = 0 ; 
  local_socket[s].conn = NOTCONNECT; 
  local_socket[s].status = CLOSE ; 
  if( local_socket[s].tsock != NULL ) { 
      free(local_socket[s].tsock) ; 
      local_socket[s].tsock = NULL;            /* make sure they are NULL */ 
  } 
}    
 
int PASCAL FAR wattcp_init(void) 
{ 
    int i ; 
    for(i=0; i < MAX_SOCK; i++) { 
	local_socket[i].tsock = NULL;    /* make sure they are NULL */ 
	local_socket[i].conn = NOTCONNECT ; 
	local_socket[i].status = CLOSE ; 
    } 
    i = sock_init() ;                          /* starts the wattcp kernal */ 
    /* sock_yield(NULL,Yield);*/  /* set up to yield windows' function */ 
    return (1) ; 
} 
 
/* --- Windows Socket API --- */ 
 
/* socket - create a socket */ 
SOCKET PASCAL FAR wat_socket(int domain, int type, int protocol) 
{ 
    int i ; 
    /* search for the available socket */ 
    for (i=0; i < MAX_SOCK; i++) { 
	 if ( local_socket[i].status == CLOSE ) { 
	      local_socket[i].status = OPEN; 
	      break ; 
	 } 
    } 
    if(i > MAX_SOCK) 
       return(WSAEMFILE); 
    if( (type != SOCK_STREAM) && (type != SOCK_DGRAM) ) 
       return(WSAESOCKTNOSUPPORT); 
    local_socket[i].type = type ; 
    return(i); 
} /* wat_socket */ 
 
 
/* connect - establish a connection to a peer */ 
int PASCAL FAR wat_connect(SOCKET s, struct sockaddr FAR *name, int namelen) 
{ 
    int type ; 
    longword host ; 
    word port, status = 1; 
    tcp_Socket *lsocket;   
     
    if( local_socket[s].status != OPEN ) 
	return(WSAENOTSOCK);            /* s is not a socket */ 
    if( local_socket[s].conn == ISCONNECT )  
	return(WSAEISCONN);             /* socket is in used */ 
    if( !(host = name->s_ip) ) 
	return(WSAEADDRNOTAVAIL); 
    if( !name->s_port )   
	return(WSAEDESTADDRREQ); 
     
    port = ntohs(name->s_port) ;   /* tcp_open uses host order */ 
     
    if( local_socket[s].tsock == NULL) 
	lsocket = local_socket[s].tsock = malloc(sizeof(tcp_Socket)); 
    if( lsocket == NULL ) 
	return(WSAENOBUFS) ;     /* can't allocate any space */ 
     
    if ( local_socket[s].type  == SOCK_STREAM ) {             
	 if (!tcp_open(lsocket,0,host,port,NULL)) { 
	     free_socket( s ) ; 
	     return(WSAENETUNREACH);             /* open fail */ 
	 } 
	 /* poll until connected, sock_delay is parsed from wattcp.cfg */ 
	 sock_wait_established(lsocket,10,NULL,&status); 
    } 
    else if ( local_socket[s].type == SOCK_DGRAM ) { 
	 if (!udp_open(lsocket,0,host,port,NULL))  
	     return(WSAENETUNREACH);             /* open fail */ 
	    
	 /* update socket status */ 
	 local_socket[s].conn = ISCONNECT; 
    } 
 
    /* sock_err is used by the sock_wait_established routine */ 
    sock_err: 
	switch(status) { 
	   case  0 :  local_socket[s].conn = ISCONNECT; 
		      break; 
	   case -1 :  free_socket( s ) ; 
		      return(WSAETIMEDOUT) ; 
	} 
    return(0); 
} /* wat_connect */ 
 
 
/* closesocket - close a socket */ 
int PASCAL FAR wat_closesocket(SOCKET s) 
{ 
    word status = 1; 
    tcp_Socket *lsocket; 
 
    lsocket = local_socket[s].tsock ; 
    if (local_socket[s].conn != ISCONNECT) { 
	free_socket( s ); 
	return(0) ; 
    } 
     
    sock_close ( lsocket ) ; 
    if ( local_socket[s].type == SOCK_STREAM )     /* for TCP socket */ 
	 sock_wait_closed (lsocket,10,NULL,&status) ;   
     
    /* sock_err is used by the sock_wait... routine */ 
    sock_err: 
	switch(status) { 
	   case 1 :  free_socket( s ) ; 
		     break; 
	   case -1 : return(WSAENETDOWN); 
	} 
    return(0); 
} /* wat_closesocket */ 
 
 
 
/* scan through fd_set for the number of readable sockets */ 
int chk_read(fd_set *readfds, int rcount) 
{ 
    int i, nbit = 0 ; 
    tcp_Socket *s; 
    word status ; 
    for (i=0; i < rcount; i++) { 
	 s = local_socket[i].tsock ; 
	 if(local_socket[i].conn != ISCONNECT) { 
	    if(FD_ISSET(i,readfds)) 
	       FD_CLR(i, readfds); 
	    continue ; 
	 } 
	 if(!tcp_tick( s ) ) 
	    local_socket[i].conn == CONNABORT ; /* connection aborted */ 
	  
	 if(!sock_dataready( s ) ) { 
	    if(FD_ISSET(i,readfds)) 
	       FD_CLR(i,readfds); 
	    continue ; 
	 } 
	 if(!FD_ISSET(i,readfds)) 
	     FD_SET(i,readfds); 
	 nbit++ ; 
    } 
    return(nbit); 
} 
 
 
/* scan through fd_set for the number of writable sockets */ 
int chk_write(fd_set *writefds, int wcount) 
{ 
    int i, nbit = 0 ; 
    tcp_Socket *s; 
 
    for (i=0; i < wcount; i++) { 
	 if (local_socket[i].conn == ISCONNECT) { 
	     if(!FD_ISSET(i, writefds))  
		 FD_SET(i, writefds) ; 
	     nbit++ ; 
	 }else 
	     if( FD_ISSET(i, writefds)) 
		 FD_CLR(i, writefds) ; 
    } 
    return(nbit); 
} 
 
 
/* select - determine the status of one of more sockets */ 
int PASCAL FAR wat_select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, struct timeval FAR *timeout) 
{ 
    int i, nbit=0 ; 
    tcp_Socket *s; 
    longword timer;  
    int rc, wc ; 
 
/*    timer = set_timeout( timeout->tv_sec ); */ 
    timer = set_timeout( 20 );  
 
    if ( (readfds != (fd_set *)0) && (writefds != (fd_set *)0) ) { 
       rc = readfds->fd_count ; 
       wc = writefds->fd_count ; 
       while(1) { 
	  nbit = chk_read(readfds,rc) ; 
	  nbit += chk_write(writefds,wc) ; 
	  if ( nbit || chk_timeout(timer))  
	       break ; 
	  win_yield() ;                           /* yield to Windows */ 
       }  
    }else if ( readfds != (fd_set *)0 )  { 
       rc = readfds->fd_count ; 
       while(1) { 
	  nbit = chk_read(readfds,rc) ; 
	  if ( nbit || chk_timeout(timer))  
	       break ; 
	  win_yield() ;                           /* yield to Windows */ 
       }  
    }else if ( writefds != (fd_set *)0 ) { 
       wc = writefds->fd_count ; 
       while(1) { 
	  nbit = chk_write(writefds,wc) ; 
	  if ( nbit || chk_timeout(timer))  
	     break ; 
	  win_yield() ;                           /* yield to Windows */ 
       }  
    }    
     
    return( nbit );                                                               
} 
 
 
/* wat_receive - receive data from a socket */ 
int PASCAL FAR wat_receive(SOCKET s, char FAR *buf, int len, int flags) 
{ 
    int nc , type ; 
    word status ; 
    char bigbuf[MAX_LEN] ; 
    tcp_Socket *socket ; 
    
    if ((s < 0) || (s > MAX_SOCK))   
	return(WSAENOTSOCK) ; 
    if (local_socket[s].conn == NOTCONNECT ) 
	return(0) ;    
    if (local_socket[s].conn == CONNABORT ) { 
	free_socket( s ) ; 
	return(WSAECONNABORTED) ;     /* shutdown abortively from select */ 
    } 
    socket = local_socket[s].tsock ; 
    type = local_socket[s].type ;  
     
    switch (type) { 
	 
	case SOCK_STREAM :                  /* tcp socket */ 
	     if(!(nc = sock_fastread(socket,buf,MAX_LEN)) ) { 
		 if(!tcp_tick(socket)) { 
		    local_socket[s].conn = CONNABORT ; 
		    return(WSAECONNABORTED); 
		 } 
		 nc = sock_fastread(socket,buf,MAX_LEN) ;  /* try again */ 
	     } 
	     if (nc != 0) 
		 buf[nc] = 0 ; 
	     break;    
 
	case SOCK_DGRAM :                   /* udp socket */ 
	     sock_recv_init(socket, bigbuf, sizeof(bigbuf)) ; /*needed for udp */ 
	     sock_mode(socket,UDP_MODE_NOCHK);  /* turn off checksums */ 
	     tcp_tick( NULL ) ;             /* chk for recv data */ 
	     nc = sock_recv(socket, buf, len) ;   /* read the data */ 
	     buf[nc] = 0;        /* must terminate it */ 
	     break; 
    } 
     
    sock_err : 
       switch(status) { 
	  case 1 : /*foreign host closed */ 
		   return(0) ;         /* according to spec */ 
	  case -1 : /* timedout */ 
		   return(WSAETIMEDOUT) ; 
       } 
     
    return(nc); 
} /* wat_recv */ 
 
 
 
/* send - send data on a connected socket */ 
int PASCAL FAR wat_send(SOCKET s, char FAR *buf, int len, int flags) 
{ 
    int nc , type ; 
    tcp_Socket *socket; 
     
    if ((s < 0) || (s > MAX_SOCK))   
	return(WSAENOTSOCK) ; 
    if (local_socket[s].conn == NOTCONNECT ) 
	return(SOCKET_ERROR) ;    
    if (local_socket[s].conn == CONNABORT ) 
	return(WSAECONNABORTED) ;     /* shutdown abortively from select */ 
     
    type = local_socket[s].type ; 
    socket = local_socket[s].tsock ; 
     
    if( (type == SOCK_DGRAM) && (len < sock_tbleft(socket)) ) 
	   return(WSAEMSGSIZE); 
    nc = sock_puts(socket, buf);         /* send and flush on next send */ 
    return(nc); 
} /* wat_send */ 
 
 
/* gethostbyname - get host information corresponding to a hostname */ 
struct hostent FAR * PASCAL FAR wat_gethostbyname(char FAR *name) 
{ 
   static struct hostent FAR * PASCAL FAR host ; 
   longword  addr ; 
   addr = resolve(name) ; 
 
   host->h_name = name ; 
   host->h_aliases[0] = name ; 
   host->h_addrtype = PF_INET ; 
   host->h_length = 4 ; 
   host->h_addr_list[0] = (char *)addr ; 
 
   return(host); 
} /* wat_gethostbyname */ 
 
 
/* inet_addr - convert a string containin a dotted address */ 
unsigned long PASCAL FAR wat_inet_addr(char FAR *cp) 
{ 
    return(resolve(cp)); 
} /* wat_inet_addr */ 
 
 
/* host to network byte order */ 
u_long PASCAL FAR wat_htonl(u_long hostlong) 
{ 
    return(htonl(hostlong)); 
} /* wat_htonl */ 
 
u_short PASCAL FAR wat_htons(u_short hostshort) 
{ 
    return(htons(hostshort)); 
} /* wat_htons */ 
 
/* network to host byte order */ 
u_long PASCAL FAR wat_ntohl(u_long netlong) 
{    
    return(ntohl(netlong)); 
} /* ntohl */ 
 
u_short PASCAL FAR wat_ntohs(u_short netshort) 
{ 
    return(ntohs(netshort)); 
} /* ntohs */ 
 
 
 
/* FD_ISSET supporting function */ 
int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *set) 
{ 
    int i; 
    if (set == (fd_set FAR *) 0) 
	return(0); 
    i = set->fd_count; 
    while (i--) 
	if (set->fd_array[i] == fd) 
	    return(1); 
    return(0); 
} /* __WSAFDIsSet */ 
 
 
int PASCAL FAR wat_WSACleanup(void) 
{ 
   sock_exit(); 
   return(1) ; 
}