Пример #1
0
/*
 * 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;
}
Пример #2
0
/* 
 * 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;
}
Пример #3
0
// 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;
}
Пример #4
0
// 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
}