//-------------------------------------------------------------------------------------------------- static tu_UserRef_t GetUserInfo ( le_msg_SessionRef_t currentSession, ///< [IN] Get the user information for this message ///< session. bool* wasCreated ///< [OUT] Was the user info created for this request? ///< Pass NULL if you don't need this. ) //-------------------------------------------------------------------------------------------------- { LE_FATAL_IF(currentSession == NULL, "Bad user message session reference."); // Look up the user id of the requesting connection... uid_t userId; LE_FATAL_IF(le_msg_GetClientUserId(currentSession, &userId) == LE_CLOSED, "tu_GetUserInfo must be called within an active connection."); // Now that we have a user ID, let's see if we can look them up. tu_UserRef_t userRef = GetUser(userId, wasCreated); LE_ASSERT(userRef != NULL); LE_DEBUG("** Found user <%p>: '%s', %u with default tree, '%s'.", userRef, userRef->userName, userRef->userId, userRef->treeName); return userRef; }
//-------------------------------------------------------------------------------------------------- void cgrp_Init ( void ) { // Setup the cgroup root directory if it does not already exist. if (!fs_IsMounted(ROOT_NAME, ROOT_PATH)) { LE_FATAL_IF(mount(ROOT_NAME, ROOT_PATH, "tmpfs", 0, NULL) != 0, "Could not mount cgroup root file system. %m."); } // Setup a separate cgroup hierarch for each supported subsystem. cgrp_SubSys_t subSys = 0; for (; subSys < CGRP_NUM_SUBSYSTEMS; subSys++) { char dir[LIMIT_MAX_PATH_BYTES] = ROOT_PATH; LE_ASSERT(le_path_Concat("/", dir, sizeof(dir), SubSysName[subSys], (char*)NULL) == LE_OK); LE_ASSERT(le_dir_Make(dir, S_IRWXU) != LE_FAULT); if (!fs_IsMounted(SubSysName[subSys], dir)) { LE_FATAL_IF(mount(SubSysName[subSys], dir, "cgroup", 0, SubSysName[subSys]) != 0, "Could not mount cgroup subsystem '%s'. %m.", SubSysName[subSys]); LE_INFO("Mounted cgroup hiearchy for subsystem '%s'.", SubSysName[subSys]); } } }
//-------------------------------------------------------------------------------------------------- void smack_RevokeSubject ( const char* subjectLabelPtr ///< [IN] Subject label. ) { // Open the SMACK revoke file. int fd; do { fd = open(SMACK_REVOKE_FILE, O_WRONLY); } while ( (fd == -1) && (errno == EINTR) ); LE_FATAL_IF(fd == -1, "Could not open %s. %m.\n", SMACK_REVOKE_FILE); // Write the label to the SMACK revoke file. int numBytes = 0; do { numBytes = write(fd, subjectLabelPtr, strlen(subjectLabelPtr)); } while ( (numBytes == -1) && (errno == EINTR) ); LE_FATAL_IF(numBytes < 0, "Could not revoke SMACK label '%s'. %m.", subjectLabelPtr); fd_Close(fd); LE_DEBUG("Revoked SMACK label '%s'.", subjectLabelPtr); }
//-------------------------------------------------------------------------------------------------- LE_SHARED void cfgInstall_Add ( const char* appName ) //-------------------------------------------------------------------------------------------------- { le_result_t result; char filePath[256] = "/opt/legato/apps/"; result = le_utf8_Append(filePath, appName, sizeof(filePath), NULL); LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName); result = le_utf8_Append(filePath, "/root.cfg", sizeof(filePath), NULL); LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName); LE_INFO("Importing configuration for application '%s' from '%s'.", appName, filePath); le_cfg_IteratorRef_t i = le_cfg_CreateWriteTxn("/apps"); result = le_cfgAdmin_ImportTree(i, filePath, appName); LE_FATAL_IF(result != LE_OK, "Failed to import configuration from '%s' to 'root:/apps/%s' (%s)", filePath, appName, LE_RESULT_TXT(result)); le_cfg_CommitTxn(i); }
//-------------------------------------------------------------------------------------------------- static void CheckLabel ( const char* labelPtr ///< [IN] Label to check. ) { // Check lengths. size_t labelSize = strlen(labelPtr); LE_FATAL_IF(labelSize == 0, "SMACK label cannot be empty."); LE_FATAL_IF(labelSize > LIMIT_MAX_SMACK_LABEL_LEN, "SMACK label length, %zd chars, is too long. Labels must be less than %d chars", labelSize, LIMIT_MAX_SMACK_LABEL_LEN); // Check for invalid characters. LE_FATAL_IF(labelPtr[0] == '-', "SMACK label '%s' is invalid because it begins with '-'.", labelPtr); int i; for (i = 0; i < labelSize; i++) { char c = labelPtr[i]; if ( !isprint(c) || !isascii(c) || (c == '/') || (c == '\\') || (c == '\'') || (c == '"') ) { LE_FATAL("SMACK label '%s' contain invalid character(s).", labelPtr); } } }
//-------------------------------------------------------------------------------------------------- event_PerThreadRec_t* fa_event_CreatePerThreadInfo ( void ) { event_LinuxPerThreadRec_t* recPtr = le_mem_ForceAlloc(PerThreadPool); // Create the epoll file descriptor for this thread. This will be used to monitor for // events on various file descriptors. recPtr->epollFd = epoll_create1(0); LE_FATAL_IF(recPtr->epollFd < 0, "epoll_create1(0) failed with errno %d.", errno); // Open an eventfd for this thread. This will be uses to signal to the epoll fd that there // are Event Reports on the Event Queue. recPtr->eventQueueFd = eventfd(0, 0); LE_FATAL_IF(recPtr->eventQueueFd < 0, "eventfd() failed with errno %d.", errno); // Add the eventfd to the list of file descriptors to wait for using epoll_wait(). struct epoll_event ev; memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN | EPOLLWAKEUP; ev.data.ptr = NULL; // This being set to NULL is what tells the main event loop that this // is the Event Queue FD, rather than another FD that is being // monitored. if (epoll_ctl(recPtr->epollFd, EPOLL_CTL_ADD, recPtr->eventQueueFd, &ev) == -1) { LE_FATAL( "epoll_ctl(ADD) failed for fd %d. errno = %d", recPtr->eventQueueFd, errno); } return &recPtr->portablePerThreadRec; }
//-------------------------------------------------------------------------------------------------- void le_fdMonitor_Enable ( le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object. short events ///< [in] Bit map of events. ) //-------------------------------------------------------------------------------------------------- { // Look up the File Descriptor Monitor object using the safe reference provided. // Note that the safe reference map is shared by all threads in the process, so it // must be protected using the mutex. The File Descriptor Monitor objects, on the other // hand, are only allowed to be accessed by the one thread that created them, so it is // safe to unlock the mutex after doing the safe reference lookup. LOCK FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef); UNLOCK LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef); LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr, "FD Monitor '%s' (fd %d) is owned by another thread.", monitorPtr->name, monitorPtr->fd); short filteredEvents = events & (POLLIN | POLLOUT | POLLPRI); if (filteredEvents != events) { char textBuff[64]; LE_WARN("Attempt to enable events that can't be disabled (%s).", GetPollEventsText(textBuff, sizeof(textBuff), events & ~filteredEvents)); } uint32_t epollEvents = PollToEPoll(filteredEvents); // If the fd doesn't support epoll, we assume it is always ready for read and write. // As long as EPOLLIN or EPOLLOUT (or both) is enabled for one of these fds, DispatchToHandler() // keeps re-queueing itself to the thread's event queue. But it will stop doing that if // EPOLLIN and EPOLLOUT are both disabled. So, here is where we get things going again when // EPOLLIN or EPOLLOUT is enabled outside DispatchToHandler() for that fd. if ( (monitorPtr->isAlwaysReady) && (epollEvents & (EPOLLIN | EPOLLOUT)) && ((monitorPtr->epollEvents & (EPOLLIN | EPOLLOUT)) == 0) ) { // Fetch the pointer to the FD Monitor from thread-specific data. // This will be NULL if we are not inside an FD Monitor handler. FdMonitor_t* handlerMonitorPtr = pthread_getspecific(FDMonitorPtrKey); // If no handler is running or some other fd's handler is running, if ((handlerMonitorPtr == NULL) || (handlerMonitorPtr->safeRef == monitorRef)) { // Queue up DispatchToHandler() for this fd. fdMon_Report(monitorRef, epollEvents & (EPOLLIN | EPOLLOUT)); } } // Bit-wise OR the newly enabled event flags into the FD Monitor's epoll(7) flags set. monitorPtr->epollEvents |= epollEvents; UpdateEpollFd(monitorPtr); }
//-------------------------------------------------------------------------------------------------- le_msg_SessionEventHandlerRef_t le_msg_AddServiceCloseHandler ( le_msg_ServiceRef_t serviceRef, ///< [in] Reference to the service. le_msg_SessionEventHandler_t handlerFunc,///< [in] Handler function. void* contextPtr ///< [in] Opaque pointer value to pass to handler. ) //-------------------------------------------------------------------------------------------------- { LE_FATAL_IF(serviceRef == NULL, "Service doesn't exist. Make sure service is started before setting handlers"); LE_FATAL_IF(serviceRef->serverThread != le_thread_GetCurrent(), "Service (%s:%s) not owned by calling thread.", serviceRef->id.name, le_msg_GetProtocolIdStr(serviceRef->id.protocolRef)); // Create the node. SessionEventHandler_t* closeEventPtr = le_mem_ForceAlloc(HandlerEventPoolRef); // Initialize the node. closeEventPtr->handler = handlerFunc; closeEventPtr->contextPtr = contextPtr; closeEventPtr->link = LE_DLS_LINK_INIT; closeEventPtr->listPtr = &serviceRef->closeListPtr; // Add the node to the head of the list by passing in the node's link. le_dls_Stack(&serviceRef->closeListPtr, &closeEventPtr->link); // Need to return a unique reference that will be used by the remove function. closeEventPtr->ref = le_ref_CreateRef(HandlersRefMap, &closeEventPtr->link); return closeEventPtr->ref; }
//-------------------------------------------------------------------------------------------------- void le_fdMonitor_SetDeferrable ( le_fdMonitor_Ref_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object. bool isDeferrable ///< [in] true (deferrable) or false (urgent). ) //-------------------------------------------------------------------------------------------------- { // Look up the File Descriptor Monitor object using the safe reference provided. // Note that the safe reference map is shared by all threads in the process, so it // must be protected using the mutex. The File Descriptor Monitor objects, on the other // hand, are only allowed to be accessed by the one thread that created them, so it is // safe to unlock the mutex after doing the safe reference lookup. LOCK FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef); UNLOCK LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef); LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr, "FD Monitor '%s' (fd %d) is owned by another thread.", monitorPtr->name, monitorPtr->fd); // Set/clear the EPOLLWAKEUP flag in the FD Monitor's epoll(7) flags set. if (isDeferrable) { monitorPtr->epollEvents &= ~EPOLLWAKEUP; } else { monitorPtr->epollEvents |= EPOLLWAKEUP; } UpdateEpollFd(monitorPtr); }
//-------------------------------------------------------------------------------------------------- void le_msg_AdvertiseService ( le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service. ) //-------------------------------------------------------------------------------------------------- { LE_FATAL_IF(serviceRef->state != LE_MSG_SERVICE_HIDDEN, "Re-advertising before hiding service '%s:%s'.", serviceRef->id.name, le_msg_GetProtocolIdStr(serviceRef->id.protocolRef)); serviceRef->state = LE_MSG_SERVICE_CONNECTING; // Open a socket. int fd = unixSocket_CreateSeqPacketUnnamed(); serviceRef->directorySocketFd = fd; // Check for failure. LE_FATAL_IF(fd == LE_NOT_PERMITTED, "Permission to open socket denied."); LE_FATAL_IF(fd == LE_FAULT, "Failed to open socket."); // Warn if one of the three standard I/O streams have been somehow connected to the // Service Directory. if (fd < 3) { const char* streamNameStr; switch (fd) { case 0: streamNameStr = "stdin"; break; case 1: streamNameStr = "stdout"; break; case 2: streamNameStr = "stderr"; break; } LE_WARN("Service Directory connection mapped to %s.", streamNameStr); } // Set the socket non-blocking. fd_SetNonBlocking(fd); // Start monitoring the socket for events. StartMonitoringDirectorySocket(serviceRef); // Connect the socket to the Service Directory. le_result_t result = unixSocket_Connect(fd, LE_SVCDIR_SERVER_SOCKET_NAME); LE_FATAL_IF((result != LE_OK) && (result != LE_WOULD_BLOCK), "Failed to connect to Service Directory. Result = %d (%s).", result, LE_RESULT_TXT(result)); // Wait for writeability notification on the socket. See DirectorySocketWriteable(). }
//-------------------------------------------------------------------------------------------------- void le_msg_AdvertiseService ( le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service. ) //-------------------------------------------------------------------------------------------------- { // Open a socket and connect it to the Service Directory. int fd = unixSocket_CreateSeqPacketUnnamed(); // Check for failure. LE_FATAL_IF(fd == LE_NOT_PERMITTED, "Permission to open socket denied."); LE_FATAL_IF(fd == LE_FAULT, "Failed to open socket."); // Warn if one of the three standard I/O streams have been somehow connected to the // Service Directory. if (fd < 3) { const char* streamNameStr; switch (fd) { case 0: streamNameStr = "stdin"; break; case 1: streamNameStr = "stdout"; break; case 2: streamNameStr = "stderr"; break; } LE_WARN("Service Directory connection mapped to %s.", streamNameStr); } le_result_t result = unixSocket_Connect(fd, LE_SVCDIR_SERVER_SOCKET_NAME); LE_FATAL_IF(result != LE_OK, "Failed to connect to Service Directory. Result = %d (%s).", result, LE_RESULT_TXT(result)); serviceRef->directorySocketFd = fd; // Set the socket non-blocking. fd_SetNonBlocking(fd); // Start monitoring the socket for events. StartMonitoringDirectorySocket(serviceRef); // Send the Service ID to the Service Directory. msgService_SendServiceId(serviceRef, fd); // Wait for the Service Directory to respond by either dropping the connection // (meaning that we have been denied permission to offer this service) or by // forwarding us file descriptors for authenticated client connections. }
//-------------------------------------------------------------------------------------------------- static void CheckFor ( appCfg_Iter_t iterRef, IterType_t type ) { LE_FATAL_IF(iterRef == NULL, "Iterator reference can not be NULL."); LE_FATAL_IF(iterRef->type != type, "Expected %s, but received %s instead.", TypeToStr(type), TypeToStr(iterRef->type)); }
//-------------------------------------------------------------------------------------------------- bool smack_HasAccess ( const char* subjectLabelPtr, ///< [IN] Subject label. const char* accessModePtr, ///< [IN] Access mode. const char* objectLabelPtr ///< [IN] Object label. ) { CheckLabel(subjectLabelPtr); CheckLabel(objectLabelPtr); // Create the SMACK rule. char rule[SMACK_RULE_STR_BYTES]; MakeRuleStr(subjectLabelPtr, accessModePtr, objectLabelPtr, rule, sizeof(rule)); // Open the SMACK access file. int fd; do { fd = open(SMACK_ACCESS_FILE, O_RDWR); } while ( (fd == -1) && (errno == EINTR) ); LE_FATAL_IF(fd == -1, "Could not open %s. %m.\n", SMACK_ACCESS_FILE); // Write the rule to the SMACK access file. int numBytes = 0; do { numBytes = write(fd, rule, sizeof(rule)-1); } while ( (numBytes == -1) && (errno == EINTR) ); LE_FATAL_IF(numBytes < 0, "Could not write SMACK rule '%s'. %m.", rule); // Read the SMACK access file to see if access would be granted. char a; do { numBytes = read(fd, &a, 1); } while ( (numBytes == -1) && (errno == EINTR) ); LE_FATAL_IF(numBytes <= 0, "Could not read '%s'. %m.", SMACK_ACCESS_FILE); fd_Close(fd); return (a == '1'); }
//-------------------------------------------------------------------------------------------------- le_event_FdHandlerRef_t le_event_SetFdHandler ( le_event_FdMonitorRef_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object. le_event_FdEventType_t eventType, ///< [in] The type of event to be reported to this handler. le_event_FdHandlerFunc_t handlerFunc ///< [in] The handler function. ) //-------------------------------------------------------------------------------------------------- { LE_ASSERT(handlerFunc != NULL); // Look up the File Descriptor Monitor object using the safe reference provided. // Note that the safe reference map is shared by all threads in the process, so it // must be protected using the mutex. The File Descriptor Monitor objects, on the other // hand, are only allowed to be accessed by the one thread that created them, so it is // safe to unlock the mutex after doing the safe reference lookup. LOCK FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef); UNLOCK LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef); LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr, "FD Monitor '%s' (fd %d) is owned by another thread.", monitorPtr->name, monitorPtr->fd); // Get a pointer to the Handler object in the appropriate spot for this type of event in the // FD Monitor's array of handlers. Handler_t* handlerPtr = &(monitorPtr->handlerArray[eventType]); // Double check that no one has tried setting this handler yet. LE_FATAL_IF(handlerPtr->handlerFunc != NULL, "FD handler already set for event '%s' on FD Monitor '%s' (fd %d).", GetFdEventTypeName(eventType), monitorPtr->name, monitorPtr->fd); // Initialize the Handler object. handlerPtr->handlerFunc = handlerFunc; handlerPtr->contextPtr = NULL; handlerPtr->monitorPtr = monitorPtr; LOCK handlerPtr->safeRef = le_ref_CreateRef(HandlerRefMap, handlerPtr); UNLOCK // Enable the monitoring of this event. EnableFdMonitoring(monitorPtr, eventType); return handlerPtr->safeRef; }
//-------------------------------------------------------------------------------------------------- void le_msg_DeleteService ( le_msg_ServiceRef_t serviceRef ///< [in] Reference to the service. ) //-------------------------------------------------------------------------------------------------- { LE_FATAL_IF(serviceRef->serverThread != le_thread_GetCurrent(), "Attempted to delete service (%s:%s) not owned by thread.", serviceRef->id.name, le_msg_GetProtocolIdStr(serviceRef->id.protocolRef)); // If the service is still advertised, hide it. le_msg_HideService(serviceRef); // Close any remaining open sessions. CloseAllSessions(serviceRef); // NOTE: Lock the mutex here to prevent a race between this thread dropping ownership // of the service and another thread trying to offer the same service. This is very // unlikely to ever happen, but just in case, make sure it fails with a sensible // ("duplicate") log message, instead of just quietly messing up the hashmap or something. LOCK // Clear out the server thread reference. serviceRef->serverThread = NULL; // Release the server's hold on the object. le_mem_Release(serviceRef); UNLOCK }
//-------------------------------------------------------------------------------------------------- void TriggerCallbackTestRespond ( ServerCmdRef_t _cmdRef ) { LE_ASSERT(_cmdRef != NULL); // Get the message related data le_msg_MessageRef_t _msgRef = (le_msg_MessageRef_t)_cmdRef; _Message_t* _msgPtr = le_msg_GetPayloadPtr(_msgRef); __attribute__((unused)) uint8_t* _msgBufPtr = _msgPtr->buffer; // Ensure the passed in msgRef is for the correct message LE_ASSERT(_msgPtr->id == _MSGID_TriggerCallbackTest); // Ensure that this Respond function has not already been called LE_FATAL_IF( !le_msg_NeedsResponse(_msgRef), "Response has already been sent"); // Pack any "out" parameters // Return the response LE_DEBUG("Sending response to client session %p", le_msg_GetSession(_msgRef)); le_msg_Respond(_msgRef); }
//-------------------------------------------------------------------------------------------------- void atmachinestring_AddInList ( le_dls_List_t *list, ///< List of atmachinestring_t const char **patternListPtr ///< List of pattern ) { uint32_t i = 0; if (!patternListPtr) { return; } while(patternListPtr[i] != NULL) { atmachinestring_t* newStringPtr = le_mem_ForceAlloc(AtStringPool); LE_FATAL_IF( (strlen(patternListPtr[i])>ATSTRING_SIZE), "%s is too long (%zd): Max size %d", patternListPtr[i],strlen(patternListPtr[i]),ATSTRING_SIZE); strncpy(newStringPtr->line,patternListPtr[i],ATSTRING_SIZE); newStringPtr->line[ATSTRING_SIZE-1]='\0'; newStringPtr->link = LE_DLS_LINK_INIT; le_dls_Queue(list,&(newStringPtr->link)); i++; } }
//-------------------------------------------------------------------------------------------------- void le_sem_Wait ( le_sem_Ref_t semaphorePtr ///< [IN] Pointer to the semaphore ) { // TODO: Implement this: // if (semaphorePtr->isTraceable) // { // } // else { int result; sem_ThreadRec_t* perThreadRecPtr = thread_GetSemaphoreRecPtr(); ListOfSemaphoresChgCnt++; perThreadRecPtr->waitingOnSemaphore = semaphorePtr; AddToWaitingList(semaphorePtr, perThreadRecPtr); result = sem_wait(&semaphorePtr->semaphore); RemoveFromWaitingList(semaphorePtr, perThreadRecPtr); ListOfSemaphoresChgCnt++; perThreadRecPtr->waitingOnSemaphore = NULL; LE_FATAL_IF( (result!=0), "Thread '%s' failed to wait on semaphore '%s'. Error code %d (%m).", le_thread_GetMyName(), semaphorePtr->nameStr, result); } }
//-------------------------------------------------------------------------------------------------- static pid_t GetTasksId ( int fd ///< [IN] File descriptor to an opened procs or tasks file. ) { // Read a pid from the file. pid_t pid; char pidStr[100]; le_result_t result = fd_ReadLine(fd, pidStr, sizeof(pidStr)); LE_FATAL_IF(result == LE_OVERFLOW, "Buffer to read PID is too small."); if (result == LE_OK) { // Convert the string to a pid and store it in the caller's buffer. le_result_t r = le_utf8_ParseInt(&pid, pidStr); if (r == LE_OK) { return pid; } LE_ERROR("Could not convert '%s' to a PID. %s.", pidStr, LE_RESULT_TXT(r)); result = LE_FAULT; } return result; }
//-------------------------------------------------------------------------------------------------- void allParametersRespond ( ServerCmdRef_t _cmdRef, uint32_t b, size_t outputNumElements, uint32_t* outputPtr, char* response, char* more ) { LE_ASSERT(_cmdRef != NULL); // Get the message related data le_msg_MessageRef_t _msgRef = (le_msg_MessageRef_t)_cmdRef; _Message_t* _msgPtr = le_msg_GetPayloadPtr(_msgRef); __attribute__((unused)) uint8_t* _msgBufPtr = _msgPtr->buffer; // Ensure the passed in msgRef is for the correct message LE_ASSERT(_msgPtr->id == _MSGID_allParameters); // Ensure that this Respond function has not already been called LE_FATAL_IF( !le_msg_NeedsResponse(_msgRef), "Response has already been sent"); // Pack any "out" parameters _msgBufPtr = PackData( _msgBufPtr, &b, sizeof(uint32_t) ); _msgBufPtr = PackData( _msgBufPtr, &outputNumElements, sizeof(size_t) ); _msgBufPtr = PackData( _msgBufPtr, outputPtr, outputNumElements*sizeof(uint32_t) ); _msgBufPtr = PackString( _msgBufPtr, response ); _msgBufPtr = PackString( _msgBufPtr, more ); // Return the response LE_DEBUG("Sending response to client session %p", le_msg_GetSession(_msgRef)); le_msg_Respond(_msgRef); }
//-------------------------------------------------------------------------------------------------- le_msg_ServiceRef_t le_msg_CreateService ( le_msg_ProtocolRef_t protocolRef, ///< [in] Reference to the protocol to be used. const char* serviceName ///< [in] The service instance name. ) //-------------------------------------------------------------------------------------------------- { // Must lock the mutex to prevent races between different threads trying to offer the // same service at the same time, or one thread trying to delete a service while another // tries to create it, or accessing the Service List hashmap while another thread // is updating it. LOCK // Get a Service object. Service_t* servicePtr = GetService(protocolRef, serviceName); // If the Service object already has a server thread, then it means that this service // is already being offered by someone else in this very process. LE_FATAL_IF(servicePtr->serverThread != NULL, "Duplicate service (%s:%s) offered in same process.", serviceName, le_msg_GetProtocolIdStr(protocolRef)); servicePtr->serverThread = le_thread_GetCurrent(); UNLOCK return servicePtr; }
//-------------------------------------------------------------------------------------------------- static Service_t* GetService ( le_msg_ProtocolRef_t protocolRef, const char* serviceName ) //-------------------------------------------------------------------------------------------------- { ServiceId_t id; id.protocolRef = protocolRef; LE_FATAL_IF(le_utf8_Copy(id.name, serviceName, sizeof(id.name), NULL) == LE_OVERFLOW, "Service ID '%s' too long (should only be %zu bytes total).", serviceName, sizeof(id.name)); Service_t* servicePtr = le_hashmap_Get(ServiceMapRef, &id); if (servicePtr == NULL) { servicePtr = CreateService(protocolRef, serviceName); } else { le_mem_AddRef(servicePtr); } return servicePtr; }
//-------------------------------------------------------------------------------------------------- void userAddRemove_Add ( const char* appName ) //-------------------------------------------------------------------------------------------------- { le_result_t result; uid_t uid; gid_t gid; char userName[256] = "app"; result = le_utf8_Append(userName, appName, sizeof(userName), NULL); LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName); LE_INFO("Creating user '%s' for application '%s'.", userName, appName); // Start a read transaction and go to node /apps/app-name le_cfg_ConnectService(); le_cfg_IteratorRef_t i = le_cfg_CreateReadTxn("/apps"); le_cfg_GoToNode(i, appName); // If the node doesn't exist, bail out. if (!le_cfg_NodeExists(i, "")) { fprintf(stderr, "** ERROR: App '%s' doesn't exist in the system configuration.\n", appName); } else { result = user_Create(userName, &uid, &gid); if (result == LE_OK) { printf("Created user '%s' (uid %u, gid %u).\n", userName, uid, gid); // TODO: Groups configuration. le_cfg_CancelTxn(i); exit(EXIT_SUCCESS); } else if (result == LE_DUPLICATE) { // TODO: Verify correct groups configuration. printf("User '%s' already exists (uid %u, gid %u).\n", userName, uid, gid); le_cfg_CancelTxn(i); exit(EXIT_SUCCESS); } else { fprintf(stderr, "** ERROR: user_Create() failed for user '%s'.\n", userName); } } le_cfg_CancelTxn(i); exit(EXIT_FAILURE); }
//-------------------------------------------------------------------------------------------------- void le_mem_DeleteSubPool ( le_mem_PoolRef_t subPool ///< [IN] The sub-pool to be deleted. ) { LE_ASSERT(subPool != NULL); Lock(); // Make sure all sub-pool objects are free. le_mem_PoolRef_t superPool = subPool->superPoolPtr; LE_FATAL_IF(subPool->numBlocksInUse != 0, "Subpool '%s' deleted while %zu blocks remain allocated.", subPool->name, subPool->numBlocksInUse); size_t numBlocks = subPool->totalBlocks; // Move the blocks from the subPool back to the superpool. MoveBlocks(superPool, subPool, numBlocks); // Update the superPool's block use count. superPool->numBlocksInUse -= numBlocks; // Remove the sub-pool from the list of sub-pools. ListOfPoolsChgCnt++; le_dls_Remove(&ListOfPools, &(subPool->poolLink)); Unlock(); // Release the sub-pool. le_mem_Release(subPool); }
//-------------------------------------------------------------------------------------------------- le_avdata_AssetInstanceRef_t le_avdata_Create ( const char* assetName ///< [IN] ) { // Get the client's credentials. pid_t pid; uid_t uid; if (le_msg_GetClientUserCreds(le_avdata_GetClientSessionRef(), &uid, &pid) != LE_OK) { LE_KILL_CLIENT("Could not get credentials for the client."); return NULL; } // Look up the process's application name. char appName[LE_LIMIT_APP_NAME_LEN+1]; le_result_t result = le_appInfo_GetName(pid, appName, sizeof(appName)); LE_FATAL_IF(result == LE_OVERFLOW, "Buffer too small to contain the application name."); // TODO: Should this be LE_KILL_CLIENT instead? LE_FATAL_IF(result != LE_OK, "Could not get app name"); // Create an instance of the asset assetData_InstanceDataRef_t instRef; int instanceId; LE_ASSERT( assetData_CreateInstanceByName(appName, assetName, -1, &instRef) == LE_OK ); LE_ASSERT( instRef != NULL ); LE_ASSERT( assetData_GetInstanceId(instRef, &instanceId) == LE_OK ); LE_PRINT_VALUE("%i", instanceId); // Return a safe reference for the instance InstanceRefData_t* instRefDataPtr = le_mem_ForceAlloc(InstanceRefDataPoolRef); instRefDataPtr->clientSessionRef = le_avdata_GetClientSessionRef(); instRefDataPtr->instRef = instRef; instRef = le_ref_CreateRef(InstanceRefMap, instRefDataPtr); return instRef; }
//-------------------------------------------------------------------------------------------------- void aus_RegisterFieldEventHandlers ( const char* appNamePtr, ///< Namespace for the object. int objectId, ///< The Id of the object. assetData_AssetActionHandlerFunc_t assetHandlerPtr, ///< Handler for object level events. const int* monitorFields, ///< List of fields to monitor. size_t monFieldCount, ///< Size of the field list. assetData_FieldActionHandlerFunc_t fieldHandlerPtr ///< Handler to be called for field ///< activity. ) //-------------------------------------------------------------------------------------------------- { assetData_AssetDataRef_t assetRef = NULL; LE_DEBUG("Registering on %s/%d.", appNamePtr, objectId); LE_FATAL_IF(assetData_GetAssetRefById(appNamePtr, objectId, &assetRef) != LE_OK, "Could not reference object %s/%d data.", appNamePtr, objectId); if (assetHandlerPtr != NULL) { LE_DEBUG("Registering AssetActionHandler"); LE_FATAL_IF(assetData_client_AddAssetActionHandler(assetRef, assetHandlerPtr, NULL) == NULL, "Could not register for instance activity on %s/%d.", appNamePtr, objectId); } for (size_t i = 0; i < monFieldCount; i++) { LE_DEBUG("Registering %s/%d/%d field handler.", appNamePtr, objectId, monitorFields[i]); LE_FATAL_IF(assetData_client_AddFieldActionHandler(assetRef, monitorFields[i], fieldHandlerPtr, NULL) == NULL, "Could not register for object %s/%d field activity.", appNamePtr, objectId); } }
//-------------------------------------------------------------------------------------------------- static void LoadIpcBindingConfig ( void ) { // Fork a process. pid_t pid = fork(); LE_FATAL_IF(pid < 0, "Failed to fork child process. %m."); if (pid == 0) { // Launch the child program. This should not return unless there was an error. execlp("sdir", "sdir", "load", (char*)NULL); // The program could not be started. LE_FATAL("'sdir' could not be started: %m"); } int status; pid_t p; do { p = waitpid(pid, &status, 0); } while((p == -1) && (errno == EINTR)); if (p != pid) { if (p == -1) { LE_FATAL("waitpid() failed: %m"); } else { LE_FATAL("waitpid() returned unexpected result %d", p); } } if (WIFSIGNALED(status)) { LE_FATAL("Couldn't load IPC binding config. `sdir load` received signal: %d.", WTERMSIG(status)); } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) != EXIT_SUCCESS) { LE_FATAL("Couldn't load IPC binding config. `sdir load` exited with code: %d.", WEXITSTATUS(status)); } } else { LE_FATAL("Couldn't load IPC binding config. `sdir load` failed for an unknown reason (status = %d).", status); } }
//-------------------------------------------------------------------------------------------------- void le_event_ClearFdHandlerByEventType ( le_event_FdMonitorRef_t monitorRef, ///< [in] Reference to the File Descriptor Monitor object. le_event_FdEventType_t eventType ///< [in] The type of event to clear the handler for. ) //-------------------------------------------------------------------------------------------------- { LE_ASSERT(eventType < LE_EVENT_NUM_FD_EVENT_TYPES); // Look up the File Descriptor Monitor object using the safe reference provided. // Note that the safe reference map is shared by all threads in the process, so it // must be protected using the mutex. The File Descriptor Monitor objects, on the other // hand, are only allowed to be accessed by the one thread that created them, so it is // safe to unlock the mutex after doing the safe reference lookup. LOCK FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef); UNLOCK LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef); LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr, "FD Monitor '%s' (fd %d) is owned by another thread.", monitorPtr->name, monitorPtr->fd); // Get a pointer to the Handler object in the appropriate spot for this type of event in the // FD Monitor's array of handlers. Handler_t* handlerPtr = &(monitorPtr->handlerArray[eventType]); LE_CRIT_IF(handlerPtr->handlerFunc == NULL, "Handler cleared when not set for FD Monitor '%s' (fd %d), event type %d.", monitorPtr->name, monitorPtr->fd, eventType); // Clear the Handler object. handlerPtr->handlerFunc = NULL; handlerPtr->contextPtr = NULL; LOCK le_ref_DeleteRef(HandlerRefMap, handlerPtr->safeRef); UNLOCK handlerPtr->safeRef = NULL; // Disable the monitoring of this event. DisableFdMonitoring(monitorPtr, eventType); }
//-------------------------------------------------------------------------------------------------- const char* properties_GetValue ( properties_Iter_Ref_t iteratorRef ///< [IN] Reference to the iterator. ) { LE_FATAL_IF(!HasValidKeyValue(iteratorRef), "Iterator does not contain a valid key-value."); return (const char*)iteratorRef->valuePtr; }
//-------------------------------------------------------------------------------------------------- static void ConfigureSensorGpio ( void ) { // Configure IoT1_GPIO1 as input and set its initial value as high LE_FATAL_IF(le_sensorGpio_SetInput(LE_SENSORGPIO_ACTIVE_HIGH) != LE_OK, "Couldn't configure cf3 gpio as default input high"); }