Example #1
0
int esif_ws_init(void)
{
	int index=0;
	int retVal=0;
	char *ipaddr = (char*)g_ws_ipaddr;
	char *portPtr = g_ws_port;

	struct sockaddr_in addrSrvr = {0};
	struct sockaddr_in addrClient = {0};
	socklen_t len_inet = 0;
	
	esif_ccb_socket_t client_socket = INVALID_SOCKET;
	
	int option = 1;
	eEsifError req_results = ESIF_OK;
	ClientRecordPtr clientPtr = NULL;

	int selRetVal = 0;
	int maxfd = 0;
	int setsize = 0;
	
	struct timeval tv={0}; 	/* Timeout value */
	fd_set workingSet = {0};

	esif_ccb_mutex_init(&g_web_socket_lock);
	atomic_inc(&g_ws_threads);
	atomic_set(&g_ws_quit, 0);

	CMD_OUT("Starting WebServer %s %s\n", ipaddr, portPtr);

	esif_ccb_socket_init();

	// Allocate pool of Client Records and HTTP input buffer
	g_clients = (ClientRecordPtr )esif_ccb_malloc(MAX_CLIENTS * sizeof(*g_clients));
	g_ws_http_buffer = (char *)esif_ccb_malloc(WS_BUFFER_LENGTH);
	if (NULL == g_clients || NULL == g_ws_http_buffer) {
		ESIF_TRACE_DEBUG("Out of memory");
		goto exit;
	}

	esif_ws_server_initialize_clients();

	len_inet = sizeof(addrSrvr);

	retVal   = esif_ws_server_create_inet_addr(&addrSrvr, &len_inet, ipaddr, portPtr, (char*)"top");
	if (retVal < 0 && !addrSrvr.sin_port) {
		ESIF_TRACE_DEBUG("Invalid server address/port number");
		goto exit;
	}

	g_listen = socket(PF_INET, SOCK_STREAM, 0);
	if (g_listen == SOCKET_ERROR) {
		ESIF_TRACE_DEBUG("open socket error");
		goto exit;
	}
	
	retVal = setsockopt(g_listen, SOL_SOCKET, SO_REUSEADDR, (char*)&option, sizeof(option));
	if (retVal < 0) {
		esif_ccb_socket_close(g_listen);
		g_listen = INVALID_SOCKET;
		ESIF_TRACE_DEBUG("setsockopt failed");
		goto exit;
	}

	retVal = bind(g_listen, (struct sockaddr*)&addrSrvr, len_inet);
	if (retVal < -1) {
		esif_ccb_socket_close(g_listen);
		g_listen = INVALID_SOCKET;
		ESIF_TRACE_DEBUG("bind sysem call failed");
		goto exit;
	}
	
	retVal = listen(g_listen, MAX_CLIENTS);
	if (retVal < 0) {
		ESIF_TRACE_DEBUG("listen system call failed");
		goto exit;
	}

	/* Accept client requests and new connections until told to quit */
	while (!atomic_read(&g_ws_quit)) {
	
		/* Build file descriptor set of active sockets */
		maxfd = 0;
		setsize = 0;

		/* Clear the FD set we will check after each iteration */
		FD_ZERO(&workingSet);

		/* Add our listner to the FD set to check */
		if (g_listen != INVALID_SOCKET) {
			FD_SET((u_int)g_listen, &workingSet);
			maxfd = (int)g_listen + 1;
			setsize++;
		}

		/* Add our current clients to the FD set to check */
		for (index = 0; index <  MAX_CLIENTS && setsize < FD_SETSIZE; index++) {
			if (g_clients[index].socket != INVALID_SOCKET) {
				FD_SET((u_int)g_clients[index].socket, &workingSet);
				maxfd = esif_ccb_max(maxfd, (int)g_clients[index].socket + 1);
				setsize++;
			}
		}
		/* If we have nothing functional in te FD set to check; break */
		if (maxfd == 0) {
			break;
		}

		/*
		 *  timeout of N + 0.05 secs
		 */
		tv.tv_sec  = 2;
		tv.tv_usec = 50000;

		/* Check our FD set for sockets ready to be accepted (listener) or read (others already accepted) */
		selRetVal  = select(maxfd, &workingSet, NULL, NULL, &tv);

		if (selRetVal == SOCKET_ERROR) {
			break;
		} else if (!selRetVal) {
			continue;
		}

		/* Accept any new connections on the listening socket */
		if (FD_ISSET(g_listen, &workingSet)) {
			int sockets = (g_listen == INVALID_SOCKET ? 0 : 1);
			len_inet = sizeof addrClient;

			client_socket = (int)accept(g_listen, (struct sockaddr*)&addrClient, &len_inet);

			if (client_socket == SOCKET_ERROR) {
				ESIF_TRACE_DEBUG("accept(2)");
				goto exit;
			}

			/* Find the first empty client in our list */
			for (index = 0; index < MAX_CLIENTS && sockets < FD_SETSIZE; index++) {
				if (g_clients[index].socket == INVALID_SOCKET) {
					esif_ws_client_initialize_client(&g_clients[index]);
					g_clients[index].socket = client_socket;
					break;
				}
				sockets++;
			}

			/* If all clients are in use, close the new client */
			if (index >= MAX_CLIENTS || sockets >= FD_SETSIZE) {
				ESIF_TRACE_DEBUG("Connection Limit Exceeded (%d)", MAX_CLIENTS);
				esif_ccb_socket_close(client_socket);
				client_socket = INVALID_SOCKET;
				continue;
			}
		}

		/* Go through our client list and check if the FD set indicates any have activity */
		for (index = 0; index < MAX_CLIENTS; index++) {
			client_socket = g_clients[index].socket;
			if (client_socket == INVALID_SOCKET || client_socket == g_listen) {
				continue;
			}

			/* Process client if it is in the set of active file descriptors */
			if (FD_ISSET(client_socket, &workingSet)) {
				ESIF_TRACE_DEBUG("Client %d connected\n", client_socket);

				/******************** Process the client request ********************/
				clientPtr = &g_clients[index];
				req_results = esif_ws_client_process_request(clientPtr);

				if (req_results == ESIF_E_WS_DISC) {
					ESIF_TRACE_DEBUG("Client %d disconnected\n", client_socket);
					esif_ws_client_initialize_client(clientPtr); /* reset */
				}
				else if (req_results == ESIF_E_NO_MEMORY) {
					ESIF_TRACE_DEBUG("Out of memory\n");
					esif_ws_client_initialize_client(clientPtr); /* reset */
				}

				/* Clear everything after use */
				esif_ws_protocol_initialize(&clientPtr->prot);
			}
		}
	}

exit:
	/* cleanup */
	if (g_listen != INVALID_SOCKET) {
		esif_ccb_socket_close(g_listen);
		g_listen = INVALID_SOCKET;
	}
	if (g_clients) {
		for (index = 0; index < MAX_CLIENTS; index++) {
			esif_ws_client_close_client(&g_clients[index]);
		}
		esif_ccb_free(g_clients);
		g_clients = NULL;
	}
	esif_ccb_free(g_rest_out);
	esif_ccb_free(g_ws_http_buffer);
	g_rest_out = NULL;
	g_ws_http_buffer = NULL;
	esif_ccb_socket_exit();
	atomic_dec(&g_ws_threads);
	return 0;
}
Example #2
0
// Search and Replace
ZString IString_ReplaceIString (
	IStringPtr self,
	IStringPtr what,
	IStringPtr with,
	int IgnoreCase
	)
{
	ZString from, to, find;
	u32 count, oldsize, newsize;

	// Sanity checks. Cannot replace an empty string
	ESIF_ASSERT(self && what && with);
	if (self->data_len <= 1 || what->data_len <= 1) {
		return 0;
	}

	// Count occurances of replacment string in original string
	for (count = 0, find = (ZString)self->buf_ptr; (find = (ZString)strfind(find, (ZString)what->buf_ptr, IgnoreCase)) != NULL; count++)
		find += what->data_len - 1;

	// Compute new string size and Resize if necessary
	oldsize = self->data_len;
	newsize = self->data_len + (count * (int)(esif_ccb_max(with->data_len, 1) - what->data_len));
	if (newsize > self->buf_len) {
#ifdef ISTRING_AUTOGROW
		if (IString_Resize(self, newsize + ISTRING_AUTOGROW) == NULL)
#endif
		return 0;
	}

	// Do an in-string replacement so that another copy of the string does not need to be allocated
	// a) newsize <= oldsize: Do a left-to-right copy replacment
	// b) newsize >  oldsize: Move string to end of newsize buffer, then do a left-to-right copy replacement
	from = to = (ZString)self->buf_ptr;
	self->data_len = newsize;
	if (newsize > oldsize) {
		// Move string to end of reallocated (data_len) buffer
		esif_ccb_memmove(((ZString)self->buf_ptr) + (newsize - oldsize), (ZString)self->buf_ptr, oldsize);
		from += newsize - oldsize;
	}
	// Do a left-to-right copy (from -> to), replacing each occurance of old string (what) with new string (with)
	while ((find = (ZString)strfind(from, (ZString)what->buf_ptr, IgnoreCase)) != NULL) {
		if (from > to) {
			esif_ccb_memcpy(to, from, (size_t)(find - from));
		}
		to += (size_t)(find - from);
		if (with->data_len > 0) {
			esif_ccb_memcpy(to, (ZString)with->buf_ptr, with->data_len - 1);
			to += with->data_len - 1;
		}
		from = find + (what->data_len > 0 ? what->data_len - 1 : 0);
	}
	// Copy remainder of string, if any
	if (to < from) {
		esif_ccb_memcpy(to, from, newsize - (size_t)(to - (ZString)self->buf_ptr));
	}
	to += newsize - (size_t)(to - (ZString)self->buf_ptr);
	// zero out remainder of old string, if any
	if (oldsize > newsize) {
		esif_ccb_memset(to, 0, oldsize - newsize);
	}
	return (ZString)self->buf_ptr;
}
Example #3
0
/* Set */
eEsifError DataVault_SetValue(
	DataVaultPtr self,
	EsifDataPtr path,
	EsifDataPtr value,
	esif_flags_t flags
	)
{
	eEsifError rc = ESIF_OK;
	DataCacheEntryPtr keypair;

	if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) {
		return ESIF_E_READONLY;
	}

	// Ignore value for DELETEs
	if (FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_DELETE)) {
		value = NULL;
	}

	// AUTO data types or AUTO_ALLOCATE are not allowed for SET
	if (value && (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE)) {
		return ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE;
	}

	// Reject SETs for static-sized data types whose buffer is too small
	if (value) {
		u32 len = (u32) esif_data_type_sizeof(value->type);
		if (len > 0 && value->buf_len < len) {
			value->data_len = len;
			return ESIF_E_NEED_LARGER_BUFFER;
		}
	}

	// Write to Log
	DataVault_WriteLog(self, (flags & ESIF_SERVICE_CONFIG_DELETE ? "DELETE" : "SET"), self->name, path, flags, value);

	// Delete DataVault Key(s)?
	if (esif_ccb_strpbrk((esif_string)path->buf_ptr, "*?") != NULL) {
		if (flags & ESIF_SERVICE_CONFIG_DELETE) {
			UInt32 item = 0;
			while (item < self->cache->size) {
				if (esif_ccb_strmatch((esif_string)self->cache->elements[item].key.buf_ptr, (esif_string)path->buf_ptr)) {
					flags |= FLAGS_TEST(self->cache->elements[item].flags, ESIF_SERVICE_CONFIG_PERSIST);
					if (DataCache_DeleteValue(self->cache, (esif_string)self->cache->elements[item].key.buf_ptr) == ESIF_OK) {
						continue;
					}
				}
				item++;
			}
			goto exit;
		}
		return ESIF_E_NOT_SUPPORTED; // Keys may not contain "*" or "?"
	}

	// Read data from File
	// TODO: Change Parser Logic and Syntax instead
	if (value && value->buf_ptr && esif_ccb_strncmp((char*)value->buf_ptr, "<<", 2) == 0) {
		void *buffer  = 0;
		UInt32 buflen = 0;
		if (ReadFileIntoBuffer((char*)value->buf_ptr + 2, &buffer, &buflen) == ESIF_OK) {
			if (value->buf_len) {
				esif_ccb_free(value->buf_ptr);
			}
			value->buf_ptr = buffer;
			if (value->type == ESIF_DATA_STRING) {
				buflen++;	// Include Null Terminator
			}
			value->buf_len = value->data_len = buflen;
		} else {
			return ESIF_E_UNSPECIFIED;	// TODO: File Not Found
		}
	}

	// Get the Data Row or create it if it does not exist
	keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr);
	if (keypair) {	// Match Found
		// READONLY?
		if (keypair->flags & ESIF_SERVICE_CONFIG_READONLY) {
			rc = ESIF_E_READONLY;
		}
		// DELETE?
		else if (flags & ESIF_SERVICE_CONFIG_DELETE) {
			flags |= keypair->flags;
			DataCache_DeleteValue(self->cache, (esif_string)path->buf_ptr);
		} else if (value && value->buf_ptr) {
			// UPDATE
			if (keypair->value.buf_len > 0 && value->data_len != keypair->value.buf_len) {
				void *new_buf = NULL;
				u32 new_buf_len = 0;
				
				// Grow or shrink buffer if it was allocated, otherwise ask for a larger buffer
				new_buf_len = esif_ccb_max(1, value->data_len);
				new_buf= (void *)esif_ccb_realloc(keypair->value.buf_ptr, new_buf_len);

				if (new_buf == NULL) {
					return ESIF_E_NEED_LARGER_BUFFER;
				}
				else {
					keypair->value.buf_len = new_buf_len;
					keypair->value.buf_ptr = new_buf;
				}
			} 

			// Replace the File Offset stored in buf_ptr with a copy of the data for updated NOCACHE values
			if (keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE && keypair->value.buf_len == 0) {
				keypair->value.buf_len = esif_ccb_max(1, value->data_len);
				keypair->value.buf_ptr = esif_ccb_malloc(value->buf_len);
			}
			keypair->flags = flags;
			keypair->value.type     = value->type;
			keypair->value.data_len = value->data_len;
			
			esif_ccb_memcpy(keypair->value.buf_ptr, value->buf_ptr, value->data_len);
			rc = ESIF_OK;
		}
	} else if (value && value->buf_ptr && !(flags & ESIF_SERVICE_CONFIG_DELETE)) {
		EsifDataPtr valueClonePtr = NULL;

		//
		// The data passed in may be in a buffer owned elsewhere, so clone the data
		//
		valueClonePtr = EsifData_Clone(value);
		if (NULL == valueClonePtr) {
			rc = ESIF_E_NO_MEMORY;
			goto exit;
		}

		DataCache_InsertValue(self->cache, (esif_string)path->buf_ptr, valueClonePtr, flags);

		EsifData_Destroy(valueClonePtr);
	}
exit:
	// If Persisted, Flush to disk
	if (rc == ESIF_OK && FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_PERSIST)) {
		rc = DataVault_WriteVault(self);
	}
	return rc;
}
Example #4
0
// Retrieve a single value from a DataVault
eEsifError DataVault_GetValue(
	DataVaultPtr self,
	EsifDataPtr path,
	EsifDataPtr value,
	esif_flags_t *flagsPtr
	)
{
	eEsifError rc = ESIF_E_NOT_FOUND;
	DataCacheEntryPtr keypair = NULL;

	if (!self)
		return ESIF_E_PARAMETER_IS_NULL;

	if (flagsPtr)
		*flagsPtr = 0;

	// Return "keyname1|keyname2|..." if path contains "*" or "?"
	if (esif_ccb_strpbrk((esif_string)path->buf_ptr, "*?") != NULL) {
		EsifDataPtr nameSpace = EsifData_CreateAs(ESIF_DATA_STRING, esif_ccb_strdup(self->name), ESIFAUTOLEN, ESIFAUTOLEN);
		EsifDataPtr key		  = EsifData_CreateAs(ESIF_DATA_STRING, path->buf_ptr, 0, ESIFAUTOLEN);
		EsifConfigFindContext context = NULL;
		esif_string keylist = NULL;
		u32 data_len = 0;
		
		// Verify valid Data Type and Data Buffer size
		if (value->type != ESIF_DATA_STRING && value->type != ESIF_DATA_AUTO) {
			rc = ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE;
		}
		
		if (rc == ESIF_E_NOT_FOUND && nameSpace != NULL && key != NULL && (rc = EsifConfigFindFirst(nameSpace, key, NULL, &context)) == ESIF_OK) {
			do {
				data_len += (u32)key->data_len;
				esif_string newlist = esif_ccb_realloc(keylist, data_len);
				if (newlist == NULL) {
					EsifData_Set(key, ESIF_DATA_STRING, "", 0, ESIFAUTOLEN);
					rc = ESIF_E_NO_MEMORY;
					break;
				}
				keylist = newlist;
				esif_ccb_sprintf_concat(data_len, keylist, "%s%s", (*keylist ? "|" : ""), (char *)key->buf_ptr);
				EsifData_Set(key, ESIF_DATA_STRING, path->buf_ptr, 0, ESIFAUTOLEN);
			} while ((rc = EsifConfigFindNext(nameSpace, key, NULL, &context)) == ESIF_OK);
		
			EsifConfigFindClose(&context);
			if (rc == ESIF_E_ITERATION_DONE) {
				rc = ESIF_OK;
			}
		}
		EsifData_Destroy(nameSpace);
		EsifData_Destroy(key);
		if (!keylist || rc != ESIF_OK) {
			esif_ccb_free(keylist);
			return rc;
		}

		// Return keylist value and data type
		if (value->type == ESIF_DATA_AUTO) {
			value->type = ESIF_DATA_STRING;
		}
		if (value->buf_len == ESIF_DATA_ALLOCATE) {
			esif_ccb_free(value->buf_ptr);
			value->buf_ptr = esif_ccb_strdup(keylist);
			value->buf_len = data_len;
			value->data_len = data_len;
		}
		else if (value->buf_len < data_len) {
			rc = ESIF_E_NEED_LARGER_BUFFER;
			value->data_len = data_len;
		}
		else if (value->buf_ptr) {
			esif_ccb_strcpy(value->buf_ptr, keylist, value->buf_len);
			value->data_len = data_len;
		}
		esif_ccb_free(keylist);
		return rc;
	}

	// Write to Log before retrieval if AUTO
	if (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE) {
		DataVault_WriteLog(self, "AUTO", (esif_string)(self->name), path, 0, value);
	}

	keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr);
	
	if (NULL != keypair) {
		UInt32 data_len = keypair->value.data_len;
		void *buf_ptr   = keypair->value.buf_ptr;
		UInt32 buf_len  = 0;
		Bool buf_alloc = ESIF_FALSE;

		// File Redirect?
		if (keypair->flags & ESIF_SERVICE_CONFIG_FILELINK) {
			if (ReadFileIntoBuffer((esif_string)buf_ptr, &buf_ptr, &data_len) != ESIF_OK) {
				value->data_len = 0;
				if (value->type == ESIF_DATA_AUTO) {
					value->type = keypair->value.type;
				}
				if (value->buf_len == ESIF_DATA_ALLOCATE) {
					value->buf_len = 0;
					value->buf_ptr = 0;
				}
				return ESIF_OK;	// return OK and a blank buffer if file not found/error
			}
			// Include Null Terminator if result is STRING
			if (value->buf_len == ESIF_DATA_ALLOCATE && (value->type == ESIF_DATA_STRING || (value->type == ESIF_DATA_AUTO && keypair->value.type == ESIF_DATA_STRING))) {
				data_len++;
			}
			buf_len = data_len;
			buf_alloc = ESIF_TRUE;
		}

		// Match Found. Verify Data Type matches unless AUTO
		if (value->type != keypair->value.type && value->type != ESIF_DATA_AUTO) {
			rc = ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE;	// TODO: ESIF_E_INVALID_DATA_TYPE
		}
		// Verify Data Buffer is large enough unless Auto-Allocate
		else if (value->buf_len < data_len && value->buf_len != ESIF_DATA_ALLOCATE) {
			value->data_len = data_len;
			rc = ESIF_E_NEED_LARGER_BUFFER;
		}
		// Return pointer to static contents if this is a static vault
		else if ((self->flags & ESIF_SERVICE_CONFIG_STATIC) &&
				 (value->type == ESIF_DATA_AUTO) &&
				 (value->buf_len == ESIF_DATA_ALLOCATE)) {
			value->type     = keypair->value.type;
			value->data_len = data_len;
			value->buf_len  = 0;	// Caller MUST NOT Free!
			value->buf_ptr  = buf_ptr;
			rc = ESIF_OK;
		} 
		else {
			// Set Data Type and Auto-Allocate Buffer?
			if (value->type == ESIF_DATA_AUTO) {
				value->type = keypair->value.type;
			}
			if (ESIF_DATA_ALLOCATE == value->buf_len) {
				value->buf_len = esif_ccb_max(1, data_len);
				value->buf_ptr = esif_ccb_malloc(value->buf_len);
				if (!value->buf_ptr) {
					if (buf_alloc) {
						esif_ccb_free(buf_ptr);
					}
					return ESIF_E_NO_MEMORY;
				}
			}

			// Read from file if NOCACHE option
			if ((keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE) && keypair->value.buf_len == 0) {
				size_t offset = (size_t)keypair->value.buf_ptr;
				if (DataVault_GetFromSource(self, (esif_string)value->buf_ptr, data_len, offset) != ESIF_OK) {
					if (buf_alloc) {
						esif_ccb_free(buf_ptr);
					}
					return ESIF_E_NOT_FOUND;
				}
				// Unscramble Data?
				if (keypair->flags & ESIF_SERVICE_CONFIG_SCRAMBLE) {
					UInt32 byte;
					for (byte = 0; byte < data_len; byte++)
						((UInt8*)(value->buf_ptr))[byte] = ~((UInt8*)(value->buf_ptr))[byte];
				}
			} else {
				esif_ccb_memcpy(value->buf_ptr, buf_ptr, data_len);
			}
			value->data_len = data_len;
			rc = ESIF_OK;
		}

		// Return flags
		if (rc == ESIF_OK) {
			if (flagsPtr != NULL)
				*flagsPtr = keypair->flags;
		}

		// Destroy Dynamically copied data, such as FILELINK contents
		if (buf_alloc) {
			esif_ccb_free(buf_ptr);
		}
	}
	// Write to Log
	DataVault_WriteLog(self, "GET", (esif_string)self->name, path, 0, value);
	return rc;
}
Example #5
0
// Reads a key/value pair from the current location in the open DataVault stream
static eEsifError DataVault_ReadNextKeyValuePair(
	DataVaultPtr self,
	esif_flags_t *flagsPtr,
	EsifDataPtr keyPtr,
	EsifDataPtr valuePtr
	)
{
	eEsifError rc = ESIF_OK;
	IOStreamPtr vault = NULL;
	size_t bytes = 0;

	ESIF_ASSERT(self != NULL);
	ESIF_ASSERT(flagsPtr != NULL);
	ESIF_ASSERT(keyPtr != NULL);
	ESIF_ASSERT(valuePtr != NULL);

	vault = self->stream;

	// Read Flags
	if ((bytes = IOStream_Read(vault, flagsPtr, sizeof(*flagsPtr))) != sizeof(*flagsPtr)) {
		// Check if we are done
		if (bytes != 0) {
			rc = ESIF_E_IO_ERROR;
		}
		rc = ESIF_E_ITERATION_DONE;
		goto exit;
	}

	// Read key length
	keyPtr->type = ESIF_DATA_STRING;
	if (IOStream_Read(vault, &keyPtr->data_len, sizeof(keyPtr->data_len)) < sizeof(keyPtr->data_len)) {
		rc = ESIF_E_IO_ERROR;
		goto exit;
	}
	if (keyPtr->data_len > MAX_DV_DATALEN) {
		rc = ESIF_E_PARAMETER_IS_OUT_OF_BOUNDS;
		goto exit;
	}

	// Use Memory Pointers for Static DataVaults, otherwise allocate memory
	if ((IOStream_GetType(vault) == StreamMemory) && (self->flags & ESIF_SERVICE_CONFIG_STATIC)) {
		keyPtr->buf_len = 0;
		keyPtr->buf_ptr = IOStream_GetMemoryBuffer(vault) + IOStream_GetOffset(vault);
		if (IOStream_Seek(vault, keyPtr->data_len, SEEK_CUR) != EOK) {
			rc = ESIF_E_IO_ERROR;
			goto exit;
		}
		*flagsPtr &= ~ESIF_SERVICE_CONFIG_NOCACHE;	// ignore for Static DataVaults
	}
	else {
		keyPtr->buf_len = esif_ccb_max(1, keyPtr->data_len);
		keyPtr->buf_ptr = esif_ccb_malloc(keyPtr->buf_len);
		if (!keyPtr->buf_ptr) {
			rc = ESIF_E_NO_MEMORY;
			goto exit;
		}
		if (IOStream_Read(vault, keyPtr->buf_ptr, keyPtr->data_len) != keyPtr->data_len) {
			rc = ESIF_E_IO_ERROR;
			goto exit;
		}
		else if (keyPtr->data_len) {
			((esif_string)(keyPtr->buf_ptr))[keyPtr->data_len - 1] = 0;
		}
	}

	// Read Value
	if (IOStream_Read(vault, &valuePtr->type, sizeof(valuePtr->type)) != sizeof(valuePtr->type)) {
		rc = ESIF_E_IO_ERROR;
		goto exit;
	}
	if (IOStream_Read(vault, &valuePtr->data_len, sizeof(valuePtr->data_len)) != sizeof(valuePtr->data_len)) {
		rc = ESIF_E_IO_ERROR;
		goto exit;
	}
	if  (valuePtr->data_len > MAX_DV_DATALEN) {
		rc = ESIF_E_PARAMETER_IS_OUT_OF_BOUNDS;
		goto exit;
	}

	// If NOCACHE mode, use buf_ptr to store the file offset of the data and skip the file
	if (*flagsPtr & ESIF_SERVICE_CONFIG_NOCACHE) {
		size_t offset = IOStream_GetOffset(vault);
		if (IOStream_Seek(vault, valuePtr->data_len, SEEK_CUR) != EOK) {
			rc = ESIF_E_IO_ERROR;
			goto exit;
		}
		valuePtr->buf_ptr = (void*)offset; // For non-cached...we save the offset in the file as the buffer pointer. Really???
		valuePtr->buf_len = 0;	// buf_len == 0 so we don't release buffer as not allocated; data_len = original length
	} 
	else {
		// Use static pointer for static data vaults (unless scrambled), otherwise make a dynamic copy
		if ((IOStream_GetType(vault) == StreamMemory) && (self->flags & ESIF_SERVICE_CONFIG_STATIC) && !(*flagsPtr & ESIF_SERVICE_CONFIG_SCRAMBLE)) {
			valuePtr->buf_len = 0;	// static
			valuePtr->buf_ptr = IOStream_GetMemoryBuffer(vault) + IOStream_GetOffset(vault);
			if (valuePtr->buf_ptr == NULL || IOStream_Seek(vault, valuePtr->data_len, SEEK_CUR) != EOK) {
				rc = ESIF_E_IO_ERROR;
				goto exit;
			}
		} 
		else {
			valuePtr->buf_len = esif_ccb_max(1, valuePtr->data_len); // dynamic
			valuePtr->buf_ptr = esif_ccb_malloc(valuePtr->buf_len);
			if (valuePtr->buf_ptr == NULL) {
				rc = ESIF_E_NO_MEMORY;
				goto exit;
			}
			else if (IOStream_Read(vault, valuePtr->buf_ptr, valuePtr->data_len) != valuePtr->data_len) {
				rc = ESIF_E_IO_ERROR;
				goto exit;
			}
		}
			
		//  Unscramble Data?
		if (*flagsPtr & ESIF_SERVICE_CONFIG_SCRAMBLE) {
			UInt32 byte;
			for (byte = 0; byte < valuePtr->data_len; byte++)
				((UInt8*)(valuePtr->buf_ptr))[byte] = ~((UInt8*)(valuePtr->buf_ptr))[byte];
		}
	}
exit:
	return rc;
}
Example #6
0
/* Set */
eEsifError DataVault_SetValue (
	DataVaultPtr self,
	EsifDataPtr path,
	EsifDataPtr value,
	esif_flags_t flags
	)
{
	eEsifError rc = ESIF_OK;
	DataCacheEntryPtr keypair;

	if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) {
		return ESIF_E_READONLY;
	}

	// Ignore value for DELETEs
	if (FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_DELETE)) {
		value = NULL;
	}

	// TODO: Locking

	// AUTO data types or AUTO_ALLOCATE are not allowed for SET
	if (value && (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE)) {
		return ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE;
	}

	// Write to Log
	DataVault_WriteLog(self, (flags & ESIF_SERVICE_CONFIG_DELETE ? "DELETE" : "SET"), self->name, path, flags, value);

	// Delete entire DataVault?
	if (strcmp((esif_string)path->buf_ptr, "*") == 0) {
		if (flags & ESIF_SERVICE_CONFIG_DELETE) {
			DataCache_Destroy(self->cache);
			if ((self->cache = DataCache_Create()) == NULL) {
				return ESIF_E_NO_MEMORY;
			}
			DataVault_WriteVault(self);
			return ESIF_OK;
		}
		return ESIF_E_NOT_SUPPORTED;// "*" is an invalid key value
	}

	// Read data from File
	// TODO: Change Parser Logic and Syntax instead
	if (value && value->buf_ptr && esif_ccb_strncmp((char*)value->buf_ptr, "<<", 2) == 0) {
		void *buffer  = 0;
		UInt32 buflen = 0;
		if (DataVault_ReadFile(self, (char*)value->buf_ptr + 2, &buffer, &buflen) == ESIF_OK) {
			value->buf_ptr = buffer;
			if (value->type == ESIF_DATA_STRING) {
				buflen++;	// Include Null Terminator
			}
			value->buf_len = value->data_len = buflen;
		} else {
			return ESIF_E_UNSPECIFIED;	// TODO: File Not Found
		}
	}

	// Get the Data Row or create it if it does not exist
	keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr);
	if (keypair) {	// Match Found
		// READONLY?
		if (keypair->flags & ESIF_SERVICE_CONFIG_READONLY) {
			rc = ESIF_E_READONLY;
		}
		// DELETE?
		else if (flags & ESIF_SERVICE_CONFIG_DELETE) {
			flags |= keypair->flags;
			DataCache_Delete(self->cache, (esif_string)path->buf_ptr);
		} else if (value && value->buf_ptr) {
			// UPDATE
#ifdef ESIF_ATTR_OS_WINDOWS
			// Update Registry Value for REGKEY values if REGLINK is *NOT* specified in SET command
			if ((keypair->flags & ESIF_SERVICE_CONFIG_REGLINK) && !(flags & ESIF_SERVICE_CONFIG_REGLINK)) {
				keypair->value.type = value->type;
				rc = DataVault_WriteRegistry(self, (esif_string)keypair->value.buf_ptr, value);
			} else	// ...
#endif
			if (keypair->value.buf_len && value->data_len > keypair->value.buf_len) {
				rc = ESIF_E_NEED_LARGER_BUFFER;
			} else {
				keypair->flags = flags;
				keypair->value.type     = value->type;
				keypair->value.data_len = value->data_len;

				// Replace the File Offset stored in buf_ptr with a copy of the data for updated NOCACHE values
				if (keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE && keypair->value.buf_len == 0) {
					keypair->value.buf_ptr = esif_ccb_malloc(value->data_len);
					keypair->value.buf_len = value->data_len;
				}
				esif_ccb_memcpy(keypair->value.buf_ptr, value->buf_ptr, value->data_len);
				rc = ESIF_OK;
			}
		}
	} else if (value && value->buf_ptr && !(flags & ESIF_SERVICE_CONFIG_DELETE)) {
		// Copy Key/Value Pair to new Data Row
		EsifData newkey   = {ESIF_DATA_STRING, esif_ccb_strdup((esif_string)path->buf_ptr), path->data_len, path->data_len};
		EsifData newvalue = {value->type, esif_ccb_malloc(esif_ccb_max(value->buf_len, value->data_len)), value->data_len, value->data_len};
		esif_ccb_memcpy(newvalue.buf_ptr, value->buf_ptr, value->data_len);
		DataCache_SetValue(self->cache, (esif_string)newkey.buf_ptr, newvalue, flags);
		esif_ccb_free(newkey.buf_ptr);
	}

	// If Persisted, Flush to disk
	if (rc == ESIF_OK && FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_PERSIST)) {
		DataVault_WriteVault(self);
	}
	return rc;
}
Example #7
0
int EsifTraceMessage(
	esif_tracemask_t module, 
	int level, 
	const char *func, 
	const char *file, 
	int line, 
	const char *msg, 
	...)
{
	int rc=0;
	char *appname  = "";
	char *fmtDetail= "%s%s:[<%s>%s@%s#%d]<%llu ms>: ";
	char *fmtInfo  = "%s%s:[<%s>]<%llu ms>: ";
	const char *sep=NULL;
	size_t fmtlen=esif_ccb_strlen(msg, 0x7FFFFFFF);
	int  detailed_message = (level >= DETAILED_TRACELEVEL ? ESIF_TRUE : ESIF_FALSE);
	va_list args;
	esif_ccb_time_t msec = 0;
	enum esif_tracemodule moduleid = ESIF_TRACEMODULE_DEFAULT;
	const char *module_name = NULL;

	esif_ccb_system_time(&msec);

	while (module >>= 1)
		moduleid++;
	module_name = EsifTraceModule_ToString(moduleid);

	level = esif_ccb_min(level, ESIF_TRACELEVEL_MAX);
	level = esif_ccb_max(level, ESIF_TRACELEVEL_FATAL);
	if ((sep = strrchr(file, *ESIF_PATH_SEP)) != NULL)
		file = sep+1;

	// Do not log function/file/line information for DPTF app interface messages logged from EsifSvcWriteLog
	if (moduleid == ESIF_TRACEMODULE_DPTF) {
		detailed_message = ESIF_FALSE;
	}

	if (g_traceinfo[level].routes & ESIF_TRACEROUTE_CONSOLE) {
		if (detailed_message)
			rc =  CMD_CONSOLE(fmtDetail, appname, g_traceinfo[level].label, module_name, func, file, line, msec);
		else
			rc =  CMD_CONSOLE(fmtInfo, appname, g_traceinfo[level].label, module_name, msec);
		va_start(args, msg);
		rc += EsifConsole_WriteConsole(msg, args);
		va_end(args);

		if (fmtlen && msg[fmtlen-1]!='\n')
			CMD_CONSOLE("\n");
	}

	if (g_traceinfo[level].routes & ESIF_TRACEROUTE_LOGFILE && EsifLogFile_IsOpen(ESIF_LOG_TRACE)) {
		time_t now=0;
		char timestamp[MAX_CTIME_LEN]={0};

		time(&now);
		esif_ccb_ctime(timestamp, sizeof(timestamp), &now);
		timestamp[20] = 0; // truncate year

		if (detailed_message)
			rc = EsifLogFile_Write(ESIF_LOG_TRACE, fmtDetail, timestamp + 4, g_traceinfo[level].label, module_name, func, file, line, msec);
		else
			rc =  EsifLogFile_Write(ESIF_LOG_TRACE, fmtInfo, timestamp+4, g_traceinfo[level].label, module_name, msec);
		va_start(args, msg);
		rc += EsifLogFile_WriteArgsAppend(ESIF_LOG_TRACE, "\n", msg, args);
		va_end(args);
	}

#ifdef ESIF_ATTR_OS_WINDOWS
	if (g_traceinfo[level].routes & (ESIF_TRACEROUTE_DEBUGGER)) {
		size_t  msglen=0;
		char *buffer=0;
		int  offset=0;

		va_start(args, msg);
		msglen = esif_ccb_vscprintf(msg, args) + esif_ccb_strlen(g_traceinfo[level].label, MAX_PATH) + esif_ccb_strlen(appname, MAX_PATH) + esif_ccb_strlen(func, MAX_PATH) + esif_ccb_strlen(file, MAX_PATH) + esif_ccb_strlen(module_name, MAX_PATH) + 22;
		va_end(args);
		msglen += (detailed_message ? esif_ccb_strlen(fmtDetail, MAX_PATH) : esif_ccb_strlen(fmtInfo, MAX_PATH));
		buffer = (char *)esif_ccb_malloc(msglen);

		if (NULL != buffer) {
			if (detailed_message)
				rc =  esif_ccb_sprintf(msglen, buffer, fmtDetail, appname, g_traceinfo[level].label, module_name, func, file, line, msec);
			else
				rc =  esif_ccb_sprintf(msglen, buffer, fmtInfo, appname, g_traceinfo[level].label, module_name, msec);

			offset = rc;
			va_start(args, msg);
			rc += esif_ccb_vsprintf(msglen-offset, buffer+offset, msg, args);
			va_end(args);
			if (rc && buffer[rc-1]!='\n')
				esif_ccb_strcat(buffer, "\n", msglen);

			OutputDebugStringA(buffer); 
			esif_ccb_free(buffer);
		}
	}
	if (g_traceinfo[level].routes & (ESIF_TRACEROUTE_EVENTLOG)) {
		size_t  msglen=0;
		char *buffer=0;
		char *replaced=0;
		int  offset=0;
		int  backset=0;
		WORD eventType;

		appname  = "";
		fmtInfo  = "%sESIF(%s) TYPE: %s MODULE: %s TIME %llu ms\n\n";
		fmtDetail= "%sESIF(%s) TYPE: %s MODULE: %s FUNC: %s FILE: %s LINE: %d TIME: %llu ms\n\n";
		backset  = 0;

		va_start(args, msg);
		msglen = esif_ccb_vscprintf(msg,args) + esif_ccb_strlen(g_traceinfo[level].label, MAX_PATH) + esif_ccb_strlen(appname, MAX_PATH) + esif_ccb_strlen(func, MAX_PATH) + esif_ccb_strlen(file, MAX_PATH) + esif_ccb_strlen(module_name, MAX_PATH) + 32;
		va_end(args);
		msglen += (detailed_message ? esif_ccb_strlen(fmtDetail, MAX_PATH) : esif_ccb_strlen(fmtInfo, MAX_PATH));
		buffer = (char *)esif_ccb_malloc(msglen);

		if (NULL != buffer) {
			if (detailed_message)
				rc = esif_ccb_sprintf(msglen, buffer, fmtDetail, appname, ESIF_UF_VERSION, g_traceinfo[level].label, module_name, func, file, line, msec);
			else
				rc = esif_ccb_sprintf(msglen, buffer, fmtInfo, appname, ESIF_UF_VERSION, g_traceinfo[level].label, module_name, msec);

			if (backset && backset < rc)
				buffer[rc-backset-1] = 0;
			offset = rc-backset;
			va_start(args, msg);
			rc += esif_ccb_vsprintf(msglen-(offset+backset), buffer+offset+backset, msg, args);
			va_end(args);
			if (rc && buffer[rc-1]=='\n')
				buffer[--rc] = 0;

			switch (g_traceinfo[level].level) {
			case ESIF_TRACELEVEL_FATAL:
			case ESIF_TRACELEVEL_ERROR:
				eventType = EVENTLOG_ERROR_TYPE;
				break;
			case ESIF_TRACELEVEL_WARN:
				eventType = EVENTLOG_WARNING_TYPE;
				break;
			case ESIF_TRACELEVEL_INFO:
			case ESIF_TRACELEVEL_DEBUG:
			default:
				eventType = EVENTLOG_INFORMATION_TYPE;
				break;
			}
			// Escape any "%" in message before writing to EventLog
			if ((replaced = esif_str_replace(buffer, "%", "%%")) != NULL) {
				esif_ccb_free(buffer);
				buffer = replaced;
				replaced = NULL;
			}
			report_event_to_event_log(CATEGORY_GENERAL, eventType, buffer);
			esif_ccb_free(buffer);
		}
	}
#endif
#ifdef ESIF_ATTR_OS_LINUX
	if (g_traceinfo[level].routes & (ESIF_TRACEROUTE_EVENTLOG|ESIF_TRACEROUTE_DEBUGGER)) {
		size_t  msglen=0;
		char *buffer=0;
		int  offset=0;
		int priority;

		fmtDetail= "%s:[<%s>%s@%s#%d]<%llu ms>: ";
		fmtInfo  = "%s:[<%s>]<%llu ms>: ";

		va_start(args, msg);
		msglen = esif_ccb_vscprintf(msg,args) + esif_ccb_strlen(g_traceinfo[level].label, MAX_PATH) + esif_ccb_strlen(func, MAX_PATH) + esif_ccb_strlen(file, MAX_PATH) + esif_ccb_strlen(module_name, MAX_PATH) + 22;
		va_end(args);
		msglen += (detailed_message ? esif_ccb_strlen(fmtDetail, MAX_PATH) : esif_ccb_strlen(fmtInfo, MAX_PATH));
		buffer = (char *)esif_ccb_malloc(msglen);

		if (NULL != buffer) {
			char *lf;
			if (detailed_message)
				rc =  esif_ccb_sprintf(msglen, buffer, fmtDetail, g_traceinfo[level].label, module_name, func, file, line, msec);
			else
				rc =  esif_ccb_sprintf(msglen, buffer, fmtInfo, g_traceinfo[level].label, module_name, msec);

			offset = rc;
			va_start(args, msg);
			rc += esif_ccb_vsprintf(msglen-offset, buffer+offset, msg, args);
			va_end(args);
			if (rc && buffer[rc-1]=='\n')
				buffer[--rc] = 0;

			while ((lf = esif_ccb_strchr(buffer, '\n')) != NULL)
				*lf = '\t';

			switch (g_traceinfo[level].level) {
			case ESIF_TRACELEVEL_FATAL:
				priority = ESIF_PRIORITY_FATAL;
				break;
			case ESIF_TRACELEVEL_ERROR:
				priority = ESIF_PRIORITY_ERROR;
				break;
			case ESIF_TRACELEVEL_WARN:
				priority = ESIF_PRIORITY_WARNING;
				break;
			case ESIF_TRACELEVEL_INFO:
				priority = ESIF_PRIORITY_INFO;
				break;
			case ESIF_TRACELEVEL_DEBUG:
			default:
				priority = ESIF_PRIORITY_DEBUG;
				break;
			}
		#ifdef ESIF_ATTR_OS_ANDROID
			__android_log_write(priority, IDENT, buffer);
		#else
			openlog(IDENT, OPTION, FACILITY);
			syslog(priority, "%s", buffer);
			closelog();
		#endif
			esif_ccb_free(buffer);
		}
	}
#endif
	return rc;
}