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

📄 stream.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
			REQUIRES_S( stream->flags & STREAM_FFLAG_BUFFERSET );

			/* 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 ] );
		}

	retIntError_Stream( stream );
	}

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

/* Perform an IOCTL on a stream */

RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int sioctl( INOUT STREAM *stream, \
			IN_ENUM( STREAM_IOCTL ) const STREAM_IOCTL_TYPE type, 
			IN_OPT void *data, IN_INT const int dataLen )
	{
#ifdef USE_TCP
	NET_STREAM_INFO *netStream = ( NET_STREAM_INFO * ) stream->netStreamInfo;
#endif /* USE_TCP */
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );

	/* Check that the input parameters are in order */
	if( !isWritePtr( stream, sizeof( STREAM ) ) )
		retIntError();

	REQUIRES_S( sanityCheck( stream ) );
	REQUIRES_S( ( ( stream->type == STREAM_TYPE_FILE || \
					sIsVirtualFileStream( stream ) ) && \
				( type == STREAM_IOCTL_IOBUFFER || \
				  type == STREAM_IOCTL_PARTIALREAD ) ) || \
				( stream->type == STREAM_TYPE_NETWORK ) );
	REQUIRES_S( type > STREAM_IOCTL_NONE && type < STREAM_IOCTL_LAST );

	switch( type )
		{
		case STREAM_IOCTL_IOBUFFER:
			assert( ( data == NULL && dataLen == 0 ) || \
					isWritePtr( data, dataLen ) );

			REQUIRES_S( ( data == NULL && dataLen == 0 ) || \
						( data != NULL && \
						  dataLen > 0 && dataLen < MAX_INTLENGTH ) );
			REQUIRES_S( dataLen == 0 || \
						dataLen == 512 || dataLen == 1024 || \
						dataLen == 2048 || dataLen == 4096 || \
						dataLen == 8192 || dataLen == 16384 );

#ifdef VIRTUAL_FILE_STREAM 
			/* If it's a virtual file stream emulated in memory, don't do
			   anything */
			if( sIsVirtualFileStream( stream ) )
				return( CRYPT_OK );
#endif /* VIRTUAL_FILE_STREAM */

			/* Set up the buffer variables.  File streams don't make use of
			   the bufEnd indicator so we set it to the same value as 
			   bufSize to ensure that the stream passes the sanity checks */
			stream->buffer = data;
			stream->bufSize = stream->bufEnd = 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 the position change was within the 
			   same buffer then the POSCHANGED flag won't have been set 
			   since only the bufPos will have changed) */
			stream->bufPos = stream->bufCount = 0;
			sClearError( stream );
			stream->flags &= ~( STREAM_FFLAG_BUFFERSET | \
								STREAM_FFLAG_EOF | \
								STREAM_FFLAG_POSCHANGED_NOSKIP );
			stream->flags |= STREAM_FFLAG_POSCHANGED;
			if( data != NULL )
				stream->flags |= STREAM_FFLAG_BUFFERSET;

			return( CRYPT_OK );

		case STREAM_IOCTL_PARTIALREAD:
			REQUIRES_S( data == NULL );
			REQUIRES_S( dataLen == FALSE || dataLen == TRUE );

			if( dataLen )
				stream->flags |= STREAM_FLAG_PARTIALREAD;
			else
				stream->flags &= ~STREAM_FLAG_PARTIALREAD;

			return( CRYPT_OK );

		case STREAM_IOCTL_PARTIALWRITE:
			REQUIRES_S( data == NULL );
			REQUIRES_S( dataLen == FALSE || dataLen == TRUE );

			if( dataLen )
				stream->flags |= STREAM_FLAG_PARTIALWRITE;
			else
				stream->flags &= ~STREAM_FLAG_PARTIALWRITE;

			return( CRYPT_OK );

		case STREAM_IOCTL_ERRORINFO:
			assert( isReadPtr( data, sizeof( ERROR_INFO ) ) );

			REQUIRES( data != NULL && dataLen == 0 );

			/* If this stream type doesn't record extended error information,
			   there's nothing to do */
			if( stream->type != STREAM_TYPE_NETWORK )
				return( CRYPT_OK );

			/* Copy the error information to the stream */
			copyErrorInfo( NETSTREAM_ERRINFO, data );

			return( CRYPT_OK );
#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 )
				{
				REQUIRES_S( dataLen == 0 );

				*( ( int * ) data ) = netStream->timeout;
				}
			else
				{
				REQUIRES_S( dataLen >= 0 && dataLen < MAX_INTLENGTH );

				netStream->timeout = dataLen;
				if( netStream->iTransportSession != CRYPT_ERROR )
					{
					status = krnlSendMessage( netStream->iTransportSession,
									IMESSAGE_SETATTRIBUTE, &netStream->timeout,
									( type == STREAM_IOCTL_READTIMEOUT ) ? \
										CRYPT_OPTION_NET_READTIMEOUT : \
										CRYPT_OPTION_NET_WRITETIMEOUT );
					if( cryptStatusError( status ) )
						return( status );
					}
				}
			return( CRYPT_OK );

		case STREAM_IOCTL_HANDSHAKECOMPLETE:
			REQUIRES_S( data == NULL && dataLen == 0 );
			REQUIRES_S( netStream->timeout > 0 && \
						netStream->timeout < MAX_INTLENGTH );
			REQUIRES_S( netStream->savedTimeout >= 0 && \
						netStream->savedTimeout < MAX_INTLENGTH );

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

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

				*( ( int * ) data ) = \
					( netStream->nFlags & STREAM_NFLAG_LASTMSG ) ? FALSE : TRUE;
				}
			else
				{
				REQUIRES_S( dataLen == TRUE || dataLen == FALSE );

				if( dataLen )
					netStream->nFlags &= ~STREAM_NFLAG_LASTMSG;
				else
					netStream->nFlags |= STREAM_NFLAG_LASTMSG;
				}
			return( CRYPT_OK );

		case STREAM_IOCTL_GETCLIENTNAME:
			{
			assert( isWritePtr( data, dataLen ) );

			REQUIRES_S( data != NULL && \
						dataLen > 8 && dataLen < MAX_INTLENGTH );

			if( netStream->clientAddressLen <= 0 )
				return( CRYPT_ERROR_NOTFOUND );
			if( netStream->clientAddressLen > dataLen )
				return( CRYPT_ERROR_OVERFLOW );
			memcpy( data, netStream->clientAddress, netStream->clientAddressLen );

			return( CRYPT_OK );
			}

		case STREAM_IOCTL_GETCLIENTNAMELEN:
			REQUIRES_S( data != NULL && dataLen == 0 );

			if( netStream->clientAddressLen <= 0 )
				return( CRYPT_ERROR_NOTFOUND );
			*( ( int * ) data ) = netStream->clientAddressLen;

			return( CRYPT_OK );

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

			if( netStream->clientPort <= 0 )
				return( CRYPT_ERROR_NOTFOUND );
			*( ( int * ) data ) = netStream->clientPort;

			return( CRYPT_OK );

		case STREAM_IOCTL_HTTPREQTYPES:
			REQUIRES_S( netStream->protocol == STREAM_PROTOCOL_HTTP );
			REQUIRES_S( data == NULL );
			REQUIRES_S( dataLen > STREAM_HTTPREQTYPE_NONE && \
						dataLen < STREAM_HTTPREQTYPE_LAST );

			netStream->nFlags &= ~STREAM_NFLAG_HTTPREQMASK;
			switch( dataLen )
				{
				case STREAM_HTTPREQTYPE_GET:
					netStream->nFlags |= STREAM_NFLAG_HTTPGET;
					break;

				case STREAM_HTTPREQTYPE_POST:
					netStream->nFlags |= STREAM_NFLAG_HTTPPOST;
					break;

				case STREAM_HTTPREQTYPE_ANY:
					netStream->nFlags |= STREAM_NFLAG_HTTPGET | \
									  STREAM_NFLAG_HTTPPOST;
					break;

				default:
					retIntError();
				}

			/* If only an HTTP GET is possible and it's a client-side 
			   stream, it's read-only */
			if( dataLen == STREAM_HTTPREQTYPE_GET && \
				!( netStream->nFlags & STREAM_NFLAG_ISSERVER ) )
				stream->flags = STREAM_FLAG_READONLY;
			else
				{
				/* Reset the read-only flag if we're changing the HTTP
				   operation type to one that allows writes */
				stream->flags &= ~STREAM_FLAG_READONLY;
				}
			return( CRYPT_OK );

		case STREAM_IOCTL_LASTMESSAGE:
			REQUIRES_S( netStream->protocol == STREAM_PROTOCOL_HTTP || \
						netStream->protocol == STREAM_PROTOCOL_CMP );
			REQUIRES_S( data == NULL && dataLen == TRUE );

			netStream->nFlags |= STREAM_NFLAG_LASTMSG;
			return( CRYPT_OK );

		case STREAM_IOCTL_CLOSESENDCHANNEL:
			REQUIRES_S( data == NULL && dataLen == 0 );
			REQUIRES_S( !( netStream->nFlags & 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( !( netStream->nFlags & STREAM_NFLAG_USERSOCKET ) )
				netStream->transportDisconnectFunction( netStream, FALSE );

			return( CRYPT_OK );
#endif /* USE_TCP */
		}

	retIntError_Stream( stream );
	}

/****************************************************************************
*																			*
*								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 */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int sFileToMemStream( INOUT STREAM *memStream, INOUT STREAM *fileStream,
					  OUT_BUFFER_ALLOC( length ) void **bufPtrPtr, 
					  IN_LENGTH const int length )
	{
	void *bufPtr;
	int status;

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

	/* Check that the input parameters are in order */
	if( !isWritePtr( memStream, sizeof( STREAM ) ) || \
		!isWritePtr( fileStream, sizeof( STREAM ) ) || \
		!isWritePtr( bufPtrPtr, sizeof( void * ) ) )
		retIntError_Stream( memStream );

	/* We have to use REQUIRES() here rather than REQUIRES_S() since it's 
	   not certain which of the two streams to set the status for */
	REQUIRES( sanityCheck( fileStream ) && \
			  fileStream->flags & STREAM_FFLAG_BUFFERSET );
	REQUIRES( fileStream->type == STREAM_TYPE_FILE );
	REQUIRES( length > 0 && length < MAX_INTLENGTH );

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

#ifdef VIRTUAL_FILE_STREAM 
	/* 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 > fileStream->bufSize - fileStream->bufPos )
			return( CRYPT_ERROR_UNDERFLOW );

		/* Create a second reference to the memory-mapped stream and advance 
		   the read pointer in the memory-mapped file stream to mimic the 
		   behaviour of a read from it to the memory 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 );
		}
#endif /* VIRTUAL_FILE_STREAM */

	/* 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 + -