ANSC_STATUS
AnscLpccoTcpBwoRemove
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSocket
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PANSC_LPCCO_TCP_OBJECT          pMyObject     = (PANSC_LPCCO_TCP_OBJECT        )hThisObject;
    PANSC_DAEMON_SERVER_TCP_OBJECT  pDaemonServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer;
    PANSC_BROKER_SERVER_TCP_OBJECT  pBrokerServer = (PANSC_BROKER_SERVER_TCP_OBJECT)pMyObject->hBrokerServer;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pConnTimerObj = (PANSC_TIMER_DESCRIPTOR_OBJECT )pMyObject->hConnTimerObj;
    PANSC_BROKER_SOCKET_TCP_OBJECT  pBrokerSocket = (PANSC_BROKER_SOCKET_TCP_OBJECT)hSocket;
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp   = (PANSC_BUFFER_DESCRIPTOR       )pBrokerSocket->GetBufferContext((ANSC_HANDLE)pBrokerSocket);
    PANSC_LPC_PARTY_ADDR            pPartyAddr    = (PANSC_LPC_PARTY_ADDR          )pBrokerSocket->GetClientContext((ANSC_HANDLE)pBrokerSocket);

    pBrokerSocket->SetClientContext((ANSC_HANDLE)pBrokerSocket, (ANSC_HANDLE)NULL         );
    pBrokerSocket->SetBufferContext((ANSC_HANDLE)pBrokerSocket, NULL, 0, (ANSC_HANDLE)NULL);

    if ( pBufferDesp )
    {
        AnscFreeBdo((ANSC_HANDLE)pBufferDesp);
    }

    if ( pPartyAddr )
    {
        pPartyAddr->Timestamp   = AnscGetTickInSeconds();
        pPartyAddr->PartyState &= ~ANSC_LPC_PARTY_STATE_connectedOut;
        pPartyAddr->PartySocket = (ANSC_HANDLE)NULL;

        /*
         * We shouldn't return until the reference count of 'pPartyAddr' reaches zero. Because if
         * we do, the socket may be deleted while there's still active task is trying to send
         * message to this party. For example: if LPC manager is issuing a LOCO call to all LPC
         * parties while one party is trying disconnect, a race condition is formed.
         */
        while ( pPartyAddr->ActiveCalls > 0 )
        {
            AnscSleep(20);
        }

        if ( !(pPartyAddr->PartyState & ANSC_LPC_PARTY_STATE_connectedIn ) &&
             !(pPartyAddr->PartyState & ANSC_LPC_PARTY_STATE_connectedOut) )
        {
            if ( pMyObject->bActive )
            {
                pConnTimerObj->Stop       ((ANSC_HANDLE)pConnTimerObj);
                pConnTimerObj->SetInterval((ANSC_HANDLE)pConnTimerObj, ANSC_LPCCO_DEF_CONN_TIMEOUT);
                pConnTimerObj->Start      ((ANSC_HANDLE)pConnTimerObj);
            }
        }
    }

    return  ANSC_STATUS_SUCCESS;
}
BOOL
Process_IsUpdated
    (
        ANSC_HANDLE                 hInsContext
    )
{
    if (!last_tick) 
    {
        last_tick = AnscGetTickInSeconds();
        return TRUE;
    }
    
    if (last_tick >= TIME_NO_NEGATIVE(AnscGetTickInSeconds() - REFRESH_INTERVAL))
    {
        return FALSE;
    }
    else 
    {
        last_tick = AnscGetTickInSeconds();
        return TRUE;
    }
}
Пример #3
0
/**********************************************************************  

    caller:     owner of this object 

    prototype: 

        ULONG
        Host_Synchronize
            (
                ANSC_HANDLE                 hInsContext
            );

    description:

        This function is called to synchronize the table.

    argument:   ANSC_HANDLE                 hInsContext,
                The instance handle;

    return:     The status of the operation.

**********************************************************************/
ULONG
Host_Synchronize
    (
        ANSC_HANDLE                 hInsContext
    )
{
    ULONG count,i;

    CosaDmlHostsGetHosts(NULL,&count);

    HostsUpdateTime = AnscGetTickInSeconds();

    return 0;
}
Пример #4
0
ANSC_STATUS
TlsSeoInitialize
    (
        ANSC_HANDLE                 hThisObject
    )
{
    PTLS_SESSION_ENTRY_OBJECT       pMyObject     = (PTLS_SESSION_ENTRY_OBJECT)hThisObject;
    PTLS_SESSION_STATE              pSessionState = (PTLS_SESSION_STATE       )&pMyObject->SessionState;

    /*
     * Until you have to simulate C++ object-oriented progtlsming style with standard C, you don't
     * appreciate all the nice little things come with C++ language and all the dirty works that
     * have been done by the C++ compilers. Member initialization is one of these things. While in
     * C++ you don't have to initialize all the member fields inherited from the base class since
     * the compiler will do it for you, such is not the case with C.
     */
    AnscCoInitialize((ANSC_HANDLE)pMyObject);

    /*
     * Although we have initialized some of the member fields in the "create" member function, we
     * repeat the work here for completeness. While this simulation approach is pretty stupid from
     * a C++/Java progtlsmer perspective, it's the best we can get for universal embedded network
     * progtlsming. Before we develop our own operating system (don't expect that to happen any
     * time soon), this is the way things gonna be.
     */
    pMyObject->Oid             = TLS_SESSION_ENTRY_OID;
    pMyObject->Create          = TlsSeoCreate;
    pMyObject->Remove          = TlsSeoRemove;
    pMyObject->EnrollObjects   = TlsSeoEnrollObjects;
    pMyObject->Initialize      = TlsSeoInitialize;

    pMyObject->Timestamp       = AnscGetTickInSeconds();

    pMyObject->GetSessionState = TlsSeoGetSessionState;
    pMyObject->SetSessionState = TlsSeoSetSessionState;
    pMyObject->Reset           = TlsSeoReset;

    pMyObject->Match1          = TlsSeoMatch1;
    pMyObject->Match2          = TlsSeoMatch2;

    /*
     * We shall initialize the object properties to the default values, which may be changed later
     * via the exposed member functions. If any of the future extensions needs to change the object
     * property, the following code also needs to be changed.
     */
    TlsInitSessionState(pSessionState);

    return  ANSC_STATUS_SUCCESS;
}
Пример #5
0
/**********************************************************************  

    caller:     owner of this object 

    prototype: 

        BOOL
        Host_IsUpdated
            (
                ANSC_HANDLE                 hInsContext
            );

    description:

        This function is checking whether the table is updated or not.

    argument:   ANSC_HANDLE                 hInsContext,
                The instance handle;

    return:     TRUE or FALSE.

**********************************************************************/
BOOL
Host_IsUpdated
    (
        ANSC_HANDLE                 hInsContext
    )
{
    if ( HostsUpdateTime == 0 ) 
    {
        HostsUpdateTime = AnscGetTickInSeconds();

        return TRUE;
    }
    
    if ( HostsUpdateTime >= TIME_NO_NEGATIVE(AnscGetTickInSeconds() - COSA_DML_USERS_USER_ACCESS_INTERVAL ) )
    {
        return FALSE;
    }
    else 
    {
        HostsUpdateTime = AnscGetTickInSeconds();

        return TRUE;
    }
}
BOOL
Eventlog_IsUpdated
    (
        ANSC_HANDLE                 hInsContext
    )
{
    if ( !eventlog_last_tick ) 
    {
        eventlog_last_tick = AnscGetTickInSeconds();

        return TRUE;
    }
    
    if ( eventlog_last_tick >= TIME_NO_NEGATIVE(AnscGetTickInSeconds() - REFRESH_INTERVAL) )
    {
        return FALSE;
    }
    else 
    {
        eventlog_last_tick = AnscGetTickInSeconds();

        return TRUE;
    }
}
ANSC_HANDLE
BwrmPmoGetPage
    (
        ANSC_HANDLE                 hThisObject,
        char*                       root_path,
        char*                       file_path
    )
{
    ANSC_STATUS                     returnStatus      = ANSC_STATUS_SUCCESS;
    PBWRM_PAGE_MANAGER_OBJECT       pMyObject         = (PBWRM_PAGE_MANAGER_OBJECT    )hThisObject;
    PBWRM_PAGE_MANAGER_PROPERTY     pProperty         = (PBWRM_PAGE_MANAGER_PROPERTY  )&pMyObject->Property;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pCacheTimerObject = (PANSC_TIMER_DESCRIPTOR_OBJECT)pMyObject->hCacheTimerObject;
    PBWRM_COOKED_PAGE_OBJECT        pCookedPage       = (PBWRM_COOKED_PAGE_OBJECT     )NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry       = (PSINGLE_LINK_ENTRY           )NULL;
    ULONG                           ulHashIndex       = (ULONG                        )AnscHashString(file_path, AnscSizeOfString(file_path), BWRM_PMO_CPO_TABLE_SIZE);
    ULONG                           ulCurTime         = AnscGetTickInSeconds();

    pMyObject->Timestamp = ulCurTime;

    AnscAcquireLock(&pMyObject->CpoTableLock);

    pSLinkEntry = AnscSListGetFirstEntry(&pMyObject->CpoTable[ulHashIndex]);

    while ( pSLinkEntry )
    {
        pCookedPage = ACCESS_BWRM_COOKED_PAGE_OBJECT(pSLinkEntry);
        pSLinkEntry = AnscSListGetNextEntry(pSLinkEntry);

        if ( pCookedPage->MatchPath
                (
                    (ANSC_HANDLE)pCookedPage,
                    root_path,
                    file_path
                ) )
        {
            pCookedPage->SetTimestamp((ANSC_HANDLE)pCookedPage, ulCurTime);
            pCookedPage->IncRefCount ((ANSC_HANDLE)pCookedPage);

            AnscReleaseLock(&pMyObject->CpoTableLock);

            return  (ANSC_HANDLE)pCookedPage;
        }
    }

    AnscReleaseLock(&pMyObject->CpoTableLock);

    return  (ANSC_HANDLE)NULL;
}
Пример #8
0
ANSC_STATUS
PsmSysroSysRamNotify
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSysRepFolder,
        ULONG                       ulEvent
    )
{
    ANSC_STATUS                     returnStatus    = ANSC_STATUS_SUCCESS;
    PPSM_SYS_REGISTRY_OBJECT       pMyObject       = (PPSM_SYS_REGISTRY_OBJECT    )hThisObject;
    PPSM_SYS_REGISTRY_PROPERTY     pProperty       = (PPSM_SYS_REGISTRY_PROPERTY  )&pMyObject->Property;
    PPSM_FILE_LOADER_OBJECT        pPsmFileLoader = (PPSM_FILE_LOADER_OBJECT     )pMyObject->hPsmFileLoader;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pRegTimerObj    = (PANSC_TIMER_DESCRIPTOR_OBJECT)pMyObject->hRegTimerObj;
//CcspTraceInfo(("\n##PsmSysroSysRamNotify() begins##\n"));
    if ( pMyObject->bNoSave || pMyObject->bSaveInProgress )
    {
        return  ANSC_STATUS_SUCCESS;
    }

    switch ( ulEvent )
    {
        case    SYS_RAM_EVENT_folderAdded   :
        case    SYS_RAM_EVENT_folderUpdated :
        case    SYS_RAM_EVENT_folderDeleted :
        case    SYS_RAM_EVENT_folderCleared :
        case    SYS_RAM_EVENT_recordAdded   :
        case    SYS_RAM_EVENT_recordUpdated :
        case    SYS_RAM_EVENT_recordDeleted :

                /*
                pRegTimerObj->Stop ((ANSC_HANDLE)pRegTimerObj);
                pRegTimerObj->Start((ANSC_HANDLE)pRegTimerObj);
                */
                pMyObject->LastRegWriteAt = AnscGetTickInSeconds();
                pMyObject->bNeedFlush     = TRUE;

                break;

        default :

                break;
    }
//CcspTraceInfo(("\n##PsmSysroSysRamNotify() ends##\n"));
    return  returnStatus;
}
BOOL
SlapEcoGetPendingCallInfo
    (
        ANSC_HANDLE                 hThisObject,
        char**                      call_name,
        ULONG*                      call_timestamp,     /* in number of seconds after system is up */
        ULONG*                      call_age            /* in number of seconds */
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PSLAP_ENV_CONTROLLER_OBJECT     pMyObject    = (PSLAP_ENV_CONTROLLER_OBJECT)hThisObject;

    *call_name      = AnscCloneString(pMyObject->PendingCallName);
    *call_timestamp = pMyObject->PendingCallTimestamp;
    *call_age       = AnscGetTickInSeconds() - pMyObject->PendingCallTimestamp;

    return  pMyObject->bCallPending;
}
ANSC_STATUS
BwrmPmoCacheTimerInvoke
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus      = ANSC_STATUS_SUCCESS;
    PBWRM_PAGE_MANAGER_OBJECT       pMyObject         = (PBWRM_PAGE_MANAGER_OBJECT    )hThisObject;
    PBWRM_PAGE_MANAGER_PROPERTY     pProperty         = (PBWRM_PAGE_MANAGER_PROPERTY  )&pMyObject->Property;
    PANSC_TIMER_DESCRIPTOR_OBJECT   pCacheTimerObject = (PANSC_TIMER_DESCRIPTOR_OBJECT)pMyObject->hCacheTimerObject;
    ULONG                           ulCurTime         = AnscGetTickInSeconds();

    if ( (ulCurTime - pMyObject->Timestamp) > pProperty->CacheTimeout )
    {
        pMyObject->DelAllPages((ANSC_HANDLE)pMyObject);
    }

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
TlsSmoAddSession
(
    ANSC_HANDLE                 hThisObject,
    ANSC_HANDLE                 hSession
)
{
    PTLS_SESSION_MANAGER_OBJECT     pMyObject     = (PTLS_SESSION_MANAGER_OBJECT  )hThisObject;
    PTLS_SESSION_ENTRY_OBJECT       pSessionEntry = (PTLS_SESSION_ENTRY_OBJECT    )hSession;
    ULONG                           ulHashIndex   = AnscHashUlong(pSessionEntry->SessionState.PeerID, TLS_SMO_SEO_TABLE_SIZE);

    pSessionEntry->Timestamp        = AnscGetTickInSeconds();

    AnscAcquireLock   (&pMyObject->SeoTableLock);
    AnscQueuePushEntry(&pMyObject->SeoTable[ulHashIndex], &pSessionEntry->Linkage);
    AnscReleaseLock   (&pMyObject->SeoTableLock);

    return  ANSC_STATUS_SUCCESS;
}
Пример #12
0
ANSC_STATUS
AnscSstoStsAdjustClock1
    (
        ANSC_HANDLE                 hThisObject,
        ULONG                       ulSeconds,
        int                         iTimeOffset
    )
{
    ANSC_STATUS                     returnStatus      = ANSC_STATUS_SUCCESS;
    PANSC_SIMPLE_SYS_TIME_OBJECT    pMyObject         = (PANSC_SIMPLE_SYS_TIME_OBJECT)hThisObject;
    
    pMyObject->AcquireAccess(hThisObject);

    pMyObject->LastTick    = AnscGetTickInSeconds();
    pMyObject->LastSecond  = ulSeconds;
    pMyObject->iTimeOffset = iTimeOffset;

    pMyObject->ReleaseAccess(hThisObject);

    return returnStatus;
}
Пример #13
0
ANSC_STATUS
AnscSstoStsSysTickToCalendar
    (
        ANSC_HANDLE                 hThisObject,
        ULONG                       ulTicks,
        ANSC_HANDLE                 hCalendar
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_SIMPLE_SYS_TIME_OBJECT    pMyObject    = (PANSC_SIMPLE_SYS_TIME_OBJECT)hThisObject;
    ULONG                           ulCurTick    = (ULONG                       )AnscGetTickInSeconds();
    ULONG                           ulCurSecs    = (ULONG                       )pMyObject->GetCurrSecond((ANSC_HANDLE)pMyObject);
    int                             iTbpSecs     = (int                         )0;

    iTbpSecs  = (int)ulCurSecs - ((int)ulCurTick - (int)ulTicks);
    iTbpSecs += pMyObject->iTimeOffset;

    return  pMyObject->SecondToCalendar
                (
                    (ANSC_HANDLE)pMyObject,
                    (ULONG      )iTbpSecs,
                    hCalendar
                );
}
ANSC_STATUS
AnscDeuoClean
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_DAEMON_ENGINE_UDP_OBJECT  pMyObject    = (PANSC_DAEMON_ENGINE_UDP_OBJECT)hThisObject;
    PANSC_DAEMON_SERVER_UDP_OBJECT  pServer      = (PANSC_DAEMON_SERVER_UDP_OBJECT)pMyObject->hDaemonServer;
    PANSC_DSUO_WORKER_OBJECT        pWorker      = (PANSC_DSUO_WORKER_OBJECT      )pServer->hWorker;
    PANSC_DAEMON_SOCKET_UDP_OBJECT  pSocket      = NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry  = NULL;
    ULONG                           ulHashIndex  = 0;
    BOOL                            bSocketFound = FALSE;
    ULONG                           ulCurTime    = AnscGetTickInSeconds();

    if ( !pMyObject->bStarted )
    {
        return  ANSC_STATUS_SUCCESS;
    }
    else if ( pMyObject->ControlFlags & ANSC_DEUO_FLAG_NO_TIMEOUT )
    {
        return  ANSC_STATUS_SUCCESS;
    }

    ulHashIndex  = 0;
    bSocketFound = FALSE;

    while ( ulHashIndex < ANSC_DEUO_SOCKET_TABLE_SIZE )
    {
        AnscAcquireLock(&pMyObject->SocketTableLock);

        bSocketFound = FALSE;
        pSLinkEntry  = AnscSListGetFirstEntry(&pMyObject->SocketTable[ulHashIndex]);

        while ( pSLinkEntry )
        {
            pSocket     = ACCESS_ANSC_DAEMON_SOCKET_UDP_OBJECT(pSLinkEntry);
            pSLinkEntry = AnscSListGetNextEntry(pSLinkEntry);

            if ( ((ulCurTime - pSocket->LastRecvAt) >= pMyObject->SocketTimeOut) &&
                 ((ulCurTime - pSocket->LastSendAt) >= pMyObject->SocketTimeOut) )
            {
                bSocketFound = TRUE;

                break;
            }
        }

        AnscReleaseLock(&pMyObject->SocketTableLock);

        if ( bSocketFound )
        {
            returnStatus =
                pWorker->Notify
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pSocket,
                        ANSC_DSUOWO_EVENT_TIME_OUT,
                        (ANSC_HANDLE)NULL
                    );

            returnStatus =
                pMyObject->DelSocket
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pSocket
                    );
        }
        else
        {
            ulHashIndex++;
        }
    }

    return  ANSC_STATUS_SUCCESS;
}
Пример #15
0
ANSC_STATUS
AnscBetoSendTask
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_BROKER_ENGINE_TCP_OBJECT  pMyObject    = (PANSC_BROKER_ENGINE_TCP_OBJECT)hThisObject;
    ansc_fd_set*                    pSendSet1    = (ansc_fd_set*                  )pMyObject->SendSocketSet;
    xskt_fd_set*                    pSendSet2    = (xskt_fd_set*                  )pMyObject->SendSocketSet;
    PANSC_BROKER_SERVER_TCP_OBJECT  pServer      = (PANSC_BROKER_SERVER_TCP_OBJECT)pMyObject->hBrokerServer;
    PANSC_BSTO_WORKER_OBJECT        pWorker      = (PANSC_BSTO_WORKER_OBJECT      )pServer->hWorker;
    PANSC_BETO_PACKET_OBJECT        pPacket      = NULL;
    PANSC_BROKER_SOCKET_TCP_OBJECT  pSocket      = NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry  = NULL;
    BOOL                            bSendable    = FALSE;
    int                             s_result     = 0;
    int                             s_error      = 0;

    AnscTrace("AnscBetoSendTask is activated ...!\n");

    /*
     * As a scalable server implemention, we shall accept as many incoming client connections as
     * possible and can only be limited by the system resources. Once the listening socket becomes
     * readable, which means an incoming connection attempt has arrived. We create a new socket
     * object and associate it with the client. This is a repeated process until the socket owner
     * closes the socket.
     */
    while ( pMyObject->bStarted )
    {
        AnscAcquireLock(&pMyObject->PacketQueueLock);
        pSLinkEntry = AnscQueuePopEntry(&pMyObject->PacketQueue);
        AnscReleaseLock(&pMyObject->PacketQueueLock);

        if ( !pSLinkEntry )
        {
            continue;
        }
        else
        {
            pPacket = ACCESS_ANSC_BETO_PACKET_OBJECT(pSLinkEntry);
            pSocket = (PANSC_BROKER_SOCKET_TCP_OBJECT)pPacket->hSocket;
        }

	#if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX)
        AnscAcquireLock(&pMyObject->SendSocketSetLock);
        bSendable = (pServer->Mode & ANSC_BSTO_MODE_XSOCKET)? XSKT_SOCKET_FD_ISSET(pSocket->Socket, pSendSet2) : ANSC_SOCKET_FD_ISSET(pSocket->Socket, pSendSet1);
        AnscReleaseLock(&pMyObject->SendSocketSetLock);

        if ( !bSendable )
        {
            returnStatus =
                pWorker->SendComplete
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pSocket,
                        pPacket->hWorkerReserved,
                        ANSC_STATUS_FAILURE
                    );

            AnscFreeMemory(pPacket);

            continue;
        }
	#endif

        if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET )
        {
            s_result = _xskt_send(((XSKT_SOCKET)pSocket->Socket), pPacket->PacketBuffer, (int)pPacket->PacketSize, 0);
        }
        else
        {
            s_result = _ansc_send(pSocket->Socket, pPacket->PacketBuffer, (int)pPacket->PacketSize, 0);
        }

        if ( ((s_result == XSKT_SOCKET_ERROR) &&  (pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) ||
             ((s_result == ANSC_SOCKET_ERROR) && !(pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) )
        {
            s_error = (pServer->Mode & ANSC_BSTO_MODE_XSOCKET)? _xskt_get_last_error() : _ansc_get_last_error();

            returnStatus =
                pWorker->SendComplete
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pSocket,
                        pPacket->hWorkerReserved,
                        ANSC_STATUS_FAILURE
                    );

            if ( pServer->Mode & ANSC_BSTO_MODE_AUTO_CLOSE )
            {
                pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket);
            }
        }
        else
        {
            returnStatus =
                pWorker->SendComplete
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pSocket,
                        pPacket->hWorkerReserved,
                        ANSC_STATUS_SUCCESS
                    );

            pSocket->SendBytesCount += pPacket->PacketSize;
            pSocket->LastSendAt      = AnscGetTickInSeconds();
        }
    }

    AnscSetEvent(&pMyObject->SendEvent);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_HANDLE
Bmc2ReqcoPecGetCookedPage
    (
        ANSC_HANDLE                 hThisObject,
        char*                       page_path
    )
{
    ANSC_STATUS                     returnStatus       = ANSC_STATUS_SUCCESS;
    PBMC2_REQ_CONTROLLER_OBJECT     pMyObject          = (PBMC2_REQ_CONTROLLER_OBJECT)hThisObject;
    PBMC2_ENV_CONTROLLER_OBJECT     pBmc2EnvController = (PBMC2_ENV_CONTROLLER_OBJECT)pMyObject->hBmc2EnvController;
    PBMC2_COM_DOMAIN_OBJECT         pBmc2ComDomain     = (PBMC2_COM_DOMAIN_OBJECT    )pMyObject->hBmc2ComDomain;
    PBMC2_COM_TERMINAL_OBJECT       pBmc2ComTerminal   = (PBMC2_COM_TERMINAL_OBJECT  )pBmc2ComDomain->hBmc2ComTerminal;
    PBMC2_COM_EXECUTOR_OBJECT       pBmc2ComExecutor   = (PBMC2_COM_EXECUTOR_OBJECT  )pBmc2EnvController->hBmc2ComExecutor;
    PBWRM_ENV_CONTROLLER_OBJECT     pBwrmEnvController = (PBWRM_ENV_CONTROLLER_OBJECT)pBmc2EnvController->hBwrmEnvController;
    PBWRM_RAM_INTERFACE             pBwrmRamIf         = (PBWRM_RAM_INTERFACE        )pBwrmEnvController->GetBwrmRamIf((ANSC_HANDLE)pBwrmEnvController);
    char*                           pRootPath          = (char*                      )pBmc2EnvController->Property.RootPath;
    PBWRM_COOKED_PAGE_OBJECT        pBwrmCookedPage    = (PBWRM_COOKED_PAGE_OBJECT   )NULL;
    void*                           pPageBuffer        = (void*                      )NULL;
    ULONG                           ulPageSize         = (ULONG                      )0;

    /*
     * The script parsing can take fairly long time, which mandates some sort of page caching
     * mechanism to be used. The BWRM (BroadWay Web Resource Manager) module is responsible for
     * file-based page access and page caching. We first try to retrieve the requested page from
     * the in-memory cache, and only load the page from the underlying storage system if the
     * requested page is not in the cache.
     */
    returnStatus =
        pBwrmRamIf->GetCookedPage
            (
                pBwrmRamIf->hOwnerContext,
                pRootPath,
                page_path,
                &pBwrmCookedPage
            );

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        returnStatus =
            pBwrmRamIf->GetRawPage
                (
                    pBwrmRamIf->hOwnerContext,
                    pRootPath,
                    page_path,
                    &pPageBuffer,
                    &ulPageSize
                );

        if ( returnStatus != ANSC_STATUS_SUCCESS )
        {
            return  (ANSC_HANDLE)NULL;
        }
        else
        {
            pBwrmCookedPage =
                (PBWRM_COOKED_PAGE_OBJECT)pBmc2ComExecutor->PreparePage
                    (
                        (ANSC_HANDLE)pBmc2ComExecutor,
                        page_path,
                        pPageBuffer,
                        ulPageSize
                    );
        }

        if ( !pBwrmCookedPage )
        {
            AnscFreeMemory(pPageBuffer);

            return  (ANSC_HANDLE)NULL;
        }
        else if ( pBmc2EnvController->Property.bCacheScpPages || pBwrmRamIf->IsPageCacheForced(pBwrmRamIf->hOwnerContext, page_path) )
        {
            returnStatus =
                pBwrmRamIf->AddCookedPage
                    (
                        pBwrmRamIf->hOwnerContext,
                        pRootPath,
                        page_path,
                        (ANSC_HANDLE)pBwrmCookedPage
                    );
        }
        else
        {
            pBwrmCookedPage->SetRootPath ((ANSC_HANDLE)pBwrmCookedPage, pRootPath             );
            pBwrmCookedPage->SetPagePath ((ANSC_HANDLE)pBwrmCookedPage, page_path             );
            pBwrmCookedPage->SetTimestamp((ANSC_HANDLE)pBwrmCookedPage, AnscGetTickInSeconds());
        }
    }

    return  (ANSC_HANDLE)pBwrmCookedPage;
}
Пример #17
0
ANSC_STATUS
SlapEcoUoaInvokeObject
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSlapObject,
        char*                       method_name,
        SLAP_PARAMETER_LIST*        params_in,
        SLAP_PARAMETER_LIST**       params_out,
        SLAP_VARIABLE**             return_var
    )
{
    ANSC_STATUS                     returnStatus      = ANSC_STATUS_SUCCESS;
    PSLAP_ENV_CONTROLLER_OBJECT     pMyObject         = (PSLAP_ENV_CONTROLLER_OBJECT)hThisObject;
    PSLAP_OBJ_MAPPER_OBJECT         pSlapObjMapper    = (PSLAP_OBJ_MAPPER_OBJECT    )pMyObject->hSlapObjMapper;
    PSLAP_OBJ_CONTAINER_OBJECT      pSlapObjContainer = (PSLAP_OBJ_CONTAINER_OBJECT )NULL;
    PSLAP_OBJ_ENTITY_OBJECT         pSlapObjEntity    = (PSLAP_OBJ_ENTITY_OBJECT    )NULL;
    PSLAP_OBJ_RECORD_OBJECT         pSlapObjRecord    = (PSLAP_OBJ_RECORD_OBJECT    )hSlapObject;
    PSLAP_SRV_COMPONENT_OBJECT      pSlapSrvComponent = (PSLAP_SRV_COMPONENT_OBJECT )pSlapObjRecord->hSlapSrvComponent;
    ULONG                           ulObjType         = (ULONG                      )0;

    pMyObject->bCallPending         = TRUE;
    pMyObject->PendingCallTimestamp = AnscGetTickInSeconds();

    AnscZeroMemory(pMyObject->PendingCallName, 256);
    AnscCopyString(pMyObject->PendingCallName, method_name);

    /*
     * There're certain object methods should not be simply relayed to the target logic object. For
     * example, the external modules may try to invoke method "Remove" to delete the target object.
     * Handling of such methods should be taken care by UOA interface.
     */
    if ( AnscEqualString(method_name, "Remove", FALSE) &&
         (params_in             != NULL              ) &&
         (params_in->ParamCount == 0                 ) )
    {
        returnStatus =
            pMyObject->UoaDeleteObject
                (
                    (ANSC_HANDLE)pMyObject,
                    (ANSC_HANDLE)pSlapObjRecord
                );

        pMyObject->bCallPending = FALSE;

        return  returnStatus;
    }

    if ( !pSlapSrvComponent )
    {
        pMyObject->bCallPending = FALSE;

        return  ANSC_STATUS_UNAPPLICABLE;
    }
    else
    {
        ulObjType = pSlapSrvComponent->ObjType;

        if ( ulObjType & SLAP_OBJ_TYPE_serializedCalls )
        {
            pSlapObjRecord->AcqAccess((ANSC_HANDLE)pSlapObjRecord);
        }

        returnStatus =
            pSlapSrvComponent->InvokeDispatch
                (
                    (ANSC_HANDLE)pSlapSrvComponent,
                    method_name,
                    params_in,
                    params_out,
                    return_var
                );

        if ( ulObjType & SLAP_OBJ_TYPE_serializedCalls )
        {
            pSlapObjRecord->RelAccess((ANSC_HANDLE)pSlapObjRecord);
        }
    }

    pMyObject->bCallPending = FALSE;

    return  returnStatus;
}
Пример #18
0
ANSC_STATUS
AnscBetoRecvTask
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PANSC_BROKER_ENGINE_TCP_OBJECT  pMyObject     = (PANSC_BROKER_ENGINE_TCP_OBJECT)hThisObject;
    PANSC_BROKER_SERVER_TCP_OBJECT  pServer       = (PANSC_BROKER_SERVER_TCP_OBJECT)pMyObject->hBrokerServer;
    ansc_fd_set*                    pRecvSet1     = (ansc_fd_set*                  )pMyObject->RecvSocketSet;
    xskt_fd_set*                    pRecvSet2     = (xskt_fd_set*                  )pMyObject->RecvSocketSet;
    PANSC_BROKER_SOCKET_TCP_OBJECT  pSocket       = NULL;
    ULONG                           ulLastCleanAt = AnscGetTickInSeconds();
    ANSC_SOCKET                     s_socket      = ANSC_SOCKET_INVALID_SOCKET;
    int                             s_result      = 0;
    int                             s_result_excp = 0;
    int                             s_error       = 0;
    int                             i             = 0;
    uni_fd_set                      read_fd_set;
    /*uni_fd_set                      excp_fd_set;*/
    uni_timeval                     timeval;

    AnscTrace("AnscBetoRecvTask is activated ...!\n");

    /*
     * As a scalable server implemention, we shall accept as many incoming client connections as
     * possible and can only be limited by the system resources. Once the listening socket becomes
     * readable, which means an incoming connection attempt has arrived. We create a new socket
     * object and associate it with the client. This is a repeated process until the socket owner
     * closes the socket.
     */
    while ( pMyObject->bStarted )
    {
        ANSC_COMMIT_TASK();

        /*
         * To avoid letting the old half-dead sockets hogging up the system resource, we need to
         * periodically invoke the cleaning routine. The default interval is 10 seconds, and the
         * idle timeout value is 90 seconds.
         */
        if ( pMyObject->bCleaningDemanded  || 
             (AnscGetTickInSeconds() - ulLastCleanAt) >= ANSC_BETO_CLEAN_TASK_INTERVAL )
        {
            pMyObject->Clean((ANSC_HANDLE)pMyObject);

            ulLastCleanAt                = AnscGetTickInSeconds();
            pMyObject->bCleaningDemanded = FALSE;
        }

        /*
         * The _ansc_select() function returns the total number of socket handles that are ready
         * and contained in the fd_set structures, zero if the time limit expired, or SOCKET_ERROR
         * if an error occurred. Upon return, the structures are updated to reflect the subset of
         * these sockets that meet the specified condition.
         */
    
        if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET )
        {
            /*
             * no need to use lock for read_fd_set here, dirty read does not matter.
             */
            read_fd_set.xset = *pRecvSet2;

            if( XSKT_SOCKET_FD_ISNUL(&read_fd_set.xset) )
            {
                if ( pServer->Mode & ANSC_BSTO_MODE_EVENT_SYNC )
                {
                    AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_BETO_WAIT_EVENT_INTERVAL);
                    AnscResetEvent(&pMyObject->NewSocketEvent);
                }
                else
                {
                    AnscSleep(ANSC_BETO_TASK_BREAK_INTERVAL);
                }

                continue;
            }

            timeval.xtv.tv_sec  = (ANSC_BETO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval.xtv.tv_usec = (ANSC_BETO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */

            s_result = _xskt_select(XSKT_SOCKET_FD_SETSIZE, &read_fd_set.xset, NULL, NULL, &timeval.xtv);

            if ( s_result == 0 )
            {
                continue;
            }

            if ( s_result == XSKT_SOCKET_ERROR )
            {
                s_error = _xskt_get_last_error();
                pMyObject->Reset((ANSC_HANDLE)pMyObject);
                continue;
            }
            
        }
        else
        {
            /*
             * no need to use lock for read_fd_set here, dirty read does not matter.
             */
            read_fd_set.aset = *pRecvSet1;

            if( ANSC_SOCKET_FD_ISNUL(&read_fd_set.aset) )
            {

                if ( pServer->Mode & ANSC_BSTO_MODE_EVENT_SYNC )
                {
                    AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_BETO_WAIT_EVENT_INTERVAL);
                    AnscResetEvent(&pMyObject->NewSocketEvent);
                }
                else
                {
                    AnscSleep(ANSC_BETO_TASK_BREAK_INTERVAL);
                }

                continue;
            }

            timeval.atv.tv_sec  = (ANSC_BETO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval.atv.tv_usec = (ANSC_BETO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */

            s_result = _ansc_select(ANSC_SOCKET_FD_SETSIZE, &read_fd_set.aset, NULL, NULL, &timeval.atv);

            if ( s_result == 0 )
            {
                continue;
            }

            if ( s_result == ANSC_SOCKET_ERROR )
            {
                s_error = _ansc_get_last_error();
                pMyObject->Reset((ANSC_HANDLE)pMyObject);
                continue;
            }
            
        }

        /*
         * If there're multiple sockets are receiving data, we loop through the returned fd_set
         * structure and process them one-by-one. However, we have a slight problem: the resulted
         * fd_set consists of only the native socket handles, not the associated Socket Objects.
         * We have to first retrieve the peer's IP address from the socket, and use it to find
         * the associated socket object.
         */
        for ( i = 0; i < s_result; i++ )
        {
            if ( !pMyObject->bStarted )
            {
                break;
            }

            if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET )
            {
                XSKT_SOCKET_FD_GET(&read_fd_set.xset, s_socket, (ULONG)i);
                if( s_socket == XSKT_SOCKET_INVALID_SOCKET )
                {
                    break;
                }

                if( ! XSKT_SOCKET_FD_ISSET(s_socket, pRecvSet2) )
                {
                    AnscTraceError(("AnscBetoRecvTask: XSKT_SOCKET_FD_ISSET returned FALSE.\n"));
                    continue;
                }
            }
            else
            {
                ANSC_SOCKET_FD_GET(&read_fd_set.aset, s_socket, (ULONG)i);
                if( s_socket == ANSC_SOCKET_INVALID_SOCKET )
                {
                    break;
                }

                if( ! ANSC_SOCKET_FD_ISSET(s_socket, pRecvSet1) )
                {
                    AnscTraceError(("AnscBetoRecvTask: XSKT_SOCKET_FD_ISSET returned FALSE.\n"));
                    continue;
                }
            }

            pSocket =
                (PANSC_BROKER_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket
                    (
                        (ANSC_HANDLE)pMyObject,
                        s_socket
                    );
 
            if ( !pSocket )
            {
                continue;
            }

            /*
             * We should make sure this socket is still valid before proceeding with the socket
             * receive operations. For example, the peer may have already closed or reset the
             * TCP connection while we're serving the previous socket request.
             *
             * 10/06/04 - It's believed this modification is slowing down the GUI and we're not
             * seeing tangible evidence that GUI responsivenss has been improved. So we disable
             * it for now.
             *
             * 11/20/09 - Re-activate the following code segment to validate the socket before
             * proceeding.
             */
            /*
            if ( pServer->Mode & ANSC_BSTO_MODE_XSOCKET )
            {
                XSKT_SOCKET_FD_ZERO((&excp_fd_set.xset));
                XSKT_SOCKET_FD_SET ((XSKT_SOCKET)s_socket, (&excp_fd_set.xset));

                timeval.xtv.tv_sec  = 0;
                timeval.xtv.tv_usec = 0;

                s_result_excp = _xskt_select(XSKT_SOCKET_FD_SETSIZE, NULL, NULL, &excp_fd_set.xset, &timeval.xtv);
            }
            else
            {
                ANSC_SOCKET_FD_ZERO((&excp_fd_set.aset));
                ANSC_SOCKET_FD_SET (s_socket, (&excp_fd_set.aset));

                timeval.atv.tv_sec  = 0;
                timeval.atv.tv_usec = 0;

                s_result_excp = _ansc_select(ANSC_SOCKET_FD_SETSIZE, NULL, NULL, &excp_fd_set.aset, &timeval.atv);
            }

            if ( ((s_result_excp == 1                )                                             ) ||
                 ((s_result_excp == XSKT_SOCKET_ERROR) &&  (pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) ||
                 ((s_result_excp == ANSC_SOCKET_ERROR) && !(pServer->Mode & ANSC_BSTO_MODE_XSOCKET)) )
            {
                if ( TRUE )
                {
                    pSocket->bBroken      = TRUE;
                    pSocket->bToBeCleaned = TRUE;

                    pMyObject->EnableRecv((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE);
                    pMyObject->EnableSend((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE);
                }

                if ( pServer->Mode & ANSC_BSTO_MODE_AUTO_CLOSE )
                {
                    pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket);
                }

                continue;
            }
            */

            returnStatus = 
                pMyObject->Recv
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pSocket
                    );
 
        }
    }

    AnscSetEvent(&pMyObject->RecvEvent);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
CcspCwmpAcscoRequest
    (
        ANSC_HANDLE                 hThisObject,
        char*                       pSoapMessage,
        char*                       pMethodName,
        ULONG                       ulReqEnvCount,
        ULONG                       ulRepEnvCount
    )
{
    PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject      = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject;
    PHTTP_SIMPLE_CLIENT_OBJECT      pHttpClient     = (PHTTP_SIMPLE_CLIENT_OBJECT)pMyObject->hHttpSimpleClient;
    PCCSP_CWMP_SESSION_OBJECT       pWmpSession     = (PCCSP_CWMP_SESSION_OBJECT   )pMyObject->hCcspCwmpSession;
    PCCSP_CWMP_CPE_CONTROLLER_OBJECT pCcspCwmpCpeController = (PCCSP_CWMP_CPE_CONTROLLER_OBJECT)pWmpSession->hCcspCwmpCpeController;
    PCCSP_CWMP_STAT_INTERFACE       pCcspCwmpStatIf = (PCCSP_CWMP_STAT_INTERFACE)pCcspCwmpCpeController->hCcspCwmpStaIf;
	PCCSP_CWMP_CFG_INTERFACE		pCcspCwmpCfgIf	= (PCCSP_CWMP_CFG_INTERFACE)pCcspCwmpCpeController->hCcspCwmpCfgIf;
    PCCSP_CWMP_MCO_INTERFACE        pCcspCwmpMcoIf  = (PCCSP_CWMP_MCO_INTERFACE        )pWmpSession->hCcspCwmpMcoIf;
    PHTTP_HFP_INTERFACE             pHttpHfpIf      = (PHTTP_HFP_INTERFACE)pHttpClient->GetHfpIf((ANSC_HANDLE)pHttpClient);
    PHTTP_CAS_INTERFACE             pHttpCasIf      = NULL;
    PHTTP_REQUEST_URI               pHttpReqInfo    = NULL;
    ANSC_STATUS                     returnStatus    = ANSC_STATUS_SUCCESS;
    PANSC_ACS_INTERN_HTTP_CONTENT   pHttpGetReq     = &intHttpContent;
    BOOL                            bApplyTls       = FALSE;
    PCHAR                           pRequestURL     = NULL;
    PCHAR                           pTempString     = NULL;
    PHTTP_AUTH_CLIENT_OBJECT        pAuthClientObj  = NULL;
    char                            pNewUrl[257]    = { 0 };
    ULONG                           uRedirect       = 0;
    ULONG                           uMaxRedirect    = 5;
	ULONG							ulRpcCallTimeout= CCSP_CWMPSO_RPCCALL_TIMEOUT; 

    /* If the response is 401 authentication required, we need to try again */
    int                             nMaxAuthRetries = 2;

    if( pMyObject->AcsUrl == NULL || AnscSizeOfString(pMyObject->AcsUrl) <= 10 || pHttpHfpIf == NULL)
    {
        return ANSC_STATUS_NOT_READY;
    }

    AnscZeroMemory(pHttpGetReq, sizeof(ANSC_ACS_INTERN_HTTP_CONTENT));

    CcspTr069PaTraceDebug(("CcspCwmpAcscoRequest -- AcsUrl = '%s'\n", pMyObject->AcsUrl));

    pHttpCasIf  = (PHTTP_CAS_INTERFACE)pHttpClient->GetCasIf((ANSC_HANDLE)pHttpClient);

    if ( pHttpCasIf != NULL)
    {
        if( pMyObject->Username == NULL || AnscSizeOfString(pMyObject->Username) == 0)
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, FALSE);
        }
        else
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, TRUE);

            pAuthClientObj  = (PHTTP_AUTH_CLIENT_OBJECT)pHttpClient->GetClientAuthObj((ANSC_HANDLE)pHttpClient);

            if ( pAuthClientObj != NULL)
            {
                pAuthClientObj->SetAcmIf((ANSC_HANDLE)pAuthClientObj, (ANSC_HANDLE)pMyObject->hHttpAcmIf);
            }
            else
            {
                CcspTr069PaTraceError(("Failed to Get HttpAuthClient object.\n"));
            }
        }
    }

#ifdef   _DEBUG
    if ( !pSoapMessage )
    {
        CcspTr069PaTraceDebug(("CPE Request:\n<EMPTY>\n"));
    }
    else if ( AnscSizeOfString(pSoapMessage) <= CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH )
    {
        CcspTr069PaTraceDebug(("CPE Request:\n%s\n", pSoapMessage));
    }
    else
    {
        char                        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+1+8];

        AnscCopyMemory(partSoap, pSoapMessage, CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH);
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH] = '\n';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+1] = '.';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+2] = '.';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+3] = '.';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+4] = '\n';
        partSoap[CCSP_CWMP_TRACE_MAX_SOAP_MSG_LENGTH+5] = 0;
        CcspTr069PaTraceDebug(("CPE Request:\n%s\n", partSoap));
    }
#endif
    
START:
    pRequestURL = pMyObject->AcsUrl;

    pHttpReqInfo =
        (PHTTP_REQUEST_URI)pHttpHfpIf->ParseHttpUrl
            (
                pHttpHfpIf->hOwnerContext,
                pRequestURL,
                AnscSizeOfString(pRequestURL)
            );

    if ( !pHttpReqInfo )
    {
        return ANSC_STATUS_INTERNAL_ERROR;
    }

    pHttpReqInfo->Type = HTTP_URI_TYPE_ABS_PATH;

    /* init the request */
    AnscZeroMemory(pHttpGetReq, sizeof(ANSC_ACS_INTERN_HTTP_CONTENT));
    pHttpGetReq->bIsRedirect    = FALSE;
    pHttpGetReq->SoapMessage    = pSoapMessage;

    /* When there is more than one envelope in a single HTTP Request,
     * when there is a SOAP response in an HTTP Request, or when there is a
     * SOAP Fault response in an HTTP Request, the SOAPAction header in the
     * HTTP Request MUST have no value (with no quotes), indicating that this
     * header provides no information as to the intent of the message."
     */
    if( ulReqEnvCount == 1 && ulRepEnvCount == 0)
    {
        pHttpGetReq->MethodName     = pMethodName;
    }

    AnscInitializeEvent(&pHttpGetReq->CompleteEvent);

    while ( nMaxAuthRetries > 0 )
    {
        CcspTr069PaTraceInfo(("ACS Request now at: %u\n", (unsigned int)AnscGetTickInSeconds()));

        if ( AnscEqualString2(pRequestURL, "https", 5, FALSE) )
        {
            bApplyTls = TRUE;
        }
        else if ( AnscEqualString2(pRequestURL, "http", 4, FALSE) )
        {
            if ( bIsComcastImage() ){                
#ifdef _SUPPORT_HTTP
               CcspTr069PaTraceInfo(("HTTP request from ACS is supported\n"));
               bApplyTls = FALSE;
#else
               CcspTr069PaTraceInfo(("TR-069 blocked unsecured traffic from ACS\n"));
               pHttpGetReq->CompleteStatus = ANSC_STATUS_NOT_SUPPORTED;
               pHttpGetReq->bUnauthorized = TRUE;
               pHttpGetReq->bIsRedirect = FALSE;
               break;
#endif
            }
            else {
               bApplyTls = FALSE; 
            }
        }
        else
        {
             pHttpGetReq->CompleteStatus = ANSC_STATUS_NOT_SUPPORTED;
             pHttpGetReq->bUnauthorized = FALSE;
             pHttpGetReq->bIsRedirect = FALSE;
             break;
        }

        if(pHttpGetReq->pContent != NULL)
        {
            CcspTr069PaFreeMemory(pHttpGetReq->pContent);

            pHttpGetReq->pContent = NULL;
        }

        pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE;
        pHttpGetReq->bUnauthorized  = FALSE;
        AnscResetEvent     (&pHttpGetReq->CompleteEvent);

        returnStatus =
            pHttpClient->Request
                (
                    (ANSC_HANDLE)pHttpClient,
                    (ULONG      )HTTP_METHOD_CODE_POST,
                    (ANSC_HANDLE)pHttpReqInfo,
                    (ANSC_HANDLE)pHttpGetReq,
                    bApplyTls
                );

        if( returnStatus != ANSC_STATUS_SUCCESS)
        {
            CcspTr069PaTraceError(("ACS Request failed: returnStatus = %.X\n", (unsigned int)returnStatus));
			break;
        }

		if ( pCcspCwmpCfgIf && pCcspCwmpCfgIf->GetCwmpRpcTimeout )
		{
			ulRpcCallTimeout = pCcspCwmpCfgIf->GetCwmpRpcTimeout(pCcspCwmpCfgIf->hOwnerContext);	
			if ( ulRpcCallTimeout < CCSP_CWMPSO_RPCCALL_TIMEOUT )
			{
				ulRpcCallTimeout = CCSP_CWMPSO_RPCCALL_TIMEOUT;
			}
		}

        AnscWaitEvent(&pHttpGetReq->CompleteEvent, ulRpcCallTimeout * 1000);
        if ( pHttpGetReq->CompleteStatus == ANSC_STATUS_SUCCESS && pHttpGetReq->bUnauthorized && nMaxAuthRetries > 0 )
        {
            CcspTr069PaTraceError(("ACS Request is not authenticated, try again.\n"));
            nMaxAuthRetries --;
			
#ifdef _ANSC_USE_OPENSSL_
            if( bApplyTls )
        	{
	        	if ( ANSC_STATUS_SUCCESS == CcspTr069PaSsp_GetTr069CertificateLocationForSyndication( &openssl_client_ca_certificate_files ) )
        		{
					openssl_load_ca_certificates( SSL_CLIENT_CALLS );
        		}
        	}
#endif /* _ANSC_USE_OPENSSL_ */
        }
        else
        {
            CcspTr069PaTraceInfo(("ACS Request has completed with status code %lu, at %lu\n", pHttpGetReq->CompleteStatus, AnscGetTickInSeconds()));

            break;
        }
    }

    /* AnscResetEvent (&pHttpGetReq->CompleteEvent); */
    AnscFreeEvent(&pHttpGetReq->CompleteEvent);

    CcspTr069PaFreeMemory(pHttpReqInfo);

    if ( pHttpGetReq->CompleteStatus != ANSC_STATUS_SUCCESS )
    {
        if ( pHttpGetReq->CompleteStatus == ANSC_STATUS_RESET_SESSION )
        {
            goto  REDIRECTED;
        }
        else
        {
            returnStatus = pHttpGetReq->CompleteStatus;

            goto  EXIT;
        }
    }
    else if( pHttpGetReq->bUnauthorized)
    {
        returnStatus = ANSC_STATUS_FAILURE;

        if( pCcspCwmpStatIf)
        {
            pCcspCwmpStatIf->IncTcpFailure(pCcspCwmpStatIf->hOwnerContext);
        }

        goto EXIT;
    }

REDIRECTED:
    if( pHttpGetReq->bIsRedirect)
    {
        if( _ansc_strstr((PCHAR)pHttpGetReq->pContent, "http") == pHttpGetReq->pContent)
        {
            if ( pMyObject->AcsUrl ) CcspTr069PaFreeMemory(pMyObject->AcsUrl);
            pMyObject->AcsUrl = CcspTr069PaCloneString(pHttpGetReq->pContent);
        }
        else
        {
            /* if it's partial path */
            pTempString = _ansc_strstr(pRequestURL, "//");

            if( pTempString == NULL)
            {
                returnStatus = ANSC_STATUS_FAILURE;

                goto EXIT;
            }

            pTempString += AnscSizeOfString("//");
            pTempString  = _ansc_strstr(pTempString, "/");

            if( pTempString == NULL)
            {
                returnStatus = ANSC_STATUS_FAILURE;

                goto EXIT;
            }

            AnscCopyMemory(pNewUrl, pRequestURL, (ULONG)(pTempString - pRequestURL));
            AnscCatString(pNewUrl, (PCHAR)pHttpGetReq->pContent);

            if ( pMyObject->AcsUrl ) CcspTr069PaFreeMemory(pMyObject->AcsUrl);
            pMyObject->AcsUrl = CcspTr069PaCloneString(pNewUrl);
        }

        uRedirect ++;

        if( uRedirect >= uMaxRedirect)
        {
            CcspTr069PaTraceDebug(("Maximum Redirection reached. Give up!\n"));

            returnStatus = ANSC_STATUS_FAILURE;

            goto EXIT;
        }
        else
        {
            CcspTr069PaTraceDebug(("Acs connection redirection #%u: '%s'\n", (unsigned int)uRedirect, pMyObject->AcsUrl));

            /* in case redirected ACS challenges CPE again */
            nMaxAuthRetries = 2;

            /* tear down current HTTP session before redirecting to new ACS,
             * otherwise, there might be case that ACS sends out redirection
             * response and immediately closes the socket, CWMP may be 
             * confused by closing CWMP session prematurely. 
             */
            pHttpClient->DelAllWcsos((ANSC_HANDLE)pHttpClient);

            goto START;
        }
    }

    if(pWmpSession != NULL)
    {
        if( pHttpGetReq->ulContentSize > 0 && pHttpGetReq->pContent != NULL)
        {
            CcspTr069PaTraceDebug(("Response:\n%s\n", (char*)pHttpGetReq->pContent));

            returnStatus =
                pWmpSession->RecvSoapMessage
                    (
                       pWmpSession,
                       (PCHAR)pHttpGetReq->pContent
                    );
        }
        else
        {
            CcspTr069PaTraceDebug(("Response: <EMPTY>\n"));

            returnStatus =
                pCcspCwmpMcoIf->NotifyAcsStatus
                    (
                        pCcspCwmpMcoIf->hOwnerContext,
                        TRUE,           /* no more requests */
                        FALSE
                    );
        }
    }

EXIT:

    if(pHttpGetReq->pContent != NULL)
    {
        CcspTr069PaFreeMemory(pHttpGetReq->pContent);

        pHttpGetReq->pContent = NULL;
    }

    /******************************************************************
                GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS
    ******************************************************************/

    return returnStatus;
}
ANSC_STATUS
HttpWcsoRequest
    (
        ANSC_HANDLE                 hThisObject,
        ULONG                       ulMethod,
        ANSC_HANDLE                 hReqUri,
        ANSC_HANDLE                 hReqContext
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PHTTP_WEBC_SESSION_OBJECT       pMyObject    = (PHTTP_WEBC_SESSION_OBJECT  )hThisObject;
    PHTTP_WEBC_SESSION_PROPERTY     pProperty    = (PHTTP_WEBC_SESSION_PROPERTY)&pMyObject->Property;
    PHTTP_BSP_INTERFACE             pBspIf       = (PHTTP_BSP_INTERFACE        )pMyObject->hBspIf;
    PHTTP_REQUEST_URI               pReqUri      = (PHTTP_REQUEST_URI          )hReqUri;
    PHTTP_WEBC_TRANS_OBJECT         pWebcTrans   = NULL;
    PHTTP_REQUEST_URI               pHttpReqUri  = NULL;

    if ( pMyObject->SessionState != HTTP_WCSO_STATE_SERVER_CONNECTED )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }
    else
    {
        pWebcTrans = (PHTTP_WEBC_TRANS_OBJECT)pMyObject->GetCurWcto((ANSC_HANDLE)pMyObject);
    }

    if ( !pWebcTrans )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }
    else if ( pWebcTrans->GetTransState((ANSC_HANDLE)pWebcTrans) != HTTP_WCTO_STATE_INITIALIZED )
    {
        pWebcTrans->ReleaseAccess((ANSC_HANDLE)pWebcTrans);

        return  ANSC_STATUS_UNAPPLICABLE;
    }

    pHttpReqUri  = (PHTTP_REQUEST_URI)AnscAllocateMemory(sizeof(HTTP_REQUEST_URI));

    if ( !pHttpReqUri )
    {
    	AnscTrace("HttpWcsoRequest - can't create http request URI!\n");
        return ANSC_STATUS_RESOURCES;
    }

    *pHttpReqUri    = *pReqUri;

    if ( pMyObject->hReqUri )
    {
        AnscFreeMemory(pMyObject->hReqUri);
    }

    pMyObject->hReqUri      = (ANSC_HANDLE)pHttpReqUri;
    pMyObject->ReqMethod    = ulMethod;

    pMyObject->Timestamp    = AnscGetTickInSeconds();
    pMyObject->bRemoveMe    = FALSE;

    returnStatus =
        pWebcTrans->Request
            (
                (ANSC_HANDLE)pWebcTrans,
                ulMethod,
                (ANSC_HANDLE)pReqUri,
                hReqContext
            );

    pWebcTrans->ReleaseAccess((ANSC_HANDLE)pWebcTrans);

    return  returnStatus;
}
ANSC_STATUS
DslhWmpdoMonitorTimerInvoke
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus       = ANSC_STATUS_SUCCESS;
    PDSLH_WMP_DATABASE_OBJECT       pMyObject          = (PDSLH_WMP_DATABASE_OBJECT  )hThisObject;
    PDSLH_WMP_DATABASE_PROPERTY     pProperty          = (PDSLH_WMP_DATABASE_PROPERTY)&pMyObject->Property;
    PDSLH_CPE_CONTROLLER_OBJECT     pDslhCpeController = (PDSLH_CPE_CONTROLLER_OBJECT)pMyObject->hDslhCpeController;
    PDSLH_WMPDO_MONITOR_PARAM       pMonitorParam      = (PDSLH_WMPDO_MONITOR_PARAM  )NULL;
    PDSLH_VAR_RECORD_OBJECT         pDslhVarRecord     = (PDSLH_VAR_RECORD_OBJECT    )NULL;
    PDSLH_VAR_ENTITY_OBJECT         pDslhVarEntity     = (PDSLH_VAR_ENTITY_OBJECT    )NULL;
    PDSLH_CWMP_PARAM_DESCR          pParamDesp         = (PDSLH_CWMP_PARAM_DESCR     )NULL;
    PSLAP_VARIABLE                  pNewParamValue     = (PSLAP_VARIABLE             )NULL;
    BOOL                            bValueNotUpdated   = (BOOL                       )TRUE;
    char*                           pParamFullName     = (char*                      )NULL;
    PSINGLE_LINK_ENTRY              pSLinkEntry        = (PSINGLE_LINK_ENTRY         )NULL;
    BOOL                            bActiveNotify      = FALSE;
    int                             oldValue           = 0; /* Only for notification with threshold */
    int                             newValue           = 0; /* Only for notification with threshold */

    AnscAcquireLock(&pMyObject->MpoQueueLock);

    pSLinkEntry = AnscQueueGetFirstEntry(&pMyObject->MpoQueue);

    while ( pSLinkEntry )
    {
        pMonitorParam  = ACCESS_DSLH_WMPDO_MONITOR_PARAM(pSLinkEntry);
        pDslhVarRecord = (PDSLH_VAR_RECORD_OBJECT)pMonitorParam->hVarRecord;
        pSLinkEntry    = AnscQueueGetNextEntry(pSLinkEntry);

        /*
         * DO NOT synchronize the value if value-changing is in progress...
         */
        if ( pDslhVarRecord->TempParamValue )
        {
            continue;
        }

        /*
         * DO NOT synchronize the value if the active notification parameter is rate-regulated and
         * the last update was notified less than "NotificationLimit" seconds ago.
         */
        if ( (pDslhVarRecord->Notification      == DSLH_CWMP_NOTIFICATION_active) &&
             (pMonitorParam ->NotificationLimit >  0                            ) )
        {
            if ( (AnscGetTickInSeconds() - pMonitorParam->Timestamp) < pMonitorParam->NotificationLimit )
            {
                continue;
            }
        }

        if ( pMonitorParam->PreviousValue )
        {
            pNewParamValue   = pDslhVarRecord->GetValue((ANSC_HANDLE)pDslhVarRecord);
            bValueNotUpdated = TRUE;

            if ( !pNewParamValue )
            {
                continue;
            }
            else
            {
            	SlapEqualVariables(pMonitorParam->PreviousValue, pNewParamValue, bValueNotUpdated);
            }

            if ( !bValueNotUpdated )
            {
                /* Notificatoin with threshold check */
                pDslhVarEntity = (PDSLH_VAR_ENTITY_OBJECT)pDslhVarRecord->hDslhVarEntity;
                pParamDesp     = (PDSLH_CWMP_PARAM_DESCR )pDslhVarEntity->ParamDescr;
                
                if ( pParamDesp && pParamDesp->bThresholdEnabled == TRUE )
                {
                    oldValue  = pMonitorParam ->PreviousValue->Variant.varInt;
                    newValue  = pNewParamValue->Variant.varInt;
                    
                    if ( 
                           (oldValue < pParamDesp->NotifyThresholdMin && newValue < pParamDesp->NotifyThresholdMin) ||
                           (oldValue > pParamDesp->NotifyThresholdMax && newValue > pParamDesp->NotifyThresholdMax) ||
                           (oldValue >= pParamDesp->NotifyThresholdMin && oldValue <= pParamDesp->NotifyThresholdMax && newValue >= pParamDesp->NotifyThresholdMin && newValue <= pParamDesp->NotifyThresholdMax)
                       )
                    {
                        if ( pMonitorParam->PreviousValue )
                        {
                            SlapFreeVariable(pMonitorParam->PreviousValue);
                        }
                        
                        pMonitorParam->PreviousValue = pNewParamValue;
                        continue;
                    }
                }
                
                /* save the previous value as old */
                if( pDslhVarRecord->OldParamValue != NULL)
                {
                    SlapFreeVariable(pDslhVarRecord->OldParamValue);
                }

                pDslhVarRecord->OldParamValue = pMonitorParam->PreviousValue;
                /* SlapFreeVariable(pMonitorParam->PreviousValue); */

                pMonitorParam->PreviousValue = pNewParamValue;
                pParamFullName               = pDslhVarRecord->GetFullName((ANSC_HANDLE)pDslhVarRecord);

                if ( pParamFullName )
                {
                    bActiveNotify |= (pDslhVarRecord->Notification == DSLH_CWMP_NOTIFICATION_active);					 
                    pMonitorParam->Timestamp = AnscGetTickInSeconds();

                    pDslhVarRecord->NotifyValueChanged(pDslhVarRecord);

                    AnscTraceWarning(("DslhWmpdoMonitorTimerInvoke - value change detected on parameter <%s>.\n", pParamFullName));
					pDslhVarRecord->ReqSenderID = 0;
					pMonitorParam->PreviousValue->ReqSenderID = 0;
                    AnscFreeMemory(pParamFullName);
                }
            }
            else
            {
                SlapFreeVariable(pNewParamValue);
            }
        }
        else
        {
            pMonitorParam->PreviousValue = pDslhVarRecord->GetValue((ANSC_HANDLE)pDslhVarRecord);
        }
    }

    AnscReleaseLock(&pMyObject->MpoQueueLock);

    return  ANSC_STATUS_SUCCESS;
}
/**********************************************************************

    prototype:

        ANSC_STATUS
        CcspCwmpAcscoRequestOny
            (
                ANSC_HANDLE                 hThisObject
            );

    description:

        This function is called to send the last empty request to ACS.

    argument:

                ANSC_HANDLE                 hThisObject
                The caller object.

    return:     the status of the operation;

**********************************************************************/
ANSC_STATUS
CcspCwmpAcscoRequestOnly
    (
        ANSC_HANDLE                 hThisObject
    )
{
    PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject      = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject;

    return  pMyObject->Request((ANSC_HANDLE)pMyObject, NULL, NULL, 0, 0);

#if 0
    PHTTP_SIMPLE_CLIENT_OBJECT      pHttpClient     = (PHTTP_SIMPLE_CLIENT_OBJECT)pMyObject->hHttpSimpleClient;
    PCCSP_CWMP_SESSION_OBJECT       pWmpSession     = (PCCSP_CWMP_SESSION_OBJECT   )pMyObject->hCcspCwmpSession;
    PCCSP_CWMP_MCO_INTERFACE        pCcspCwmpMcoIf  = (PCCSP_CWMP_MCO_INTERFACE    )pWmpSession->hCcspCwmpMcoIf;
    PHTTP_HFP_INTERFACE             pHttpHfpIf      = (PHTTP_HFP_INTERFACE)pHttpClient->GetHfpIf((ANSC_HANDLE)pHttpClient);
    PHTTP_CAS_INTERFACE             pHttpCasIf      = NULL;
    PHTTP_REQUEST_URI               pHttpReqInfo    = NULL;
    ANSC_STATUS                     returnStatus    = ANSC_STATUS_SUCCESS;
    ANSC_ACS_INTERN_HTTP_CONTENT    intHttpContent  = { 0 };
    PANSC_ACS_INTERN_HTTP_CONTENT   pHttpGetReq     = &intHttpContent;
    BOOL                            bApplyTls       = FALSE;
    PCHAR                           pRequestURL     = NULL;
    PCHAR                           pTempString     = NULL;
    PHTTP_AUTH_CLIENT_OBJECT        pAuthClientObj  = NULL;
    char                            pNewUrl[257]    = { 0 };
    ULONG                           uRedirect       = 0;
    ULONG                           uMaxRedirect    = 5;

    if( pMyObject->AcsUrl == NULL || AnscSizeOfString(pMyObject->AcsUrl) <= 10 || pHttpHfpIf == NULL)
    {
        return ANSC_STATUS_NOT_READY;
    }

    CcspTr069PaTraceDebug(("CcspCwmpAcscoRequest -- AcsUrl = '%s'\n", pMyObject->AcsUrl));

    pRequestURL = pMyObject->AcsUrl;

    if ( AnscEqualString2(pRequestURL, "https", 5, FALSE) )
    {
        bApplyTls = TRUE;
    }
    else if ( AnscEqualString2(pRequestURL, "http", 4, FALSE) )
    {
        bApplyTls = FALSE;
    }
    else
    {
        return ANSC_STATUS_NOT_SUPPORTED;
    }

    pHttpCasIf  = (PHTTP_CAS_INTERFACE)pHttpClient->GetCasIf((ANSC_HANDLE)pHttpClient);

    if ( pHttpCasIf != NULL)
    {
        if( pMyObject->Username == NULL || AnscSizeOfString(pMyObject->Username) == 0)
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, FALSE);
        }
        else
        {
            pHttpCasIf->EnableAuth(pHttpCasIf->hOwnerContext, TRUE);

            pAuthClientObj  = (PHTTP_AUTH_CLIENT_OBJECT)pHttpClient->GetClientAuthObj((ANSC_HANDLE)pHttpClient);

            if ( pAuthClientObj != NULL)
            {
                pAuthClientObj->SetAcmIf((ANSC_HANDLE)pAuthClientObj, (ANSC_HANDLE)pMyObject->hHttpAcmIf);
            }
            else
            {
                CcspTr069PaTraceError(("Failed to Get HttpAuthClient object.\n"));
            }
        }
    }

    pHttpReqInfo =
        (PHTTP_REQUEST_URI)pHttpHfpIf->ParseHttpUrl
            (
                pHttpHfpIf->hOwnerContext,
                pRequestURL,
                AnscSizeOfString(pRequestURL)
            );

    if ( !pHttpReqInfo )
    {
        return ANSC_STATUS_INTERNAL_ERROR;
    }

    pHttpReqInfo->Type = HTTP_URI_TYPE_ABS_PATH;


    CcspTr069PaTraceInfo(("Send empty request to now at: %u\n", (unsigned int)AnscGetTickInSeconds()));

    returnStatus =
        pHttpClient->Request
            (
                (ANSC_HANDLE)pHttpClient,
                (ULONG      )HTTP_METHOD_CODE_POST,
                (ANSC_HANDLE)pHttpReqInfo,
                (ANSC_HANDLE)NULL,
                bApplyTls
            );

    AnscSleep(500);

    CcspTr069PaFreeMemory(pHttpReqInfo);

    return returnStatus;
#endif
}
Пример #23
0
ANSC_HANDLE
HttpScoAddWcso
(
    ANSC_HANDLE                 hThisObject,
    char*                       host,
    USHORT                      port,
    ANSC_HANDLE                 hReqContext,
    BOOL                        bUseTls
)
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PHTTP_SIMPLE_CLIENT_OBJECT      pMyObject    = (PHTTP_SIMPLE_CLIENT_OBJECT  )hThisObject;
    PHTTP_SIMPLE_CLIENT_PROPERTY    pProperty    = (PHTTP_SIMPLE_CLIENT_PROPERTY)&pMyObject->Property;
    PHTTP_BSP_INTERFACE             pBspIf       = (PHTTP_BSP_INTERFACE         )pMyObject->hBspIf;
    PHTTP_HFP_INTERFACE             pHfpIf       = (PHTTP_HFP_INTERFACE         )pMyObject->hHfpIf;
    PHTTP_WEBC_SESSION_OBJECT       pWebcSession = (PHTTP_WEBC_SESSION_OBJECT   )pMyObject->AcquireWcso((ANSC_HANDLE)pMyObject);
    ULONG                           ulHashIndex  = AnscHashString2(host, AnscSizeOfString(host), HTTP_SCO_WCSO_TABLE_SIZE);

    if ( !pWebcSession )
    {
        AnscTrace("HttpScoAddWcso - can't acquire web client session object!\n");
        return  (ANSC_HANDLE)NULL;
    }
    else
    {
        ULONG                       ulWebcSessionMode   = bUseTls? HTTP_WCSO_FLAG_tlsEnabled : 0;

        if ( pMyObject->ClientMode & HTTP_SCO_MODE_XSOCKET )
        {
            ulWebcSessionMode   |= HTTP_WCSO_FLAG_xsocketEnabled;
        }

        if ( pMyObject->ClientMode & HTTP_SCO_MODE_NOTIFY_ON_ALL_CONN_ONCE )
        {
            ulWebcSessionMode   |= HTTP_WCSO_FLAG_BspNotifyOnAllConnOnce;
        }

        pWebcSession->hBspReqContext = hReqContext;
        pWebcSession->Timestamp      = AnscGetTickInSeconds();
        pWebcSession->HashIndex      = ulHashIndex;

        pWebcSession->SetPeerName    ((ANSC_HANDLE)pWebcSession, host               );
        pWebcSession->SetPeerPort    ((ANSC_HANDLE)pWebcSession, port               );
        pWebcSession->SetHostPort    ((ANSC_HANDLE)pWebcSession, 0                  );
        pWebcSession->SetSessionFlags((ANSC_HANDLE)pWebcSession, ulWebcSessionMode  );
        pWebcSession->SetBspIf       ((ANSC_HANDLE)pWebcSession, (ANSC_HANDLE)pBspIf);
        pWebcSession->SetHfpIf       ((ANSC_HANDLE)pWebcSession, (ANSC_HANDLE)pHfpIf);
    }

    returnStatus = pWebcSession->Open((ANSC_HANDLE)pWebcSession);

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        pWebcSession->Return((ANSC_HANDLE)pWebcSession);

        return  (ANSC_HANDLE)NULL;
    }

    AnscAcquireLock   (&pMyObject->WcsoTableLock);
    AnscSListPushEntry(&pMyObject->WcsoTable[ulHashIndex], &pWebcSession->Linkage);
    pWebcSession->AcquireAccess((ANSC_HANDLE)pWebcSession);
    AnscReleaseLock   (&pMyObject->WcsoTableLock);

    return  (ANSC_HANDLE)pWebcSession;
}
ANSC_STATUS
AnscDeuoSend
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSocket,
        PVOID                       buffer,
        ULONG                       ulSize,
        ANSC_HANDLE                 hReserved
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_DAEMON_ENGINE_UDP_OBJECT  pMyObject    = (PANSC_DAEMON_ENGINE_UDP_OBJECT)hThisObject;
    PANSC_DAEMON_SERVER_UDP_OBJECT  pServer      = (PANSC_DAEMON_SERVER_UDP_OBJECT)pMyObject->hDaemonServer;
    PANSC_DSUO_WORKER_OBJECT        pWorker      = (PANSC_DSUO_WORKER_OBJECT      )pServer->hWorker;
    PANSC_DAEMON_SOCKET_UDP_OBJECT  pSocket      = (PANSC_DAEMON_SOCKET_UDP_OBJECT)hSocket;
    int                             s_result     = 0;
    int                             s_error      = 0;
    ansc_socket_addr_in             to_addr;
    xskt_socket_addr_in             xskt_to_addr;

    if ( pSocket->bClosed )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }
    else
    {
        if ( pServer->Mode & ANSC_DSUO_MODE_XSOCKET )
        {
            xskt_to_addr.sin_family                                 = XSKT_SOCKET_AF_INET;
            ((pansc_socket_addr_in)&xskt_to_addr)->sin_addr.s_addr  = pSocket->PeerAddress.Value;
            xskt_to_addr.sin_port                                   = _xskt_htons(pSocket->PeerPort);
        }
        else
        {
            to_addr.sin_family      = ANSC_SOCKET_AF_INET;
            to_addr.sin_addr.s_addr = pSocket->PeerAddress.Value;
            to_addr.sin_port        = _ansc_htons(pSocket->PeerPort);
        }
    }

    if ( pMyObject->ControlFlags & ANSC_DEUO_FLAG_ASYNC_SEND )
    {
        returnStatus = ANSC_STATUS_UNAPPLICABLE;
    }
    else
    {
        if ( pServer->Mode & ANSC_DSUO_MODE_XSOCKET )
        {
            s_result = _xskt_sendto(pSocket->Socket, buffer, (int)ulSize, 0, (xskt_socket_addr*)&xskt_to_addr, sizeof(xskt_to_addr));
        }
        else
        {
            s_result = _ansc_sendto(pSocket->Socket, buffer, (int)ulSize, 0, (ansc_socket_addr*)&to_addr, sizeof(to_addr));
        }

        if ( s_result == ANSC_SOCKET_ERROR )
        {
            s_error = _ansc_get_last_error();

            returnStatus =
                pWorker->SendComplete
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pSocket,
                        hReserved,
                        ANSC_STATUS_FAILURE
                    );

            returnStatus =
                pWorker->Notify
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pSocket,
                        ANSC_DSUOWO_EVENT_SOCKET_ERROR,
                        hReserved
                    );

            if ( pServer->Mode & ANSC_DSUO_MODE_AUTO_CLOSE )
            {
                pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket);
            }

            returnStatus = ANSC_STATUS_FAILURE;
        }
        else
        {
            returnStatus =
                pWorker->SendComplete
                    (
                        pWorker->hWorkerContext,
                        (ANSC_HANDLE)pSocket,
                        hReserved,
                        ANSC_STATUS_SUCCESS
                    );

            pSocket->SendBytesCount += ulSize;
            pSocket->LastSendAt      = AnscGetTickInSeconds();

            returnStatus = ANSC_STATUS_SUCCESS;
        }
    }

    return  returnStatus;
}
ANSC_STATUS
AnscSctoEngage
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_SIMPLE_CLIENT_TCP_OBJECT  pMyObject    = (PANSC_SIMPLE_CLIENT_TCP_OBJECT)hThisObject;
    PANSC_SCTO_WORKER_OBJECT        pWorker      = (PANSC_SCTO_WORKER_OBJECT      )pMyObject->hWorker;
    int                             s_error      = 0;
    ansc_socket_addr_in             ansc_client_addr;
    ansc_socket_addr_in             ansc_server_addr;
    xskt_socket_addr_in             xskt_client_addr;
    xskt_socket_addr_in             xskt_server_addr;

#ifdef _ANSC_IPV6_COMPATIBLE_
    ansc_addrinfo                   ansc_hints            = {0};
    ansc_addrinfo*                  pansc_server_addrinfo = NULL;
    ansc_addrinfo*                  pansc_client_addrinfo = NULL;
    xskt_addrinfo                   xskt_hints            = {0};
    xskt_addrinfo*                  pxskt_server_addrinfo = NULL;
    xskt_addrinfo*                  pxskt_client_addrinfo = NULL;
    USHORT                          usPort                = 0;
    char                            port[6] = {0};
#endif

    if ( pMyObject->bActive )
    {
        return  ANSC_STATUS_SUCCESS;
    }
    else if ( !pWorker )
    {
        return  ANSC_STATUS_UNAPPLICABLE;
    }
    else
    {
        /*
         * Just like any other socket-based ANSC object, we will create a separate async recv task
         * which is dedicated to receiving packets. This async recv task is controlled by 'bActive'
         * flag. What if at this moment right before we're about to enable the socket operation and
         * setting 'bActive' flag to TRUE, the old recv task created by the last call of Engage()
         * is still running? While it may not cause crash, but it certainly confuses the owner
         * object because all async recv tasks share the same worker interface. The most obvious
         * solution is to wait for previous recv task to exit before creating a new one.
         */
    	while ( pMyObject->EngineTaskCount != 0 )
        {
            AnscSleep(50);
        }

        pMyObject->bActive = TRUE;
        pMyObject->bClosed = FALSE;
    }

    /*
     * The underlying socket wrapper may require an explicit startup() call, such is the case on
     * Microsoft windows platforms. The wrapper initialization has to done for each task. On most
     * real-time operating systems, this call is not required.
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        AnscStartupXsocketWrapper((ANSC_HANDLE)pMyObject);
    }
    else
    {
        AnscStartupSocketWrapper((ANSC_HANDLE)pMyObject);
    }

    #ifdef _ANSC_IPV6_COMPATIBLE_

    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        xskt_hints.ai_family   = AF_UNSPEC;
        xskt_hints.ai_socktype = XSKT_SOCKET_STREAM;
        xskt_hints.ai_flags    = AI_CANONNAME;

        usPort = pMyObject->GetPeerPort((ANSC_HANDLE)pMyObject);
        _ansc_sprintf(port, "%d", usPort);

        AnscTrace("!!! Peer Port: %s !!!\n", port);

        char * pPeerName = pMyObject->GetPeerName((ANSC_HANDLE)pMyObject);

        AnscTrace("Peer Name: %s!!!\n", pPeerName);

/*
        struct addrinfo hints,*res=NULL;
	memset(&hints,0,sizeof(hints));
	hints.ai_family=PF_UNSPEC;
	hints.ai_socktype=SOCK_DGRAM;
	hints.ai_protocol=IPPROTO_UDP;
	s_error=getaddrinfo("127.0.0.1","123",&hints,&res);
*/
/*
         s_error = _xskt_getaddrinfo
                (
                    "10.74.52.92",
                    port,
                    &xskt_hints,
                    &pxskt_server_addrinfo
                );

        AnscTrace("!!!!!! _xskt_getaddrinfo returns: %d %s !!!\n", s_error, gai_strerror(s_error));
*/
        if ( _xskt_getaddrinfo
                (
                    pMyObject->GetPeerName((ANSC_HANDLE)pMyObject), 
                    port,
                    &xskt_hints,
                    &pxskt_server_addrinfo
                ) ||
             _xskt_getaddrinfo
                (
                    "localhost", 
                    NULL,
                    &xskt_hints,
                    &pxskt_client_addrinfo
                )

            )
        {
            AnscTrace("!!! error 1 !!!\n");

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	            	(
            		    pWorker->hWorkerContext,
            		    ANSC_SCTOWO_EVENT_SOCKET_ERROR,
            		    (ANSC_HANDLE)NULL
            		);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }

        AnscTrace("!!! after getaddrinfo !!!\n");
    }
    else
    {
        ansc_hints.ai_family   = AF_UNSPEC;
        ansc_hints.ai_socktype = ANSC_SOCKET_STREAM;
        ansc_hints.ai_flags    = AI_CANONNAME;

        usPort = pMyObject->GetPeerPort((ANSC_HANDLE)pMyObject);
        _ansc_sprintf(port, "%d", usPort);

        if ( _ansc_getaddrinfo
                (
                    pMyObject->GetPeerName((ANSC_HANDLE)pMyObject), 
                    port,
                    &ansc_hints,
                    &pansc_server_addrinfo
                ) ||
             _ansc_getaddrinfo
                (
                    "localhost", 
                    NULL,
                    &ansc_hints,
                    &pansc_client_addrinfo
                )
            )
        {
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	            	(
            		    pWorker->hWorkerContext,
		                ANSC_SCTOWO_EVENT_SOCKET_ERROR,
            	        (ANSC_HANDLE)NULL
	                );
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
    }

#endif

    /*
     * To engage the Tcp Client, we need to perform following acts in the respective order:
     *
     *      (1) create the os-dependent socket
     *      (2) bind to the newly socket
     *      (3) connect to the specified  server address
     *      (4) allocate a buffer for receiving
     *      (5) spawn a separate thread and start receiving
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        pMyObject->Socket = (ANSC_SOCKET)_xskt_socket(pxskt_server_addrinfo->ai_family, pxskt_server_addrinfo->ai_socktype, 0);
#else
        pMyObject->Socket = (ANSC_SOCKET)_xskt_socket(XSKT_SOCKET_AF_INET, XSKT_SOCKET_STREAM, 0);
#endif

        if ( (XSKT_SOCKET)pMyObject->Socket == XSKT_SOCKET_INVALID_SOCKET )
        {
            AnscTrace("!!!!!!!!!! _xskt_socket error !!!!!!!!!!\n");
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
        else  AnscTrace("Opening IPv4 socket Ok\n");
    }
    else
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        pMyObject->Socket = _ansc_socket(pansc_server_addrinfo->ai_family, pansc_server_addrinfo->ai_socktype, 0);
#else
        pMyObject->Socket = _ansc_socket(ANSC_SOCKET_AF_INET, ANSC_SOCKET_STREAM, 0);
#endif

        if ( pMyObject->Socket == ANSC_SOCKET_INVALID_SOCKET )
        {
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT1;
        }
    }
    /*
     * Normally we don't need to know which local network interface we shall bind to, and the
     * underlying operating system usually supports such notation as "any address".
     */
#ifndef _ANSC_IPV6_COMPATIBLE_
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        xskt_client_addr.sin_family = XSKT_SOCKET_AF_INET;
        xskt_client_addr.sin_port   = _xskt_htons(pMyObject->HostPort);

        if (pMyObject->bSocketBindToDevice && *(pMyObject->SocketDeviceName)) 
        {
            if (_xskt_setsocketopt
                    (
                         pMyObject->Socket, 
                         XSKT_SOCKET_SOL_SOCKET, 
                         XSKT_SOCKET_SO_BINDTODEVICE, 
                         pMyObject->SocketDeviceName, 
                         _ansc_strlen(pMyObject->SocketDeviceName) + 1
                    )
                < 0)
            {
                perror("setsockopt-SOL_SOCKET-SO_BINDTODEVICE");
                returnStatus = ANSC_STATUS_FAILURE;
                goto EXIT2;
            }
        }
        //        fprintf(stderr, "<RT XSKT> Binding socket to Device '%s'.\n", pMyObject->SocketDeviceName); 

        if ( pMyObject->HostAddress.Value == 0 )
        {
            ((pansc_socket_addr_in)&xskt_client_addr)->sin_addr.s_addr = XSKT_SOCKET_ANY_ADDRESS;
        }
        else
        {
            ((pansc_socket_addr_in)&xskt_client_addr)->sin_addr.s_addr = pMyObject->HostAddress.Value;
        }

        if ( _xskt_bind((XSKT_SOCKET)pMyObject->Socket, (xskt_socket_addr*)&xskt_client_addr, sizeof(xskt_client_addr)) != 0 )
        {
            AnscTrace("!!!!!!!!!! _xskt_bind error: socket=%d, error=%d !!!!!!!!!!\n", (XSKT_SOCKET)pMyObject->Socket, errno);
            {
                int j;                 
                char s[256];
                char *ptr1 = ((xskt_socket_addr*)(&xskt_client_addr))->sa_data;
                char stmp[16];

                s[0] = '\0';                  
                for(j=0; j<13; j++) {
                    sprintf(stmp, "%.2x:", *(ptr1++));
                    strcat(s, stmp);
                }
                sprintf(stmp, "%.2x", *ptr1); 
                strcat(s, stmp);
                AnscTrace("!!!!!!!!!! _xskt_bind error: client_addr=%s\n", s);
            }
            perror("_xskt_bind error");

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }
            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }
    else
    {
        ansc_client_addr.sin_family = ANSC_SOCKET_AF_INET;
        ansc_client_addr.sin_port   = _ansc_htons(pMyObject->HostPort);

        if (pMyObject->bSocketBindToDevice && *(pMyObject->SocketDeviceName)) 
        {
            if (_xskt_setsocketopt
                    (
                         pMyObject->Socket, 
                         ANSC_SOCKET_SOL_SOCKET, 
                         ANSC_SOCKET_SO_BINDTODEVICE, 
                         pMyObject->SocketDeviceName, 
                         _ansc_strlen(pMyObject->SocketDeviceName) + 1
                    )
                < 0)
            {
                perror("setsockopt-SOL_SOCKET-SO_BINDTODEVICE");
                returnStatus = ANSC_STATUS_FAILURE;
                goto EXIT2;
            }
        }
        // fprintf(stderr, "<RT AnscSKT> Binding socket to Device '%s'.\n", pMyObject->SocketDeviceName); 


        if ( pMyObject->HostAddress.Value == 0 )
        {
            ansc_client_addr.sin_addr.s_addr = ANSC_SOCKET_ANY_ADDRESS;
        }
        else
        {
            ansc_client_addr.sin_addr.s_addr = pMyObject->HostAddress.Value;
        }

        if ( _ansc_bind(pMyObject->Socket, (ansc_socket_addr*)&ansc_client_addr, sizeof(ansc_client_addr)) != 0 )
        {
            AnscTrace("!!!!!!!!!! _ansc_bind error: socket=%d, error=%d !!!!!!!!!!\n", (XSKT_SOCKET)pMyObject->Socket, errno);
            {
                int j;                 
                char s[256];
                char *ptr1 = ((ansc_socket_addr*)(&ansc_client_addr))->sa_data;
                char stmp[16];

                s[0] = '\0';                  
                for(j=0; j<13; j++) {
                    sprintf(stmp, "%.2x:", *(ptr1++));
                    strcat(s, stmp);
                }
                sprintf(stmp, "%.2x", *ptr1); 
                strcat(s, stmp);
                AnscTrace("!!!!!!!!!! _ansc_bind error: client_addr=%s\n", s);
            }
            perror("_ansc_bind error");

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_ERROR,
				    	(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }
#endif

    /*
     * As a Tcp client application, we now try to connect the network server, whose address is
     * specified by the "peer address" and "peer port" fields.
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
#ifdef _ANSC_IPV6_COMPATIBLE_
        BOOL                        bNoConn = TRUE;
#endif

        _ansc_memset(&xskt_server_addr, 0, sizeof(xskt_server_addr));
    	xskt_server_addr.sin_family                                 = XSKT_SOCKET_AF_INET;
        xskt_server_addr.sin_addr.s_addr  = pMyObject->PeerAddress.Value;
        xskt_server_addr.sin_port                                   = _xskt_htons(pMyObject->PeerPort);

#ifdef _ANSC_IPV6_COMPATIBLE_
        while ( bNoConn && pxskt_server_addrinfo )
        {
            if ( _xskt_connect((XSKT_SOCKET)pMyObject->Socket, pxskt_server_addrinfo->ai_addr, pxskt_server_addrinfo->ai_addrlen) != 0 )
            {
                pxskt_server_addrinfo = pxskt_server_addrinfo->ai_next;     /* try next ip address */
            }
            else
            {
                bNoConn = FALSE;
                break;
            }
        }

        if ( bNoConn )
#else
            if ( _xskt_connect((XSKT_SOCKET)pMyObject->Socket, (xskt_socket_addr*)&xskt_server_addr, sizeof(xskt_server_addr)) != 0 )
#endif
        {
            AnscTrace("!!!!!!!!!! _xskt_connect error: socket=%d, error=%d !!!!!!!!!!\n", (XSKT_SOCKET)pMyObject->Socket, errno);
            {
                int j;                 
                char s[256];
                char *ptr1 = ((xskt_socket_addr*)(&xskt_server_addr))->sa_data;
                char stmp[16];

                s[0] = '\0';                  
                for(j=0; j<13; j++) {
                    sprintf(stmp, "%.2x:", *(ptr1++));
                    strcat(s, stmp);
                }
                sprintf(stmp, "%.2x", *ptr1); 
                strcat(s, stmp);
                AnscTrace("!!!!!!!!!! _xskt_connect error: server_addr=%s\n", s);
            }
            perror("_xskt_connect error");

            s_error = _xskt_get_last_error();

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
	    			(
		    			pWorker->hWorkerContext,
			    		ANSC_SCTOWO_EVENT_SOCKET_TIMEOUT,
				    	(ANSC_HANDLE)NULL
    				);
            }
            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }
    else
    {
        _ansc_memset(&ansc_server_addr, 0, sizeof(ansc_server_addr));
        ansc_server_addr.sin_family      = ANSC_SOCKET_AF_INET;
        ansc_server_addr.sin_addr.s_addr = pMyObject->PeerAddress.Value;
        ansc_server_addr.sin_port        = _ansc_htons(pMyObject->PeerPort);

#ifdef _ANSC_IPV6_COMPATIBLE_
        if ( _ansc_connect(pMyObject->Socket, pansc_server_addrinfo->ai_addr, pansc_server_addrinfo->ai_addrlen) != 0 )
#else
        if ( _ansc_connect(pMyObject->Socket, (ansc_socket_addr*)&ansc_server_addr, sizeof(ansc_server_addr)) != 0 )
#endif
        {
            s_error = _ansc_get_last_error();

            AnscTrace("!!! Connect error: %d, %s !!!\n", s_error, strerror(s_error));

            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
				    (
			    		pWorker->hWorkerContext,
		    			ANSC_SCTOWO_EVENT_SOCKET_TIMEOUT,
	    				(ANSC_HANDLE)NULL
    				);
            }

            returnStatus = ANSC_STATUS_FAILURE;

            goto  EXIT2;
        }
    }

    /*
     * We have gone so far that all socket operations succeeded, we want to allocate a buffer that
     * is big enough for any incoming message.
     */
    if ( !pMyObject->RecvBuffer && !(pMyObject->Mode & ANSC_SCTO_MODE_FOREIGN_BUFFER) )
    {
        pMyObject->RecvBuffer     = AnscAllocateMemory(pMyObject->RecvBufferSize);
        pMyObject->RecvPacketSize = 0;
        pMyObject->RecvOffset     = 0;

        if ( !pMyObject->RecvBuffer )
        {
            returnStatus = ANSC_STATUS_RESOURCES;

            goto  EXIT2;
        }
    }

    pMyObject->RecvBytesCount = 0;
    pMyObject->SendBytesCount = 0;
    pMyObject->LastRecvAt     = AnscGetTickInSeconds();
    pMyObject->LastSendAt     = AnscGetTickInSeconds();

    /*
     * If the compilation option '_ANSC_SOCKET_TLS_LAYER_' is enabled, we can simply let the ANSC
     * socket layer to perform the SSL/TLS functionality; otherwise, we need to prepare for doing
     * SSL/TLS internally.
     */
    if ( pMyObject->Mode & ANSC_SCTO_MODE_TLS_ENABLED )
    {
#ifdef _ANSC_USE_OPENSSL_
        pMyObject->bTlsEnabled = TRUE;
        if ( !openssl_init(SSL_CLIENT_CALLS) )
        {
            AnscTrace("AnscSctoEngage - openssl_init() failed!\n");
            returnStatus = ANSC_STATUS_FAILURE;
            goto  EXIT2;
        }

#else
        #ifdef  _ANSC_SOCKET_TLS_LAYER_
        {
            _ansc_en_usetls(pMyObject->Socket);

            pMyObject->bTlsEnabled = FALSE;
        }
        #else
        {
            pMyObject->hTlsScsIf   = (pMyObject->hTlsScsIf != NULL)? pMyObject->hTlsScsIf : AnscSocketTlsGetScsIf();
            pMyObject->bTlsEnabled = TRUE;
        }
        #endif
#endif
    }

    /*
     * To save the worker object from having to deal with blocking/non-blocking/async receiving
     * functions provided by underlying socket layer, we create a separate task to do that.
     */
    returnStatus =
        pMyObject->SpawnTask3
            (
                (ANSC_HANDLE)pMyObject,
                (void*      )pMyObject->RecvTask,
                (ANSC_HANDLE)pMyObject,
                ANSC_SCTO_RECV_TASK_NAME,
                USER_DEFAULT_TASK_PRIORITY,
                11*USER_DEFAULT_TASK_STACK_SIZE

            );
#ifdef _ANSC_USE_OPENSSL_
    if ( pMyObject->bTlsEnabled )
    {
   	    SSL *ssl = NULL;
   	    ssl = openssl_connect (pMyObject->Socket);
	    if ( !ssl )
		{

	        pMyObject->bTlsConnected = FALSE;
	        returnStatus = ANSC_STATUS_FAILURE;

	        //PANSC_SCTO_WORKER_OBJECT        pWorker      = (PANSC_SCTO_WORKER_OBJECT)pMyObject->hWorker;
            if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
            {
                pWorker->Notify
                    (
                        pWorker->hWorkerContext,
                        ANSC_SCTOWO_EVENT_TLS_ERROR,
                        (ANSC_HANDLE)0L
                    );
            }
		}
	    else
	    {
			s_error = openssl_validate_certificate (pMyObject->Socket, pMyObject->HostName, ssl, SSL_CLIENT_CALLS);
		    if ( s_error == 0 )
		    {
		        AnscTrace("AnscSctoEngage - openssl_validate_certificate() failed %p.\n", ssl);

		        //PANSC_SCTO_WORKER_OBJECT        pWorker      = (PANSC_SCTO_WORKER_OBJECT      )pMyObject->hWorker;
                if ( pMyObject->Mode & ANSC_SCTO_MODE_NO_BSP_NOTIFY_CONN_ERR == 0 )
                {
	                pWorker->Notify
	                    (
	                        pWorker->hWorkerContext,
	                        ANSC_SCTOWO_EVENT_TLS_ERROR,
	                        (ANSC_HANDLE)NULL
	                    );
                }
		        returnStatus = ANSC_STATUS_FAILURE;
		    }

		    pMyObject->hTlsConnection = ssl;
		    pMyObject->bTlsConnected = TRUE;
	    }
    }
#else
    /*
     * If SSL/TLS is enabled, we should complete TLS handshake before returning from Engage(). This
     * behavior allows a single consistent API to used between this object and the worker object.
     * Since the handshake will take multiple messages to complete, we need to block the current
     * task until being notified by the TLS module.
     */
    if ( pMyObject->bTlsEnabled && pMyObject->hTlsScsIf )
    {
        pMyObject->bTlsConnected = FALSE;

        pMyObject->InitTlsClient((ANSC_HANDLE)pMyObject);
    }
#endif

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
    	goto  EXIT2;
    }

    return  ANSC_STATUS_SUCCESS;


    /******************************************************************
                GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS
    ******************************************************************/

EXIT2:

	AnscTrace("AnscSctoEngage - failed with status %lu, socket error %d!\n", returnStatus, s_error);

    if ( pMyObject->Mode & ANSC_SCTO_MODE_XSOCKET )
    {
        _xskt_closesocket((XSKT_SOCKET)pMyObject->Socket);
    }
    else
    {
        _ansc_closesocket(pMyObject->Socket);
    }

EXIT1:

    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        pMyObject->bActive = FALSE;

        pMyObject->Reset((ANSC_HANDLE)pMyObject);
    }

    return  returnStatus;
}
ANSC_STATUS
AnscDsuoAcceptTask
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus  = ANSC_STATUS_SUCCESS;
    PANSC_DAEMON_SERVER_UDP_OBJECT  pMyObject     = (PANSC_DAEMON_SERVER_UDP_OBJECT)hThisObject;
    PANSC_DSUO_WORKER_OBJECT        pWorker       = (PANSC_DSUO_WORKER_OBJECT      )pMyObject->hWorker;
    PANSC_DAEMON_ENGINE_UDP_OBJECT  pCurEngine    = NULL;
    PANSC_DSUO_PACKET_OBJECT        pNewPacket    = NULL;
    int                             s_result      = 0;
    int                             s_error       = 0;
    char*                           recv_buffer   = NULL;
    int                             recv_size     = 0;
    ansc_fd_set                     read_fd_set;
    xskt_fd_set                     read_fd_set2;
    ansc_timeval                    timeval;
    xskt_timeval                    timeval2;
    ansc_socket_addr_in             client_addr;
    xskt_socket_addr_in             client_addr2;
    int                             addrlen;

    AnscTrace("AnscDsuoAcceptTask is activated ...!\n");

    /*
     * As a scalable server implemention, we shall accept as many incoming client connections as
     * possible and can only be limited by the system resources. Once the listening socket becomes
     * readable, which means an incoming connection attempt has arrived. We create a new socket
     * object and associate it with the client. This is a repeated process until the socket owner
     * closes the socket.
     */
    while ( pMyObject->bActive )
    {
        ANSC_COMMIT_TASK();
        
        /*
         * Since the original bsd compatible socket api doesn't support asynchronous operation, the
         * nonblocking status polling is the best we can get. As a matter of fact, the current unix
         * and linux actually still don't support asynchronous notification on any socket operation.
         */

        /*
         * Since only one socket is included in the fd_set, we only distinguish the result between
         * one and non-one values. If error is detected, we shall close the socket and notify the
         * socket owner immediately.
         */
        if ( pMyObject->Mode & ANSC_DSUO_MODE_XSOCKET )
        {
            XSKT_SOCKET_FD_ZERO(&read_fd_set2);
            XSKT_SOCKET_FD_SET ((XSKT_SOCKET)pMyObject->Socket, &read_fd_set2);
            timeval2.tv_sec  = (ANSC_DSUO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval2.tv_usec = (ANSC_DSUO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */

            s_result = _xskt_select(pMyObject->Socket + 1, &read_fd_set2, NULL, NULL, &timeval2);
        }
        else
        {
            ANSC_SOCKET_FD_ZERO(&read_fd_set);
            ANSC_SOCKET_FD_SET (pMyObject->Socket, &read_fd_set);
            timeval.tv_sec  = (ANSC_DSUO_POLL_INTERVAL_MS / 1000);          /* number of seconds      */
            timeval.tv_usec = (ANSC_DSUO_POLL_INTERVAL_MS % 1000) * 1000;   /* number of microseconds */

            s_result = _ansc_select(pMyObject->Socket + 1, &read_fd_set, NULL, NULL, &timeval);
        }

        if ( s_result == 0 )
        {
            continue;
        }
        else if ( s_result == ANSC_SOCKET_ERROR )
        {
            s_error = _ansc_get_last_error();

            continue;
        }

        /*
         * According to de facto standards of bsd compatible socket api, if the socket is currently
         * in the listen state, it will be marked as readable if an incoming connection request has
         * been received such that an accept is guaranteed to complete without blocking.
         */

        pNewPacket =
            (PANSC_DSUO_PACKET_OBJECT)pMyObject->AcquirePacket
                (
                    (ANSC_HANDLE)pMyObject
                );

        if ( !pNewPacket )
        {
            continue;
        }
        else
        {
            recv_buffer = pNewPacket->RecvBuffer;
            recv_size   = pNewPacket->RecvBufferSize;
        }

        if ( pMyObject->Mode & ANSC_DSUO_MODE_XSOCKET )
        {
            client_addr2.sin_family                                 = ANSC_SOCKET_AF_INET;
            ((pansc_socket_addr_in)&client_addr2)->sin_addr.s_addr  = 0;
            client_addr2.sin_port                                   = _xskt_htons(pMyObject->HostPort);
            addrlen                                                 = sizeof(client_addr2);
            s_result = _xskt_recvfrom(pMyObject->Socket, recv_buffer, recv_size, 0, (xskt_socket_addr*)&client_addr2, &addrlen);
        }
        else
        {
            client_addr.sin_family      = ANSC_SOCKET_AF_INET;
            client_addr.sin_addr.s_addr = 0;
            client_addr.sin_port        = _ansc_htons(pMyObject->HostPort);
            addrlen                     = sizeof(client_addr);
            s_result = _ansc_recvfrom(pMyObject->Socket, recv_buffer, recv_size, 0, (ansc_socket_addr*)&client_addr, &addrlen);
        }

        if ( s_result == ANSC_SOCKET_ERROR )
        {
            s_error = _ansc_get_last_error();

            returnStatus =
                pMyObject->ReleasePacket
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pNewPacket
                    );

            continue;
        }
        else if ( !pMyObject->bActive )
        {
            returnStatus =
                pMyObject->ReleasePacket
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pNewPacket
                    );

            break;
        }
        else
        {
            recv_size = s_result;
        }

        if ( pMyObject->Mode & ANSC_DSUO_MODE_XSOCKET )
        {
            pNewPacket->PeerAddress.Value = ((pansc_socket_addr_in)&client_addr2)->sin_addr.s_addr;
            pNewPacket->PeerPort          = _ansc_ntohs(client_addr2.sin_port);
        }
        else
        {
            pNewPacket->PeerPort          = _ansc_ntohs(client_addr.sin_port);
            pNewPacket->PeerAddress.Value = client_addr.sin_addr.s_addr;
        }
        pNewPacket->RecvPacketSize    = (ULONG)recv_size;
        pNewPacket->RecvAt            = AnscGetTickInSeconds();

        /*
         * We have to assign an engine object to this new packet object. The assignment is done by
         * address-hashing. However, we need to make sure that the assigned engine object is not
         * over-loaded. If it is, there're nothing we can do except throwing the packet away.
         */
        pCurEngine =
            (PANSC_DAEMON_ENGINE_UDP_OBJECT)pMyObject->AssignEngine
                (
                    (ANSC_HANDLE)pMyObject,
                    (ANSC_HANDLE)pNewPacket
                );

        if ( !pCurEngine )
        {
            returnStatus =
                pMyObject->ReleasePacket
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pNewPacket
                    );

            continue;
        }
        else
        {
            returnStatus =
                pCurEngine->AddPacket
                    (
                        (ANSC_HANDLE)pCurEngine,
                        (ANSC_HANDLE)pNewPacket
                    );
        }

        if ( returnStatus != ANSC_STATUS_SUCCESS )
        {
            returnStatus =
                pMyObject->ReleasePacket
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pNewPacket
                    );
        }
    }

    AnscSetEvent(&pMyObject->AcceptEvent);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
BbhmDiageoResultQueryTask
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus        = ANSC_STATUS_SUCCESS;
    PBBHM_DIAG_EXEC_OBJECT          pMyObject           = (PBBHM_DIAG_EXEC_OBJECT     )hThisObject;
    PDSLH_DIAG_INFO_BASE            pDiagInfo           = NULL;
    BOOLEAN                         bQueryDone          = FALSE;

    AnscTraceFlow(("BbhmDiageoResultQueryTask ...\n"));

    do
    {
        returnStatus = pMyObject->RetrieveResult((ANSC_HANDLE)pMyObject);

        if ( returnStatus == ANSC_STATUS_SUCCESS )
        {
            pDiagInfo  = (PDSLH_DIAG_INFO_BASE)pMyObject->hDslhDiagInfo;
            bQueryDone = TRUE;

            if ( (pDiagInfo->DiagnosticState != DSLH_DIAG_STATE_TYPE_Inprogress)
                  && (pDiagInfo->DiagnosticState != DSLH_DIAG_STATE_TYPE_Requested) )
            {
                pMyObject->ResultTimestamp = AnscGetTickInSeconds();
                break;
            }
        }
        else
        {
            /* internal error occurs, quit immediatelly */
            break;
        }

        AnscWaitEvent(&pMyObject->ResultQueryEvent, 1000);
    }
    while ( pMyObject->bResultQueryRunning );

    if ( TRUE/*pDiagInfo->RequestType == DSLH_DIAGNOSTIC_REQUEST_TYPE_Acs*/ )
    {
        /* Always notify the initiator */
        CcspTraceInfo(("BbhmDiageoResultQueryTask -- notify initiator.....\n"));

        /* send out the notification */
        if ( ANSC_STATUS_SUCCESS != CosaSendDiagCompleteSignal() )
        {
            AnscTraceWarning(("Failed to send event for diagnostics completion.\n"));
        }
    }

    AnscAcquireLock(&pMyObject->AccessLock);

    AnscTraceFlow(("BbhmDiageoResultQueryTask -- quiting...\n"));

    /*
     *  stop the diagnostic process
     */
    pMyObject->bResultQueryRunning  = FALSE;

    if ( !bQueryDone )
    {
        pMyObject->StopDiag((ANSC_HANDLE)pMyObject);
    }

    AnscSetEvent(&pMyObject->ResultQueryExitEvent);

    AnscReleaseLock(&pMyObject->AccessLock);

    AnscTraceFlow(("BbhmDiageoStartDiag -- exit...\n"));

    return  ANSC_STATUS_SUCCESS;
}
Пример #28
0
ANSC_STATUS
BwrmPmoInitialize
    (
        ANSC_HANDLE                 hThisObject
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PBWRM_PAGE_MANAGER_OBJECT       pMyObject    = (PBWRM_PAGE_MANAGER_OBJECT)hThisObject;
    ULONG                           i            = 0;

    /*
     * Until you have to simulate C++ object-oriented programming style with standard C, you don't
     * appreciate all the nice little things come with C++ language and all the dirty works that
     * have been done by the C++ compilers. Member initialization is one of these things. While in
     * C++ you don't have to initialize all the member fields inherited from the base class since
     * the compiler will do it for you, such is not the case with C.
     */
    AnscCoInitialize((ANSC_HANDLE)pMyObject);

    /*
     * Although we have initialized some of the member fields in the "create" member function, we
     * repeat the work here for completeness. While this simulation approach is pretty stupid from
     * a C++/Java programmer perspective, it's the best we can get for universal embedded network
     * programming. Before we develop our own operating system (don't expect that to happen any
     * time soon), this is the way things gonna be.
     */
    pMyObject->Oid                = BWRM_PAGE_MANAGER_OID;
    pMyObject->Create             = BwrmPmoCreate;
    pMyObject->Remove             = BwrmPmoRemove;
    pMyObject->EnrollObjects      = BwrmPmoEnrollObjects;
    pMyObject->Initialize         = BwrmPmoInitialize;

    pMyObject->Timestamp          = AnscGetTickInSeconds();
    pMyObject->bActive            = FALSE;

    pMyObject->GetCacheEnabled    = BwrmPmoGetCacheEnabled;
    pMyObject->SetCacheEnabled    = BwrmPmoSetCacheEnabled;
    pMyObject->GetCacheEntryCount = BwrmPmoGetCacheEntryCount;
    pMyObject->SetCacheEntryCount = BwrmPmoSetCacheEntryCount;
    pMyObject->GetCacheMemorySize = BwrmPmoGetCacheMemorySize;
    pMyObject->SetCacheMemorySize = BwrmPmoSetCacheMemorySize;
    pMyObject->GetCacheTimeout    = BwrmPmoGetCacheTimeout;
    pMyObject->SetCacheTimeout    = BwrmPmoSetCacheTimeout;

    pMyObject->GetProperty        = BwrmPmoGetProperty;
    pMyObject->SetProperty        = BwrmPmoSetProperty;
    pMyObject->ResetProperty      = BwrmPmoResetProperty;
    pMyObject->Reset              = BwrmPmoReset;

    pMyObject->Engage             = BwrmPmoEngage;
    pMyObject->Cancel             = BwrmPmoCancel;
    pMyObject->CacheTimerInvoke   = BwrmPmoCacheTimerInvoke;

    pMyObject->GetPageCount       = BwrmPmoGetPageCount;
    pMyObject->GetOldestPage      = BwrmPmoGetOldestPage;
    pMyObject->GetPage            = BwrmPmoGetPage;
    pMyObject->AddPage            = BwrmPmoAddPage;
    pMyObject->DelPage            = BwrmPmoDelPage;
    pMyObject->DelAllPages        = BwrmPmoDelAllPages;

    for ( i = 0; i < BWRM_PMO_CPO_TABLE_SIZE; i++ )
    {
        AnscSListInitializeHeader(&pMyObject->CpoTable[i]);
    }
    AnscInitializeLock(&pMyObject->CpoTableLock);

    /*
     * We shall initialize the configuration properties to the default values, which may be changed
     * later via the set_property() member function. Note that this call may not guarantee a valid
     * and legtimate configuration.
     */
    pMyObject->ResetProperty((ANSC_HANDLE)pMyObject);

    return  ANSC_STATUS_SUCCESS;
}
ANSC_STATUS
CcspCwmpsoAddCwmpEvent
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hCwmpEvent,
        BOOL                        bConnectNow
    )
{
    ANSC_STATUS                     returnStatus       = ANSC_STATUS_SUCCESS;
    PCCSP_CWMP_SESSION_OBJECT       pMyObject          = (PCCSP_CWMP_SESSION_OBJECT   )hThisObject;
    PCCSP_CWMP_PROCESSOR_OBJECT     pCcspCwmpProcessor = (PCCSP_CWMP_PROCESSOR_OBJECT )pMyObject->hCcspCwmpProcessor;
    PCCSP_CWMP_EVENT                pCcspCwmpEvent     = (PCCSP_CWMP_EVENT           )hCwmpEvent;
    PCCSP_CWMP_EVENT                pCcspCwmpEventExist= (PCCSP_CWMP_EVENT           )NULL;
    BOOL                            bExist             = FALSE;
    ULONG                           i                  = 0;

    if ( pMyObject->EventCount >= CCSP_CWMPSO_MAX_EVENT_NUMBER )
    {
        CcspCwmpFreeEvent(pCcspCwmpEvent);
	}
	else
	{
        /*
         *  Bin Zhu updated here on 12/18/2006
         *  According to WT151, for all the single event (starts with a number "0" - "9"),
         *  If there's only already in the array, the new one will be discarded.
         */
        if( pCcspCwmpEvent->EventCode[0] >= '0' && pCcspCwmpEvent->EventCode[0] <= '9')
        {
            for( i = 0; i < pMyObject->EventCount; i ++)
            {
                pCcspCwmpEventExist = (PCCSP_CWMP_EVENT)pMyObject->EventArray[i];

                if( AnscEqualString(pCcspCwmpEvent->EventCode, pCcspCwmpEventExist->EventCode, TRUE))
                {
                    bExist = TRUE;

                    CcspTr069PaTraceWarning(("The event '%s' is already there, discarded.\n", pCcspCwmpEvent->EventCode));

                    break;
                }
            }
        } 
        else 
        if ( pCcspCwmpEvent->EventCode[0] >= 'M' )
        {
            for( i = 0; i < pMyObject->EventCount; i ++)
            {
                pCcspCwmpEventExist = (PCCSP_CWMP_EVENT)pMyObject->EventArray[i];

                if ( AnscEqualString(pCcspCwmpEvent->EventCode, pCcspCwmpEventExist->EventCode, TRUE) &&
                     ( (!pCcspCwmpEvent->CommandKey && !pCcspCwmpEventExist->CommandKey) || 
                        (pCcspCwmpEvent->CommandKey && pCcspCwmpEventExist->CommandKey &&
                         AnscEqualString(pCcspCwmpEvent->CommandKey, pCcspCwmpEventExist->CommandKey, TRUE)) ) )
                {
                    bExist = TRUE;

                    CcspTr069PaTraceWarning
                        ((
                            "The event '%s' with CommandKey '%s' is already there, discarded.\n", 
                            pCcspCwmpEvent->EventCode,
                            pCcspCwmpEvent->CommandKey
                        ));

                    break;
                }
            }
        }

        if( !bExist )
        {
  		    pMyObject->EventArray[pMyObject->EventCount++] = (ANSC_HANDLE)pCcspCwmpEvent;
            CcspTr069PaTraceDebug(("<RT> Event '%s' with CommandKey '%s' added at location '%d'\n",
                                   pCcspCwmpEvent->EventCode, pCcspCwmpEvent->CommandKey, pMyObject->EventCount));
        }
        else
        {
            CcspCwmpFreeEvent(pCcspCwmpEvent);
        }
	}

    if ( bConnectNow )
    {
		PANSC_TIMER_DESCRIPTOR_OBJECT   pDelayedActiveNotifTimerObj
                                                        = (PANSC_TIMER_DESCRIPTOR_OBJECT)pMyObject->hDelayedActiveNotifTimerObj;
    	PCCSP_CWMP_PROCESSOR_PROPERTY   pProperty       = (PCCSP_CWMP_PROCESSOR_PROPERTY)&pCcspCwmpProcessor->Property;
		BOOL							bInformDelayed  = FALSE;
        PCCSP_CWMP_EVENT                pFirstEvent     = (PCCSP_CWMP_EVENT)pMyObject->EventArray[0];
	
		/* Active Notification Throttling */	
		if ( pMyObject->EventCount == 1 /* "4 VALUE CHANGE" event is the only one to trigger Inform */ && 
			 AnscEqualString(pFirstEvent->EventCode, CCSP_CWMP_INFORM_EVENT_NAME_ValueChange, TRUE) &&
			 pProperty->DefActiveNotifThrottle != 0 && 
			 pProperty->LastActiveNotifTime != 0 )
		{
			/* calculate the delay inform timer interval */
			ULONG						ulTimeNow = AnscGetTickInSeconds();
			ULONG						ulDelta   = 0;
			ULONG						ulInterval= 0;

			if ( ulTimeNow >= pProperty->LastActiveNotifTime )
			{
				ulDelta = ulTimeNow - pProperty->LastActiveNotifTime;
			}
			else
			{
				ulDelta = 0xFFFFFFFF - pProperty->LastActiveNotifTime + ulTimeNow;
			}

			if ( ulDelta < pProperty->DefActiveNotifThrottle )
			{
				bInformDelayed = TRUE;

				ulInterval = pProperty->DefActiveNotifThrottle - ulDelta;
 
    			CcspTr069PaTraceDebug(("Active notification will be delayed by %u seconds\n", ulInterval));

                if ( !pMyObject->bDelayedActiveNotifTimerScheduled )
                {
		            pDelayedActiveNotifTimerObj->SetInterval((ANSC_HANDLE)pDelayedActiveNotifTimerObj, ulInterval * 1000);
	    	        pDelayedActiveNotifTimerObj->Start((ANSC_HANDLE)pDelayedActiveNotifTimerObj);
    				pMyObject->bDelayedActiveNotifTimerScheduled = TRUE;
                }
 			}
		}


		if ( !bInformDelayed )
		{
            ULONG                   ulActiveSessions    = pCcspCwmpProcessor->GetActiveWmpSessionCount((ANSC_HANDLE)pCcspCwmpProcessor, TRUE);

            if ( ulActiveSessions == 0 )
            {
        	    pMyObject->SessionState = CCSP_CWMPSO_SESSION_STATE_connectNow;
    	        returnStatus            =
        	        pCcspCwmpProcessor->SignalSession
            	        (
                	        (ANSC_HANDLE)pCcspCwmpProcessor,
                    	    (ANSC_HANDLE)pMyObject
	                    );
            }
            else
            {
                pMyObject->bInformWhenActive = TRUE;
            }
		}
    }

    return 	returnStatus; 
}
ANSC_STATUS
AnscSctoTsaRecvAppMessage
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hMessageBdo
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PANSC_SIMPLE_CLIENT_TCP_OBJECT  pMyObject    = (PANSC_SIMPLE_CLIENT_TCP_OBJECT)hThisObject;
    PANSC_SCTO_WORKER_OBJECT        pWorker      = (PANSC_SCTO_WORKER_OBJECT      )pMyObject->hWorker;
    PANSC_BUFFER_DESCRIPTOR         pPayloadBdo  = (PANSC_BUFFER_DESCRIPTOR       )hMessageBdo;
    void*                           pRecvBuffer  = (void*                         )NULL;
    ANSC_HANDLE                     hRecvHandle  = (ANSC_HANDLE                   )NULL;
    ULONG                           ulRecvSize   = (ULONG                         )0;
    ULONG                           ulLeftSize   = (ULONG                         )AnscBdoGetBlockSize(pPayloadBdo);
    ULONG                           ulCopySize   = (ULONG                         )0;

    while ( ulLeftSize > 0 )
    {
        pRecvBuffer =
            pMyObject->GetRecvBuffer
                (
                    (ANSC_HANDLE)pMyObject,
                    &ulRecvSize
                );

        if ( !pRecvBuffer )
        {
            returnStatus =
                pWorker->Notify
                    (
                        pWorker->hWorkerContext,
                        ANSC_SCTOWO_EVENT_RESOURCES,
                        (ANSC_HANDLE)NULL
                    );

            break;
        }

        if ( ulRecvSize >= ulLeftSize )
        {
            ulCopySize = ulLeftSize;
        }
        else
        {
            ulCopySize = ulRecvSize;
        }

        if ( TRUE )
        {
            AnscCopyMemory
                (
                    pRecvBuffer,
                    AnscBdoGetBlock(pPayloadBdo),
                    ulCopySize
                );

            AnscBdoShrinkRight(pPayloadBdo, ulCopySize);

            ulLeftSize -= ulCopySize;
        }

        pMyObject->RecvBytesCount += ulCopySize;
        pMyObject->LastRecvAt      = AnscGetTickInSeconds();

        returnStatus =
            pMyObject->Recv
                (
                    (ANSC_HANDLE)pMyObject,
                    pRecvBuffer,
                    ulCopySize
                );
    }

    goto  EXIT1;


    /******************************************************************
                GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS
    ******************************************************************/

EXIT1:

    if ( pPayloadBdo )
    {
        AnscFreeBdo((ANSC_HANDLE)pPayloadBdo);
    }

    return  returnStatus;
}