//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Rejects a Peer's request for communication // Should only be used by App GSUdpErrorCode gsUdpEngineRejectPeer(unsigned int theIp, unsigned short thePort) { GSUdpRemotePeer aRemotePeer; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } if (theIp == 0 || thePort == 0) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Invalid parameter(s), check ip, port\n"); return GS_UDP_PARAMETER_ERROR; } // Find the connection to reject in our array of peers aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpRemotePeer *aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); gt2Reject(aPeerFound->mConnection, NULL, 0); ArrayDeleteAt(aUdp->mRemotePeers, index); } return GS_UDP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Based on an IP and port, the function will return the amount of free space // of a peer's buffer. int gsUdpEngineGetPeerOutBufferFreeSpace(unsigned int theIp, unsigned short thePort) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpRemotePeer aRemotePeer, *aRemotePeerFound; int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return 0; } aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { aRemotePeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); return gt2GetOutgoingBufferFreeSpace(aRemotePeerFound->mConnection); } return 0; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // Used obtain the peer's state // theIp and thePort cannot be 0 (Zero) GSUdpErrorCode gsUdpEngineGetPeerState(unsigned int theIp, unsigned short thePort, GSUdpPeerState *thePeerState) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpRemotePeer aPeer, *aPeerFound; int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); GS_ASSERT(thePeerState != NULL); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_State, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); *thePeerState = GS_UDP_PEER_CLOSED; return GS_UDP_NOT_INITIALIZED; } aPeer.mAddr = theIp; aPeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aPeer, gsUdpRemotePeerCompare, 0, 0); if (index == NOT_FOUND) { *thePeerState = GS_UDP_PEER_CLOSED; return GS_UDP_NO_ERROR; } aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); *thePeerState = (GSUdpPeerState)gt2GetConnectionState(aPeerFound->mConnection); return GS_UDP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // When a message handler is done or shutting down, the message handler should remove // itself from the UDP Layer // The header cannot be empty GSUdpErrorCode gsUdpEngineRemoveMsgHandler(char theHeader[GS_UDP_MSG_HEADER_LEN]) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpMsgHandler aHandler; int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theHeader); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } if (!theHeader || !theHeader[0]) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] invalid or empty header\n"); return GS_UDP_PARAMETER_ERROR; } memcpy(aHandler.mHeader, theHeader, GS_UDP_MSG_HEADER_LEN); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare2, 0, 0); if (index != NOT_FOUND) { ArrayDeleteAt(aUdp->mMsgHandlers, index); } return GS_UDP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Requests for communication from a peer is handled by first checking if the // initial message has a message handler registered for it. Otherwise // the message is passed onto the app. void gsUdpConnAttemptCB(GT2Socket socket, GT2Connection connection, unsigned int ip, unsigned short port, int latency, GT2Byte * message, int len) { // Get the message handler for the connection int index; GSUdpMsgHandler aHandler; GSUdpRemotePeer aRemotePeer; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); char anAddr[GS_IP_ADDR_AND_PORT]; gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection attempt from %s\n", gt2AddressToString(ip, port, anAddr)); //If there is a handler, automatically accept a connection if the initial message is //the same as the handler's registered initial message if (len >= GS_UDP_MSG_HEADER_LEN) { memcpy(aHandler.mInitialMsg, message, GS_UDP_MSG_HEADER_LEN); aRemotePeer.mAddr = ip; aRemotePeer.mPort = port; aRemotePeer.mConnection = connection; ArrayAppend(aUdp->mRemotePeers, &aRemotePeer); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare, 0, 0); if (index != NOT_FOUND) { GT2ConnectionCallbacks aCallbacks; aCallbacks.closed = gsUdpClosedRoutingCB; aCallbacks.connected = gsUdpConnectedRoutingCB; aCallbacks.ping = gsUdpPingRoutingCB; aCallbacks.received = gsUdpReceivedRoutingCB; // Automatically accept connections for Message Handlers gt2Accept(aRemotePeer.mConnection, &aCallbacks); gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection attempt auto-accepted for message handler\n"); return; } } // all other messages go to the app if (aUdp->mAppConnAttempt) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection attempt from %s, asking app to accept/reject\n", gt2AddressToString(ip, port, anAddr)); aUdp->mAppConnAttempt(ip, port, latency, (unsigned char *)message, (unsigned int)len, aUdp->mAppUserData); } else { // Reject any un-handled connections or unknown connections gt2Reject(connection, NULL, 0); ArrayRemoveAt(aUdp->mRemotePeers, ArrayLength(aUdp->mRemotePeers) -1); } GSI_UNUSED(socket); GSI_UNUSED(anAddr); }
void TableEnter(HashTable table, const void *newElem) { int hash, itempos; hash = table->hashfn(newElem, table->nbuckets); itempos = ArraySearch(table->buckets[hash], newElem, table->compfn, 0, 0); if (itempos == NOT_FOUND) ArrayAppend(table->buckets[hash], newElem); else ArrayReplaceAt(table->buckets[hash], newElem, itempos); }
void *TableLookup(HashTable table, const void *elemKey) { int hash, itempos; hash = table->hashfn(elemKey, table->nbuckets); itempos = ArraySearch(table->buckets[hash], elemKey, table->compfn, 0, 0); if (itempos == NOT_FOUND) return NULL; else return ArrayNth(table->buckets[hash], itempos); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Lets the App and Message Handlers know a peer left void gsUdpClosedRoutingCB(GT2Connection theConnection, GT2CloseReason reason) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpRemotePeer aRemotePeer; int index, len; GSUdpCloseReason aReason; char anAddr[GS_IP_ADDR_AND_PORT]; if (reason == GT2CommunicationError || reason == GT2SocketError) aReason = GS_UDP_CLOSED_BY_COMM_ERROR; else if (reason == GT2NotEnoughMemory) aReason = GS_UDP_CLOSED_BY_LOW_MEM; else aReason = (GSUdpCloseReason)reason; gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection closed to %s\n", gt2AddressToString(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), anAddr)); len = ArrayLength(aUdp->mMsgHandlers); for (index = 0; index < len; index++) { GSUdpMsgHandler *aHandler = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); if (aHandler->mClosed) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection closed: passed to message handler\n"); aHandler->mClosed(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), aReason, aHandler->mUserData); } } if (aUdp->mAppClosed) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connection closed: passed to app\n"); aUdp->mAppClosed(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), aReason, aUdp->mAppUserData); } aRemotePeer.mConnection = theConnection; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare2, 0, 0); if (index != NOT_FOUND) { ArrayDeleteAt(aUdp->mRemotePeers, index); } GSI_UNUSED(anAddr); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Any data received prompts the UDP layer to first find a higher level // message handler to handle the data. If there was no message handler // found, the data is passed to the higher level app. void gsUdpReceivedRoutingCB(GT2Connection theConnection, GT2Byte *theMessage, int theMessageLen, GT2Bool reliable) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GSUdpMsgHandler aHandler; int index; char anAddr[GS_IP_ADDR_AND_PORT]; gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Received data from %s\n", gt2AddressToString(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), anAddr)); //If there is a handler, pass it to the handler //The header should not be stripped off if (theMessageLen >= GS_UDP_MSG_HEADER_LEN) { memcpy(aHandler.mHeader, theMessage, GS_UDP_MSG_HEADER_LEN); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare2, 0, 0); if (index != NOT_FOUND) { GSUdpMsgHandler *aHandlerFound = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); if (aHandlerFound->mReceived) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passed to message handler\n"); aHandlerFound->mReceived(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), theMessage + GS_UDP_MSG_HEADER_LEN, (unsigned int)(theMessageLen - GS_UDP_MSG_HEADER_LEN), reliable, aHandlerFound->mUserData); return; } } } if (aUdp->mAppRecvData) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passed to app\n"); aUdp->mAppRecvData(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), theMessage, (unsigned int)theMessageLen, reliable, aUdp->mAppUserData); } GSI_UNUSED(anAddr); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Accepts a Peer's request for communication // Should only be used by App GSUdpErrorCode gsUdpEngineAcceptPeer(unsigned int theIp, unsigned short thePort) { GSUdpRemotePeer aRemotePeer; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } if (theIp == 0 || thePort == 0) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Invalid parameter(s), check ip, port\n"); return GS_UDP_PARAMETER_ERROR; } aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { GT2ConnectionCallbacks aCallbacks; GSUdpRemotePeer *aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); aCallbacks.closed = gsUdpClosedRoutingCB; aCallbacks.connected = gsUdpConnectedRoutingCB; aCallbacks.ping = gsUdpPingRoutingCB; aCallbacks.received = gsUdpReceivedRoutingCB; gt2Accept(aPeerFound->mConnection, &aCallbacks); } return GS_UDP_NO_ERROR; }
void Visitor() /* code block to perform visitor operation */ { int condnToWait,who,i,j, num; int talkingTime; int checkCorrectOperatorV; int phoneToUse,gotPhone; int thisActivate; int operatorToUse; int callPresident; /* Some common parameters */ char lockName[30]; char condName1[30]; char condName2[30]; int presidentStatus; int phoneStatus; char printing[50]; int lockID1, lockID2, lockID3, lockID4, lockID5, lockID6, condID1, condID2, condID3, condID4; int indOpLock[20], waitForOperVerCV[20], waitForCallerCV[20]; int activate, authMechanism, freeOperators, operatorStatus; int repositoryMoney; presidentStatus = CreateSharedInt("presidentStatus",15,1); phoneStatus = CreateSharedInt("phoneStatus",11,NOOFPHONES); freeOperators = CreateSharedInt("freeOperators",13,1); operatorStatus = CreateSharedInt("operatorStatus",14,Nop); activate = CreateSharedInt("activate",sizeof("activate"),Nop); authMechanism = CreateSharedInt("authMechanism",sizeof("authMechanism"),Nop); repositoryMoney = CreateSharedInt("repositoryMoney",sizeof("repositoryMoney"),Nop); lockID1 = CreateLock("phoneLock",10); /* obtain a master lock for all phones */ lockID2 = CreateLock("GlobalOpLock",12); /* obtain a master lock for all the operators */ lockID3 = CreateLock("visitorCountLock",17); /* obtain a lock to keep track of the number of visitors permitted to make a call */ lockID4 = CreateLock("NumSenators",12); lockID5 = CreateLock("NumVisitors",12); lockID6 = CreateLock("NumOperators",13); /* displayLock = CreateLock("DispLock",7); */ /* Lock **individualOperatorLock; */ /* obtain an individual lock for every operator */ condID1 = CreateCondition("presiNeedsPhone",16); /* condition variable for the condition that president needs phone */ condID2 = CreateCondition("senatorNeedsPhone",18); /* condition variable for the condition that senator needs phone */ condID3 = CreateCondition("visitorNeedsPhone",18); /* condition variable for the condition that visitor needs phone */ condID4 = CreateCondition("processCustomer",16); /* condition variable to allow president/senator/visitor to make a call */ for (i=0;i<Nop;i++) { Concatenate("OperatorLock",sizeof("OperatorLock"),i,lockName); Concatenate("waitForOpVer",sizeof("waitForOpVer"),i,condName1); Concatenate("waitForCaller",sizeof("waitForCaller"),i,condName2); indOpLock[i] = CreateLock(lockName,sizeof(lockName)); waitForOperVerCV[i] = CreateCondition(condName1,sizeof(condName1)); waitForCallerCV[i] = CreateCondition(condName2,sizeof(condName2)); } /* End of common parameters */ AcquireLock(lockID5); who = NumVisitor; NumVisitor++; ReleaseLock(lockID5); AcquireLock(lockID1); /* loop to check if the president or senator is waiting. If any one is waiting, then visitor has to wait before he/she can make a call. Otherwise visitor can go ahead */ do { condnToWait = TRUE; if(GetSharedInt(presidentStatus,0) == 1) condnToWait = TRUE; /* Check if some senator is already waiting! */ else if(CheckCondWaitQueue(condID2)==1) { /* Bad luck, there seems to be a senator. */ condnToWait = TRUE; } else { /* for(i=0;i<NOOFPHONES;i++) { if(GetSharedInt(phoneStatus,i)==FREE) { phoneToUse = i; SetSharedInt(phoneStatus,i,BUSY); condnToWait = FALSE; break; } } */ phoneToUse = GetOneIndex(phoneStatus); if(phoneToUse!=NOOFPHONES) condnToWait = FALSE; } if(condnToWait) WaitCV(condID3,lockID1); /* visitor waits if there is a president or a senator already waitng to make a call. */ }while(condnToWait); ReleaseLock(lockID1); /* Visitor has got a phone */ /* Need to get an operator now */ AcquireLock(lockID2); while(GetSharedInt(freeOperators,0)==0) WaitCV(condID4,lockID2); /* visitor has to wait if there are no free operators available */ /* Some operator is available. Though I don't know who it is. Let us find out. */ /* for(j=0;j<Nop;j++) { if(GetSharedInt(operatorStatus,j)==FREE) { operatorToUse = j; break; } } */ operatorToUse = GetOneIndex(operatorStatus); /* operator obtained */ checkCorrectOperatorV = operatorToUse; /* check if the operator to whom the visitor pays money is the same as the one the permits/denies the visitor to make a call */ AcquireLock(indOpLock[operatorToUse]); SetSharedInt(activate, operatorToUse, 2); SetSharedInt(operatorStatus, operatorToUse, BUSY); SetSharedInt(freeOperators, 0, GetSharedInt(freeOperators, 0) - 1); ReleaseLock(lockID2); SetSharedInt(authMechanism, operatorToUse, 3); /* 1 for President | 2 for Senators | 3 for Visitors */ SetSharedInt(repositoryMoney, operatorToUse, ((RandomFunction(100)-1)>80)?0:1); /* randomly generate whether the visitor pays $1 or not */ /* If operator is sleeping, wake up */ SignalCV(waitForCallerCV[operatorToUse],indOpLock[operatorToUse]); SignalCV(waitForCallerCV[operatorToUse],indOpLock[operatorToUse]); while(GetSharedInt(activate,operatorToUse)==2) WaitCV(waitForOperVerCV[operatorToUse],indOpLock[operatorToUse]); thisActivate=0; thisActivate=GetSharedInt(activate, operatorToUse); ReleaseLock(indOpLock[operatorToUse]); if (thisActivate==0) { /* visitor is denied access to phone beacause he/she didn't pay $1. */ j=0; talkingTime=0; /* printf("Visitor%d \t UNAVAILABLE \t %d/%d units \t %d \t NOTAPPLICABLE DENIED \t Money paid is $0 - verified by operator %d \n",who+1,j,talkingTime,operatorToUse+1,checkCorrectOperatorV+1); */ /* AcquireLock(displayLock); */ Write("Visitor ",8,1); num = who+1; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" \t UNAVAILABLE \t",100,1); num = j; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write("/",1,1); num=talkingTime; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" units \t ",10,1); num=operatorToUse+1; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" \t",6,1); Write(" NOTAPPLICABLE DENIED \t Money paid is $0 - verified by operator ",100,1); num=checkCorrectOperatorV+1; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" \n",3,1); /*ReleaseLock(displayLock);*/ Yield(); /* printf("Access to Phone for visitor %d Denied by Operator %d!\n",who+1,operatorToUse+1); */ } else if (thisActivate==1) /* visitor has paid $1. Operator verifies and visitor is allowed to make a call */ { /* Now Talk */ talkingTime = RandomFunction(5); /* randomly generate the amount of time the visitor will talk on the phone */ /* loop for the visitor to talk on the phone for the randomly generated time period */ for (i=1;i<=talkingTime;i++){ /* printf("Visitor%d \t %d \t\t %d/%d units \t %d \t NOTAPPLICABLE ACCEPTED \t Money paid is $1 - verified by operator %d \n",who+1,phoneToUse+1,i,talkingTime,operatorToUse+1,checkCorrectOperatorV+1); */ /*AcquireLock(displayLock);*/ Write("Visitor ",8,1); num = who+1; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" \t",2,1); num = phoneToUse+1; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write("\t\t ",5,1); num = i; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write("/",1,1); num=talkingTime; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" units \t ",10,1); num=operatorToUse+1; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" \t",6,1); Write(" NOTAPPLICABLE ACCEPTED \t Money paid is $1 - verified by operator ",100,1); num=checkCorrectOperatorV+1; itoa(printing,10,num); Write(printing,sizeof(printing),1); Write(" \n",3,1); /*ReleaseLock(displayLock);*/ /*Yield();*/ } /* visitor is done talking */ /* Set the phone status to be free */ } AcquireLock(lockID1); SetSharedInt(phoneStatus,phoneToUse,FREE); if(GetSharedInt(presidentStatus,0)==0) /* president is not waking to talk */ { if(CheckCondWaitQueue(condID2)) SignalCV(condID2,lockID1); /* wake up the next senator waiting to talk */ else SignalCV(condID3,lockID1); /* if no senator is waiting, then wake up the next visitor waiting to talk */ } else /* president is waiting to talk, so senators and visitors will have to wait */ { callPresident = TRUE; /* for(i=0;i<NOOFPHONES;i++) if((i!=phoneToUse)&&(GetSharedInt(phoneStatus,i)==BUSY)) // check if even a single phone is busy other than the phone just used by the visitor which he/she sets to free { callPresident = FALSE; break; }*/ i = ArraySearch(phoneStatus, phoneToUse, BUSY); if(i!=NOOFPHONES) callPresident = FALSE; if(callPresident==TRUE) SignalCV(condID1,lockID1); /* if all phones are free, then no one is talking currently and so, signal the president */ } /* visitor goes away and does not return. Remember visitors can make a maximum of just one call */ ReleaseLock(lockID1); WriteMe("Visitor ");WriteNum(who + 1);WriteMe("Leaving\n"); Exit(0); }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // Sends a message to a peer using IP and Port // An empty header constitutes the app sending this message. // theIp and thePort cannot be 0 (Zero) // // WARNING: Messages should not be greater than the outgoing buffer size minus the header // and the 7 byte header for reliable messages (used for internal gt2 operations). Most // UDP fragmentation occurs if messages are bigger than 1500 bytes. Also, some routers are // known to drop those packets that are larger than 1500 bytes. The recommended outgoing // buffer size is the default (1460). So take that, and subtract 16 for message handler header // and reliable message header (if sending data reliably). // freeSpace = 1460 - 16 - 7 GSUdpErrorCode gsUdpEngineSendMessage(unsigned int theIp, unsigned short thePort, char theHeader[GS_UDP_MSG_HEADER_LEN], unsigned char *theMsg, unsigned int theMsgLen, gsi_bool theReliable) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int aTotalMessageLen, index; GSUdpRemotePeer aRemotePeer, *aRemotePeerFound; GT2Byte *fullMessage; GT2Result aResult; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } // Messages being sent with an empty header are treated as app messages if (!theHeader[0]) aTotalMessageLen = (int)theMsgLen; else aTotalMessageLen = (int)(GS_UDP_MSG_HEADER_LEN + theMsgLen); aRemotePeer.mAddr = theIp; aRemotePeer.mPort = thePort; index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index == NOT_FOUND) { char anAddr[GS_IP_ADDR_AND_PORT]; gt2AddressToString(theIp, thePort, anAddr); gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_WarmError, "[Udp Engine] address not found for sending message\n", anAddr); return GS_UDP_ADDRESS_ERROR; } else { aRemotePeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); } if (aTotalMessageLen > gt2GetOutgoingBufferSize(aRemotePeerFound->mConnection) && theReliable) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_WarmError, "[Udp Engine] Message Size too large, dropping message\n"); return GS_UDP_MSG_TOO_BIG; } fullMessage = (GT2Byte *)gsimalloc((unsigned long)aTotalMessageLen); memcpy(fullMessage, theHeader, GS_UDP_MSG_HEADER_LEN); memcpy(fullMessage + GS_UDP_MSG_HEADER_LEN, theMsg, theMsgLen); // Send the message // reliable messages will be kept in the outgoing buffers till they are sent aResult = gt2Send(aRemotePeerFound->mConnection, fullMessage, aTotalMessageLen, theReliable); gsifree(fullMessage); if (aResult != GT2Success) return GS_UDP_SEND_FAILED; return GS_UDP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // UDP Layer must be initialized // theIp and thePort cannot be 0 (Zero) // Starts a request to open a communication channel with another peer based on // IP and port. GSUdpErrorCode gsUdpEngineStartTalkingToPeer(unsigned int theIp, unsigned short thePort, char theInitMsg[GS_UDP_MSG_HEADER_LEN], int timeOut) { char anAddr[GS_IP_ADDR_AND_PORT]; GSUdpRemotePeer aRemotePeer; GSUdpMsgHandler aHandler; GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); GT2ConnectionCallbacks aCallbacks; int index; GS_ASSERT(aUdp->mInitialized); GS_ASSERT(theIp); GS_ASSERT(thePort); if (!aUdp->mInitialized) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine not initialized\n"); return GS_UDP_NETWORK_ERROR; } if (theIp == 0 || thePort == 0) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Invalid parameter(s), check ip, port"); return GS_UDP_PARAMETER_ERROR; } aRemotePeer.mAddr = theIp; // In Network Byte Order for GT2 aRemotePeer.mPort = thePort; // In Host Byte Order for GT2 index = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpRemotePeer *aPeerFound = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, index); GT2ConnectionState aState = gt2GetConnectionState(aPeerFound->mConnection); if (aState == GT2Connected) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Debug, "[Udp Engine] Engine is already talking to remote address\n"); return GS_UDP_ADDRESS_ALREADY_IN_USE; } else if (aState == GT2Connecting) { memcpy(aHandler.mInitialMsg, theInitMsg, GS_UDP_MSG_HEADER_LEN); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpMsgHandler *aHandlerFound = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); ArrayAppend(aHandlerFound->mPendingConnections, aPeerFound); } } } else { gt2AddressToString(theIp, thePort, anAddr); aCallbacks.closed = gsUdpClosedRoutingCB; aCallbacks.connected = gsUdpConnectedRoutingCB; aCallbacks.ping = gsUdpPingRoutingCB; aCallbacks.received = gsUdpReceivedRoutingCB; // start the connect without blocking since we want the engine to be as asynchronous as possible gt2Connect(aUdp->mSocket, &aRemotePeer.mConnection, anAddr, (unsigned char *)theInitMsg, GS_UDP_MSG_HEADER_LEN, timeOut, &aCallbacks, GT2False); ArrayAppend(aUdp->mRemotePeers, &aRemotePeer); memcpy(aHandler.mInitialMsg, theInitMsg, GS_UDP_MSG_HEADER_LEN); index = ArraySearch(aUdp->mMsgHandlers, &aHandler, gsUdpMsgHandlerCompare, 0, 0); if (index != NOT_FOUND) { GSUdpRemotePeer *aRemotePeerPtr = (GSUdpRemotePeer *)ArrayNth(aUdp->mRemotePeers, ArrayLength(aUdp->mRemotePeers) - 1); GSUdpMsgHandler *aHandlerFound = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, index); ArrayAppend(aHandlerFound->mPendingConnections, &aRemotePeerPtr); } else { aUdp->mAppPendingConnections++; } } return GS_UDP_NO_ERROR; }
//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // When a peer has accepted a GT2Connection the UDP layer needs to let // higher level app or message handler know that it accepted the request to // to message a peer. void gsUdpConnectedRoutingCB(GT2Connection theConnection, GT2Result theResult, GT2Byte *theMessage, int theMessageLen) { GSUdpEngineObject *aUdp = gsUdpEngineGetEngine(); int aIndex, len; GSUdpErrorCode aCode; char anAddr[GS_IP_ADDR_AND_PORT]; switch(theResult) { case GT2NegotiationError: aCode = GS_UDP_REMOTE_ERROR; break; case GT2Rejected: aCode = GS_UDP_REJECTED; break; case GT2TimedOut: aCode = GS_UDP_TIMED_OUT; break; case GT2Success: aCode = GS_UDP_NO_ERROR; break; default: aCode = GS_UDP_UNKNOWN_ERROR; break; } if (theResult == GT2Rejected) { int aRemotePeerIdx; GSUdpRemotePeer aRemotePeer; aRemotePeer.mAddr = gt2GetRemoteIP(theConnection); aRemotePeer.mPort = gt2GetRemotePort(theConnection); aRemotePeerIdx = ArraySearch(aUdp->mRemotePeers, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (aRemotePeerIdx != NOT_FOUND) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Connect rejected by %s\n", gt2AddressToString(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), anAddr)); ArrayDeleteAt(aUdp->mRemotePeers, aRemotePeerIdx); } } len = ArrayLength(aUdp->mMsgHandlers); for (aIndex = 0; aIndex < len; aIndex++) { int aRemotePeerIdx; GSUdpRemotePeer aRemotePeer; GSUdpMsgHandler *aTempHandler = (GSUdpMsgHandler *)ArrayNth(aUdp->mMsgHandlers, aIndex); aRemotePeer.mAddr = gt2GetRemoteIP(theConnection); aRemotePeer.mPort = gt2GetRemotePort(theConnection); aRemotePeerIdx = ArraySearch(aTempHandler->mPendingConnections, &aRemotePeer, gsUdpRemotePeerCompare, 0, 0); if (aRemotePeerIdx != NOT_FOUND) { if (aTempHandler->mConnected) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passing connect result to message handler\n"); aTempHandler->mConnected(gt2GetRemoteIP(theConnection), gt2GetRemotePort(theConnection), aCode, theResult == GT2Rejected ? gsi_true : gsi_false, aTempHandler->mUserData); } ArrayDeleteAt(aTempHandler->mPendingConnections, aRemotePeerIdx); return; } } if (aUdp->mAppPendingConnections > 0) { if (aUdp->mAppConnected) { gsDebugFormat(GSIDebugCat_Common, GSIDebugType_Network, GSIDebugLevel_Comment, "[Udp Engine] Passing connect result to app\n"); aUdp->mAppConnected(gt2GetRemoteIP(theConnection),gt2GetRemotePort(theConnection), aCode, theResult == GT2Rejected ? gsi_true : gsi_false, aUdp->mAppUserData); } aUdp->mAppPendingConnections--; } GSI_UNUSED(theMessage); GSI_UNUSED(theMessageLen); GSI_UNUSED(anAddr); }