diff options
author | Camil Staps | 2015-07-01 17:36:37 +0200 |
---|---|---|
committer | Camil Staps | 2015-07-01 17:36:37 +0200 |
commit | 7553b7f9d4dddc2235c137d41de8ce22547bebe3 (patch) | |
tree | 34f8fb4b36640317d728a60586424f67f9befbe7 /Linux_C_12/cTCP_121.c | |
parent | gitignore (diff) |
Initial commit
Diffstat (limited to 'Linux_C_12/cTCP_121.c')
-rw-r--r-- | Linux_C_12/cTCP_121.c | 781 |
1 files changed, 781 insertions, 0 deletions
diff --git a/Linux_C_12/cTCP_121.c b/Linux_C_12/cTCP_121.c new file mode 100644 index 0000000..e880b82 --- /dev/null +++ b/Linux_C_12/cTCP_121.c @@ -0,0 +1,781 @@ +/********************************************************************************************
+ Clean OS Windows library module version 1.2.1.
+ This module is part of the Clean Object I/O library, version 1.2.1,
+ for the Windows platform.
+********************************************************************************************/
+
+/********************************************************************************************
+ About this module:
+ Routines related to printing.
+********************************************************************************************/
+//#define FD_SETSIZE "maximal number of sockets to select on" (default is 64)
+
+#include <winsock.h>
+#include "util_121.h"
+#include "Clean.h"
+#include "cTCP_121.h"
+#define trace(x)
+
+/*
+------------------------ THE FUNCTION PROTOTYPES ------------------------------------------
+
+Naming convention: functions, which are called from Clean end with a "C". Function's that
+*/
+
+//************************************************
+// functions, which are called from Clean (semantic is explained in tcp.icl or ostcp.icl)
+
+int os_eom(SOCKET endpointRef);
+int os_disconnected(SOCKET endpointRef);
+int os_connectrequestavailable(SOCKET endpointRef);
+void abortedHost_syncC(CleanString inetAddr, int *errCode, int *ipAddr);
+void abortedHost_asyncC(CleanString inetAddr, int *errCode, HANDLE *endpointRef);
+void openTCP_ListenerC(int portNum, int *pErrCode, SOCKET *pEndpointRef);
+void acceptC(SOCKET endpointRef, int *pErrCode, int *pInetHost, SOCKET *pEndpointRef);
+void os_connectTCPC(int isIOProg, int block, int doTimeout, unsigned int stopTime,
+ int ipAddr, int portnum,
+ int *errCode, int *timeoutExpiredP, int *endpointRefP
+ );
+void sendC(SOCKET endpointRef, CleanString data, int begin, int nBytes, int *pErrCode, int *pSentBytes);
+void receiveC(SOCKET endpointRef, int maxSize, CleanString *data);
+int getRcvBuffSizeC();
+void resizeStringC(CleanString string, int newSize);
+int data_availableC(SOCKET endpointRef);
+void disconnectGracefulC(SOCKET endpointRef);
+void disconnectBrutalC(SOCKET endpointRef);
+void garbageCollectEndpointC(SOCKET endpointRef);
+void os_select_inetevents(SOCKET endpointRef, int receiverCategory,
+ int referenceCount, int getReceiveEvents, int getSendEvents,
+ int aborted
+ );
+void selectChC(int justForMac, int nonBlocking, int doTimeout, unsigned int stopTime,
+ SOCKET *pRChannels, int *justForMac2, SOCKET *pSChannels,
+ int *pErrCode
+ );
+int tcpPossibleC(void);
+
+//************************************************
+// other functions
+
+void StartUp(int abort);
+ // initialize winsock (if not started yet. uses global "tcpStartedUp")
+ // if succesful: tcpStartedUp==TRUE afterwards
+ // if not succesful && abort: aborts
+ // if not succesful && !abort: tcpStartedUp==FALSE afterwards
+void CleanUp(void);
+
+//************************************************
+// functions to deal with the endpoint dictionary:
+
+int insertNewDictionaryItem(SOCKET endpointRef);
+ // allocates memory for new dictionary item, initializes it as far as possible and
+ // adds it to the dictionary. returns error code: 0==ok, 1==not ok
+dictitem* lookup(SOCKET endpointRef);
+ // lookup entry (CFN)
+void setEndpointDataC(int endpointRef, int referenceCount,
+ int hasReceiveNotifier, int hasSendableNotifier, int aborted);
+ // set the corresponding fields of the entry
+void getEndpointDataC(int endpointRef, int *referenceCount,
+ int *hasReceiveNotifier, int *hasSendableNotifier, int *aborted);
+ // returns the corresponding fields of the entry
+void removeDictionaryItem(SOCKET endpointRef);
+ // remove one item via pointer manipulations (must not be called from notifier)
+
+//--------------------- GLOBAL VARIABLES ------------------------------------------
+
+// The inetEventQueue: To append easily a new item to the end of the list, "toLastNext" points
+// to the "next" field of the last list element (or to &inetEventQueue)
+
+
+dictitem *endpointDict = NULL;
+
+int tcpStartedUp = FALSE;
+int rcvBuffSize; // contains the size of the sockets internal buffer for receiving data.
+CleanString pRcvBuff;
+
+extern DNSInfo *DNSInfoList;
+extern HWND ghMainWindow;
+extern void (*exit_tcpip_function)(); // the function will be called, when the Clean
+ // program terminates
+
+//--------------------- FUNCTION IMPLEMENTATION -----------------------------------
+
+int tcpPossibleC(void)
+{
+ printf("tcpPossibleC\n");
+ StartUp(FALSE);
+ return tcpStartedUp;
+}
+
+int os_eom(SOCKET endpointRef)
+{
+ int err, err2;
+ char dummyBuffer[1];
+ dictitem *pDictitem;
+ printf("os_eom\n");
+
+ err = recv( endpointRef, dummyBuffer, 1, MSG_PEEK);
+ err2 = WSAGetLastError();
+ if (err>0)
+ return FALSE;
+ if (err<0 && err2==WSAEWOULDBLOCK)
+ return FALSE;
+ pDictitem = lookup(endpointRef);
+ trace( if (!pDictitem)
+ rMessageBox(NULL, MB_APPLMODAL, "in os_eom", "ERROR");)
+ if (pDictitem->availByteValid)
+ return FALSE;
+ if (err==0)
+ return TRUE;
+ return TRUE;
+}
+
+int os_disconnected(SOCKET endpointRef)
+{
+ int err;
+ char string[1];
+ dictitem *pDictitem;
+ printf("os_disconnected\n");
+
+ pDictitem = lookup(endpointRef);
+ trace( if (!pDictitem)
+ rMessageBox(NULL, MB_APPLMODAL, "in os_disconnected", "ERROR");)
+ if (pDictitem->disconnected)
+ return TRUE;
+ err = send( endpointRef, string, 0, 0);
+ if (err!=SOCKET_ERROR)
+ return FALSE;
+ else
+ return WSAGetLastError()!=WSAEWOULDBLOCK;
+ // only this error can happen with sockets that can still send
+}
+
+int os_connectrequestavailable(SOCKET endpointRef)
+{
+ FD_SET readSet;
+ TIMEVAL timeout;
+ int nr;
+ printf("os_connectrequestavailable\n");
+
+ FD_ZERO(&readSet);
+ FD_SET(endpointRef,&readSet);
+
+ timeout.tv_sec = 0; // Timeout in sec's
+ timeout.tv_usec = 0; // Timeout in microsec's
+ nr = select(0,&readSet,NULL,NULL,&timeout);
+ return nr>0 && FD_ISSET(endpointRef,&readSet);
+}
+
+#define majorVrs 1
+#define minorVrs 1
+
+void StartUp(int abort)
+{
+ printf("StartUp\n");
+ if (!tcpStartedUp)
+ {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err, four=4;
+ SOCKET s;
+
+ wVersionRequested = MAKEWORD(majorVrs, minorVrs);
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
+ if (abort) {
+ rMessageBox(NULL, MB_APPLMODAL, "ERROR", "can't start up winsock"
+ "\nprogram aborts");
+ ExitProcess (255);
+ }
+ else
+ return;
+ }
+
+ /* Confirm that the Windows Sockets DLL supports version mj.mi.*/
+ /* Note that if the DLL supports versions greater */
+ /* than mj.mi in addition to mj.mi, it will still return */
+ /* mj.mi in wVersion since that is the version we */
+ /* requested. */
+
+ if ( LOBYTE( wsaData.wVersion ) != majorVrs ||
+ HIBYTE( wsaData.wVersion ) != minorVrs ) {
+ WSACleanup();
+ if (abort) {
+ rMessageBox(NULL, MB_APPLMODAL, "ERROR", "winsock 1.1 or higher not available"
+ "\nprogram aborts");
+ ExitProcess (255);
+ }
+ else
+ return;
+ };
+
+ // initialize rcvBuffSize
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s==INVALID_SOCKET) {
+ rMessageBox(NULL, MB_APPLMODAL, "ERROR", "can't create a socket"
+ "\nprogram aborts");
+ ExitProcess (255);
+ };
+ if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*) &rcvBuffSize, &four)) {
+ rMessageBox(NULL, MB_APPLMODAL, "ERROR", "can't call getsockopt"
+ "\nprogram aborts");
+ ExitProcess (255);
+ };
+
+ pRcvBuff = (CleanString) LocalAlloc(LMEM_FIXED, rcvBuffSize+4);
+ if (pRcvBuff==NULL) {
+ rMessageBox(NULL, MB_APPLMODAL, "ERROR", "out of memory"
+ "\nprogram aborts");
+ ExitProcess (255);
+ };
+ exit_tcpip_function = CleanUp;
+ tcpStartedUp = TRUE;
+ };
+}
+
+
+void lookupHost_syncC(CleanString inetAddr, int *errCode, int *ipAddrP)
+// error code: 0 ok, 1 error (also: addr doesn't exist)
+{
+ HOSTENT *hostentP;
+ unsigned long ipAddr;
+ printf("lookupHost_syncC\n");
+
+ StartUp(TRUE);
+ ipAddr = inet_addr(CleanStringCharacters(inetAddr));
+ if (ipAddr!=INADDR_NONE)
+ {
+ *errCode = 0;
+ *ipAddrP = ntohl(ipAddr);
+ return;
+ };
+ *errCode = 1;
+ hostentP = gethostbyname(CleanStringCharacters(inetAddr)); // string is alphanumerical
+ if (hostentP!=NULL)
+ { *ipAddrP = ntohl(((DWORD *)(*(hostentP->h_addr_list)))[0]);
+ if (*ipAddrP!=0)
+ *errCode = 0;
+ };
+}
+
+void lookupHost_asyncC(CleanString inetAddr, int *errCode, HANDLE *endpointRef)
+// errCode: 0 ok, 1 not ok
+{
+ DNSInfo *newPtr;
+ HANDLE dnsHdl;
+ printf("lookupHost_asyncC\n");
+
+ StartUp(TRUE);
+
+ *errCode = 1;
+ newPtr = (DNSInfo*) LocalAlloc(LMEM_FIXED,sizeof(DNSInfo));
+ if (newPtr==NULL) {
+ *errCode = 1;
+ return;
+ };
+
+ newPtr->next = DNSInfoList;
+ DNSInfoList = newPtr;
+
+ // and fill the fields and initiate DNS lookup.
+ dnsHdl = WSAAsyncGetHostByName(ghMainWindow,PM_DNS_EVENT,CleanStringCharacters(inetAddr),
+ DNSInfoList->junion.freeSpace,
+ MAXGETHOSTSTRUCT);
+ // this will cause the sending of a PM_DNS_EVENT message to the main window.
+ // The wParam value of that message will be equal to dnsHdl so that
+ // the ipAdress of the lookedup host can be retrieved then.
+ // The element of the List should be deallocated then
+ if (dnsHdl==0)
+ return;
+
+ DNSInfoList->dnsHdl = dnsHdl;
+ *errCode = 0;
+ *endpointRef = dnsHdl;
+}
+
+void openTCP_ListenerC(int portNum, int *pErrCode, SOCKET *pEndpointRef)
+// errCode: 0:ok; otherwise:not ok
+{
+ SOCKET s;
+ SOCKADDR_IN srvAdr;
+ printf("openTCP_ListenerC\n");
+
+ StartUp(TRUE);
+
+ *pErrCode = 1;
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s==INVALID_SOCKET)
+ return;
+
+ srvAdr.sin_family = AF_INET; // of course internet adress family
+ srvAdr.sin_addr.s_addr = INADDR_ANY; // internet address will be given after "accept"
+ srvAdr.sin_port = htons((short int)portNum);
+
+ *pErrCode = bind(s, (LPSOCKADDR) &srvAdr, sizeof(srvAdr));
+ if (*pErrCode) {
+ closesocket(s);
+ return;
+ };
+
+ *pErrCode = listen(s,5);
+ if (*pErrCode) {
+ closesocket(s);
+ return;
+ };
+ *pEndpointRef = s;
+
+ *pErrCode = insertNewDictionaryItem(s);
+ if (*pErrCode)
+ return;
+
+ setEndpointDataC(s, 1,0,0,0);
+}
+
+void acceptC(SOCKET listener, int *pErrCode, int *pInetHost, SOCKET *pEndpointRef)
+// errCode: 0:ok; otherwise:not ok
+{
+ SOCKET endpointRef;
+ SOCKADDR_IN clientAdr;
+ int clientAdrSize, tru;
+ printf("acceptC\n");
+
+ clientAdrSize = sizeof(clientAdr);
+ endpointRef = accept(listener,(LPSOCKADDR) &clientAdr, &clientAdrSize);
+ tru = TRUE;
+ ioctlsocket(endpointRef, FIONBIO, &tru); // set mode to non blocking
+ *pErrCode = endpointRef==INVALID_SOCKET;
+ if (*pErrCode)
+ return;
+
+ *pInetHost = ntohl(clientAdr.sin_addr.s_addr);
+ *pEndpointRef = endpointRef;
+
+ *pErrCode = insertNewDictionaryItem(endpointRef);
+ if (*pErrCode)
+ return;
+
+ setEndpointDataC(endpointRef,2,0,0,0);
+}
+
+void os_connectTCPC(int onlyForMac, int block, int doTimeout, unsigned int stopTime,
+ int ipAddr, int portnum,
+ int *errCodeP, int *timeoutExpiredP, int *endpointRefP)
+// errCode: 0 ok; 1 not ok
+{
+ SOCKET client;
+ SOCKADDR_IN srvAdr,clientAdr;
+ int err, tru;
+ printf("os_connectTCPC\n");
+
+ *errCodeP = 1;
+ *timeoutExpiredP = FALSE;
+
+ client = socket(PF_INET, SOCK_STREAM, 0);
+ if (client==INVALID_SOCKET)
+ return;
+
+ clientAdr.sin_family = AF_INET; // of course internet adress family
+ clientAdr.sin_addr.s_addr = INADDR_ANY; // internet adress will be given after "connect"
+ clientAdr.sin_port = 0; // the winsock library will choose a free number between 1024 and 5000
+
+ err = bind(client, (LPSOCKADDR) &clientAdr, sizeof(clientAdr));
+ if (err)
+ {
+ closesocket(client);
+ return;
+ };
+
+ srvAdr.sin_family = AF_INET; // of course internet adress family
+ srvAdr.sin_addr.s_addr = htonl(ipAddr);
+ srvAdr.sin_port = htons((short int)portnum);
+
+ tru = TRUE;
+
+ //////////////////////////////////////////////////////////////////////////
+ if (block && doTimeout)
+ {
+ ioctlsocket(client, FIONBIO, &tru); // set mode to non blocking
+ err = connect(client, (LPSOCKADDR) &srvAdr, sizeof(srvAdr));
+ if (!err) {
+ *errCodeP = 0;
+ *timeoutExpiredP = FALSE;
+ *endpointRefP = client;
+ }
+ else if (WSAGetLastError()!=WSAEWOULDBLOCK) {
+ closesocket(client);
+ return;
+ }
+ else
+ {
+ FD_SET writeSet, exptnSet;
+ TIMEVAL timeout;
+ unsigned int now;
+ int noOfWritableSockets, timeoutTicks;
+ FD_ZERO(&writeSet);
+ FD_SET(client,&writeSet);
+ FD_ZERO(&exptnSet);
+ FD_SET(client,&exptnSet);
+
+ now = GetTickCount();
+ timeoutTicks = ((int)stopTime) - ((int)now);
+ if (timeoutTicks<=0)
+ { // timeout expired
+ closesocket(client);
+ *timeoutExpiredP = TRUE;
+ return;
+ };
+ timeout.tv_sec = timeoutTicks / 1000; // Timeout in sec's
+ timeout.tv_usec = (timeoutTicks % 1000)*1000; // Timeout in microsec's
+ noOfWritableSockets = select(0,NULL,&writeSet,&exptnSet,&timeout);
+ *errCodeP = noOfWritableSockets<0
+ || (noOfWritableSockets>0 && FD_ISSET(client,&exptnSet));
+ *timeoutExpiredP = noOfWritableSockets==0;
+ *endpointRefP = client;
+ if (*errCodeP || *timeoutExpiredP) {
+ closesocket(client);
+ return;
+ };
+ };
+ };
+ ///////////////////////////////////////////////////////////////////////////
+ if (block && !doTimeout)
+ {
+ err = connect(client, (LPSOCKADDR) &srvAdr, sizeof(srvAdr));
+ if (err)
+ {
+ closesocket(client);
+ return;
+ };
+
+ ioctlsocket(client, FIONBIO, &tru); // set mode to non blocking
+
+ *errCodeP = 0;
+ *timeoutExpiredP = FALSE;
+ *endpointRefP = client;
+ };
+ ////////////////////////////////////////////////////////////////////////////
+ if (!block)
+ {
+
+ err = WSAAsyncSelect(client,ghMainWindow,PM_SOCKET_EVENT,FD_CONNECT);
+ if (err)
+ {
+ closesocket(client);
+ return;
+ };
+
+ err = connect(client, (LPSOCKADDR) &srvAdr, sizeof(srvAdr));
+ if (err==SOCKET_ERROR)
+ {
+ err = WSAGetLastError(); // a WSAEWOULDBLOCK error is a pretty harmless thing
+ if (err!=WSAEWOULDBLOCK)
+ {
+ closesocket(client);
+ return;
+ };
+ };
+ *errCodeP = 0;
+ *timeoutExpiredP = FALSE;
+ *endpointRefP = client;
+ };
+ //////////////////////////////////////////////////////////////////////////////
+
+ *errCodeP = insertNewDictionaryItem(client);
+ if (*errCodeP)
+ {
+ closesocket(client);
+ return;
+ };
+ if (block)
+ setEndpointDataC(client,2,0,0,0);
+ else
+ {
+ dictitem *ptr;
+ ptr = lookup(client);
+ ptr->referenceCount = 1;
+ ptr->hasReceiveNotifier = 0;
+ ptr->hasSendableNotifier = 1;
+ ptr->aborted = 0;
+ };
+}
+
+void sendC(SOCKET endpointRef, CleanString data, int begin, int nBytes,
+ int *pErrCode, int *pSentBytes)
+{
+ int sentBytes;
+ printf("sendC\n");
+
+ *pErrCode = 0;
+ sentBytes = send(endpointRef, CleanStringCharacters(data)+begin,nBytes, 0);
+ if (sentBytes==SOCKET_ERROR) {
+ int err;
+ sentBytes = 0;
+ err = WSAGetLastError();
+ if (err!=WSAEWOULDBLOCK) {
+ dictitem *pDictitem;
+ pDictitem = lookup(endpointRef);
+ trace( if (!pDictitem)
+ rMessageBox(NULL, MB_APPLMODAL, "in sendC", "ERROR");)
+ pDictitem->disconnected =1;
+ *pErrCode = 1;
+ }
+ };
+ *pSentBytes = sentBytes;
+}
+
+
+void receiveC(SOCKET endpointRef, int maxSize, CleanString *pReceived)
+{
+ int size, received;
+ dictitem *pDictitem;
+ printf("receiveC\n");
+
+ *pReceived = (CleanString) pRcvBuff;
+ size = maxSize<=0 ? rcvBuffSize : maxSize;
+ received = recv( endpointRef, CleanStringCharacters(pRcvBuff), size, 0);
+ pDictitem = lookup(endpointRef);
+ trace( if (!pDictitem)
+ rMessageBox(NULL, MB_APPLMODAL, "in receiveC", "ERROR");)
+ if (received>0) {
+ pDictitem->availByteValid = 0;
+ CleanStringLength(pRcvBuff) = received;
+ }
+ else if (pDictitem->availByteValid) {
+ CleanStringCharacters(pRcvBuff)[0] = pDictitem->availByte;
+ pDictitem->availByteValid = 0;
+ CleanStringLength(pRcvBuff) = 1;
+ }
+ else
+ CleanStringLength(pRcvBuff) = 0;
+}
+
+int data_availableC(SOCKET endpointRef)
+{
+ dictitem *pDictitem;
+ int err;
+ printf("data_availableC\n");
+
+ pDictitem = lookup(endpointRef);
+ trace( if (!pDictitem)
+ rMessageBox(NULL, MB_APPLMODAL, "in data_availableC",
+ "ERROR\nendpoint %i not found", endpointRef);)
+ if (pDictitem->availByteValid)
+ return TRUE;
+ err = recv( endpointRef, &pDictitem->availByte, 1, MSG_PEEK);
+ if (err>0) {
+ pDictitem->availByteValid = 1;
+ return TRUE;
+ };
+ return FALSE;
+}
+
+void disconnectGracefulC(SOCKET endpointRef)
+{
+ printf("disconnecteGracefulC\n");
+ shutdown(endpointRef,1); // 1: graceful
+}
+
+void disconnectBrutalC(SOCKET endpointRef)
+{
+ LINGER linger;
+ printf("disconnectBrutalC\n");
+
+ linger.l_onoff = 1;
+ linger.l_linger = 0;
+ setsockopt(endpointRef, SOL_SOCKET, SO_LINGER, (char*) &linger, sizeof(linger));
+}
+
+void garbageCollectEndpointC(SOCKET endpointRef)
+{
+ dictitem *pDictitem;
+ printf("garbageCollectEndpointC\n");
+
+ pDictitem = lookup(endpointRef);
+ if (pDictitem!=NULL && pDictitem->referenceCount==0) {
+ closesocket(endpointRef);
+ removeDictionaryItem(endpointRef);
+ };
+}
+
+
+void os_select_inetevents( SOCKET endpointRef, int receiverCategory,
+ int referenceCount, int getReceiveEvents, int getSendEvents,
+ int aborted)
+{
+ printf("os_select_inetevents\n");
+ setEndpointDataC(endpointRef, referenceCount, getReceiveEvents, getSendEvents, aborted);
+}
+
+void initFD_SET(FD_SET **ppSet, SOCKET sockets[], int n)
+{
+ int i;
+ FD_SET *pSet;
+ printf("initFD_SET\n");
+
+ pSet = (FD_SET*) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, n*sizeof(SOCKET)+sizeof(u_int));
+ for(i=0; i<n; i++)
+ FD_SET(sockets[i], pSet);
+ *ppSet = pSet;
+}
+
+void selectChC( int justForMac, int nonBlocking, int doTimeout, unsigned int stopTime,
+ SOCKET *pRChannels, int *justForMac2, SOCKET *pSChannels,
+ int *pErrCode)
+// error code: 0=ok; 1=timeout expired, 3=other errors
+{
+ int nRChannels, nSChannels, i;
+ FD_SET *pReadSet, *pWriteSet;
+ TIMEVAL timeout;
+ unsigned int now;
+ int n, timeoutTicks;
+ printf("selectChC\n");
+
+ nRChannels = (int) pRChannels[-2];
+ nSChannels = (int) pSChannels[-2];
+ if (doTimeout)
+ {
+ now = GetTickCount();
+ timeoutTicks = nonBlocking ? 0 : ((int)stopTime) - ((int)now);
+ if (timeoutTicks<0)
+ {
+ *pErrCode = 1;
+ return;
+ };
+ timeout.tv_sec = timeoutTicks / 1000; // Timeout in sec's
+ timeout.tv_usec = (timeoutTicks % 1000)*1000; // Timeout in microsec's
+ };
+ initFD_SET(&pReadSet, pRChannels, nRChannels);
+ initFD_SET(&pWriteSet, pSChannels, nSChannels);
+ n = select(0,pReadSet,pWriteSet,NULL, doTimeout ? &timeout : NULL);
+ if (n==0)
+ { // timeout expired
+ *pErrCode = 1;
+ return;
+ };
+ if (n<0)
+ {
+ *pErrCode = 3;
+ return;
+ };
+ for(i=0; i<nRChannels; i++)
+ if (FD_ISSET(pRChannels[i], pReadSet))
+ pRChannels[i] = 0;
+ for(i=0; i<nSChannels; i++)
+ if (FD_ISSET(pSChannels[i], pWriteSet))
+ pSChannels[i] = 0;
+ *pErrCode = 0;
+}
+
+// this function is called from Cleans runtime system via *exit_tcpip_function
+void CleanUp(void)
+{
+ dictitem *pDictitem, *pTemp;
+ int referenceCount;
+ pDictitem = endpointDict;
+ printf("CleanUp\n");
+
+ while (pDictitem) {
+ referenceCount = pDictitem->referenceCount;
+ if (referenceCount!=0) {
+ if (referenceCount==1 && pDictitem->aborted) {
+ disconnectBrutalC(pDictitem->endpointRef);
+ }
+ else
+ disconnectGracefulC(pDictitem->endpointRef);
+ closesocket(pDictitem->endpointRef);
+ };
+ pTemp = pDictitem;
+ pDictitem = pDictitem->next;
+ GlobalFree((char*) pTemp);
+ };
+ WSACleanup();
+}
+
+
+//------------------------ FUNCTION IMPLEMENTATIONS FOR THE ENDPOINT DICTIONARY -------
+
+int insertNewDictionaryItem(SOCKET endpointRef)
+{
+ dictitem *newItem;
+ printf("insertNewDictionaryItem\n");
+
+ newItem = (dictitem*) GlobalAlloc(LMEM_FIXED, sizeof(dictitem));
+ if (newItem==NULL)
+ return 1;
+
+ newItem->endpointRef = endpointRef;
+ newItem->next = endpointDict;
+ newItem->availByteValid = 0;
+ newItem->aborted = 0;
+ newItem->disconnected = 0;
+ endpointDict = newItem;
+
+ return 0;
+}
+
+dictitem* lookup(SOCKET endpointRef)
+{
+ dictitem *ptr=endpointDict;
+ printf("lookup\n");
+ while (ptr!=NULL && (ptr->endpointRef!=endpointRef))
+ ptr = ptr->next;
+
+ return ptr;
+}
+
+void setEndpointDataC( int endpointRef, int referenceCount,
+ int hasReceiveNotifier, int hasSendableNotifier, int aborted)
+{
+ dictitem *ptr;
+ printf("setEndpointDataC\n");
+ ptr = lookup((SOCKET) endpointRef);
+
+ if (ptr!=NULL)
+ { ptr->referenceCount = referenceCount;
+ ptr->hasReceiveNotifier = hasReceiveNotifier ? 1 : 0;
+ ptr->hasSendableNotifier = hasSendableNotifier ? 1 : 0;
+ ptr->aborted = aborted ? 1 : 0;
+ };
+ WSAAsyncSelect(endpointRef, ghMainWindow, PM_SOCKET_EVENT,
+ (hasReceiveNotifier ? FD_READ | FD_OOB | FD_ACCEPT | FD_CLOSE : 0)
+ | (hasSendableNotifier ? FD_WRITE | FD_CLOSE : 0));
+}
+
+
+void getEndpointDataC( int endpointRef, int *referenceCount,
+ int *hasReceiveNotifier, int *hasSendableNotifier, int *aborted)
+{
+ dictitem *ptr;
+ printf("getEndpointDataC\n");
+ ptr = lookup((SOCKET) endpointRef);
+
+ if (ptr!=NULL)
+ { *referenceCount = ptr->referenceCount;
+ *hasReceiveNotifier = ptr->hasReceiveNotifier!=0;
+ *hasSendableNotifier = ptr->hasSendableNotifier!=0;
+ *aborted = ptr->aborted!=0;
+ };
+}
+
+
+void removeDictionaryItem(SOCKET endpointRef)
+// the dictionary MUST contain a valid item with the endpointRef
+{
+ dictitem **ptr, *temp;
+ int notRemoved;
+ printf("removeDictionaryItem\n");
+
+ ptr = &endpointDict;
+ notRemoved = TRUE;
+ while(notRemoved)
+ if ((*ptr)->endpointRef==endpointRef)
+ {
+ temp = *ptr;
+ *ptr = (*ptr)->next;
+ GlobalFree((char*) temp);
+ notRemoved = FALSE;
+ }
+ else
+ ptr = &((*ptr)->next);
+}
|