/* * Replacement for std fgets which seems to dislike windows return character */ char *CWFgets(char *buf, int bufSize, FILE * f) { int i = -1; if (buf == NULL || f == NULL || bufSize <= 0) return NULL; CW_ZERO_MEMORY(buf, bufSize); do { i++; buf[i] = getc(f); if (buf[i] == EOF) { i--; break; } } while (i < bufSize && buf[i] != '\n' && buf[i] != '\r'); if (i == -1) return NULL; i++; buf[i] = '\0'; return buf; }
/* * Receive a message, that can be fragmented. This is useful not only for the Join State */ CWBool CWReceiveMessage(CWProtocolMessage *msgPtr) { CWList fragments = NULL; int readBytes; char buf[CW_BUFFER_SIZE]; CWBool dataFlag = CW_FALSE; CW_REPEAT_FOREVER { CW_ZERO_MEMORY(buf, CW_BUFFER_SIZE); #ifdef CW_NO_DTLS char *pkt_buffer = NULL; CWLockSafeList(gPacketReceiveList); while (CWGetCountElementFromSafeList(gPacketReceiveList) == 0) CWWaitElementFromSafeList(gPacketReceiveList); pkt_buffer = (char*)CWRemoveHeadElementFromSafeListwithDataFlag(gPacketReceiveList, &readBytes,&dataFlag); CWUnlockSafeList(gPacketReceiveList); CW_COPY_MEMORY(buf, pkt_buffer, readBytes); CW_FREE_OBJECT(pkt_buffer); #else if(!CWSecurityReceive(gWTPSession, buf, CW_BUFFER_SIZE, &readBytes)) {return CW_FALSE;} #endif if(!CWProtocolParseFragment(buf, readBytes, &fragments, msgPtr, &dataFlag, NULL)) { if(CWErrorGetLastErrorCode() == CW_ERROR_NEED_RESOURCE) { // we need at least one more fragment continue; } else { // error CWErrorCode error; error=CWErrorGetLastErrorCode(); switch(error) { case CW_ERROR_SUCCESS: {CWDebugLog("ERROR: Success"); break;} case CW_ERROR_OUT_OF_MEMORY: {CWDebugLog("ERROR: Out of Memory"); break;} case CW_ERROR_WRONG_ARG: {CWDebugLog("ERROR: Wrong Argument"); break;} case CW_ERROR_INTERRUPTED: {CWDebugLog("ERROR: Interrupted"); break;} case CW_ERROR_NEED_RESOURCE: {CWDebugLog("ERROR: Need Resource"); break;} case CW_ERROR_COMUNICATING: {CWDebugLog("ERROR: Comunicating"); break;} case CW_ERROR_CREATING: {CWDebugLog("ERROR: Creating"); break;} case CW_ERROR_GENERAL: {CWDebugLog("ERROR: General"); break;} case CW_ERROR_OPERATION_ABORTED: {CWDebugLog("ERROR: Operation Aborted"); break;} case CW_ERROR_SENDING: {CWDebugLog("ERROR: Sending"); break;} case CW_ERROR_RECEIVING: {CWDebugLog("ERROR: Receiving"); break;} case CW_ERROR_INVALID_FORMAT: {CWDebugLog("ERROR: Invalid Format"); break;} case CW_ERROR_TIME_EXPIRED: {CWDebugLog("ERROR: Time Expired"); break;} case CW_ERROR_NONE: {CWDebugLog("ERROR: None"); break;} } CWDebugLog("~~~~~~"); return CW_FALSE; } } else break; // the message is fully reassembled } return CW_TRUE; }
// replacement for std fgets which seems to dislike windows return character char *CWFgets(char *buf, int bufSize, FILE *f) { int i = -1; if(buf == NULL || f == NULL || bufSize <= 0) return NULL; CW_ZERO_MEMORY(buf, bufSize); do { if(!autelan_feof(f)) { i++; buf[i] = autelan_getc(f); }else //reach the end of file break; /* if(buf[i] == EOF) { i--; break; }*/ } while (i < bufSize && buf[i] != '\n' && buf[i] != '\r'); if(i == -1) return NULL; i++; buf[i] = '\0'; return buf; }
// perform wait on a semaphore CWBool CWThreadSemWait(CWThreadSem *semPtr) { #ifdef CW_USE_NAMED_SEMAPHORES if(semPtr == NULL || semPtr->semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); #else if(semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); #endif //CWDebugLog("Sem Wait"); #ifdef CW_USE_NAMED_SEMAPHORES while(sem_wait(semPtr->semPtr) < 0 ) { #else while(sem_wait(semPtr) < 0 ) { #endif if(errno == EINTR) continue; else { CWErrorRaiseSystemError(CW_ERROR_GENERAL); } } return CW_TRUE; } // perform post on a semaphore CWBool CWThreadSemPost(CWThreadSem *semPtr) { #ifdef CW_USE_NAMED_SEMAPHORES if(semPtr == NULL || semPtr->semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); #else if(semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); #endif #ifdef CW_USE_NAMED_SEMAPHORES if(sem_post(semPtr->semPtr) < 0 ) { #else if(sem_post(semPtr) < 0 ) { #endif CWErrorRaiseSystemError(CW_ERROR_GENERAL); } return CW_TRUE; } // get the value of a semaphore CWBool CWThreadSemGetValue(CWThreadSem *semPtr, int *valuePtr) { #ifdef CW_USE_NAMED_SEMAPHORES if(valuePtr == NULL || semPtr == NULL || semPtr->semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); #else if(valuePtr == NULL || semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); #endif #ifdef CW_USE_NAMED_SEMAPHORES if(sem_getvalue(semPtr->semPtr, valuePtr) < 0) { // note: broken on Mac OS X? Btw we don't need it CWErrorRaiseSystemError(CW_ERROR_GENERAL); } #else if(sem_getvalue(semPtr, valuePtr) < 0) { CWErrorRaiseSystemError(CW_ERROR_GENERAL); } #endif if(*valuePtr < 0 ) { *valuePtr = 0; } return CW_TRUE; } __inline__ sem_t *CWThreadGetSemT(CWThreadSem *semPtr) { #ifdef CW_USE_NAMED_SEMAPHORES return (semPtr->semPtr); #else return semPtr; #endif } // creates a semaphore that can be used with CWThreadTimedSemWait(). This type of semaphore // is different from CWThreadSemaphore to support platforms that don't have sem_timedwait() (e.g. Mac OS X) CWBool CWThreadCreateTimedSem(CWThreadTimedSem *semPtr, int value) { #ifdef HAVE_SEM_TIMEDWAIT return CWThreadCreateSem(semPtr, value); #else // if we don't have sem_timedwait(), the timed semaphore is a pair of unix domain sockets. // We write a dummy packet on a socket (client) when we want to post, and select() with timer on the other socket // when we want to wait. struct sockaddr_un serverAddr, clientAddr; int i; if(semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL); if((((*semPtr)[0] = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) || (((*semPtr)[1] = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) { // create a pair of datagram unix domain socket close((*semPtr)[0]); CWErrorRaiseSystemError(CW_ERROR_CREATING); } CW_ZERO_MEMORY(&serverAddr, sizeof(serverAddr)); serverAddr.sun_family = AF_LOCAL; if(tmpnam((char*) &(serverAddr.sun_path)) == NULL) { CWErrorRaiseSystemError(CW_ERROR_CREATING); } CW_ZERO_MEMORY(&clientAddr, sizeof(clientAddr)); clientAddr.sun_family = AF_LOCAL; if(tmpnam((char*) &(clientAddr.sun_path)) == NULL) { CWErrorRaiseSystemError(CW_ERROR_CREATING); } if( (bind((*semPtr)[0], (struct sockaddr*) &serverAddr, sizeof(serverAddr)) < 0) || (bind((*semPtr)[1], (struct sockaddr*) &clientAddr, sizeof(clientAddr)) < 0) || (connect((*semPtr)[1], (struct sockaddr*) &serverAddr, sizeof(serverAddr)) < 0) || // connect each socket to the other (connect((*semPtr)[0], (struct sockaddr*) &clientAddr, sizeof(clientAddr)) < 0) ) { close((*semPtr)[0]); close((*semPtr)[1]); CWErrorRaiseSystemError(CW_ERROR_CREATING); } for(i = 0; i < value; i++) { if(!CWThreadTimedSemPost(semPtr)) return CW_FALSE; } return CW_TRUE; #endif } // CW_TRUE if the semaphore has zero value, CW_FALSE otherwise CWBool CWThreadTimedSemIsZero(CWThreadTimedSem *semPtr) { #ifdef HAVE_SEM_TIMEDWAIT int value; if(!CWThreadSemGetValue(semPtr, &value)) return CW_FALSE; return (value==0) ? CW_TRUE : CW_FALSE; #else fd_set fset; int r; struct timeval timeout; if(semPtr == NULL) return CW_FALSE; FD_ZERO(&fset); FD_SET((*semPtr)[0], &fset); FD_SET((*semPtr)[1], &fset); timeout.tv_sec = 0; // poll timeout.tv_usec = 0; while((r=select(max((*semPtr)[1], (*semPtr)[0])+1, &fset, NULL, NULL, &timeout)) < 0) { if(errno == EINTR) { timeout.tv_sec = 0; timeout.tv_usec = 0; continue; } CWErrorRaiseSystemError(CW_ERROR_GENERAL); } return (r==0) ? CW_TRUE : CW_FALSE; #endif } CWBool CWThreadTimedSemSetValue(CWThreadTimedSem *semPtr, int value) { #ifdef HAVE_SEM_TIMEDWAIT // note: we can implement this, but our implemntation does't really need it in case // of a system semaphore. This is useful for our Unix Domain Socket Hack return CW_TRUE; //return CWErrorRaise(CW_ERROR_NEED_RESOURCE, "Operation Not Supported"); #else fd_set fset; int r, i; struct timeval timeout; if(semPtr == NULL) return CW_FALSE; FD_ZERO(&fset); FD_SET((*semPtr)[0], &fset); FD_SET((*semPtr)[1], &fset); timeout.tv_sec = 0; // poll timeout.tv_usec = 0; // first, remove all the pending packets CW_REPEAT_FOREVER { char dummy; while((r=select(max((*semPtr)[1], (*semPtr)[0])+1, &fset, NULL, NULL, &timeout)) < 0) { if(errno == EINTR) { timeout.tv_sec = 0; timeout.tv_usec = 0; continue; } CWErrorRaiseSystemError(CW_ERROR_GENERAL); } if(r == 0) break; if(FD_ISSET((*semPtr)[0], &fset)) { while(read((*semPtr)[0], &dummy, 1) < 0) { if(errno == EINTR) continue; CWErrorRaiseSystemError(CW_ERROR_GENERAL); } } if(FD_ISSET((*semPtr)[1], &fset)) { while(read((*semPtr)[1], &dummy, 1) < 0) { if(errno == EINTR) continue; CWErrorRaiseSystemError(CW_ERROR_GENERAL); } } } // second, send n packets, where n is the value we want to set for the semaphore for(i = 0; i < value; i++) { if(!CWThreadTimedSemPost(semPtr)) return CW_FALSE; } return CW_TRUE; #endif } void CWThreadDestroyTimedSem(CWThreadTimedSem *semPtr) { #ifdef HAVE_SEM_TIMEDWAIT CWThreadDestroySem(semPtr); #else if(semPtr == NULL) return; close((*semPtr)[0]); close((*semPtr)[1]); #endif }