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

📄 stream.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
		{
		assert( NOTREACHED );
		return( sSetError( stream, CRYPT_ERROR_READ ) );
		}

	/* If there's a problem with the stream, don't try to do anything until
	   the error is cleared */
	if( cryptStatusError( stream->status ) )
		return( stream->status );

	/* Read the data from the buffer, but without advancing the read pointer
	   like sgetc() does */
	switch( stream->type )
		{
		case  STREAM_TYPE_MEMORY:
			assert( !( stream->flags & ~STREAM_FLAG_MASK ) );

			/* Read the data from the stream buffer */
			if( stream->bufPos >= stream->bufEnd )
				{
				stream->status = CRYPT_ERROR_UNDERFLOW;
				return( CRYPT_ERROR_UNDERFLOW );
				}
			return( stream->buffer[ stream->bufPos ] );

		case STREAM_TYPE_FILE:
			assert( !( stream->flags & ~STREAM_FFLAG_MASK ) );

			/* Read the data from the file */
			if( stream->bufPos >= stream->bufEnd || \
				( stream->flags & STREAM_FFLAG_POSCHANGED ) )
				{
				int status = refillStream( stream );
				if( cryptStatusError( status ) )
					return( ( status == OK_SPECIAL ) ? 0 : status );
				}
			return( stream->buffer[ stream->bufPos ] );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR_READ );		/* Get rid of compiler warning */
	}

/****************************************************************************
*																			*
*								IOCTL Functions								*
*																			*
****************************************************************************/

/* Perform an IOCTL on a stream */

int sioctl( STREAM *stream, const STREAM_IOCTL_TYPE type, void *data,
			const int dataLen )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( ( stream->type == STREAM_TYPE_FILE && \
			  ( type == STREAM_IOCTL_IOBUFFER || \
				type == STREAM_IOCTL_PARTIALREAD ) ) || \
			( stream->type == STREAM_TYPE_NETWORK ) );
	assert( type > STREAM_IOCTL_NONE && type < STREAM_IOCTL_LAST );

	/* Check that the input parameters are in order */
	if( !isWritePtr( stream, sizeof( STREAM ) ) )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_READ );
		}

	switch( type )
		{
		case STREAM_IOCTL_IOBUFFER:
			assert( ( data == NULL && dataLen == 0 ) || \
					isWritePtr( data, dataLen ) );
			assert( dataLen == 0 || \
					dataLen == 512 || dataLen == 1024 || \
					dataLen == 2048 || dataLen == 4096 || \
					dataLen == 8192 || dataLen == 16384 );

			stream->buffer = data;
			stream->bufSize = dataLen;

			/* We've switched to a new I/O buffer, reset all buffer- and 
			   stream-state related variables and remember that we have to 
			   reset the stream position, since there may be a position-
			   change pending that hasn't been reflected down to the 
			   underlying file yet (if it was within the same buffer, the 
			   POSCHANGED flag won't have been set since only the bufPos is 
			   changed) */
			stream->bufPos = stream->bufEnd = stream->bufCount = 0;
			stream->status = CRYPT_OK;
			stream->flags &= ~( STREAM_FFLAG_EOF | \
								STREAM_FFLAG_POSCHANGED_NOSKIP );
			stream->flags |= STREAM_FFLAG_POSCHANGED;
			break;

		case STREAM_IOCTL_PARTIALREAD:
			assert( data == NULL && dataLen == 0 );

			stream->flags |= STREAM_FLAG_PARTIALREAD;
			break;

		case STREAM_IOCTL_PARTIALWRITE:
			assert( data == NULL && dataLen == 0 );

			stream->flags |= STREAM_FLAG_PARTIALWRITE;
			break;

#ifdef USE_TCP
		case STREAM_IOCTL_READTIMEOUT:
		case STREAM_IOCTL_WRITETIMEOUT:
			/* These two values are stored as a shared timeout value
			   which is updated on each data read or write by the
			   caller, so there's no need to maintain distinct values */
			if( data != NULL )
				{
				assert( dataLen == 0 );

				*( ( int * ) data ) = stream->timeout;
				}
			else
				{
				assert( dataLen >= 0 );
				stream->timeout = dataLen;
				if( stream->iTransportSession != CRYPT_ERROR )
					krnlSendMessage( stream->iTransportSession,
									 IMESSAGE_SETATTRIBUTE, &stream->timeout,
									 ( type == STREAM_IOCTL_READTIMEOUT ) ? \
										CRYPT_OPTION_NET_READTIMEOUT : \
										CRYPT_OPTION_NET_WRITETIMEOUT );
				}
			break;

		case STREAM_IOCTL_HANDSHAKECOMPLETE:
			{
			assert( data == NULL );
			assert( dataLen == 0 );
			assert( stream->timeout > 0 );
			assert( stream->savedTimeout >= 0 );

			/* The security protocol handshake has completed, change the 
			   stream timeout value from the connect/handshake timeout to
			   the standard data transfer timeout */
			stream->timeout = stream->savedTimeout;
			stream->savedTimeout = CRYPT_ERROR;
			if( stream->iTransportSession != CRYPT_ERROR )
				krnlSendMessage( stream->iTransportSession,
								 IMESSAGE_SETATTRIBUTE, &stream->timeout,
								 CRYPT_OPTION_NET_CONNECTTIMEOUT );
			break;
			}

		case STREAM_IOCTL_CONNSTATE:
			if( data != NULL )
				{
				assert( dataLen == 0 );

				*( ( int * ) data ) = \
								( stream->flags & STREAM_NFLAG_LASTMSG ) ? \
								FALSE : TRUE;
				}
			else
				{
				assert( dataLen == TRUE || dataLen == FALSE );
				if( dataLen )
					stream->flags &= ~STREAM_NFLAG_LASTMSG;
				else
					stream->flags |= STREAM_NFLAG_LASTMSG;
				}
			break;

		case STREAM_IOCTL_GETCLIENTNAME:
			assert( data != NULL );
			assert( dataLen == 0 );

			strcpy( data, stream->clientAddress );
			break;

		case STREAM_IOCTL_GETCLIENTPORT:
			assert( data != NULL );
			assert( dataLen == 0 );

			*( ( int * ) data ) = stream->clientPort;
			break;

		case STREAM_IOCTL_CONTENTTYPE:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( isWritePtr( data, dataLen ) );
			assert( dataLen > 0 && dataLen < CRYPT_MAX_TEXTSIZE );

			memcpy( stream->contentType, data, dataLen );
			stream->contentType[ dataLen ] = '\0';
			break;

		case STREAM_IOCTL_QUERY:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( ( data == NULL && dataLen == 0 ) || \
					( isWritePtr( data, dataLen ) && \
					  dataLen > 0 && dataLen < CRYPT_MAX_TEXTSIZE ) );

			/* If we're resetting the value, clear the buffer and exit */
			if( data == NULL )
				{
				if( stream->queryLen > 0 )
					memset( stream->query, 0, stream->queryLen );
				break;
				}

			/* Set up the buffer to contain the query if necessary */
			if( stream->queryLen <= dataLen + 1 )
				{
				if( stream->query != NULL )
					{
					clFree( "sioctl", stream->query );
					stream->queryLen = 0;
					}
				if( ( stream->query = \
						clAlloc( "sioctl", max( CRYPT_MAX_TEXTSIZE, \
												dataLen + 1 ) ) ) == NULL )
					{
					stream->status = CRYPT_ERROR_MEMORY;
					return( CRYPT_ERROR_MEMORY );
					}
				stream->queryLen = dataLen;
				}

			/* Copy in the query */
			memcpy( stream->query, data, dataLen );
			stream->query[ dataLen ] = '\0';
			break;

		case STREAM_IOCTL_IDEMPOTENT:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );

			if( data != NULL )
				{
				assert( dataLen == 0 );

				*( ( int * ) data ) = \
								( stream->flags & STREAM_NFLAG_IDEMPOTENT ) ? \
								TRUE : FALSE;
				}
			else
				{
				assert( data == NULL );
				assert( dataLen == TRUE || dataLen == FALSE );

				if( dataLen )
					stream->flags |= STREAM_NFLAG_IDEMPOTENT;
				else
					stream->flags &= ~STREAM_NFLAG_IDEMPOTENT;
				}
			break;

		case STREAM_IOCTL_LASTMESSAGE:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION || \
					stream->protocol == STREAM_PROTOCOL_CMP );
			assert( data == NULL );
			assert( dataLen == TRUE );

			stream->flags |= STREAM_NFLAG_LASTMSG;
			break;

		case STREAM_IOCTL_CALLBACKFUNCTION:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( data != NULL );
			assert( dataLen == 0 );

			stream->callbackFunction = ( CALLBACKFUNCTION ) data;
			break;

		case STREAM_IOCTL_CALLBACKPARAMS:
			assert( stream->protocol == STREAM_PROTOCOL_HTTP || \
					stream->protocol == STREAM_PROTOCOL_HTTP_TRANSACTION );
			assert( data != NULL );
			assert( dataLen == 0 );

			stream->callbackParams = data;
			break;

		case STREAM_IOCTL_CLOSESENDCHANNEL:
			assert( data == NULL );
			assert( dataLen == 0 );
			assert( !( stream->flags & STREAM_NFLAG_USERSOCKET ) );

			/* If this is a user-supplied socket, we can't perform a partial 
			   close without affecting the socket as seen by the user, so we 
			   only perform the partial close if it's a cryptlib-controlled 
			   socket */
			if( !( stream->flags & STREAM_NFLAG_USERSOCKET ) )
				stream->transportDisconnectFunction( stream, FALSE );
			break;
#endif /* USE_TCP */

		default:
			assert( NOTREACHED );
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Misc Functions								*
*																			*
****************************************************************************/

/* Convert a file stream to a memory stream.  Usually this allocates a 
   buffer and reads the stream into it, however if it's a read-only memory-
   mapped file it just creates a second reference to the data to save
   memory */

int sFileToMemStream( STREAM *memStream, STREAM *fileStream,
					  void **bufPtrPtr, const int length )
	{
	void *bufPtr;
	int status;

	assert( isWritePtr( memStream, sizeof( STREAM ) ) );
	assert( isWritePtr( fileStream, sizeof( STREAM ) ) );
	assert( isWritePtr( *bufPtrPtr, sizeof( void * ) ) );
	assert( length > 0 );

	/* Check that the input parameters are in order */
	if( !isWritePtr( memStream, sizeof( STREAM ) ) || \
		!isWritePtr( fileStream, sizeof( STREAM ) ) || \
		length <= 0 )
		{
		assert( NOTREACHED );
		return( CRYPT_ERROR_READ );
		}

	/* Clear return value */
	memset( memStream, 0, sizeof( STREAM ) );
	*bufPtrPtr = NULL;

	/* If it's a read-only memory-mapped file stream, create the memory 
	   stream as a reference to the file stream */
	if( ( fileStream->flags & \
		  ( STREAM_FLAG_READONLY | STREAM_FFLAG_MMAPPED ) ) == \
		( STREAM_FLAG_READONLY | STREAM_FFLAG_MMAPPED ) )
		{
		/* Make sure that there's enough data left in the memory-mapped
		   stream to reference it as a file stream */
		if( length > sMemDataLeft( fileStream ) )
			return( CRYPT_ERROR_UNDERFLOW );

		/* Create a second reference to the memory-mapped stream */
		status = sMemConnect( memStream, fileStream->buffer + \
										 fileStream->bufPos, length );
		if( cryptStatusError( status ) )
			return( status );
		status = sSkip( fileStream, length );
		if( cryptStatusError( status ) )
			{
			sMemDisconnect( memStream );
			return( status );
			}
		return( CRYPT_OK );
		}

	/* It's a file stream, allocate a buffer for the data and read it in as
	   a memory stream */
	if( ( bufPtr = clAlloc( "sFileToMemStream", length ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	status = sread( fileStream, bufPtr, length );
	if( cryptStatusOK( status ) )
		status = sMemConnect( memStream, bufPtr, length );
	if( cryptStatusError( status ) )
		{
		clFree( "sFileToMemStream", bufPtr );
		return( status );
		}
	*bufPtrPtr = bufPtr;
	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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