ANSC_STATUS AnscDetoStart ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject; if ( pMyObject->bStarted ) { return ANSC_STATUS_SUCCESS; } else { pMyObject->Reset((ANSC_HANDLE)pMyObject); pMyObject->StartTime = AnscGetTickInSecondsAbs(); pMyObject->bStarted = TRUE; } if ( TRUE ) { AnscResetEvent(&pMyObject->RecvEvent); returnStatus = AnscSpawnTask3 ( (void*)pMyObject->RecvTask, (ANSC_HANDLE)pMyObject, ANSC_DETO_RECV_TASK_NAME, ANSC_TASK_PRIORITY_NORMAL, ANSC_DETO_RECV_TASK_STACK_SIZE ); } if ( pMyObject->ControlFlags & ANSC_DETO_FLAG_ASYNC_SEND ) { AnscResetEvent(&pMyObject->SendEvent); returnStatus = AnscSpawnTask ( (void*)pMyObject->SendTask, (ANSC_HANDLE)pMyObject, ANSC_DETO_SEND_TASK_NAME ); } return ANSC_STATUS_SUCCESS; }
ANSC_STATUS BbhmDiageoStartDiag ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PBBHM_DIAG_EXEC_OBJECT pMyObject = (PBBHM_DIAG_EXEC_OBJECT)hThisObject; PDSLH_DIAG_INFO_BASE pDiagInfo = (PDSLH_DIAG_INFO_BASE )pMyObject->hDslhDiagInfo; AnscAcquireLock(&pMyObject->AccessLock); pDiagInfo->DiagnosticState = DSLH_DIAG_STATE_TYPE_Inprogress; pMyObject->bResultQueryRunning = TRUE; AnscResetEvent(&pMyObject->ResultQueryEvent); AnscReleaseLock(&pMyObject->AccessLock); returnStatus = AnscSpawnTask2 ( pMyObject->ResultQueryTask, (ANSC_HANDLE)pMyObject, "BbhmDiagTask", ANSC_TASK_PRIORITY_NORMAL ); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDeuoStart ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_UDP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_UDP_OBJECT)hThisObject; if ( pMyObject->bStarted ) { return ANSC_STATUS_SUCCESS; } else { pMyObject->bStarted = TRUE; } pMyObject->Reset((ANSC_HANDLE)pMyObject); if ( TRUE ) { AnscResetEvent(&pMyObject->RecvEvent); returnStatus = AnscSpawnTask ( (void*)pMyObject->RecvTask, (ANSC_HANDLE)pMyObject, ANSC_DEUO_RECV_TASK_NAME ); } if ( pMyObject->ControlFlags & ANSC_DEUO_FLAG_ASYNC_SEND ) { AnscResetEvent(&pMyObject->SendEvent); returnStatus = AnscSpawnTask ( (void*)pMyObject->SendTask, (ANSC_HANDLE)pMyObject, ANSC_DEUO_SEND_TASK_NAME ); } return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscSctoInitTlsClient ( 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; PTLS_SCS_INTERFACE pTlsScsIf = (PTLS_SCS_INTERFACE )pMyObject->hTlsScsIf; PTLS_TSA_INTERFACE pTlsTsaIf = (PTLS_TSA_INTERFACE )pMyObject->hTlsTsaIf; TLS_CONNECTION_PARAMS tlsConnParams; if ( !pMyObject->bTlsEnabled || !pTlsScsIf ) { return ANSC_STATUS_UNAPPLICABLE; } if ( TRUE ) { TlsInitConnParams((&tlsConnParams)); tlsConnParams.bSessionSharing = TRUE; tlsConnParams.bQuickHandshake = TRUE; tlsConnParams.bReqCertificate = FALSE; tlsConnParams.bTlsClient = TRUE; tlsConnParams.HostID = pMyObject->HostAddress.Value; tlsConnParams.PeerID = pMyObject->PeerAddress.Value; tlsConnParams.SessionIDSize = 0; tlsConnParams.CipherSuiteCount = 0; tlsConnParams.CompressionCount = 0; } pMyObject->hTlsConnection = pTlsScsIf->CreateConnection ( pTlsScsIf->hOwnerContext, (ANSC_HANDLE)pTlsTsaIf ); if ( !pMyObject->hTlsConnection ) { return ANSC_STATUS_UNAPPLICABLE; } else { returnStatus = pTlsScsIf->ConfigConnection ( pTlsScsIf->hOwnerContext, pMyObject->hTlsConnection, (ANSC_HANDLE)&tlsConnParams ); } AnscResetEvent(&pMyObject->TlsConnEvent); returnStatus = pTlsScsIf->StartConnection ( pTlsScsIf->hOwnerContext, pMyObject->hTlsConnection ); if ( returnStatus == ANSC_STATUS_SUCCESS ) { AnscWaitEvent(&pMyObject->TlsConnEvent, 0xFFFFFFFF); } if ( !pMyObject->bTlsConnected ) { returnStatus = pTlsScsIf->RemoveConnection ( pTlsScsIf->hOwnerContext, pMyObject->hTlsConnection ); pMyObject->hTlsConnection = (ANSC_HANDLE)NULL; returnStatus = ANSC_STATUS_FAILURE; } else { returnStatus = ANSC_STATUS_SUCCESS; } return returnStatus; }
ANSC_STATUS StunScoInitialize ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PSTUN_SIMPLE_CLIENT_OBJECT pMyObject = (PSTUN_SIMPLE_CLIENT_OBJECT)hThisObject; /* * 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 = STUN_SIMPLE_CLIENT_OID; pMyObject->Create = StunScoCreate; pMyObject->Remove = StunScoRemove; pMyObject->EnrollObjects = StunScoEnrollObjects; pMyObject->Initialize = StunScoInitialize; pMyObject->hStunBsmIf = (ANSC_HANDLE)NULL; pMyObject->AsyncTaskCount = 0; pMyObject->bActive = FALSE; pMyObject->ClientStage = STUN_SCO_CLIENT_STAGE_None; pMyObject->ClientState = STUN_SCO_CLIENT_STATE_Idle; pMyObject->SocketState1 = STUN_SCO_SOCKET_STATE_Idle; pMyObject->SocketStateA = STUN_SCO_SOCKET_STATE_Idle; pMyObject->SocketStateB = STUN_SCO_SOCKET_STATE_Idle; pMyObject->RetransInterval1 = STUN_MIN_RETRANSMISSION_INTERVAL; pMyObject->RetransTime1 = 0; pMyObject->LastSendMsg1 = NULL; pMyObject->LastMsgSize1 = 0; pMyObject->bMsgIntegrity1 = FALSE; pMyObject->bMsgIntegrityA = FALSE; pMyObject->bMsgIntegrityB = FALSE; pMyObject->GetStunBsmIf = StunScoGetStunBsmIf; pMyObject->SetStunBsmIf = StunScoSetStunBsmIf; pMyObject->GetClientAddr = StunScoGetClientAddr; pMyObject->SetClientAddr = StunScoSetClientAddr; pMyObject->GetClientPort = StunScoGetClientPort; pMyObject->SetClientPort = StunScoSetClientPort; pMyObject->GetServerAddr = StunScoGetServerAddr; pMyObject->SetServerAddr = StunScoSetServerAddr; pMyObject->GetServerPort = StunScoGetServerPort; pMyObject->SetServerPort = StunScoSetServerPort; pMyObject->GetUsername = StunScoGetUsername; pMyObject->SetUsername = StunScoSetUsername; pMyObject->GetPassword = StunScoGetPassword; pMyObject->SetPassword = StunScoSetPassword; pMyObject->GetMinKeepAliveInterval = StunScoGetMinKeepAliveInterval; pMyObject->SetMinKeepAliveInterval = StunScoSetMinKeepAliveInterval; pMyObject->GetMaxKeepAliveInterval = StunScoGetMaxKeepAliveInterval; pMyObject->SetMaxKeepAliveInterval = StunScoSetMaxKeepAliveInterval; pMyObject->GetProperty = StunScoGetProperty; pMyObject->SetProperty = StunScoSetProperty; pMyObject->ResetProperty = StunScoResetProperty; pMyObject->Reset = StunScoReset; pMyObject->Engage = StunScoEngage; pMyObject->Cancel = StunScoCancel; pMyObject->StageTimerInvoke = StunScoStageTimerInvoke; pMyObject->RetryTimerInvoke = StunScoRetryTimerInvoke; pMyObject->ProbeTimerInvoke = StunScoProbeTimerInvoke; pMyObject->PlayRole1 = StunScoPlayRole1; pMyObject->DiscoverBinding = StunScoDiscoverBinding; pMyObject->DiscoverBindingTimeoutA = StunScoDiscoverBindingTimeoutA; pMyObject->DiscoverBindingTimeoutB = StunScoDiscoverBindingTimeoutB; pMyObject->MaintainBinding = StunScoMaintainBinding; pMyObject->NotifyBindingChange = StunScoNotifyBindingChange; pMyObject->AsyncDiscoverTask = StunScoAsyncDiscoverTask; pMyObject->RecvBindingResponse1 = StunScoRecvBindingResponse1; pMyObject->RecvBindingResponseA = StunScoRecvBindingResponseA; pMyObject->RecvBindingResponseB = StunScoRecvBindingResponseB; pMyObject->RecvBindingErrorResponse1 = StunScoRecvBindingErrorResponse1; pMyObject->RecvBindingErrorResponseA = StunScoRecvBindingErrorResponseA; pMyObject->RecvBindingErrorResponseB = StunScoRecvBindingErrorResponseB; pMyObject->VerifyMsgIntegrity = StunScoVerifyMsgIntegrity; pMyObject->SendBindingRequest1 = StunScoSendBindingRequest1; pMyObject->SendBindingRequestA = StunScoSendBindingRequestA; pMyObject->SendBindingRequestB = StunScoSendBindingRequestB; pMyObject->Scuowo1Query = StunScoScuowo1Query; pMyObject->Scuowo1Process = StunScoScuowo1Process; pMyObject->Scuowo1Notify = StunScoScuowo1Notify; pMyObject->ScuowoAQuery = StunScoScuowoAQuery; pMyObject->ScuowoAProcess = StunScoScuowoAProcess; pMyObject->ScuowoANotify = StunScoScuowoANotify; pMyObject->ScuowoBQuery = StunScoScuowoBQuery; pMyObject->ScuowoBProcess = StunScoScuowoBProcess; pMyObject->ScuowoBNotify = StunScoScuowoBNotify; StunInitBindingInfo((&pMyObject->BindingInfo)); AnscInitializeEvent(&pMyObject->SocketEventA); AnscResetEvent (&pMyObject->SocketEventA); /* * 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. */ pMyObject->ResetProperty((ANSC_HANDLE)pMyObject); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDetoInitialize ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_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 = ANSC_DAEMON_ENGINE_TCP_OID; pMyObject->Create = AnscDetoCreate; pMyObject->Remove = AnscDetoRemove; pMyObject->EnrollObjects = AnscDetoEnrollObjects; pMyObject->Initialize = AnscDetoInitialize; pMyObject->hDaemonServer = (ANSC_HANDLE)NULL; pMyObject->CurSocketCount = 0; pMyObject->MaxSocketCount = ANSC_DETO_MAX_SOCKET_COUNT; pMyObject->ControlFlags = 0; pMyObject->StartTime = 0; pMyObject->AvgServingTime = 0; pMyObject->SocketTimeOut = ANSC_DETO_SOCKET_TIMEOUT; pMyObject->bStarted = FALSE; pMyObject->bCleaningDemanded = FALSE; pMyObject->bBusy = FALSE; pMyObject->TtcCount = 0; pMyObject->MtcCount = 0; pMyObject->TrcCount = 0; pMyObject->MrcCount = 0; pMyObject->TscCount = 0; pMyObject->MscCount = 0; pMyObject->GetDaemonServer = AnscDetoGetDaemonServer; pMyObject->SetDaemonServer = AnscDetoSetDaemonServer; pMyObject->GetMaxSocketCount = AnscDetoGetMaxSocketCount; pMyObject->SetMaxSocketCount = AnscDetoSetMaxSocketCount; pMyObject->GetControlFlags = AnscDetoGetControlFlags; pMyObject->SetControlFlags = AnscDetoSetControlFlags; pMyObject->Reset = AnscDetoReset; pMyObject->GetSocketByAddress = AnscDetoGetSocketByAddress; pMyObject->GetSocketByAddress2 = AnscDetoGetSocketByAddress2; pMyObject->GetSocketByOsocket = AnscDetoGetSocketByOsocket; pMyObject->GetSocketByOsocket2 = AnscDetoGetSocketByOsocket2; pMyObject->AddSocket = AnscDetoAddSocket; pMyObject->DelSocket = AnscDetoDelSocket; pMyObject->DelAllSockets = AnscDetoDelAllSockets; pMyObject->ExpAllSockets = AnscDetoExpAllSockets; pMyObject->EnableRecv = AnscDetoEnableRecv; pMyObject->EnableSend = AnscDetoEnableSend; pMyObject->RecvTask = AnscDetoRecvTask; pMyObject->SendTask = AnscDetoSendTask; pMyObject->Start = AnscDetoStart; pMyObject->Stop = AnscDetoStop; pMyObject->Cancel = AnscDetoCancel; pMyObject->Clean = AnscDetoClean; pMyObject->Snapshot = AnscDetoSnapshot; pMyObject->CloseUp = AnscDetoCloseUp; pMyObject->Recv = AnscDetoRecv; pMyObject->Recv2 = AnscDetoRecv2; pMyObject->Send = AnscDetoSend; pMyObject->Send2 = AnscDetoSend2; AnscInitializeEvent(&pMyObject->RecvEvent ); AnscSetEvent (&pMyObject->RecvEvent ); AnscInitializeEvent(&pMyObject->SendEvent ); AnscSetEvent (&pMyObject->SendEvent ); AnscInitializeEvent(&pMyObject->NewSocketEvent); AnscResetEvent (&pMyObject->NewSocketEvent); AnscInitializeLock(&pMyObject->RecvSocketSetLock); AnscInitializeLock(&pMyObject->SendSocketSetLock); for ( i = 0; i < ANSC_DETO_SOCKET_TABLE_SIZE; i++ ) { AnscSListInitializeHeader(&pMyObject->SocketTable[i]); } AnscInitializeLock(&pMyObject->SocketTableLock); AnscQueueInitializeHeader(&pMyObject->PacketQueue ); AnscInitializeLock (&pMyObject->PacketQueueLock); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS CcspCwmpsoInitialize ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PCCSP_CWMP_SESSION_OBJECT pMyObject = (PCCSP_CWMP_SESSION_OBJECT)hThisObject; /* * 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 = CCSP_CWMP_SESSION_OID; pMyObject->Create = CcspCwmpsoCreate; pMyObject->Remove = CcspCwmpsoRemove; pMyObject->EnrollObjects = CcspCwmpsoEnrollObjects; pMyObject->Initialize = CcspCwmpsoInitialize; pMyObject->hCcspCwmpCpeController = (ANSC_HANDLE)NULL; pMyObject->hCcspCwmpProcessor = (ANSC_HANDLE)NULL; pMyObject->AsyncTaskCount = 0; pMyObject->bActive = FALSE; pMyObject->bInformWhenActive = FALSE; pMyObject->GlobalRequestID = 1; pMyObject->SessionState = CCSP_CWMPSO_SESSION_STATE_idle; pMyObject->CpeMaxEnvelopes = CCSP_CWMP_CPE_MAX_ENVELOPES; pMyObject->AcsMaxEnvelopes = 1; pMyObject->ActiveResponses = 0; pMyObject->bHoldRequests = FALSE; pMyObject->bNoMoreRequests = FALSE; pMyObject->bLastEmptyRequestSent = FALSE; pMyObject->EventCount = 0; pMyObject->RetryCount = 0; pMyObject->ModifiedParamCount = 0; pMyObject->GetCcspCwmpAcsConnection = CcspCwmpsoGetCcspCwmpAcsConnection; pMyObject->GetCcspCwmpMcoIf = CcspCwmpsoGetCcspCwmpMcoIf; pMyObject->GetCcspCwmpCpeController = CcspCwmpsoGetCcspCwmpCpeController; pMyObject->SetCcspCwmpCpeController = CcspCwmpsoSetCcspCwmpCpeController; pMyObject->GetCcspCwmpProcessor = CcspCwmpsoGetCcspCwmpProcessor; pMyObject->SetCcspCwmpProcessor = CcspCwmpsoSetCcspCwmpProcessor; pMyObject->Reset = CcspCwmpsoReset; pMyObject->AcqAccess = CcspCwmpsoAcqAccess; pMyObject->RelAccess = CcspCwmpsoRelAccess; pMyObject->SessionTimerInvoke = CcspCwmpsoSessionTimerInvoke; pMyObject->SessionRetryTimerInvoke = CcspCwmpsoSessionRetryTimerInvoke; pMyObject->DelayedActiveNotifTimerInvoke = CcspCwmpsoDelayedActiveNotifTimerInvoke; pMyObject->StartRetryTimer = CcspCwmpsoStartRetryTimer; pMyObject->StopRetryTimer = CcspCwmpsoStopRetryTimer; pMyObject->StopDelayedActiveNotifTimer = CcspCwmpsoStopDelayedActiveNotifTimer; pMyObject->IsAcsConnected = CcspCwmpsoIsAcsConnected; pMyObject->ConnectToAcs = CcspCwmpsoConnectToAcs; pMyObject->CloseConnection = CcspCwmpsoCloseConnection; pMyObject->AddCwmpEvent = CcspCwmpsoAddCwmpEvent; pMyObject->DiscardCwmpEvent = CcspCwmpsoDiscardCwmpEvent; pMyObject->DelAllEvents = CcspCwmpsoDelAllEvents; pMyObject->AddModifiedParameter = CcspCwmpsoAddModifiedParameter; pMyObject->DelAllParameters = CcspCwmpsoDelAllParameters; pMyObject->SaveCwmpEvent = CcspCwmpsoSaveCwmpEvent; pMyObject->GetRpcMethods = CcspCwmpsoGetRpcMethods; pMyObject->Inform = CcspCwmpsoInform; pMyObject->TransferComplete = CcspCwmpsoTransferComplete; pMyObject->AutonomousTransferComplete= CcspCwmpsoAutonomousTransferComplete; pMyObject->Kicked = CcspCwmpsoKicked; pMyObject->RequestDownload = CcspCwmpsoRequestDownload; pMyObject->DUStateChangeComplete = CcspCwmpsoDUStateChangeComplete; pMyObject->AutonomousDUStateChangeComplete = CcspCwmpsoAutonomousDUStateChangeComplete; pMyObject->RecvSoapMessage = CcspCwmpsoRecvSoapMessage; pMyObject->NotifySessionClosed = CcspCwmpsoNotifySessionClosed; pMyObject->AsyncProcessTask = CcspCwmpsoAsyncProcessTask; pMyObject->CancelRetryDelay = CcspCwmpsoCancelRetryDelay; pMyObject->InformPending = CcspCwmpsoInformPending; AnscInitializeLock (&pMyObject->AccessLock ); AnscQueueInitializeHeader(&pMyObject->AsyncReqQueue ); AnscInitializeLock (&pMyObject->AsyncReqQueueLock); AnscQueueInitializeHeader(&pMyObject->SavedReqQueue ); AnscInitializeLock (&pMyObject->SavedReqQueueLock); AnscQueueInitializeHeader(&pMyObject->AsyncRepQueue ); AnscInitializeLock (&pMyObject->AsyncRepQueueLock); AnscInitializeEvent (&pMyObject->AsyncProcessEvent); AnscResetEvent (&pMyObject->AsyncProcessEvent); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDstoEngage ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_SERVER_TCP_OBJECT pMyObject = (PANSC_DAEMON_SERVER_TCP_OBJECT)hThisObject; PANSC_DSTO_WORKER_OBJECT pWorker = (PANSC_DSTO_WORKER_OBJECT )pMyObject->hWorker; int s_result = 0; #ifdef _ANSC_IPV6_COMPATIBLE_ ansc_addrinfo ansc_hints = {0}; ansc_addrinfo* pansc_local_addrinfo = NULL; xskt_addrinfo xskt_hints = {0}; xskt_addrinfo* pxskt_local_addrinfo = NULL; USHORT usPort = 0; char port[6] = {0}; #else /*RDKB-6151, CID-24487,24794; initializing variable before use*/ ansc_socket_addr_in local_addr1 = {0}; xskt_socket_addr_in local_addr2 = {0}; #endif if ( pMyObject->bActive ) { return ANSC_STATUS_SUCCESS; } else if ( !pWorker ) { return ANSC_STATUS_UNAPPLICABLE; } else { pWorker->Init(pWorker->hWorkerContext); pMyObject->StartTime = AnscGetTickInSecondsAbs(); pMyObject->bActive = TRUE; } /* * 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_DSTO_MODE_XSOCKET ) { AnscStartupXsocketWrapper((ANSC_HANDLE)pMyObject); } else { AnscStartupSocketWrapper((ANSC_HANDLE)pMyObject); } #ifdef _ANSC_IPV6_COMPATIBLE_ if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET ) { xskt_hints.ai_family = AF_UNSPEC; xskt_hints.ai_socktype = XSKT_SOCKET_STREAM; xskt_hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; usPort = pMyObject->GetHostPort((ANSC_HANDLE)pMyObject); _ansc_sprintf(port, "%d", usPort); CcspTraceInfo(("!!! Host Name: %s, Host Port: %s !!!\n", pMyObject->HostName, port)); if ( _xskt_getaddrinfo ( pMyObject->HostName[0] ? pMyObject->HostName : "::", port, &xskt_hints, &pxskt_local_addrinfo ) ) { CcspTraceError(("!!! error 1 !!!\n")); returnStatus = ANSC_STATUS_FAILURE; goto EXIT1; } pMyObject->pHostAddr2 = pxskt_local_addrinfo; } else { ansc_hints.ai_family = AF_UNSPEC; ansc_hints.ai_socktype = ANSC_SOCKET_STREAM; ansc_hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; usPort = pMyObject->GetHostPort((ANSC_HANDLE)pMyObject); _ansc_sprintf(port, "%d", usPort); CcspTraceInfo(("!!! Host Name: %s, Host Port: %s !!!\n", pMyObject->HostName, port)); if ( _ansc_getaddrinfo ( pMyObject->HostName[0] ? pMyObject->HostName : "::", port, &ansc_hints, &pansc_local_addrinfo ) ) { returnStatus = ANSC_STATUS_FAILURE; goto EXIT1; } pMyObject->pHostAddr1 = pansc_local_addrinfo; } #endif /* * To engage the Tcp Daemon, we need to perform following acts in the respective order: * * (1) create the os-dependent socket * (2) manufacture and start all the engines objects * (3) manufacture the global socket object pool * (4) bind to the socket and listen on it */ if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET ) { #ifdef _ANSC_IPV6_COMPATIBLE_ pMyObject->Socket = _xskt_socket(pxskt_local_addrinfo->ai_family, pxskt_local_addrinfo->ai_socktype, 0); #else pMyObject->Socket = _xskt_socket(XSKT_SOCKET_AF_INET, XSKT_SOCKET_STREAM, 0); #endif } else { #ifdef _ANSC_IPV6_COMPATIBLE_ pMyObject->Socket = _ansc_socket(pansc_local_addrinfo->ai_family, pansc_local_addrinfo->ai_socktype, 0); #else pMyObject->Socket = _ansc_socket(ANSC_SOCKET_AF_INET, ANSC_SOCKET_STREAM, 0); #endif } if ( ((pMyObject->Socket == XSKT_SOCKET_INVALID_SOCKET) && (pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET)) || ((pMyObject->Socket == ANSC_SOCKET_INVALID_SOCKET) && !(pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET)) ) { returnStatus = ANSC_STATUS_FAILURE; goto EXIT1; } _ansc_en_reuseaddr(pMyObject->Socket); #ifndef _ANSC_IPV6_COMPATIBLE_ if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET ) { local_addr2.sin_family = XSKT_SOCKET_AF_INET; local_addr2.sin_port = _xskt_htons(pMyObject->HostPort); if ( pMyObject->HostAddress.Value == 0 ) { ((pansc_socket_addr_in)&local_addr2)->sin_addr.s_addr = XSKT_SOCKET_ANY_ADDRESS; } else { ((pansc_socket_addr_in)&local_addr2)->sin_addr.s_addr = pMyObject->HostAddress.Value; } } else { local_addr1.sin_family = ANSC_SOCKET_AF_INET; local_addr1.sin_port = _ansc_htons(pMyObject->HostPort); if ( pMyObject->HostAddress.Value == 0 ) { local_addr1.sin_addr.s_addr = ANSC_SOCKET_ANY_ADDRESS; } else { local_addr1.sin_addr.s_addr = pMyObject->HostAddress.Value; } } #endif #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET ) { #ifdef _ANSC_IPV6_COMPATIBLE_ s_result = _xskt_bind(pMyObject->Socket, pxskt_local_addrinfo->ai_addr, pxskt_local_addrinfo->ai_addrlen); #else AnscTrace("AnscDstoEngage -- the address is 0x%lX:%d, familty %d.\n", _ansc_ntohl(local_addr2.sin_addr.s_addr), _ansc_ntohs(local_addr2.sin_port), local_addr2.sin_family); s_result = _xskt_bind(pMyObject->Socket, (xskt_socket_addr*)&local_addr2, sizeof(local_addr2)); #endif } else { #ifdef _ANSC_IPV6_COMPATIBLE_ s_result = _ansc_bind(pMyObject->Socket, pansc_local_addrinfo->ai_addr, pansc_local_addrinfo->ai_addrlen); #else s_result = _ansc_bind(pMyObject->Socket, (ansc_socket_addr*)&local_addr1, sizeof(local_addr1)); #endif } #else if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET ) { while ( _xskt_bind(pMyObject->Socket, (ansc_socket_addr*)&local_addr2, sizeof(local_addr2)) != 0 ) { AnscTrace ( "AnscDstoEngage -- failure to bind try again !socket %d family %d port %d address %X \n", pMyObject->Socket, local_addr2.sin_family, local_addr2.sin_port, ((pansc_socket_addr_in)&local_addr2)->sin_addr.s_addr ); AnscSleep(10); } } else { while ( _ansc_bind(pMyObject->Socket, (ansc_socket_addr*)&local_addr1, sizeof(local_addr1)) != 0 ) { AnscTrace ( "AnscDstoEngage -- failure to bind try again !socket %d family %d port %d address %X \n", pMyObject->Socket, local_addr1.sin_family, local_addr1.sin_port, local_addr1.sin_addr.s_addr ); AnscSleep(10); } } #endif if ( s_result != 0 ) { AnscTrace ( "AnscDstoEngage -- failed to bind to the socket, error code is %d!!!\n", (pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET) ? _xskt_get_last_error() : _ansc_get_last_error() ); returnStatus = ANSC_STATUS_FAILURE; goto EXIT2; } pMyObject->ManufactureEnginePool((ANSC_HANDLE)pMyObject); pMyObject->ManufactureSocketPool((ANSC_HANDLE)pMyObject); pMyObject->StartEngines ((ANSC_HANDLE)pMyObject); if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET ) { s_result = _xskt_listen(pMyObject->Socket, ANSC_SOCKET_BACKLOG_VALUE); } else { s_result = _ansc_listen(pMyObject->Socket, ANSC_SOCKET_BACKLOG_VALUE); } if ( s_result != 0 ) { AnscTrace("AnscDstoEngage -- failed to listen on the socket!\n"); returnStatus = ANSC_STATUS_FAILURE; goto EXIT2; } /* * 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_DSTO_MODE_TLS_ENABLED ) { #ifdef _ANSC_USE_OPENSSL_ pMyObject->bTlsEnabled = TRUE; if ( !openssl_init(SSL_SERVER_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; pMyObject->bTlsReqCert = (pMyObject->Mode & ANSC_DSTO_MODE_TLS_REQ_CERT); } #endif #endif } AnscResetEvent(&pMyObject->AcceptEvent); returnStatus = pMyObject->SpawnTask3 ( (ANSC_HANDLE)pMyObject, (void* )pMyObject->AcceptTask, (ANSC_HANDLE)pMyObject, ANSC_DSTO_ACCEPT_TASK_NAME, USER_DEFAULT_TASK_PRIORITY, 2*USER_DEFAULT_TASK_STACK_SIZE ); return ANSC_STATUS_SUCCESS; /****************************************************************** GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS ******************************************************************/ EXIT2: if ( pMyObject->Mode & ANSC_DSTO_MODE_XSOCKET ) { _xskt_closesocket(pMyObject->Socket); } else { _ansc_closesocket(pMyObject->Socket); } EXIT1: if ( returnStatus != ANSC_STATUS_SUCCESS ) { pMyObject->bActive = FALSE; } return returnStatus; }
ANSC_STATUS HttpWssoInitialize ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PHTTP_WEBS_SESSION_OBJECT pMyObject = (PHTTP_WEBS_SESSION_OBJECT)hThisObject; /* * 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 = HTTP_WEBS_SESSION_OID; pMyObject->Create = HttpWssoCreate; pMyObject->Remove = HttpWssoRemove; pMyObject->EnrollObjects = HttpWssoEnrollObjects; pMyObject->Initialize = HttpWssoInitialize; pMyObject->hWspIf = (ANSC_HANDLE)NULL; pMyObject->hHfpIf = (ANSC_HANDLE)NULL; pMyObject->hWebSocket = (ANSC_HANDLE)NULL; pMyObject->SessionState = HTTP_WSSO_STATE_INITIALIZED; pMyObject->ServeCount = 0; pMyObject->GetWspIf = HttpWssoGetWspIf; pMyObject->SetWspIf = HttpWssoSetWspIf; pMyObject->GetHfpIf = HttpWssoGetHfpIf; pMyObject->SetHfpIf = HttpWssoSetHfpIf; pMyObject->GetWebSocket = HttpWssoGetWebSocket; pMyObject->SetWebSocket = HttpWssoSetWebSocket; pMyObject->GetSessionState = HttpWssoGetSessionState; pMyObject->SetSessionState = HttpWssoSetSessionState; pMyObject->Return = HttpWssoReturn; pMyObject->Reset = HttpWssoReset; pMyObject->Open = HttpWssoOpen; pMyObject->Close = HttpWssoClose; pMyObject->AcquireAccess = HttpWssoAcquireAccess; pMyObject->ReleaseAccess = HttpWssoReleaseAccess; pMyObject->EnterWspServe = HttpWssoEnterWspServe; pMyObject->LeaveWspServe = HttpWssoLeaveWspServe; pMyObject->ClearWspServe = HttpWssoClearWspServe; pMyObject->CloseConnection = HttpWssoCloseConnection; pMyObject->GetEndWsto = HttpWssoGetEndWsto; pMyObject->GetCurWsto = HttpWssoGetCurWsto; pMyObject->AddNewWsto = HttpWssoAddNewWsto; pMyObject->DelAllWstos = HttpWssoDelAllWstos; pMyObject->Query = HttpWssoQuery; pMyObject->Recv = HttpWssoRecv; pMyObject->Finish = HttpWssoFinish; pMyObject->Accept = HttpWssoAccept; AnscInitializeEvent (&pMyObject->ServeEvent ); AnscResetEvent (&pMyObject->ServeEvent ); AnscInitializeLock (&pMyObject->AccessLock ); AnscSListInitializeHeader(&pMyObject->WstoSList ); AnscInitializeLock (&pMyObject->WstoSListLock); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS AnscDetoRecvTask ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_DAEMON_ENGINE_TCP_OBJECT pMyObject = (PANSC_DAEMON_ENGINE_TCP_OBJECT)hThisObject; PANSC_DAEMON_SERVER_TCP_OBJECT pServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hDaemonServer; PANSC_DSTO_WORKER_OBJECT pWorker = (PANSC_DSTO_WORKER_OBJECT )pServer->hWorker; #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) ansc_fd_set* pRecvSet1 = (ansc_fd_set* )pMyObject->RecvSocketSet; xskt_fd_set* pRecvSet2 = (xskt_fd_set* )pMyObject->RecvSocketSet; #endif PANSC_DAEMON_SOCKET_TCP_OBJECT pSocket = NULL; ULONG ulLastCleanAt = AnscGetTickInSecondsAbs(); ANSC_SOCKET s_socket = ANSC_SOCKET_INVALID_SOCKET; int s_result = 0; int s_result_excp = 0; int s_error = 0; int i = 0; #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) ansc_fd_set* read_fd_set1 = NULL; xskt_fd_set* read_fd_set2 = NULL; ansc_fd_set* excp_fd_set1 = NULL; xskt_fd_set* excp_fd_set2 = NULL; ansc_timeval timeval1; xskt_timeval timeval2; #endif AnscTrace("AnscDetoRecvTask is activated ...!\n"); #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) read_fd_set1 = (ansc_fd_set*)AnscAllocateMemory(sizeof(ansc_fd_set)); read_fd_set2 = (xskt_fd_set*)AnscAllocateMemory(sizeof(xskt_fd_set)); excp_fd_set1 = (ansc_fd_set*)AnscAllocateMemory(sizeof(ansc_fd_set)); excp_fd_set2 = (xskt_fd_set*)AnscAllocateMemory(sizeof(xskt_fd_set)); if ( !read_fd_set1 || !read_fd_set2 || !excp_fd_set1 || !excp_fd_set2 ) { goto EXIT1; } #endif /* * 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 !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) if ( pMyObject->bCleaningDemanded ) #else if ( FALSE ) /*if ( pMyObject->bCleaningDemanded )*/ #endif { pMyObject->Clean((ANSC_HANDLE)pMyObject); ulLastCleanAt = AnscGetTickInSecondsAbs(); pMyObject->bCleaningDemanded = FALSE; } else if ( (AnscGetTickInSecondsAbs() - ulLastCleanAt) >= ANSC_DETO_CLEAN_TASK_INTERVAL ) { pMyObject->Clean((ANSC_HANDLE)pMyObject); ulLastCleanAt = AnscGetTickInSecondsAbs(); pMyObject->bCleaningDemanded = FALSE; } /* * 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. */ #if defined(_ANSC_KERNEL) && defined(_ANSC_LINUX) if ( !pMyObject->CurSocketCount) { if ( pServer->Mode & ANSC_DSTO_MODE_EVENT_SYNC ) { AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_DETO_WAIT_EVENT_INTERVAL); AnscResetEvent(&pMyObject->NewSocketEvent); if (!pMyObject->CurSocketCount) { AnscTaskRelinquish(); continue; } } else { AnscSleep(ANSC_DETO_TASK_BREAK_INTERVAL); continue; } } #else if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set2 = *pRecvSet2; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } else { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set1 = *pRecvSet1; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && XSKT_SOCKET_FD_ISNUL(read_fd_set2)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && ANSC_SOCKET_FD_ISNUL(read_fd_set1)) ) { if ( pServer->Mode & ANSC_DSTO_MODE_EVENT_SYNC ) { AnscWaitEvent (&pMyObject->NewSocketEvent, ANSC_DETO_WAIT_EVENT_INTERVAL); AnscResetEvent(&pMyObject->NewSocketEvent); if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set2 = *pRecvSet2; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } else { AnscAcquireLock(&pMyObject->RecvSocketSetLock); *read_fd_set1 = *pRecvSet1; AnscReleaseLock(&pMyObject->RecvSocketSetLock); } if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && XSKT_SOCKET_FD_ISNUL(read_fd_set2)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && ANSC_SOCKET_FD_ISNUL(read_fd_set1)) ) { AnscTaskRelinquish(); continue; } } else { AnscSleep(ANSC_DETO_TASK_BREAK_INTERVAL); continue; } } if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { timeval2.tv_sec = (ANSC_DETO_POLL_INTERVAL_MS / 1000); /* number of seconds */ timeval2.tv_usec = (ANSC_DETO_POLL_INTERVAL_MS % 1000) * 1000; /* number of microseconds */ } else { timeval1.tv_sec = (ANSC_DETO_POLL_INTERVAL_MS / 1000); /* number of seconds */ timeval1.tv_usec = (ANSC_DETO_POLL_INTERVAL_MS % 1000) * 1000; /* number of microseconds */ } /* * 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_DSTO_MODE_XSOCKET ) { s_result = _xskt_select(XSKT_SOCKET_FD_SETSIZE, read_fd_set2, NULL, NULL, &timeval2); } else { s_result = _ansc_select(ANSC_SOCKET_FD_SETSIZE, read_fd_set1, NULL, NULL, &timeval1); } if ( s_result == 0 ) { continue; } else if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_result == XSKT_SOCKET_ERROR)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_result == ANSC_SOCKET_ERROR)) ) { s_error = (pServer->Mode & ANSC_DSTO_MODE_XSOCKET)? _xskt_get_last_error() : _ansc_get_last_error(); /* * Previously we simply reset everything when _ansc_select() fails, which is not a good * solution: we shall notify the worker module and gracefully shutdown the socket(s) * that caused the error. */ /* pMyObject->Reset((ANSC_HANDLE)pMyObject); */ pMyObject->ExpAllSockets((ANSC_HANDLE)pMyObject); continue; } else if ( !pMyObject->bStarted ) { break; } #endif /* * 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. */ #if defined(_ANSC_KERNEL) && defined(_ANSC_LINUX) if (TRUE) { int i; PSINGLE_LINK_ENTRY pSLinkEntry; for ( i = 0; i < ANSC_DETO_SOCKET_TABLE_SIZE ; i++) { if (!AnscSListQueryDepth(&pMyObject->SocketTable[i])) { continue; } AnscAcquireLock(&pMyObject->SocketTableLock); pSLinkEntry = AnscSListGetFirstEntry(&pMyObject->SocketTable[i]); AnscReleaseLock(&pMyObject->SocketTableLock); while ( pSLinkEntry ) { pSocket = ACCESS_ANSC_DAEMON_SOCKET_TCP_OBJECT(pSLinkEntry); pSLinkEntry = AnscSListGetNextEntry(pSLinkEntry); if ( pSocket->bTlsEnabled ) { pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv2 ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; } else { pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; } } if ( !pMyObject->bStarted ) { break; } } AnscSleep(10); } #else for ( i = 0; i < s_result; i++ ) { if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { XSKT_SOCKET_FD_GET(read_fd_set2, s_socket, (ULONG)i); } else { ANSC_SOCKET_FD_GET(read_fd_set1, s_socket, (ULONG)i); } if ( ( (pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_socket == XSKT_SOCKET_INVALID_SOCKET)) || (!(pServer->Mode & ANSC_DSTO_MODE_XSOCKET) && (s_socket == ANSC_SOCKET_INVALID_SOCKET)) ) { break; } else { pSocket = (PANSC_DAEMON_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket ( (ANSC_HANDLE)pMyObject, s_socket ); /* * 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. */ /* if ( pServer->Mode & ANSC_DSTO_MODE_XSOCKET ) { XSKT_SOCKET_FD_ZERO(excp_fd_set2); XSKT_SOCKET_FD_SET ((XSKT_SOCKET)s_socket, excp_fd_set2); timeval2.tv_sec = 0; timeval2.tv_usec = 0; s_result_excp = _xskt_select(XSKT_SOCKET_FD_SETSIZE, NULL, NULL, excp_fd_set2, &timeval2); } else { ANSC_SOCKET_FD_ZERO(excp_fd_set1); ANSC_SOCKET_FD_SET (s_socket, excp_fd_set1); timeval1.tv_sec = 0; timeval1.tv_usec = 0; s_result_excp = _ansc_select(ANSC_SOCKET_FD_SETSIZE, NULL, NULL, excp_fd_set1, &timeval1); } */ } /* if ( ((s_result_excp == 1 ) ) || ((s_result_excp == XSKT_SOCKET_ERROR) && (pServer->Mode & ANSC_DSTO_MODE_XSOCKET)) || ((s_result_excp == ANSC_SOCKET_ERROR) && !(pServer->Mode & ANSC_DSTO_MODE_XSOCKET)) ) { if ( TRUE ) { pSocket->bBroken = TRUE; pMyObject->EnableRecv((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE); pMyObject->EnableSend((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket, FALSE); } if ( pSocket->bTlsEnabled ) { if ( pSocket->bTlsEnabled && pSocket->bTlsConnected && !pSocket->bTlsInitializing ) { returnStatus = pWorker->Notify ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket, ANSC_DSTOWO_EVENT_SOCKET_ERROR, (ANSC_HANDLE)NULL ); } else { AnscSetEvent(&pSocket->TlsConnEvent); } } else { returnStatus = pWorker->Notify ( pWorker->hWorkerContext, (ANSC_HANDLE)pSocket, ANSC_DSTOWO_EVENT_SOCKET_ERROR, (ANSC_HANDLE)NULL ); } if ( pServer->Mode & ANSC_DSTO_MODE_AUTO_CLOSE ) { pMyObject->DelSocket((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket); } pMyObject->TrcCount++; continue; } else { pSocket = (PANSC_DAEMON_SOCKET_TCP_OBJECT)pMyObject->GetSocketByOsocket ( (ANSC_HANDLE)pMyObject, s_socket ); } */ if ( !pSocket ) { continue; } else if ( pSocket->bTlsEnabled ) { #ifdef _ANSC_USE_OPENSSL_ pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; #else pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv2 ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; #endif } else { pMyObject->bBusy = TRUE; returnStatus = pMyObject->Recv ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); pMyObject->bBusy = FALSE; } /* * Check whether 'bToBeCleaned' flag is set for this socket: if it is, we should close * this socket right away; otherwise, we continue the processing. WARNING!!! This new * change seems to incur instability in SLAP, we have to roll back to the initial * approach. */ /* if ( pSocket->bToBeCleaned ) { returnStatus = pMyObject->DelSocket ( (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pSocket ); } */ if ( !pMyObject->bStarted ) { break; } } #endif } /****************************************************************** GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS ******************************************************************/ EXIT1: AnscSetEvent(&pMyObject->RecvEvent); #if !defined(_ANSC_KERNEL) || !defined(_ANSC_LINUX) if ( read_fd_set1 ) { AnscFreeMemory(read_fd_set1); } if ( read_fd_set2 ) { AnscFreeMemory(read_fd_set2); } if ( excp_fd_set1 ) { AnscFreeMemory(excp_fd_set1); } if ( excp_fd_set2 ) { AnscFreeMemory(excp_fd_set2); } #endif return ANSC_STATUS_SUCCESS; }
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; }