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; }
// 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; }
/* 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; }
// 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; }
// 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; }
/* 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; }
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; }