⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 net.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
	if( pWinHttpGetDefaultProxyConfiguration != NULL && \
		pWinHttpGetDefaultProxyConfiguration( &proxyInfo ) && \
		proxyInfo.lpszProxy != NULL )
		{
		count = wcstombs( proxy, proxyInfo.lpszProxy, MAX_DNS_SIZE );
		GlobalFree( proxyInfo.lpszProxy );
		if( proxyInfo.lpszProxyBypass != NULL )
			GlobalFree( proxyInfo.lpszProxy );
		}

	/* The next fallback is to get the proxy info from MSIE.  This is also 
	   usually much quicker than WinHttpGetProxyForUrl(), although sometimes
	   it seems to fall back to that, based on the longish delay involved.
	   Another issue with this is that it won't work in a service process
	   that isn't impersonating an interactive user (since there isn't a
	   current user), but in that case we just fall back to 
	   WinHttpGetProxyForUrl() */
	if( pWinHttpGetIEProxyConfigForCurrentUser != NULL && \
		pWinHttpGetIEProxyConfigForCurrentUser( &ieProxyInfo ) )
		{
		count = wcstombs( proxy, ieProxyInfo.lpszProxy, MAX_DNS_SIZE );
		if( ieProxyInfo.lpszAutoConfigUrl != NULL )
			GlobalFree( ieProxyInfo.lpszAutoConfigUrl );
		if( ieProxyInfo.lpszProxy != NULL )
			GlobalFree( ieProxyInfo.lpszProxy );
		if( ieProxyInfo.lpszProxyBypass != NULL )
			GlobalFree( ieProxyInfo.lpszProxyBypass );
		if( count > 0 )
			{
			proxy[ count ] = '\0';
			return( CRYPT_OK );
			}
		}

	/* WinHttpGetProxyForUrl() requires a schema for the URL that it's 
	   performing a lookup on, if the URL doesn't contain one we use a 
	   default value of "http://" */
	if( strstr( url, "://" ) == NULL )
		{
		strcpy( urlBuffer, "http://" );
		offset = 7;
		}
	memcpy( urlBuffer + offset, url, min( urlLen, MAX_DNS_SIZE - offset ) );
	urlBuffer[ offset + min( urlLen, MAX_DNS_SIZE - offset ) ] = '\0';

	/* Locate the proxy used for accessing the resource at the supplied URL.  
	   We have to convert to and from Unicode because the WinHTTP functions 
	   all take Unicode strings as args.  Note that we use the libc widechar 
	   functions rather than the Windows ones since the latter aren't 
	   present in Win95 or Win98.
	   
	   WinHttpGetProxyForUrl() can be rather flaky, in some cases it'll fail 
	   instantly (without even trying auto-discovery) with GetLastError() = 
	   87 (parameter error), but then calling it again some time later works 
	   fine.  Because of this we leave it as the last resort after trying 
	   all the other get-proxy mechanisms */
	hSession = pWinHttpOpen( L"cryptlib/1.0", 
							 WINHTTP_ACCESS_TYPE_NO_PROXY,
							 WINHTTP_NO_PROXY_NAME, 
							 WINHTTP_NO_PROXY_BYPASS, 0 );
	if( hSession == NULL )
		return( CRYPT_ERROR_NOTFOUND );
	count = mbstowcs( unicodeURL, urlBuffer, MAX_DNS_SIZE );
	if( count <= 0 )
		{
		pWinHttpCloseHandle( hSession );
		return( CRYPT_ERROR_NOTFOUND );
		}
	unicodeURL[ count ] = L'\0';
	count = 0;
	memset( &proxyInfo, 0, sizeof( WINHTTP_PROXY_INFO ) );
	if( pWinHttpGetProxyForUrl( hSession, unicodeURL, &autoProxyOptions, 
								&proxyInfo ) == TRUE )
		{
		count = wcstombs( proxy, proxyInfo.lpszProxy, MAX_DNS_SIZE );
		GlobalFree( proxyInfo.lpszProxy );
		if( proxyInfo.lpszProxyBypass != NULL )
			GlobalFree( proxyInfo.lpszProxy );
		}

	pWinHttpCloseHandle( hSession );
	if( count <= 0 )
		return( CRYPT_ERROR_NOTFOUND );
	proxy[ count ] = '\0';
	return( CRYPT_OK );
	}

#if 0

typedef BOOL ( WINAPI *INTERNETGETPROXYINFO )( LPCSTR lpszUrl, DWORD dwUrlLength,
							LPSTR lpszUrlHostName, DWORD dwUrlHostNameLength,
							LPSTR* lplpszProxyHostName,
							LPDWORD lpdwProxyHostNameLength );
typedef BOOL ( WINAPI *INTERNETINITIALIZEAUTOPROXYDLL )( DWORD dwVersion,
							LPSTR lpszDownloadedTempFile, LPSTR lpszMime,
							AutoProxyHelperFunctions* lpAutoProxyCallbacks,
							LPAUTO_PROXY_SCRIPT_BUFFER lpAutoProxyScriptBuffer );

static int findProxyURL( char *proxy, const char *url )
	{
	static INTERNETGETPROXYINFO pInternetGetProxyInfo = NULL;
	static INTERNETINITIALIZEAUTOPROXYDLL pInternetInitializeAutoProxyDll = NULL;
	URL_INFO urlInfo;
	char urlHost[ MAX_DNS_SIZE + 1 ];
	char *proxyHost = NULL;
	int proxyHostLen, status;

	/* This gets somewhat complicated, under Win2K SP3, XP and 2003 (or at 
	   least Windows versions with WinHTTP 5.1 installed in some way, it
	   officially shipped with the versions mentioned earlier) we can use
	   WinHTTP AutoProxy support, which implements the Web Proxy Auto-
	   Discovery (WPAD) protocol from an internet draft that expired in May 
	   2001.  Under older versions of Windows we have to use the WinINet 
	   InternetGetProxyInfo.
	   
	   These functions were never meant to be used by the general public 
	   (see the comment below), so they work in an extremely peculiar way
	   and only with the exact calling sequence that's used by MS code - it
	   looks like they were only intended as components of Windows-internal 
	   implementation of proxy support, since they require manual handling
	   of proxy config script downloading, parsing, and all manner of other
	   stuff that really doesn't concern us.  Because of the extreme 
	   difficulty in doing anything with these functions, we use the WinHTTP
	   approach instead */
	if( pInternetGetProxyInfo == NULL )
		{
		HMODULE hModJS;

		if( ( hModJS = LoadLibrary( "JSProxy.dll" ) ) == NULL )
			return( CRYPT_ERROR_NOTFOUND );

		pInternetGetProxyInfo = ( INTERNETGETPROXYINFO ) \
					GetProcAddress( hModJS, "InternetGetProxyInfo" );
		pInternetInitializeAutoProxyDll = ( INTERNETINITIALIZEAUTOPROXYDLL ) \
					GetProcAddress( hModJS, "InternetInitializeAutoProxyDll" );
		if( pInternetGetProxyInfo == NULL || \
			pInternetInitializeAutoProxyDll == NULL )
			{		
			FreeLibrary( hModJS );
			return( CRYPT_ERROR_NOTFOUND );
			}
		
		pInternetInitializeAutoProxyDll( 0, TempFile, NULL, 
										 &HelperFunctions, NULL )
		}

	/* InternetGetProxyInfo() is a somewhat screwball undocumented function
	   that was crowbarred out of MS as part of the DoJ consent decree.  It
	   takes as input four parameters that do the work of a single 
	   parameter, the null-terminated target URL string.  The documentation
	   for the function was initially wrong, but has been partially 
	   corrected in places after user complaints, there are still missing
	   parts, as well as possible errors (why is it necessary to specify a
	   length for a supposedly null-terminated string?).  In order to meet
	   the strange input-parameter requirements, we have to pre-parse the
	   target URL in order to provide the various bits and pieces that
	   InternetGetProxyInfo() requires */
	status = parseURL( &urlInfo, url, strlen( url ), 80 );
	if( cryptStatusError( status ) )
		return( status );
	if( urlInfo.hostLen > MAX_DNS_SIZE )
		return( CRYPT_ERROR_OVERFLOW );
	memcpy( urlHost, urlInfo.host, urlInfo.hostLen );
	urlHost[ urlInfo.hostLen ] = '\0';
	if( !pInternetGetProxyInfo( url, strlen( url ), urlHost, urlInfo.hostLen,
								&proxyHost, &proxyHostLen ) )
		return( CRYPT_ERROR_NOTFOUND );
	memcpy( proxy, proxyHost, proxyHostLen );
	proxy[ proxyHostLen ] = '\0';
	GlobalFree( proxyHost );
	return( CRYPT_OK );
	}
#endif

#else
  #define findProxyURL( proxy, url )	CRYPT_ERROR_NOTFOUND
#endif /* __WIN32__ */

/****************************************************************************
*																			*
*								Buffering Functions							*
*																			*
****************************************************************************/

/* Buffered transport-layer read function.  This sits on top of the 
   transport-layer read function and performs speculative read-ahead 
   buffering to improve performance in protocols such as HTTP that have to
   read a byte at a time in places:

		   bPos		   bEnd
			|			|
			v			v
	+-------+-----------+-------+
	|		|///////////|		|
	+-------+-----------+-------+
			 -- Read -->

   We fill the buffer to bEnd, then empty it advancing bPos until there isn't
   enough data left to satisfy the read, whereupon we move the data down and
   refill from bEnd:

   bPos		   bEnd
	|			|
	v			v
	+-----------+---------------+
	|///////////|				|
	+-----------+---------------+
				 -- Write -->	  */

static int bufferedTransportReadFunction( STREAM *stream, BYTE *buffer,
										  const int length, const int flags )
	{
	const int bytesLeft = stream->bufEnd - stream->bufPos;
	int bytesToRead, status;

	assert( isWritePtr( buffer, length ) );
	assert( length > 0 );
	assert( bytesLeft >= 0 );

	/* If there's enough data in the buffer to satisfy the request, return it
	   directly */
	if( length <= bytesLeft )
		{
		if( length == 1 )
			/* Optimisation for HTTP header reads */
			*buffer = stream->buffer[ stream->bufPos++ ];
		else
			{
			memcpy( buffer, stream->buffer + stream->bufPos, length );
			stream->bufPos += length;
			}
		assert( stream->bufPos <= stream->bufEnd );
		return( length );
		}

	/* We're about to refill the buffer, if there's a gap at the start move 
	   everything down to make room for the new data */
	if( stream->bufPos > 0 )
		{
		if( bytesLeft > 0 )
			memmove( stream->buffer, stream->buffer + stream->bufPos, 
					 bytesLeft );
		stream->bufEnd = bytesLeft;
		stream->bufPos = 0;
		}

	assert( stream->bufPos == 0 );
	assert( length > bytesLeft );

	/* If there's more room in the buffer, refill it */
	if( stream->bufEnd < stream->bufSize )
		{
		int bytesRead;

		/* Perform an explicitly blocking read of as many bytes as we can/are
		   asked for.  Since there may be data already present from an
		   earlier speculative read, we only read as much as we need to 
		   fulfill the request */
		bytesRead = stream->transportReadFunction( stream, 
										stream->buffer + stream->bufEnd,
										min( length - bytesLeft, \
											 stream->bufSize - stream->bufEnd ),
										TRANSPORT_FLAG_BLOCKING );
		if( cryptStatusError( bytesRead ) )
			return( bytesRead );
		stream->bufEnd += bytesRead;

		/* If there's room for more, perform a second, nonblocking read for
		   whatever might still be there.  An error at this point isn't
		   fatal since this was only a speculative read  */
		if( stream->bufEnd < stream->bufSize )
			{
			bytesRead = stream->transportReadFunction( stream, 
										stream->buffer + stream->bufEnd,
										stream->bufSize - stream->bufEnd,
										TRANSPORT_FLAG_NONBLOCKING );
			if( !cryptStatusError( bytesRead ) )
				stream->bufEnd += bytesRead;
			}
		}
	assert( stream->bufEnd <= stream->bufSize );

	/* Read as much as we can from the buffer */
	bytesToRead = min( length, stream->bufEnd );
	memcpy( buffer, stream->buffer, bytesToRead );
	stream->bufPos += bytesToRead;
	assert( stream->bufPos <= stream->bufEnd );

	/* If we could satisfy the read from the buffer, we're done */
	if( length <= bytesToRead )
		return( length );

	/* We're drained the stream buffer and there's more to go, read it 
	   directly into the caller's buffer */
	status = stream->transportReadFunction( stream, 
								buffer + bytesToRead, length - bytesToRead,
								TRANSPORT_FLAG_BLOCKING );
	return( cryptStatusError( status ) ? status : status + bytesToRead );
	}

/* Buffered transport-layer write function.  This sits on top of the 
   transport-layer write function and combines two (or more, although in
   practice only two ever occur) writes into a single write.  The reason for
   this is that when using TCP transport the delayed-ACK handling means
   that performing two writes followed by a read (typical for HTTP and CMP
   messages) leads to very poor performance, usually made even worse by TCP 
   slow-start.

   The reason for this is that the TCP MSS is typically 1460 bytes on a LAN 
   (Ethernet) or 512/536 bytes on a WAN, while HTTP headers are ~200-300 
   bytes, far less than the MSS.  When an HTTP message is first sent, the 
   TCP congestion window begins at one segment, with the TCP slow-start then
   doubling its size for each ACK.  Sending the headers separately will 
   send one short segment and a second MSS-size segment, whereupon the TCP 
   stack will wait for the responder's ACK before continuing.  The responder 
   gets both segments, then delays its ACK for 200ms in the hopes of 
   piggybacking it on responder data, which is never sent since it's still 
   waiting for the rest of the HTTP body from the initiator.  As a result,
   this results in a 200ms (+ assorted RTT) delay in each message sent.
   
   There is a somewhat related situation that occurs as a result of TCP
   slow-start and that can't be avoided programmatically in which we can't
   send more than a single request initially, however most BSD-derived 
   implementations set the server's congestion window to two segments in 
   response to receiving the TCP handshake ACK, so for the initial message
   exchange the client can send a request of 1MSS and the server a response
   of 2MSS without running into congestion-control problems.

   A related problem is the fact that many TCP implementations will reset the
   congestion window after one retransmission timeout period if all data sent
   at that point has been acked, which means that both sides now restart with
   a congestion window of size 1.  Unfortunately there's nothing that can be
   done about this, however hopefully at some point TCP implementations will
   start to fall into line with RFC 3390 and allow initial windows of ~4K,
   which will fix this particular problem */

static int bufferedTransportWriteFunction( STREAM *stream, const BYTE *buffer,
										   const int length, const int flags )
	{
	const BYTE *bufPtr = buffer;
	int byteCount = length, status;

	assert( isReadPtr( buffer, length ) );

⌨️ 快捷键说明

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