Code Search for Developers
 
 
  

ThreadedOT.c from redshed at Krugle


Show ThreadedOT.c syntax highlighted

/****************************************************************************************
	ThreadedOT.c $Revision: 1.2 $
		<http://rentzsch.com/redshedthreads>
	
	Copyright © 2000-2002 Red Shed Software. All rights reserved.
	by Jonathan 'Wolf' Rentzsch (jon at redshed dot net)
	
	************************************************************************************/

#include	"ThreadedOT.h"
#include	"WaitRedShedThread.h"
#include	"require.h"
#include	"OpenTransportProtocol.h"

OTNotifyUPP	gNotifyRedShedThread = nil;

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Feb 22, 2000	Created.
	wolf		Wed, May 16, 2001	Jason Toffaletti alerted me to the fact I was using
									NewOTNotifyUPP() like a non-allocating macro, causing
									memory leaks when compiling for Carbon. Fixed.
	
	************************************************************************************/

	EndpointRef
TOTOpenEndpoint(
	RedShedThread		*thread,
	OTConfigurationRef	cfig,
	OTOpenFlags			oflag,
	TEndpointInfo		*info,
	OSStatus			*err,
	long				patience )
{
	OSStatus	err2 = noErr;
	EndpointRef	result = kOTInvalidEndpointRef;
	
	RequireRedShedThread( thread );
	Require( cfig != kOTNoMemoryConfigurationPtr && cfig != kOTInvalidConfigurationPtr );
	RequirePtrIfNotNil( info );
	RequirePtrIfNotNil( err );
	
	if( gNotifyRedShedThread == nil ) {
		gNotifyRedShedThread = NewOTNotifyUPP( NotifyRedShedThread );
		if( gNotifyRedShedThread == nil )
			err2 = memFullErr;
	}
	
	if( !err2 )
		err2 = OTAsyncOpenEndpoint( cfig, oflag, info, gNotifyRedShedThread, thread );
	
	if( !err2 ) {
		OTEventCode	event = T_OPENCOMPLETE;
		err2 = WaitOTEvent( thread, &event, (long*) &result, patience );
		if( err2 )
			result = kOTInvalidEndpointRef;
	}
	if( !err2 )
		err2 = OTSetBlocking( result );
	
	if( err )
		*err = err2;
	return( result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Feb 25, 2000	Created.
	wolf		Wed, May 16, 2001	Jason Toffaletti alerted me to the fact I was using
									NewOTNotifyUPP() like a non-allocating macro, causing
									memory leaks when compiling for Carbon. Fixed.
	
	************************************************************************************/

	InetSvcRef
TOTOpenInternetServices(
	RedShedThread		*thread,
	OTConfigurationRef	cfig,
	OSStatus			*err,
	long				patience )
{
	InetSvcRef	result = kOTInvalidInetSvcRef;
	OSStatus	err2 = noErr;
	
	RequireRedShedThread( thread );
	Require( cfig != kOTNoMemoryConfigurationPtr && cfig != kOTInvalidConfigurationPtr );
	RequirePtrIfNotNil( err );

	if( gNotifyRedShedThread == nil ) {
		gNotifyRedShedThread = NewOTNotifyUPP( NotifyRedShedThread );
		if( gNotifyRedShedThread == nil )
			err2 = memFullErr;
	}
	
	if( !err2 )
		err2 = OTAsyncOpenInternetServices( cfig, 0, gNotifyRedShedThread, thread );

	if( !err2 ) {
		OTEventCode	event = T_OPENCOMPLETE;
		err2 = WaitOTEvent( thread, &event, (long*) &result, patience );
		if( err2 )
			result = kOTInvalidInetSvcRef;
	}
	if( !err2 ) {
		err2 = OTSetBlocking( result );
	}
	
	if( err )
		*err = err2;
	return( result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Feb 22, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTBind(
	RedShedThread	*thread,
	EndpointRef		ref,
	TBind			*reqAddr,
	TBind			*retAddr,
	long			patience )
{
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	RequirePtrIfNotNil( reqAddr );
	RequirePtrIfNotNil( retAddr );
	
	err = OTBind( ref, reqAddr, nil );
	if( !err ) {
		OTEventCode	event = T_BINDCOMPLETE;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	return( err );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Wed, Mar 8, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTUnbind(
	RedShedThread	*thread,
	EndpointRef		ref,
	long			patience )
{
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	
	err = OTUnbind( ref );
	if( !err ) {
		OTEventCode	event = T_UNBINDCOMPLETE;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	return( err );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Feb 22, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTConnect(
	RedShedThread	*thread,
	EndpointRef		ref,
	TCall			*sndCall,
	TCall			*rcvCall,
	long			patience )
{
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	RequirePtrIfNotNil( sndCall );
	RequirePtrIfNotNil( rcvCall );
	
	err = OTConnect( ref, sndCall, rcvCall );
	if( err == kOTNoDataErr )
		err = kOTNoError;
	if( !err ) {
		OTEventCode	event = T_CONNECT;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	if( err == kOTLookErr ) {
		err = kECONNREFUSEDErr;
	} else if( err == noErr ) {
		err = OTRcvConnect( ref, rcvCall );
	}
	return( err );
}	

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Thu, Feb 17, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTRcv(
	RedShedThread	*thread,
	EndpointRef		ref,
	void			*buf,
	OTByteCount		nbytes,
	long			patience )
{
	OTResult	result = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	RequirePtr( buf );
	
	while( result == kOTNoError && nbytes > 0 ) {
		Boolean		leaveNotifier = OTEnterNotifier( ref );
		OTFlags		flags;
		
		result = OTRcv( ref, buf, nbytes, &flags );
		Require( result != 0 );
		
		if( leaveNotifier )
			OTLeaveNotifier( ref );
		
		if( result > 0 ) {
			nbytes -= result;
			buf = ((char*)buf) + result;
			result = kOTNoError;
		} else if( result == kOTNoDataErr ) {
			//	No more data in the pipe. Wait for a T_DATA.
			OTEventCode	event = T_DATA;
			result = WaitOTEvent( thread, &event, nil, patience );
		}
	}
	
	return( result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Thu, Feb 24, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTRcvUntil(
			RedShedThread	*thread,
			EndpointRef		ref,
			void			*buf,
			OTByteCount		*size,
	const	unsigned char	*until,
			long			patience )
{
	char			c;
	char			*bufferIt = (char*) buf;
	char			*bufferEnd = bufferIt + *size;
	const	char	*untilIt = (const char*) until + 1;
	const	char	*untilEnd = (const char*) until + until[ 0 ];
	OTResult		result = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	RequirePtr( buf );
	RequirePtr( size );
	RequirePtr( until );
	
	*size = 0;
	
	while( !result && bufferIt != bufferEnd && untilIt != untilEnd ) {
		result = TOTRcv( thread, ref, &c, 1, patience );
		
		if( result >= 0 ) {
			result = 0;
			
			*bufferIt = c;
			++bufferIt;
			++(*size);
			
			if( *untilIt == c ) {
				++untilIt;
			} else {
				untilIt = (const char*) until + 1;
			}
		}
	}
	
	if( (result == kOTNoError) && (untilIt != untilEnd) )
		result = kDelimiterNotFound;
	
	return( result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Thu, Feb 24, 2000	Created.
	wolf		Sun, May 28, 2000	Now reads until a kOTNoDataErr error is encountered.
	
	************************************************************************************/

	OSStatus
TOTFlushRcv(
	EndpointRef	ref )
{
	OTBuffer	*buffer;
	OTFlags		flags;
	OTResult	result;
	
	Require( ref != kOTInvalidEndpointRef );
	
	do {
		result = OTRcv( ref, &buffer, kOTNetbufDataIsOTBufferStar, &flags );
		Require( result != 0 );
		if( result > 0 ) {
			OTReleaseBuffer( buffer );
		}
	} while( result != kOTNoDataErr );
	
	return( kOTNoError );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Thu, Feb 17, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTSnd(
			RedShedThread	*thread,
			EndpointRef		ref,
	const	void			*buf,
			OTByteCount		nbytes,
			Boolean			moreToCome,
			long			patience )
{
	OTResult	result = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	RequirePtr( buf );
	
	while( result == kOTNoError && nbytes > 0 ) {
		Boolean		leaveNotifier = OTEnterNotifier( ref );
		
#ifdef	__cplusplus
		result = OTSnd( ref, const_cast<void*>( buf ), nbytes, moreToCome ? T_MORE : 0 );
#else
		result = OTSnd( ref, (void*) buf, nbytes, moreToCome ? T_MORE : 0 );
#endif
		Require( result != 0 );
		
		if( leaveNotifier )
			OTLeaveNotifier( ref );
		
		if( result > 0 ) {
			nbytes -= result;
			buf = ((char*)buf) + result;
			result = kOTNoError;
		} else if( result == kOTFlowErr ) {
			//	We need to wait for the other side to catch up.
			OTEventCode	event = T_GODATA;
			result = WaitOTEvent( thread, &event, nil, patience );
		} else if( result == kOTOutOfMemoryErr ) {
			//	We need to wait a little bit.
			WaitTimeDeferredTask( thread, 250 );
			result = kOTNoError;
		}
	}
	
	return( result );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Feb 22, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTSndDisconnect(
	RedShedThread	*thread,
	EndpointRef		ref,
	TCall			*call,
	long			patience )
{
	TCall		call2;
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	RequirePtrIfNotNil( call );
	
	if( call ) {
		err = OTSndDisconnect( ref, call );
	} else {
		call2.addr.maxlen = call2.addr.len = 0;
		call2.addr.buf = nil;
		call2.opt.maxlen = call2.opt.len = 0;
		call2.opt.buf = nil;
		call2.udata.maxlen = call2.udata.len = 0;
		call2.udata.buf = nil;
		call2.sequence = 0;
		
		err = OTSndDisconnect( ref, &call2 );
	}
	
	if( !err ) {
		OTEventCode	event = T_DISCONNECTCOMPLETE;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	
	return( err );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Wed, Mar 8, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTSndRcvOrderlyDisconnect(
	RedShedThread	*thread,
	EndpointRef		ref,
	long			patience )
{
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	
	err = OTSndOrderlyDisconnect( ref );
	
	if( !err ) {
		OTEventCode	event = T_ORDREL;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	if( !err ) {
		err = OTRcvOrderlyDisconnect( ref );
	}
	return( err );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Feb 25, 2000	Created.
	
	************************************************************************************/

	OSStatus
TOTInetMailExchange(
	RedShedThread		*thread,
	InetSvcRef			ref,
	char				*name,
	UInt16				*num,
	InetMailExchange	*mx,
	long				patience )
{
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidInetSvcRef );
	RequireCString( name, 1, 1024 );
	RequirePtr( num );
	Require( *num > 0 && *num < 2048 );
	RequirePtr( mx );
	
	err = OTInetMailExchange( ref, name, num, mx );
	if( !err ) {
		OTEventCode	event = T_DNRMAILEXCHANGECOMPLETE;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	return( err );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Wed, Mar 8, 2000	Created.
	wolf		Wed, May 16, 2001	Made requirement allow nil for the ret parameter.
									(You can thank Jason Toffaletti for this correction.)
	
	************************************************************************************/

	OSStatus
TOTOptionManagement(
	RedShedThread	*thread,
	EndpointRef		ref,
	TOptMgmt		*req,
	TOptMgmt		*ret,
	long			patience )
{
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( ref != kOTInvalidEndpointRef );
	RequirePtr( req );
	RequirePtrIfNotNil( ret );
	
	err = OTOptionManagement( ref, req, ret );
	if( !err ) {
		OTEventCode	event = T_OPTMGMTCOMPLETE;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	
	return( err );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Wed, Mar 8, 2000	Created.
	wolf		Sun, May 28, 2000	Made resistent to out-of-order T_PASSCON and T_DATA
									events.
	
	************************************************************************************/

	OSStatus
TOTAccept(
	RedShedThread	*thread,
	EndpointRef		listener,
	EndpointRef		worker,
	TCall			*call,
	long			patience )
{
	OTEventCode	event;
	OSStatus	err = kOTNoError;
	
	RequireRedShedThread( thread );
	Require( listener != kOTInvalidEndpointRef );
	Require( worker != kOTInvalidEndpointRef );
	RequirePtr( call );
	
	err = OTAccept( listener, worker, call );
	if( !err && listener == worker ) {
		//	If the user is accepting the connection on the same Endpoint
		//	as the listener, the Notifier will see both events.
		event = T_ACCEPTCOMPLETE;
		err = WaitOTEvent( thread, &event, nil, patience );
	}
	if( !err ) {
		//	Accept any Open Transport event.
		event = 0;
		err = WaitOTEvent( thread, &event, nil, patience );
		if( !err && event == T_DATA ) {
			//	Aha! We got the T_DATA before the T_PASSCON. Look for the T_PASSCON, it
			//	should be next.
			event = T_PASSCON;
			err = WaitOTEvent( thread, &event, nil, patience );
			if( !err ) {
				//	Excellent, we now have the T_PASSCON. Make up a new T_DATA event
				//	to replace the one we swallowed.
				err = NewRedShedThreadMessage( thread, kOTEventMessage, T_DATA, 0, 0 );
			}
		}
		if( !err && event != T_PASSCON )
			err = kOTLookErr;
	}
	
	return( err );
}



See more files for this project here

redshed

Code for Mac+WebObjects.

Project homepage: http://sourceforge.net/projects/redshed
Programming language(s): C,Java,Objective C
License: other

  CFMA5.h
  ThreadedFile.c
  ThreadedFile.h
  ThreadedOT.c
  ThreadedOT.h
  WaitRedShedThread.c
  WaitRedShedThread.h