gsoapwininet.cpp

来自「linux下简单对象应用协议的开发库」· C++ 代码 · 共 1,106 行 · 第 1/3 页

CPP
1,106
字号
    _ASSERTE( sizeof(soap->socket) >= sizeof(HINTERNET) );    return (SOAP_SOCKET) hHttpRequest;}/* gsoap documentation:    Called by http_post and http_response (through the callbacks). Emits HTTP     key: val header entries. Should return SOAP_OK, or a gSOAP error code.     Built-in gSOAP function: http_post_header. */static int wininet_post_header(    struct soap *   soap,     const char *    a_pszKey,     const char *    a_pszValue )  {    HINTERNET hHttpRequest = (HINTERNET) soap->socket;    char      szHeader[4096];    int       nLen;    BOOL      bResult = FALSE;    struct wininet_data * pData =         (struct wininet_data *) soap_lookup_plugin( soap, wininet_id );    soap->error = SOAP_OK;    /* ensure that our connection hasn't been disconnected */    if ( !wininet_have_connection( soap, pData ) )    {        return SOAP_EOF;    }    /* if this is the initial POST header then we initialize our send buffer */    if ( a_pszKey && !a_pszValue )    {        _ASSERTE( !pData->pBuffer );        pData->uiBufferLenMax = INVALID_BUFFER_LENGTH;        pData->uiBufferLen    = 0;        /* if we are using chunk output then we start with a chunk size */        pData->bIsChunkSize = ( (soap->omode & SOAP_IO) == SOAP_IO_CHUNK );    }    else if ( a_pszValue )    {         DBGLOG(TEST, SOAP_MESSAGE(fdebug,             "wininet %p: post_header, adding '%s: %s'\n",             soap, a_pszKey, a_pszValue ));        /* determine the maximum length of this message so that we can           correctly determine when we have completed the send */        if ( !strcmp( a_pszKey, "Content-Length" ) )        {            _ASSERTE( pData->uiBufferLenMax == INVALID_BUFFER_LENGTH );            pData->uiBufferLenMax = strtoul( a_pszValue, NULL, 10 );        }        nLen = _snprintf(             szHeader, 4096, "%s: %s\r\n", a_pszKey, a_pszValue );        if ( nLen < 0 )        {            return SOAP_EOM;        }        bResult = HttpAddRequestHeadersA( hHttpRequest, szHeader, nLen,             HTTP_ADDREQ_FLAG_ADD_IF_NEW );#ifdef SOAP_DEBUG        /*             we don't return an error if this fails because it isn't             (or shouldn't be) critical.         */        if ( !bResult )        {            DBGLOG(TEST, SOAP_MESSAGE(fdebug,                 "wininet %p: post_header, error %d (%s) in HttpAddRequestHeaders\n",                 soap, soap->error, wininet_error_message(soap,GetLastError()) ));        }#endif    }    return SOAP_OK; }/* gsoap documentation:    Called for all send operations to emit contents of s of length n.     Should return SOAP_OK, or a gSOAP error code. Built-in gSOAP     function: fsend   Notes:    I do a heap of buffering here because we need the entire message available    in a single buffer in order to iterate through the sending loop. I had     hoped that the SOAP_IO_STORE flag would have worked to do the same, however    this still breaks the messages up into blocks. Although there were a number    of ways this could've been implemented, this works and supports all of the    possible SOAP_IO flags, even though the entire message is still buffered     the same as if SOAP_IO_STORE was used.*/static int wininet_fsend(     struct soap *   soap,     const char *    a_pBuffer,     size_t          a_uiBufferLen ){    HINTERNET   hHttpRequest = (HINTERNET) soap->socket;    BOOL        bResult;    BOOL        bRetryPost;    DWORD       dwStatusCode;    DWORD       dwStatusCodeLen;    int         nResult = SOAP_OK;    struct wininet_data * pData =         (struct wininet_data *) soap_lookup_plugin( soap, wininet_id );    soap->error = SOAP_OK;    DBGLOG(TEST, SOAP_MESSAGE(fdebug,         "wininet %p: fsend, data len = %lu bytes\n", soap, a_uiBufferLen ));    /* allow the request to be sent with a NULL buffer */    if (a_uiBufferLen == 0)    {        pData->uiBufferLenMax = 0;    }    /* ensure that our connection hasn't been disconnected */    if ( !wininet_have_connection( soap, pData ) )    {        return SOAP_EOF;    }    /* initialize on our first time through. pData->pBuffer will always be        non-null if this is not the first call. */    if ( !pData->pBuffer )    {        /*             If we are using chunked sending, then we don't know how big the            buffer will need to be. So we start with a 0 length buffer and            grow it later to ensure that it is always large enough.                uiBufferLenMax = length of the allocated memory                uiBufferLen    = length of the data in the buffer         */        if ( (soap->mode & SOAP_IO) == SOAP_IO_CHUNK )        {            /* we make the initial allocation large enough for this chunksize                buffer, plus the next chunk of actual data, and a few extra                bytes for the final "0" chunksize block. */            size_t uiChunkSize = strtoul( a_pBuffer, NULL, 16 );            pData->uiBufferLenMax = uiChunkSize + a_uiBufferLen + 16;        }        else if ( a_uiBufferLen == pData->uiBufferLenMax )        {            /*                  If the currently supplied buffer from gsoap holds the entire                 message then we just use their buffer and avoid any memory                 allocation. This will only be true when (1) we are not using                 chunked send (so uiBufferLenMax has been previously set to                 the Content-Length header length), and (2) gsoap is sending                 the entire message at one time.              */            pData->pBuffer     = (char *) a_pBuffer;            pData->uiBufferLen = a_uiBufferLen;        }        _ASSERTE( pData->uiBufferLenMax != INVALID_BUFFER_LENGTH );    }    /*        If we can't use the gsoap buffer, then we need to allocate our own        buffer for the entire message. This is because authentication may         require the entire message to be sent multiple times. Since this send        is only a part of the message, we need to buffer until we have the         entire message.    */    if ( pData->pBuffer != a_pBuffer )    {        /*             We already have a buffer pointer, this means that it isn't the             first time we have been called. We have allocated a buffer and             are current filling it.                         If we don't have enough room in the our buffer to add this new             data, then we need to reallocate. This case will only occur with             chunked sends.          */        size_t uiNewBufferLen = pData->uiBufferLen + a_uiBufferLen;        if ( !pData->pBuffer || uiNewBufferLen > pData->uiBufferLenMax )        {            while ( uiNewBufferLen > pData->uiBufferLenMax )            {                pData->uiBufferLenMax = pData->uiBufferLenMax * 2;            }            pData->pBuffer = (char *) realloc( pData->pBuffer, pData->uiBufferLenMax );            if ( !pData->pBuffer )            {                return SOAP_EOM;            }        }        memcpy( pData->pBuffer + pData->uiBufferLen,             a_pBuffer, a_uiBufferLen );        pData->uiBufferLen = uiNewBufferLen;        /* if we are doing chunked transfers, and this is a chunk size block,           and it is "0", then this is the last block in the transfer and we           can set the maximum size now to continue to the actual send. */        if ( (soap->mode & SOAP_IO) == SOAP_IO_CHUNK             && pData->bIsChunkSize              && a_pBuffer[2] == '0' && !isalnum(a_pBuffer[3]) )        {            pData->uiBufferLenMax = pData->uiBufferLen;        }    }    /* if we haven't got the entire length of the message yet, then        we return to gsoap and let it continue */    if ( pData->uiBufferLen < pData->uiBufferLenMax )    {        /* toggle our chunk size marker if we are chunking */        pData->bIsChunkSize =             ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)             && !pData->bIsChunkSize;         return SOAP_OK;    }    _ASSERTE( pData->uiBufferLen == pData->uiBufferLenMax );    /* we've now got the entire message, now we can enter our sending loop */    bRetryPost = TRUE;    while ( bRetryPost )    {        bRetryPost = FALSE;        bResult = HttpSendRequestA(             hHttpRequest, NULL, 0, pData->pBuffer, pData->uiBufferLen );        if ( !bResult )        {            soap->error = GetLastError();            DBGLOG(TEST, SOAP_MESSAGE(fdebug,                 "wininet %p: fsend, error %d (%s) in HttpSendRequest\n",                 soap, soap->error, wininet_error_message(soap,soap->error) ));            /* see if we can handle this error, see the MSDN documentation               for InternetErrorDlg for details */            switch ( soap->error )            {            case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:            case ERROR_INTERNET_INCORRECT_PASSWORD:            case ERROR_INTERNET_INVALID_CA:            case ERROR_INTERNET_POST_IS_NON_SECURE:            case ERROR_INTERNET_SEC_CERT_CN_INVALID:            case ERROR_INTERNET_SEC_CERT_DATE_INVALID:		{		wininet_rseReturn errorResolved = rseDisplayDlg;		if (pData->pRseCallback)			errorResolved = pData->pRseCallback(hHttpRequest, soap->error);		if (errorResolved == rseDisplayDlg)			errorResolved = (wininet_rseReturn)wininet_resolve_send_error( hHttpRequest, soap->error );			if ( errorResolved == rseTrue )			{				DBGLOG(TEST, SOAP_MESSAGE(fdebug, 				"wininet %p: fsend, error %d has been resolved\n", 				soap, soap->error ));				bRetryPost = TRUE;                    /*                         we would have been disconnected by the error. Since we                         are going to try again, we will automatically be                         reconnected. Therefore we want to disregard any                         previous disconnection messages.                      */                    		pData->bDisconnect = FALSE;                     		continue;			}                }            }            /* if the error wasn't handled then we exit */            nResult = SOAP_HTTP_ERROR;            break;        }        /* get the status code from the response to determine if we need            to authorize */        dwStatusCodeLen = sizeof(dwStatusCode);        bResult = HttpQueryInfo(             hHttpRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,             &dwStatusCode, &dwStatusCodeLen, NULL);        if ( !bResult )        {            soap->error = GetLastError();            DBGLOG(TEST, SOAP_MESSAGE(fdebug,                 "wininet %p: fsend, error %d (%s) in HttpQueryInfo\n",                 soap, soap->error, wininet_error_message(soap,soap->error) ));            nResult = SOAP_HTTP_ERROR;            break;        }        DBGLOG(TEST, SOAP_MESSAGE(fdebug,             "wininet %p: fsend, HTTP status code = %lu\n",             soap, dwStatusCode));        /*             if we need authentication, then request the user for the             appropriate data. Their reply is saved into the request so             that we can use it later.         */        switch ( dwStatusCode )        {        case HTTP_STATUS_DENIED:        case HTTP_STATUS_PROXY_AUTH_REQ:	    {	    wininet_rseReturn errorResolved = rseDisplayDlg;            DBGLOG(TEST, SOAP_MESSAGE(fdebug,                 "wininet %p: fsend, user authenication required\n",                 soap ));	    if (pData->pRseCallback)			errorResolved = pData->pRseCallback(hHttpRequest, dwStatusCode);	    if (errorResolved == rseDisplayDlg)			errorResolved = (wininet_rseReturn)wininet_resolve_send_error( hHttpRequest, ERROR_INTERNET_INCORRECT_PASSWORD );	    if ( errorResolved == rseTrue )            {                DBGLOG(TEST, SOAP_MESSAGE(fdebug,                     "wininet %p: fsend, authentication has been provided\n",                     soap ));                /*                     we may have been disconnected by the error. Since we                     are going to try again, we will automatically be                     reconnected. Therefore we want to disregard any previous                    disconnection messages.                     */                pData->bDisconnect = FALSE;                 bRetryPost = TRUE;                continue;            }	    }        }    }    /* if we have an allocated buffer then we can deallocate it now */    if ( pData->pBuffer != a_pBuffer )    {        free( pData->pBuffer );    }    pData->pBuffer     = 0;    pData->uiBufferLen = 0;    pData->uiBufferLenMax = INVALID_BUFFER_LENGTH;    return nResult; }/* gsoap documentation:    Called for all receive operations to fill buffer s of maximum length n.     Should return the number of bytes read or 0 in case of an error, e.g. EOF.    Built-in gSOAP function: frecv */static size_t wininet_frecv(    struct soap *   soap,     char *          a_pBuffer,     size_t          a_uiBufferLen ) {     HINTERNET   hHttpRequest = (HINTERNET) soap->socket;    DWORD       dwBytesRead = 0;    size_t      uiTotalBytesRead = 0;    BOOL        bResult;    soap->error = SOAP_OK;    DBGLOG(TEST, SOAP_MESSAGE(fdebug,         "wininet %p: frecv, available buffer len = %lu\n",         soap, a_uiBufferLen ));    /*         NOTE: we do not check here that our connection hasn't been         disconnected because in HTTP/1.0 connections, it will always have been

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?