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) ; }