gsoapwininet.cpp
来自「linux下简单对象应用协议的开发库」· C++ 代码 · 共 1,106 行 · 第 1/3 页
CPP
1,106 行
/*gsoapWinInet.cppSee the header file for details.Redistribution: This code is redistributed as part of the gSOAP software, under the gsoap public license terms and conditions. These conditions are compatible with open source and commercial licensing.*//* system */#include <windows.h>#include <crtdbg.h>#include <wininet.h>/* gsoap */#include <stdsoap2.h>/* local */#include "gsoapWinInet.h"/* ensure that the wininet library is linked */#pragma comment( lib, "wininet.lib" )#define UNUSED_ARG(x) (x)#define INVALID_BUFFER_LENGTH ((DWORD)-1)typedef unsigned long DWORD_PTR;/* plugin id */static const char wininet_id[] = "wininet-2.0";/* plugin private data */struct wininet_data{ HINTERNET hInternet; /* internet session handle */ HINTERNET hConnection; /* current connection handle */ BOOL bDisconnect; /* connection is disconnected */ DWORD dwRequestFlags; /* extra request flags from user */ char * pBuffer; /* send buffer */ size_t uiBufferLenMax; /* total length of the message */ size_t uiBufferLen; /* length of data in buffer */ BOOL bIsChunkSize; /* expecting a chunk size buffer */ wininet_rse_callback pRseCallback; /* wininet_resolve_send_error callback. Allows clients to resolve ssl errors programatically */#ifdef SOAP_DEBUG /* this is only used for DBGLOG output */ char * pszErrorMessage; /* wininet/system error message */#endif};/* forward declarations */static BOOLwininet_init( struct soap * soap, struct wininet_data * a_pData, DWORD a_dwRequestFlags );static int wininet_copy( struct soap * soap, struct soap_plugin * a_pDst, struct soap_plugin * a_pSrc );static void wininet_delete( struct soap * soap, struct soap_plugin * a_pPluginData );static int wininet_connect( struct soap * soap, const char * a_pszEndpoint, const char * a_pszHost, int a_nPort );static int wininet_post_header( struct soap * soap, const char * a_pszKey, const char * a_pszValue );static int wininet_fsend( struct soap * soap, const char * a_pBuffer, size_t a_uiBufferLen );static size_t wininet_frecv( struct soap * soap, char * a_pBuffer, size_t a_uiBufferLen );static int wininet_disconnect( struct soap * soap );void CALLBACKwininet_callback( HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength );static BOOLwininet_have_connection( struct soap * soap, struct wininet_data * a_pData );static DWORDwininet_set_timeout( struct soap * soap, struct wininet_data * a_pData, const char * a_pszTimeout, DWORD a_dwOption, int a_nTimeout );static BOOLwininet_resolve_send_error( HINTERNET a_hHttpRequest, DWORD a_dwErrorCode );#ifdef SOAP_DEBUG/* this is only used for DBGLOG output */static const char *wininet_error_message( struct soap * a_pData, DWORD a_dwErrorMsgId );static voidwininet_free_error_message( struct wininet_data * a_pData );#else#define wininet_free_error_message(x)#endif/* plugin registration */int wininet_plugin( struct soap * soap, struct soap_plugin * a_pPluginData, void * a_dwRequestFlags ){ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: plugin registration\n", soap )); a_pPluginData->id = wininet_id; a_pPluginData->fcopy = wininet_copy; a_pPluginData->fdelete = wininet_delete; a_pPluginData->data = (void*) malloc( sizeof(struct wininet_data) ); if ( !a_pPluginData->data ) { return SOAP_EOM; } if ( !wininet_init( soap, (struct wininet_data *) a_pPluginData->data, (DWORD) a_dwRequestFlags ) ) { free( a_pPluginData->data ); return SOAP_EOM; }#ifdef SOAP_DEBUG if ( (soap->omode & SOAP_IO) == SOAP_IO_STORE ) { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: use of SOAP_IO_STORE is not recommended\n", soap )); }#endif return SOAP_OK;}/* initialize private data */static BOOLwininet_init( struct soap * soap, struct wininet_data * a_pData, DWORD a_dwRequestFlags ){ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: init private data\n", soap )); memset( a_pData, 0, sizeof(struct wininet_data) ); a_pData->dwRequestFlags = a_dwRequestFlags; /* start our internet session */ a_pData->hInternet = InternetOpenA( "gSOAP", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); if ( !a_pData->hInternet ) { soap->error = GetLastError(); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: init, error %d (%s) in InternetOpen\n", soap, soap->error, wininet_error_message(soap,soap->error) )); wininet_free_error_message( a_pData ); return FALSE; } /* set the timeouts, if any of these fail the error isn't fatal */ wininet_set_timeout( soap, a_pData, "connect", INTERNET_OPTION_CONNECT_TIMEOUT, soap->connect_timeout ); wininet_set_timeout( soap, a_pData, "receive", INTERNET_OPTION_RECEIVE_TIMEOUT, soap->recv_timeout ); wininet_set_timeout( soap, a_pData, "send", INTERNET_OPTION_SEND_TIMEOUT, soap->send_timeout ); /* set up the callback function so we get notifications */ InternetSetStatusCallback( a_pData->hInternet, wininet_callback ); /* set all of our callbacks */ soap->fopen = wininet_connect; soap->fposthdr = wininet_post_header; soap->fsend = wininet_fsend; soap->frecv = wininet_frecv; soap->fclose = wininet_disconnect; return TRUE;}void wininet_set_rse_callback( struct soap* soap, wininet_rse_callback a_pRsecallback){ struct wininet_data * pData = (struct wininet_data *) soap_lookup_plugin( soap, wininet_id ); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: resolve_send_error callback = '%p'\n", soap, a_pRsecallback )); pData->pRseCallback = a_pRsecallback;}/* copy the private data structure */static int wininet_copy( struct soap * soap, struct soap_plugin * a_pDst, struct soap_plugin * a_pSrc ){ UNUSED_ARG( soap ); UNUSED_ARG( a_pDst ); UNUSED_ARG( a_pSrc ); _ASSERTE( !"wininet doesn't support copy" ); return SOAP_FATAL_ERROR;}/* deallocate of our private structure */static void wininet_delete( struct soap * soap, struct soap_plugin * a_pPluginData ){ struct wininet_data * pData = (struct wininet_data *) a_pPluginData->data; UNUSED_ARG( soap ); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: delete private data\n", soap )); /* force a disconnect of any existing connection */ pData->bDisconnect = TRUE; wininet_have_connection( soap, pData ); /* close down the internet */ if ( pData->hInternet ) { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: closing internet handle\n", soap)); InternetCloseHandle( pData->hInternet ); pData->hInternet = NULL; } /* free our data */ wininet_free_error_message( pData ); free( a_pPluginData->data );}/* gsoap documentation: Called from a client proxy to open a connection to a Web Service located at endpoint. Input parameters host and port are micro-parsed from endpoint. Should return a valid file descriptor, or SOAP_INVALID_SOCKET and soap->error set to an error code. Built-in gSOAP function: tcp_connect*/static int wininet_connect( struct soap * soap, const char * a_pszEndpoint, const char * a_pszHost, int a_nPort ){ URL_COMPONENTSA urlComponents; char szUrlPath[MAX_PATH]; char szHost[MAX_PATH]; DWORD dwFlags; HINTERNET hConnection = NULL; HINTERNET hHttpRequest = NULL; struct wininet_data * pData = (struct wininet_data *) soap_lookup_plugin( soap, wininet_id ); soap->error = SOAP_OK; /* we parse the URL ourselves so we don't use these parameters */ UNUSED_ARG( a_pszHost ); UNUSED_ARG( a_nPort ); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, endpoint = '%s'\n", soap, a_pszEndpoint )); /* we should be initialized but not connected */ _ASSERTE( pData->hInternet ); _ASSERTE( !pData->hConnection ); _ASSERTE( soap->socket == SOAP_INVALID_SOCKET ); /* parse out the url path */ memset( &urlComponents, 0, sizeof(urlComponents) ); urlComponents.dwStructSize = sizeof(urlComponents); urlComponents.lpszHostName = szHost; urlComponents.dwHostNameLength = MAX_PATH; urlComponents.lpszUrlPath = szUrlPath; urlComponents.dwUrlPathLength = MAX_PATH; if ( !InternetCrackUrlA( a_pszEndpoint, 0, 0, &urlComponents ) ) { InternetCloseHandle( hConnection ); soap->error = GetLastError(); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, error %d (%s) in InternetCrackUrl\n", soap, soap->error, wininet_error_message(soap,soap->error) )); return SOAP_INVALID_SOCKET; } /* connect to the target url, if we haven't connected yet or if it was dropped */ hConnection = InternetConnectA( pData->hInternet, szHost, urlComponents.nPort, "", "", INTERNET_SERVICE_HTTP, 0, (DWORD_PTR) soap ); if ( !hConnection ) { soap->error = GetLastError(); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, error %d (%s) in InternetConnect\n", soap, soap->error, wininet_error_message(soap,soap->error) )); return SOAP_INVALID_SOCKET; } /* Note that although we specify HTTP/1.1 for the connection here, the actual connection may be HTTP/1.0 depending on the settings in the control panel. See the "Internet Options", "HTTP 1.1 settings". */ dwFlags = pData->dwRequestFlags; if ( soap->omode & SOAP_IO_KEEPALIVE ) { dwFlags |= INTERNET_FLAG_KEEP_CONNECTION; } if ( urlComponents.nScheme == INTERNET_SCHEME_HTTPS ) { dwFlags |= INTERNET_FLAG_SECURE; } hHttpRequest = HttpOpenRequestA( hConnection, "POST", szUrlPath, "HTTP/1.1", NULL, NULL, dwFlags, (DWORD_PTR) soap ); if ( !hHttpRequest ) { InternetCloseHandle( hConnection ); soap->error = GetLastError(); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, error %d (%s) in HttpOpenRequest\n", soap, soap->error, wininet_error_message(soap,soap->error) )); return SOAP_INVALID_SOCKET; } /* save the connection handle in our data structure */ pData->hConnection = hConnection; /* return the http request handle as our file descriptor. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?