ANSC_STATUS
HttpMboChkAppendTrailer
    (
        ANSC_HANDLE                 hThisObject,
        char*                       pRawTrailer,
        ULONG                       ulTrailerSize
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PHTTP_MBO_CHUNKED_OBJECT        pMyObject    = (PHTTP_MBO_CHUNKED_OBJECT)hThisObject;
    PHTTP_HFP_INTERFACE             pHfpIf       = (PHTTP_HFP_INTERFACE     )pMyObject->hHfpIf;
    PHTTP_BCC_INTERFACE             pBccIf       = (PHTTP_BCC_INTERFACE     )pMyObject->hBccIf;
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp  = NULL;

    pBufferDesp =
        (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
            (
                ulTrailerSize * 2,
                0,
                0
            );

    if ( !pBufferDesp )
    {
        return  ANSC_STATUS_RESOURCES;
    }
    else
    {
        AnscCopyMemory
            (
                pBufferDesp->Buffer,
                pRawTrailer,
                ulTrailerSize
            );

        AnscBdoSetBlockSize(pBufferDesp, ulTrailerSize            );
        AnscBdoSetReserved1(pBufferDesp, HTTP_MBOCHK_BTYPE_TRAILER);
    }

    pMyObject->AppendBodyBdo((ANSC_HANDLE)pMyObject, (ANSC_HANDLE)pBufferDesp);

    returnStatus =
        pMyObject->ParseTrailer
            (
                (ANSC_HANDLE)pMyObject,
                pRawTrailer,
                ulTrailerSize
            );

    returnStatus =
        pBccIf->Notify
            (
                pBccIf->hOwnerContext,
                HTTP_BCC_EVENT_ARRIVED_BODY,
                (ANSC_HANDLE)pBufferDesp
            );

    return  returnStatus;
}
BOOL
HttpApoPubwoAccept
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSocket,
        PANSC_HANDLE                phClientContext
    )
{
    ANSC_STATUS                     returnStatus   = ANSC_STATUS_SUCCESS;
    PHTTP_ADVANCED_PROXY_OBJECT     pMyObject      = (PHTTP_ADVANCED_PROXY_OBJECT   )hThisObject;
    PHTTP_ADVANCED_PROXY_PROPERTY   pProperty      = (PHTTP_ADVANCED_PROXY_PROPERTY )&pMyObject->Property;
    PANSC_SIMPLE_PROXY_TCP_OBJECT   pSimpleProxy   = (PANSC_SIMPLE_PROXY_TCP_OBJECT )pMyObject->hSimpleProxy;
    PHTTP_WAM_INTERFACE             pWamIf         = (PHTTP_WAM_INTERFACE           )pMyObject->hWamIf;
    PHTTP_SBC_INTERFACE             pSbcIf         = (PHTTP_SBC_INTERFACE           )pMyObject->hSbcIf;
    PHTTP_CBC_INTERFACE             pCbcIf         = (PHTTP_CBC_INTERFACE           )pMyObject->hCbcIf;
    PHTTP_PBC_INTERFACE             pPbcIf         = (PHTTP_PBC_INTERFACE           )pMyObject->hPbcIf;
    PANSC_BROKER_SOCKET_TCP_OBJECT  pServerSocket  = (PANSC_BROKER_SOCKET_TCP_OBJECT)hSocket;
    PHTTP_PSO_VER2_OBJECT           pPsoVer2       = NULL;
    PHTTP_TRANS_RECORD_OBJECT       pTransRecord   = NULL;
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp    = NULL;

    AnscTrace
        (
            "PubwoAccept creates a new server connection to %d.%d.%d.%d / TCP %d\n",
            pServerSocket->PeerAddress.Dot[0],
            pServerSocket->PeerAddress.Dot[1],
            pServerSocket->PeerAddress.Dot[2],
            pServerSocket->PeerAddress.Dot[3],
            pServerSocket->PeerPort
        );

    pBufferDesp =
        (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
            (
                HTTP_APO_MAX_MESSAGE_SIZE,
                0,
                0
            );

    if ( pBufferDesp )
    {
        pServerSocket->SetBufferContext
            (
                (ANSC_HANDLE)pServerSocket,
                AnscBdoGetEndOfBlock(pBufferDesp),
                AnscBdoGetLeftSize  (pBufferDesp),
                (ANSC_HANDLE)pBufferDesp
            );
    }

    return  TRUE;
}
BOOL
AnscLpccoTcpBwoAccept
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSocket,
        PANSC_HANDLE                phClientContext
    )
{
    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_BROKER_SOCKET_TCP_OBJECT  pBrokerSocket = (PANSC_BROKER_SOCKET_TCP_OBJECT)hSocket;
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp   = NULL;

    pBufferDesp =
        (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
            (
                ANSC_LPC_DEF_MESSAGE_SIZE,
                0,
                0
            );

    if ( pBufferDesp )
    {
        pBrokerSocket->SetBufferContext
            (
                (ANSC_HANDLE)pBrokerSocket,
                AnscBdoGetEndOfBlock(pBufferDesp),
                AnscBdoGetLeftSize  (pBufferDesp),
                (ANSC_HANDLE)pBufferDesp
            );
    }

    return  TRUE;
}
BOOL
HttpSpoPrvwoAccept
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSocket,
        PANSC_HANDLE                phClientContext
    )
{
    ANSC_STATUS                     returnStatus   = ANSC_STATUS_SUCCESS;
    PHTTP_SIMPLE_PROXY_OBJECT       pMyObject      = (PHTTP_SIMPLE_PROXY_OBJECT     )hThisObject;
    PHTTP_SIMPLE_PROXY_PROPERTY     pProperty      = (PHTTP_SIMPLE_PROXY_PROPERTY   )&pMyObject->Property;
    PANSC_SIMPLE_PROXY_TCP_OBJECT   pSimpleProxy   = (PANSC_SIMPLE_PROXY_TCP_OBJECT )pMyObject->hSimpleProxy;
    PHTTP_WAM_INTERFACE             pWamIf         = (PHTTP_WAM_INTERFACE           )pMyObject->hWamIf;
    PHTTP_SBC_INTERFACE             pSbcIf         = (PHTTP_SBC_INTERFACE           )pMyObject->hSbcIf;
    PHTTP_CBC_INTERFACE             pCbcIf         = (PHTTP_CBC_INTERFACE           )pMyObject->hCbcIf;
    PHTTP_PBC_INTERFACE             pPbcIf         = (PHTTP_PBC_INTERFACE           )pMyObject->hPbcIf;
    PHTTP_HFP_INTERFACE             pHfpIf         = (PHTTP_HFP_INTERFACE           )pMyObject->hHfpIf;
    PANSC_DAEMON_SOCKET_TCP_OBJECT  pClientSocket  = (PANSC_DAEMON_SOCKET_TCP_OBJECT)hSocket;
    PANSC_BROKER_SOCKET_TCP_OBJECT  pServerSocket  = (PANSC_BROKER_SOCKET_TCP_OBJECT)NULL;
    PHTTP_PROXY_SESSION_OBJECT      pSession       = (PHTTP_PROXY_SESSION_OBJECT    )pMyObject->AcquirePso((ANSC_HANDLE)pMyObject);
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp    = NULL;

    AnscTrace
        (
            "PrvwoAccept accepts a new client connection from %d.%d.%d.%d / TCP %d\n",
            pClientSocket->PeerAddress.Dot[0],
            pClientSocket->PeerAddress.Dot[1],
            pClientSocket->PeerAddress.Dot[2],
            pClientSocket->PeerAddress.Dot[3],
            pClientSocket->PeerPort
        );

    *phClientContext = (ANSC_HANDLE)NULL;

    /*
     * This routine is called when there's a new incoming connection (i.e., requested by the HTTP
     * client) is to be established. Following are the processing procedures applied:
     *
     *      (1) create a new HTTP Proxy Session Object for the connection
     *      (2) call sbc_connect(), the Server Behavior Controller either denies the
     *          connection or allows it.
     *      (3) create buffer_descriptor object and associate it with the socket object
     */
    if ( !pSession )
    {
        return  FALSE;
    }
    else
    {
        pSession->SetWamIf       ((ANSC_HANDLE)pSession, (ANSC_HANDLE)pWamIf       );
        pSession->SetSbcIf       ((ANSC_HANDLE)pSession, (ANSC_HANDLE)pSbcIf       );
        pSession->SetCbcIf       ((ANSC_HANDLE)pSession, (ANSC_HANDLE)pCbcIf       );
        pSession->SetPbcIf       ((ANSC_HANDLE)pSession, (ANSC_HANDLE)pPbcIf       );
        pSession->SetHfpIf       ((ANSC_HANDLE)pSession, (ANSC_HANDLE)pHfpIf       );
        pSession->SetClientSocket((ANSC_HANDLE)pSession, (ANSC_HANDLE)pClientSocket);
    }

    if ( !pSession->AcceptClient
            (
                (ANSC_HANDLE)pSession,
                (ANSC_HANDLE)NULL
            ) )
    {
        pSession->Return((ANSC_HANDLE)pSession);

        return  FALSE;
    }
    else
    {
        pSession->SetSessionState((ANSC_HANDLE)pSession, HTTP_PSO_STATE_CLIENT_CONNECTED);
        pSession->Open           ((ANSC_HANDLE)pSession);
    }

    pBufferDesp =
        (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
            (
                HTTP_SPO_MAX_MESSAGE_SIZE,
                0,
                0
            );

    if ( pBufferDesp )
    {
        pClientSocket->SetBufferContext
            (
                (ANSC_HANDLE)pClientSocket,
                AnscBdoGetEndOfBlock(pBufferDesp),
                AnscBdoGetLeftSize  (pBufferDesp),
                (ANSC_HANDLE)pBufferDesp
            );
    }

    *phClientContext = (ANSC_HANDLE)pSession;

    return  TRUE;
}
ANSC_STATUS
HttpWcsoConnectPeer
    (
        ANSC_HANDLE                 hThisObject,
        ULONG                       ipAddrToConnect
    )
{
    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;
    PANSC_SIMPLE_CLIENT_TCP_OBJECT  pTcpSimpleClient = (PANSC_SIMPLE_CLIENT_TCP_OBJECT)pMyObject->hTcpSimpleClient;
    PHTTP_SIMPLE_CLIENT_OBJECT      pHttpSco         = (PHTTP_SIMPLE_CLIENT_OBJECT    )pMyObject->hOwnerContext;
    ULONG                           ulSctoMode       = ANSC_SCTO_MODE_FOREIGN_BUFFER;
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp      = NULL;
    BOOL                            bGotPeerAddr     = TRUE;
    ANSC_IPV4_ADDRESS               PeerAddr;
    PANSC_BUFFER_DESCRIPTOR         pRecvBdo         = (ANSC_HANDLE)NULL;
    ULONG                           ipAddr           = ipAddrToConnect;

TRY_NEXT:
    if ( ipAddr == 0 )
    {
        goto NO_MORE_TRY;
    }

    PeerAddr.Value  = ipAddr;

    pRecvBdo     = (PANSC_BUFFER_DESCRIPTOR)pTcpSimpleClient->GetBufferContext((ANSC_HANDLE)pTcpSimpleClient);
    pTcpSimpleClient->SetBufferContext((ANSC_HANDLE)pTcpSimpleClient, NULL, 0, NULL);

    if ( pRecvBdo )
    {
        AnscReleaseBdo(pRecvBdo);
        pRecvBdo    = NULL;
    }

    returnStatus = pTcpSimpleClient->Cancel((ANSC_HANDLE)pTcpSimpleClient);

    if ( pProperty->SessionFlags & HTTP_WCSO_FLAG_tlsEnabled )
    {
        ulSctoMode |= ANSC_SCTO_MODE_TLS_ENABLED;
    }

    if ( pProperty->SessionFlags & HTTP_WCSO_FLAG_xsocketEnabled )
    {
        ulSctoMode |= ANSC_SCTO_MODE_XSOCKET;
    }

    pTcpSimpleClient->SetHostAddress   ((ANSC_HANDLE)pTcpSimpleClient, pProperty->HostAddr.Dot   );
    pTcpSimpleClient->SetHostPort      ((ANSC_HANDLE)pTcpSimpleClient, pProperty->HostPort       );
    pTcpSimpleClient->SetPeerName      ((ANSC_HANDLE)pTcpSimpleClient, pProperty->PeerName       );
    pTcpSimpleClient->SetPeerAddress   ((ANSC_HANDLE)pTcpSimpleClient, PeerAddr.Dot              );
    pTcpSimpleClient->SetPeerPort      ((ANSC_HANDLE)pTcpSimpleClient, pProperty->PeerPort       );
    pTcpSimpleClient->SetMaxMessageSize((ANSC_HANDLE)pTcpSimpleClient, HTTP_WCSO_MAX_MESSAGE_SIZE);
    pTcpSimpleClient->SetMode          ((ANSC_HANDLE)pTcpSimpleClient, ulSctoMode                );

    //    fprintf(stderr, "<RT> %s: HTTP Client DeviceName = '%s'\n", __FUNCTION__, pHttpSco ? pHttpSco->Property.BindToDevice.DeviceName : "NULL");
    if( pHttpSco && pHttpSco->Property.BindToDevice.DeviceName[0] &&
        AnscSizeOfString(pHttpSco->Property.BindToDevice.DeviceName) < ANSC_OBJ_IF_NAME_SIZE)
    {
        pTcpSimpleClient->SetSocketBindToDevice ((ANSC_HANDLE)pTcpSimpleClient, TRUE);
        pTcpSimpleClient->SetSocketDeviceName   ((ANSC_HANDLE)pTcpSimpleClient, pHttpSco->Property.BindToDevice.DeviceName);
    }
    else 
    {
        pTcpSimpleClient->SetSocketBindToDevice ((ANSC_HANDLE)pTcpSimpleClient, FALSE);
        pTcpSimpleClient->SetSocketDeviceName   ((ANSC_HANDLE)pTcpSimpleClient, "");
    }

    returnStatus = pTcpSimpleClient->Engage((ANSC_HANDLE)pTcpSimpleClient);

NO_MORE_TRY:
    if ( returnStatus != ANSC_STATUS_SUCCESS )
    {
        if ( bGotPeerAddr )
        {
            BOOL                    bSucc   = FALSE;

            bSucc   = pHttpSco->GetNextPeerAddr((ANSC_HANDLE)pHttpSco, &ipAddr);

            if ( bSucc && ipAddr != 0 )
            {
                pMyObject->SessionState = HTTP_WCSO_STATE_INITIALIZED;

                goto TRY_NEXT;
            }
        }

        return  ANSC_STATUS_FAILURE;
    }
    else
    {
        pMyObject->SessionState = HTTP_WCSO_STATE_SERVER_CONNECTED;
    }

    pBufferDesp =
        (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
            (
                HTTP_WCSO_MAX_MESSAGE_SIZE,
                0,
                0
            );

    if ( pBufferDesp )
    {
        pTcpSimpleClient->SetBufferContext
            (
                (ANSC_HANDLE)pTcpSimpleClient,
                AnscBdoGetEndOfBlock(pBufferDesp),
                AnscBdoGetLeftSize  (pBufferDesp),
                (ANSC_HANDLE)pBufferDesp
            );
    }

    return returnStatus;
}
ANSC_STATUS
HttpBmoAppendBody
    (
        ANSC_HANDLE                 hThisObject,
        PVOID                       buffer,
        ULONG                       ulSize
    )
{
    ANSC_STATUS                     returnStatus = ANSC_STATUS_SUCCESS;
    PHTTP_BASIC_MESSAGE_OBJECT      pMyObject    = (PHTTP_BASIC_MESSAGE_OBJECT)hThisObject;
    PHTTP_HFP_INTERFACE             pHfpIf       = (PHTTP_HFP_INTERFACE       )pMyObject->hHfpIf;
    PHTTP_TMH_INTERFACE             pTmhIf       = (PHTTP_TMH_INTERFACE       )pMyObject->hTmhIf;
    PHTTP_BCC_INTERFACE             pBccIf       = (PHTTP_BCC_INTERFACE       )pMyObject->hBccIf;
    PHTTP_MESSAGE_BODY_OBJECT       pMessageBody = (PHTTP_MESSAGE_BODY_OBJECT )pMyObject->hMessageBody;
    PANSC_BUFFER_DESCRIPTOR         pBodyBdo     = (PANSC_BUFFER_DESCRIPTOR   )NULL;

    if ( !pMessageBody )
    {
        pMessageBody = (PHTTP_MESSAGE_BODY_OBJECT)pMyObject->CreateMessageBody((ANSC_HANDLE)pMyObject);

        if ( !pMessageBody )
        {
            return  ANSC_STATUS_RESOURCES;
        }
        else
        {
            pMyObject->hMessageBody = (ANSC_HANDLE)pMessageBody;

            pMessageBody->SetMode ((ANSC_HANDLE)pMessageBody, pMyObject->MboMode );
            pMessageBody->SetHfpIf((ANSC_HANDLE)pMessageBody, (ANSC_HANDLE)pHfpIf);
            pMessageBody->SetBccIf((ANSC_HANDLE)pMessageBody, (ANSC_HANDLE)pBccIf);
        }
    }

    if ( TRUE )
    {
        pBodyBdo =
            (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
                (
                    ulSize,
                    0,
                    ulSize
                );

        if ( !pBodyBdo )
        {
            return  ANSC_STATUS_RESOURCES;
        }
        else
        {
            AnscCopyMemory
                (
                    AnscBdoGetBlock(pBodyBdo),
                    buffer,
                    ulSize
                );
        }
    }

    if ( pMessageBody )
    {
        returnStatus =
            pMessageBody->AppendBodyBdo
                (
                    (ANSC_HANDLE)pMessageBody,
                    (ANSC_HANDLE)pBodyBdo
                );
    }

    return  returnStatus;
}
ULONG
AnscLpccoTcpBwoQuery
    (
        ANSC_HANDLE                 hThisObject,
        ANSC_HANDLE                 hSocket,
        PVOID                       buffer,
        ULONG                       ulSize,
        PANSC_HANDLE                phQueryContext
    )
{
    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_BROKER_SOCKET_TCP_OBJECT  pBrokerSocket = (PANSC_BROKER_SOCKET_TCP_OBJECT)hSocket;
    PANSC_BUFFER_DESCRIPTOR         pBufferDesp   = (PANSC_BUFFER_DESCRIPTOR       )pBrokerSocket->GetBufferContext((ANSC_HANDLE)pBrokerSocket);
    PANSC_BUFFER_DESCRIPTOR         pNewBdo       = (PANSC_BUFFER_DESCRIPTOR       )NULL;
    PIMCP_HEADER                    pImcpHeader   = (PIMCP_HEADER                  )NULL;
    ULONG                           ulMsgSize     = (ULONG                         )0;
    ULONG                           ulCopySize    = (ULONG                         )0;
    ULONG                           ulLeftSize    = (ULONG                         )0;
    ULONG                           i             = 0;

    if ( !pBufferDesp )
    {
        return  ANSC_BSTOWO_PMODE_FINISH;
    }
    else
    {
        pBufferDesp->BlockSize += ulSize;
    }

    if ( AnscBdoGetUsableSize(pBufferDesp) <= sizeof(IMCP_HEADER) )
    {
        pNewBdo =
            (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
                (
                    ANSC_LPC_DEF_MESSAGE_SIZE,
                    0,
                    AnscBdoGetBlockSize(pBufferDesp)
                );

        if ( !pNewBdo )
        {
            return  ANSC_BSTOWO_PMODE_FINISH;
        }
        else
        {
            ulCopySize   = AnscBdoGetBlockSize(pBufferDesp);
            returnStatus =
                AnscBdoCopyFrom
                    (
                        (ANSC_HANDLE)pBufferDesp,
                        AnscBdoGetBlock(pNewBdo),
                        &ulCopySize,
                        0
                    );

            pBrokerSocket->SetBufferContext
                (
                    (ANSC_HANDLE)pBrokerSocket,
                    AnscBdoGetEndOfBlock(pNewBdo),
                    AnscBdoGetLeftSize  (pNewBdo),
                    (ANSC_HANDLE)pNewBdo
                );
        }

        AnscFreeBdo((ANSC_HANDLE)pBufferDesp);

        return  ANSC_BSTOWO_PMODE_COLLECT;
    }
    else if ( AnscBdoGetBlockSize(pBufferDesp) < sizeof(IMCP_HEADER) )
    {
        /*
         * We need to rollback the block size of the buffer descriptor before we return 'Collect'.
         * Next time when this Query() function is called, the 'ulSize' parameter will be set to
         * the total size of un-processed data, not the size of the newly received data.
         */
        pBufferDesp->BlockSize -= ulSize;

        return  ANSC_BSTOWO_PMODE_COLLECT;
    }
    else
    {
        pImcpHeader = (PIMCP_HEADER)AnscBdoGetBlock(pBufferDesp);
        ulMsgSize   = (ULONG       )ImcpGetMsgSize (pImcpHeader);
    }

    if ( ulMsgSize == AnscBdoGetBlockSize(pBufferDesp) )
    {
        pNewBdo =
            (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
                (
                    ANSC_LPC_DEF_MESSAGE_SIZE,
                    0,
                    0
                );

        if ( !pNewBdo )
        {
            return  ANSC_BSTOWO_PMODE_FINISH;
        }
        else
        {
            pBrokerSocket->SetBufferContext
                (
                    (ANSC_HANDLE)pBrokerSocket,
                    AnscBdoGetEndOfBlock(pNewBdo),
                    AnscBdoGetLeftSize  (pNewBdo),
                    (ANSC_HANDLE)pNewBdo
                );
        }

        returnStatus =
            pMyObject->Recv
                (
                    (ANSC_HANDLE)pMyObject,
                    (ANSC_HANDLE)pBrokerSocket,
                    (ANSC_HANDLE)pBufferDesp
                );

        return  ANSC_BSTOWO_PMODE_DISCARD;
    }
    else if ( ulMsgSize < AnscBdoGetBlockSize(pBufferDesp) )
    {
        pNewBdo =
            (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
                (
                    ulMsgSize,
                    0,
                    ulMsgSize
                );

        if ( !pNewBdo )
        {
            return  ANSC_BSTOWO_PMODE_FINISH;
        }
        else
        {
            ulCopySize   = ulMsgSize;
            returnStatus =
                AnscBdoCopyFrom
                    (
                        (ANSC_HANDLE)pBufferDesp,
                        AnscBdoGetBlock(pNewBdo),
                        &ulCopySize,
                        0
                    );
        }

        returnStatus =
            pMyObject->Recv
                (
                    (ANSC_HANDLE)pMyObject,
                    (ANSC_HANDLE)pBrokerSocket,
                    (ANSC_HANDLE)pNewBdo
                );

        /*
         * As Lina discovered, we cannot simply reset the 'BlockSize' to zero and make another
         * Query() call. If we do and the returned mode is COLLECT, the socket object would be
         * confused because the data processed in this call is still remembered and its size will
         * be covered in the next Query() call. We need to follow the steps as listed below to
         * ensure the packet data in the previous call is cleaned:
         *
         *      - Set the 'BlockSize' to whatever data left after processing.
         *      - Advance 'Offset' field by the message size.
         *      - Reset the buffer context of the socket object.
         *      - Calling Query() again with 'ulSize' set to zero.
         */
        ulLeftSize              = AnscBdoGetBlockSize(pBufferDesp) - ulMsgSize;
        pBufferDesp->Offset    += ulMsgSize;
        pBufferDesp->BlockSize -= ulMsgSize;

        pBrokerSocket->SetBufferContext
            (
                (ANSC_HANDLE)pBrokerSocket,
                AnscBdoGetEndOfBlock(pBufferDesp),
                AnscBdoGetLeftSize  (pBufferDesp),
                (ANSC_HANDLE)pBufferDesp
            );

        return  pMyObject->BwoQuery
                    (
                        (ANSC_HANDLE)pMyObject,
                        (ANSC_HANDLE)pBrokerSocket,
                        AnscBdoGetEndOfBlock(pBufferDesp),  /*AnscBdoGetBlock(pBufferDesp),*/
                        0,                                  /*ulLeftSize,                  */
                        phQueryContext
                    );
    }
    else if ( ulMsgSize <= AnscBdoGetUsableSize(pBufferDesp) )
    {
        /*
         * We need to rollback the block size of the buffer descriptor before we return 'Collect'.
         * Next time when this Query() function is called, the 'ulSize' parameter will be set to
         * the total size of un-processed data, not the size of the newly received data.
         */
        pBufferDesp->BlockSize -= ulSize;

        return  ANSC_BSTOWO_PMODE_COLLECT;
    }
    else
    {
        pNewBdo =
            (PANSC_BUFFER_DESCRIPTOR)AnscAllocateBdo
                (
                    ulMsgSize,
                    0,
                    AnscBdoGetBlockSize(pBufferDesp)
                );

        if ( !pNewBdo )
        {
            return  ANSC_BSTOWO_PMODE_FINISH;
        }
        else
        {
            ulCopySize   = AnscBdoGetBlockSize(pBufferDesp);
            returnStatus =
                AnscBdoCopyFrom
                    (
                        (ANSC_HANDLE)pBufferDesp,
                        AnscBdoGetBlock(pNewBdo),
                        &ulCopySize,
                        0
                    );

            pBrokerSocket->SetBufferContext
                (
                    (ANSC_HANDLE)pBrokerSocket,
                    AnscBdoGetEndOfBlock(pNewBdo),
                    AnscBdoGetLeftSize  (pNewBdo),
                    (ANSC_HANDLE)pNewBdo
                );
        }

        AnscFreeBdo((ANSC_HANDLE)pBufferDesp);

        return  ANSC_BSTOWO_PMODE_COLLECT;
    }

    return  ANSC_BSTOWO_PMODE_DISCARD;
}