ANSC_STATUS CcspCwmpAcscoHttpBspNotify ( ANSC_HANDLE hThisObject, ULONG ulEvent, ULONG ulError, ANSC_HANDLE hReqContext, ANSC_HANDLE hBmoReq, ANSC_HANDLE hBmoRep ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PANSC_ACS_INTERN_HTTP_CONTENT pHttpGetReq = (PANSC_ACS_INTERN_HTTP_CONTENT )hReqContext; PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject; 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; PHTTP_BMO_REP_OBJECT pHttpBmoRep = (PHTTP_BMO_REP_OBJECT )hBmoRep; switch ( ulEvent ) { case HTTP_BSP_EVENT_BAD_REQUEST : case HTTP_BSP_EVENT_CANNOT_RESOLVE_NAME : case HTTP_BSP_EVENT_SERVER_UNAVAILABLE : case HTTP_BSP_EVENT_NETWORK_FAILURE : case HTTP_BSP_EVENT_TIMEOUT : if( pHttpGetReq != NULL && pHttpGetReq->CompleteStatus == ANSC_STATUS_RESET_SESSION) { break; } if( pHttpGetReq && pHttpGetReq->ulContentSize == 0) { pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE; AnscSetEvent(&pHttpGetReq->CompleteEvent); } CcspTr069PaTraceDebug(("HttpClient Notify: %d\n", (int)ulEvent)); if( pCcspCwmpStatIf) { pCcspCwmpStatIf->IncTcpFailure(pCcspCwmpStatIf->hOwnerContext); } CcspCwmpAcscoHttpSessionClosed(hThisObject); break; case HTTP_BSP_EVENT_SOCKET_CLOSED: /* * During the test with Motive ACS, we observed that the web server * close the connection after sending chanllenge back, which is an option. * * In that case, we need to start a new session and send back the authentication * information. */ if( pHttpGetReq) { char* pHeaderLocation = NULL; if ( pHttpBmoRep ) { pHeaderLocation = pHttpBmoRep->GetHeaderValueByName((ANSC_HANDLE)pHttpBmoRep, "Location"); } if ( pHeaderLocation && AnscSizeOfString(pHeaderLocation) != 0 ) { ULONG ulCode = pHttpBmoRep->GetCode((ANSC_HANDLE)pHttpBmoRep); CcspTr069PaTraceInfo(("ACS URL moved (HTTP code=%u) to: %s\n", ulCode, pHeaderLocation)); pHttpGetReq->ulContentSize = AnscSizeOfString(pHeaderLocation); pHttpGetReq->pContent = CcspTr069PaCloneString(pHeaderLocation); pHttpGetReq->bIsRedirect = TRUE; } pHttpGetReq->CompleteStatus = ANSC_STATUS_RESET_SESSION; AnscSetEvent(&pHttpGetReq->CompleteEvent); } CcspTr069PaTraceDebug(("HttpClient Notify: SOCKET CLOSED\n")); /* CcspCwmpAcscoHttpSessionClosed(hThisObject); */ break; case HTTP_BSP_EVENT_TLS_TIMEOUT: case HTTP_BSP_EVENT_TLS_ERROR: CcspTr069PaTraceDebug(("HttpClient TLS Notify: %d\n", ulEvent)); if( pCcspCwmpStatIf) { pCcspCwmpStatIf->IncTlsFailure(pCcspCwmpStatIf->hOwnerContext); } if ( pHttpGetReq ) { pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE; AnscSetEvent(&pHttpGetReq->CompleteEvent); } break; default : CcspTr069PaTraceDebug(("HttpClient Notify: %d\n", ulEvent)); if ( pHttpGetReq ) { pHttpGetReq->CompleteStatus = ANSC_STATUS_FAILURE; AnscSetEvent(&pHttpGetReq->CompleteEvent); } break; } return ANSC_STATUS_SUCCESS; }
ANSC_STATUS CcspCwmpAcscoHttpBspBrowse ( ANSC_HANDLE hThisObject, ANSC_HANDLE hBmoReq, ANSC_HANDLE hBmoRep, ANSC_HANDLE hReqContext ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PCCSP_CWMP_ACS_CONNECTION_OBJECT pMyObject = (PCCSP_CWMP_ACS_CONNECTION_OBJECT)hThisObject; PHTTP_BMO_REQ_OBJECT pHttpBmoReq = (PHTTP_BMO_REQ_OBJECT )hBmoReq; PHTTP_BMO_REP_OBJECT pHttpBmoRep = (PHTTP_BMO_REP_OBJECT )hBmoRep; PANSC_ACS_INTERN_HTTP_CONTENT pHttpGetReq = (PANSC_ACS_INTERN_HTTP_CONTENT )hReqContext; PHTTP_RESPONSE_INFO pHttpRepInfo = (PHTTP_RESPONSE_INFO )pHttpBmoRep->GetRepInfo ((ANSC_HANDLE)pHttpBmoRep); ULONG ulResponseSize = (ULONG )pHttpBmoRep->GetBodySize((ANSC_HANDLE)pHttpBmoRep); char* pHttpResponse = (char* )NULL; char* pHeaderLocation = NULL; char* pCookie = NULL; ULONG ulCode = 0; char* pCookieHeader = NULL; ULONG ulCookieIndex = 0; BOOL bCookiesRemoved = FALSE; if ( pHttpGetReq == NULL) { return ANSC_STATUS_FAILURE; } ulCode = pHttpBmoRep->GetCode((ANSC_HANDLE)pHttpBmoRep); if( HTTP_STATUS_NO_CONTENT == ulCode) /* ACS has nothing to say */ { if( pHttpGetReq != NULL) { pHttpGetReq->ulContentSize = 0; pHttpGetReq->pContent = NULL; pHttpGetReq->bIsRedirect = FALSE; } returnStatus = ANSC_STATUS_SUCCESS; goto EXIT1; } else if( HTTP_STATUS_MOVED_PERMANENTLY != ulCode && HTTP_STATUS_FOUND != ulCode && HTTP_STATUS_OK != ulCode && HTTP_STATUS_UNAUTHORIZED != ulCode && HTTP_STATUS_TEMP_REDIRECT != ulCode ) { returnStatus = ANSC_STATUS_FAILURE; CcspTr069PaTraceDebug(("HttpClient returned code: %d\n", (int)ulCode)); goto EXIT1; } /* save Authorization header value */ if ( TRUE ) { char* pAuthHeaderValue = NULL; /* Authorization header in request */ pAuthHeaderValue = pHttpBmoReq->GetHeaderValueById((ANSC_HANDLE)pHttpBmoReq, HTTP_HEADER_ID_AUTHORIZATION); if ( pMyObject->AuthHeaderValue ) CcspTr069PaFreeMemory(pMyObject->AuthHeaderValue); pMyObject->AuthHeaderValue = CcspTr069PaCloneString(pAuthHeaderValue); } /* look for Set-Cookie headers */ pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE2, ulCookieIndex); if ( pCookie && AnscSizeOfString(pCookie) > 0 ) { /* pMyObject->RemoveCookies((ANSC_HANDLE)pMyObject); bCookiesRemoved = TRUE; */ while ( pCookie != NULL && AnscSizeOfString(pCookie) > 0) { pCookieHeader = CcspTr069PaAllocateMemory(AnscSizeOfString(pCookie) + 16); if ( pCookieHeader ) _ansc_sprintf(pCookieHeader, "Set-Cookie2: %s", pCookie); pMyObject->AddCookie((ANSC_HANDLE)pMyObject, pCookieHeader); CcspTr069PaFreeMemory(pCookieHeader); pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE2, ++ulCookieIndex); } } /* If Set-Cookie and Set-Cookie2 co-exist happily, we save them all */ ulCookieIndex = 0; pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE, ulCookieIndex); if( pCookie != NULL && AnscSizeOfString(pCookie) > 0) { /* if ( !bCookiesRemoved ) { pMyObject->RemoveCookies((ANSC_HANDLE)pMyObject); bCookiesRemoved = TRUE; } */ while ( pCookie && AnscSizeOfString(pCookie) ) { pCookieHeader = CcspTr069PaAllocateMemory(AnscSizeOfString(pCookie) + 16); if ( pCookieHeader ) _ansc_sprintf(pCookieHeader, "Set-Cookie: %s", pCookie); pMyObject->AddCookie((ANSC_HANDLE)pMyObject, pCookieHeader); CcspTr069PaFreeMemory(pCookieHeader); pCookie = pHttpBmoRep->GetHeaderValueById2((ANSC_HANDLE)pHttpBmoRep, HTTP_HEADER_ID_SET_COOKIE, ++ulCookieIndex); } } /* if ( !bCookiesRemoved ) { CcspTr069PaTraceDebug(("No Cookie in the response.\n")); if( pMyObject->NumCookies != 0) { for ( i = 0; i < pMyObject->NumCookies; i ++ ) { CcspTr069PaTraceDebug(("Keep the old cookie: %s\n", pMyObject->Cookies[i])); } } else { CcspTr069PaTraceDebug(("???No cookie exists...\n")); } } */ if( HTTP_STATUS_UNAUTHORIZED == ulCode) { /* make sure if server sends back challenge, terminates the session if otherwise */ char* pWwwAuth = NULL; pHttpGetReq->bUnauthorized = TRUE; pWwwAuth = pHttpBmoRep->GetHeaderValueByName((ANSC_HANDLE)pHttpBmoRep, "WWW-Authenticate"); if ( pWwwAuth ) { returnStatus = ANSC_STATUS_DO_IT_AGAIN; /* ANSC_STATUS_SUCCESS; */ } else { returnStatus = ANSC_STATUS_FAILURE; } goto EXIT1; } if( ulCode == HTTP_STATUS_MOVED_PERMANENTLY || HTTP_STATUS_FOUND == ulCode || HTTP_STATUS_TEMP_REDIRECT == ulCode) { pHeaderLocation = pHttpBmoRep->GetHeaderValueByName((ANSC_HANDLE)pHttpBmoRep, "Location" ); if( pHeaderLocation == NULL || AnscSizeOfString(pHeaderLocation) == 0) { returnStatus = ANSC_STATUS_FAILURE; goto EXIT1; } CcspTr069PaTraceInfo(("ACS URL moved (HTTP code=%u) to: %s\n", ulCode, pHeaderLocation)); pHttpGetReq->ulContentSize = AnscSizeOfString(pHeaderLocation); pHttpGetReq->pContent = CcspTr069PaCloneString(pHeaderLocation); pHttpGetReq->bIsRedirect = TRUE; /* notify underlying HTTP Webc Transaction object to clearn request * otherwise, in case ACS closes the socket first, we will get notified * again and current session will be terminated prematurely. */ returnStatus = ANSC_STATUS_NO_MORE_DATA; } else { if ( ulResponseSize == 0 ) { returnStatus = ANSC_STATUS_FAILURE; goto EXIT1; } else { pHttpResponse = (char*)CcspTr069PaAllocateMemory(ulResponseSize + 1); /* we must leave room for the NULL terminator */ if ( !pHttpResponse ) { returnStatus = ANSC_STATUS_RESOURCES; goto EXIT1; } else { returnStatus = pHttpBmoRep->CopyBodyFrom ( (ANSC_HANDLE)pHttpBmoRep, pHttpResponse, &ulResponseSize ); } } pHttpGetReq->ulContentSize = ulResponseSize; pHttpGetReq->pContent = (PVOID)pHttpResponse; pHttpGetReq->bIsRedirect = FALSE; } /****************************************************************** GRACEFUL ROLLBACK PROCEDURES AND EXIT DOORS ******************************************************************/ EXIT1: if ( pHttpGetReq ) { pHttpGetReq->CompleteStatus = (returnStatus == ANSC_STATUS_DO_IT_AGAIN || returnStatus == ANSC_STATUS_NO_MORE_DATA) ? ANSC_STATUS_SUCCESS : returnStatus; AnscSetEvent(&pHttpGetReq->CompleteEvent); } return returnStatus; }
ANSC_STATUS CcspCwmpTcpcrhoCreateTcpServers ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PCCSP_CWMP_TCPCR_HANDLER_OBJECT pMyObject = (PCCSP_CWMP_TCPCR_HANDLER_OBJECT )hThisObject; PCCSP_CWMP_TCPCR_HANDLER_PROPERTY pProperty = (PCCSP_CWMP_TCPCR_HANDLER_PROPERTY )&pMyObject->Property; PANSC_DAEMON_SERVER_TCP_OBJECT pTcpServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hTcpServer; char buf[64] = {0}; if ( pProperty->HostPort == 0 && pTcpServer ) { CcspTr069PaTraceDebug(("Port is 0 on current TcpServer: Server will be removed!!!\n")); pTcpServer->Remove((ANSC_HANDLE)pTcpServer); pMyObject->hTcpServer = (ANSC_HANDLE)NULL; } else if ( !pTcpServer && pProperty->HostPort != 0 ) { if ( bIsComcastImage() ) { // If HostAddress value is zero, then bind the outbound interface's ip address if( pProperty->HostAddress.Value == 0) { CcspTr069PaTraceInfo(("%s, HostAddress value is 0\n",__FUNCTION__)); token_t se_token; int se_fd = s_sysevent_connect(&se_token); if (0 > se_fd) { CcspTr069PaTraceError(("%s, sysevent_connect failed!!!\n",__FUNCTION__)); //return ERR_SYSEVENT_CONN; } else { // Get ipv4 address from sysevent if( 0 == sysevent_get(se_fd, se_token, "ipv4_wan_ipaddr", buf, sizeof(buf)) && '\0' != buf[0] ) { CcspTr069PaTraceInfo(("%s, ipv4_wan_ipaddr got from sysevent is: %s\n",__FUNCTION__,buf)); pProperty->HostAddress.Value = _ansc_inet_addr(buf); CcspTr069PaTraceInfo(("%s,pProperty->HostAddress.Value: %lu\n",__FUNCTION__,pProperty->HostAddress.Value)); } else { // If sysevent fails, let TR69 bind on 0.0.0.0 CcspTr069PaTraceError(("%s, sysevent_get failed to get value of ipv4_wan_ipaddr!!!\n",__FUNCTION__)); } } } CcspTr069PaTraceInfo(("%s, Call AnscCreateDaemonServerTcp\n",__FUNCTION__)); } pTcpServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)AnscCreateDaemonServerTcp ( pMyObject->hContainerContext, (ANSC_HANDLE)pMyObject, (ANSC_HANDLE)NULL ); if ( !pTcpServer ) { CcspTr069PaTraceError(("Something wrong in AnscCreateDaemonServerTCP.\n")); return ANSC_STATUS_RESOURCES; } else { pMyObject->hTcpServer = (ANSC_HANDLE)pTcpServer; } pTcpServer->SetWorker ( (ANSC_HANDLE)pTcpServer, pMyObject->hDstoWorker, sizeof(ANSC_DSTO_WORKER_OBJECT) ); } CcspTr069PaTraceInfo(("TCP server created successfully.\n")); return ANSC_STATUS_SUCCESS; }
ANSC_STATUS CcspCwmpTcpcrhoEngage ( ANSC_HANDLE hThisObject ) { ANSC_STATUS returnStatus = ANSC_STATUS_SUCCESS; PCCSP_CWMP_TCPCR_HANDLER_OBJECT pMyObject = (PCCSP_CWMP_TCPCR_HANDLER_OBJECT )hThisObject; PCCSP_CWMP_TCPCR_HANDLER_PROPERTY pProperty = (PCCSP_CWMP_TCPCR_HANDLER_PROPERTY )&pMyObject->Property; PANSC_DAEMON_SERVER_TCP_OBJECT pTcpServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hTcpServer; ULONG ulEngineCount = 1; ULONG ulSocketCount = 1; ULONG ulTcpDsoMode = ANSC_DSTO_MODE_EVENT_SYNC | ANSC_DSTO_MODE_FOREIGN_BUFFER | ANSC_DSTO_MODE_COMPACT; if ( pMyObject->bActive ) { return ANSC_STATUS_SUCCESS; } else { pMyObject->bActive = TRUE; } returnStatus = pMyObject->CreateTcpServers((ANSC_HANDLE)pMyObject); if ( returnStatus != ANSC_STATUS_SUCCESS ) { CcspTr069PaTraceDebug(("Create TCP server failed\n")); pMyObject->bActive = FALSE; return returnStatus; } if ( pProperty->ServerMode & CCSP_CWMP_TCPCR_HANDLER_MODE_useXsocket ) { ulTcpDsoMode |= ANSC_DSTO_MODE_XSOCKET; } ulEngineCount = 1; ulSocketCount = 4; pTcpServer = (PANSC_DAEMON_SERVER_TCP_OBJECT)pMyObject->hTcpServer; if ( pTcpServer ) { #ifdef _ANSC_IPV6_COMPATIBLE_ CcspTr069PaTraceDebug(("Tcp host addr=%s:%d\n", pProperty->HostAddr, pProperty->HostPort)); AnscCopyString(pTcpServer->HostName, pProperty->HostAddr); #else CcspTr069PaTraceInfo(("Tcp host addr=%d.%d.%d.%d:%d\n", pProperty->HostAddress.Dot[0], pProperty->HostAddress.Dot[1], pProperty->HostAddress.Dot[2], pProperty->HostAddress.Dot[3], pProperty->HostPort)); pTcpServer->SetHostAddress ((ANSC_HANDLE)pTcpServer, pProperty->HostAddress.Dot); #endif pTcpServer->SetHostPort ((ANSC_HANDLE)pTcpServer, pProperty->HostPort ); pTcpServer->SetMaxMessageSize((ANSC_HANDLE)pTcpServer, CCSP_CWMP_TCPCR_MAX_MSG_SIZE ); pTcpServer->SetEngineCount ((ANSC_HANDLE)pTcpServer, ulEngineCount ); pTcpServer->SetMinSocketCount((ANSC_HANDLE)pTcpServer, 0 ); pTcpServer->SetMaxSocketCount((ANSC_HANDLE)pTcpServer, ulSocketCount ); pTcpServer->SetMode ((ANSC_HANDLE)pTcpServer, ulTcpDsoMode ); returnStatus = pTcpServer->Engage((ANSC_HANDLE)pTcpServer); if ( returnStatus != ANSC_STATUS_SUCCESS ) { CcspTr069PaTraceError(("CcspCwmpTcpcrhoEngage - failed to be engaged, CWMP will not run properly!\n")); pMyObject->bActive = FALSE; return returnStatus; } } 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 }
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; }