Exemplo n.º 1
0
//--------------------------------------------------------------------------------------------------
static bool AreServiceIdsTheSame
(
    const void* firstKeyPtr,
    const void* secondKeyPtr
)
//--------------------------------------------------------------------------------------------------
{
    const ServiceId_t* firstIdPtr = firstKeyPtr;
    const ServiceId_t* secondIdPtr = secondKeyPtr;

    return (   le_hashmap_EqualsString(firstIdPtr->name, secondIdPtr->name)
            && le_hashmap_EqualsString(le_msg_GetProtocolIdStr(firstIdPtr->protocolRef),
                                       le_msg_GetProtocolIdStr(secondIdPtr->protocolRef)) );
}
Exemplo n.º 2
0
//--------------------------------------------------------------------------------------------------
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;
}
Exemplo n.º 3
0
//--------------------------------------------------------------------------------------------------
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
}
Exemplo n.º 4
0
//--------------------------------------------------------------------------------------------------
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;
}
Exemplo n.º 5
0
//--------------------------------------------------------------------------------------------------
void msgService_ProcessMessageFromClient
(
    le_msg_ServiceRef_t serviceRef, ///< [IN] Reference to the Service object.
    le_msg_MessageRef_t msgRef      ///< [IN] Message reference for the received message.
)
//--------------------------------------------------------------------------------------------------
{
    // Pass the message to the server's registered receive handler, if there is one.
    if (serviceRef->recvHandler != NULL)
    {
        // Set the thread-local received message reference so it can be retrieved by the handler.
        pthread_setspecific(ThreadLocalRxMsgKey, msgRef);

        // Call the handler function.
        serviceRef->recvHandler(msgRef, serviceRef->recvContextPtr);

        // Clear the thread-local reference.
        pthread_setspecific(ThreadLocalRxMsgKey, NULL);
    }
    // Discard the message if no handler is registered.
    else
    {
        LE_WARN("No service receive handler (%s:%s). Discarding message. Closing session.",
                serviceRef->id.name,
                le_msg_GetProtocolIdStr(serviceRef->id.protocolRef));
        le_msg_DeleteSession(le_msg_GetSession(msgRef));
        le_msg_ReleaseMsg(msgRef);
    }
}
Exemplo n.º 6
0
//--------------------------------------------------------------------------------------------------
void msgService_SendServiceId
(
    le_msg_ServiceRef_t serviceRef, ///< [in] Pointer to the service whose ID is to be sent.
    int                 socketFd    ///< [in] File descriptor of the connected socket to send on.
)
//--------------------------------------------------------------------------------------------------
{
    svcdir_ServiceId_t serviceId;

    memset(&serviceId, 0, sizeof(serviceId));

    serviceId.maxProtocolMsgSize = le_msg_GetProtocolMaxMsgSize(serviceRef->id.protocolRef);

    le_utf8_Copy(serviceId.protocolId,
                 le_msg_GetProtocolIdStr(serviceRef->id.protocolRef),
                 sizeof(serviceId.protocolId),
                 NULL);

    le_utf8_Copy(serviceId.serviceName,
                 serviceRef->id.name,
                 sizeof(serviceId.serviceName),
                 NULL);

    le_result_t result = unixSocket_SendDataMsg(socketFd, &serviceId, sizeof(serviceId));
    if (result != LE_OK)
    {
        LE_FATAL("Failed to send. Result = %d (%s)", result, LE_RESULT_TXT(result));
    }
    // NOTE: This is only done when the socket is newly opened, so this shouldn't ever
    //       return LE_NO_MEMORY to indicate send buffers being full.
}
Exemplo n.º 7
0
//--------------------------------------------------------------------------------------------------
static void StartMonitoringDirectorySocket
(
    Service_t*  servicePtr
)
//--------------------------------------------------------------------------------------------------
{
    le_event_FdHandlerRef_t handlerRef;

    char name[128];
    size_t bytes;
    le_utf8_Copy(name, le_msg_GetProtocolIdStr(servicePtr->id.protocolRef), sizeof(name), &bytes);
    le_utf8_Copy(name + bytes, servicePtr->id.name, sizeof(name) - bytes, NULL);

    servicePtr->fdMonitorRef = le_event_CreateFdMonitor(name, servicePtr->directorySocketFd);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_READABLE,
                                       DirectorySocketReadable);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_READ_HANG_UP,
                                       DirectorySocketClosed);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_WRITE_HANG_UP,
                                       DirectorySocketClosed);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_ERROR,
                                       DirectorySocketError);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);
}
Exemplo n.º 8
0
//--------------------------------------------------------------------------------------------------
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().
}
Exemplo n.º 9
0
//--------------------------------------------------------------------------------------------------
static void DirectorySocketError
(
    int fd
)
//--------------------------------------------------------------------------------------------------
{
    Service_t* servicePtr = le_event_GetContextPtr();

    LE_FATAL("Error on Service Directory connection for service (%s:%s).",
             servicePtr->id.name,
             le_msg_GetProtocolIdStr(servicePtr->id.protocolRef));
}
Exemplo n.º 10
0
//--------------------------------------------------------------------------------------------------
static void DirectorySocketClosed
(
    int fd
)
//--------------------------------------------------------------------------------------------------
{
    Service_t* servicePtr = le_event_GetContextPtr();

    LE_FATAL("Permission to offer service (%s:%s) has been denied.",
             servicePtr->id.name,
             le_msg_GetProtocolIdStr(servicePtr->id.protocolRef));
}
Exemplo n.º 11
0
//--------------------------------------------------------------------------------------------------
void le_msg_SetServiceRecvHandler
(
    le_msg_ServiceRef_t     serviceRef, ///< [in] Reference to the service.
    le_msg_ReceiveHandler_t handlerFunc,///< [in] Handler function.
    void*                   contextPtr  ///< [in] Opaque pointer value to pass to the handler.
)
//--------------------------------------------------------------------------------------------------
{
    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));

    serviceRef->recvHandler = handlerFunc;
    serviceRef->recvContextPtr = contextPtr;
}
Exemplo n.º 12
0
//--------------------------------------------------------------------------------------------------
static void StartMonitoringDirectorySocket
(
    Service_t*  servicePtr
)
//--------------------------------------------------------------------------------------------------
{
    le_event_FdHandlerRef_t handlerRef;

    char name[LIMIT_MAX_MEM_POOL_NAME_BYTES];
    char* destPtr = name;
    size_t spaceLeft = sizeof(name);
    size_t bytesCopied;
    le_utf8_Copy(destPtr, servicePtr->id.name, spaceLeft, &bytesCopied);
    destPtr += bytesCopied;
    spaceLeft -= bytesCopied;
    le_utf8_Copy(destPtr, ":", spaceLeft, &bytesCopied);
    destPtr += bytesCopied;
    spaceLeft -= bytesCopied;
    le_utf8_Copy(destPtr, le_msg_GetProtocolIdStr(servicePtr->id.protocolRef), spaceLeft, NULL);

    servicePtr->fdMonitorRef = le_event_CreateFdMonitor(name, servicePtr->directorySocketFd);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_WRITEABLE,
                                       DirectorySocketWriteable);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_READABLE,
                                       DirectorySocketReadable);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_READ_HANG_UP,
                                       DirectorySocketClosed);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_WRITE_HANG_UP,
                                       DirectorySocketClosed);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);

    handlerRef = le_event_SetFdHandler(servicePtr->fdMonitorRef,
                                       LE_EVENT_FD_ERROR,
                                       DirectorySocketError);
    le_event_SetFdHandlerContextPtr(handlerRef, servicePtr);
}
Exemplo n.º 13
0
//--------------------------------------------------------------------------------------------------
static void DirectorySocketReadable
(
    int fd
)
//--------------------------------------------------------------------------------------------------
{
    Service_t* servicePtr = le_event_GetContextPtr();
    le_result_t result;

    int clientSocketFd;

    // Receive the Client connection file descriptor from the Service Directory.
    result = unixSocket_ReceiveMsg(fd,
                                   NULL,   // dataBuffPtr
                                   0,      // dataBuffSize
                                   &clientSocketFd,
                                   NULL);  // credPtr
    if (result == LE_CLOSED)
    {
        LE_DEBUG("Connection has closed.");
    }
    else if (result != LE_OK)
    {
        LE_FATAL("Failed to receive client fd from Service Directory (%d: %s).",
                 result,
                 LE_RESULT_TXT(result));
    }
    else if (clientSocketFd < 0)
    {
        LE_ERROR("Received something other than a file descriptor from Service Directory for (%s:%s).",
                 servicePtr->id.name,
                 le_msg_GetProtocolIdStr(servicePtr->id.protocolRef));
    }
    else
    {
        // Create a server-side Session object for that connection to this Service.
        le_msg_SessionRef_t sessionRef = msgSession_CreateServerSideSession(servicePtr, clientSocketFd);

        // If successful, call the registered "open" handler, if there is one.
        if (sessionRef != NULL)
        {
            CallOpenHandler(servicePtr, sessionRef);
        }
    }
}