//===========================================================================================
//	LlamaTalk
//
//	Copyright © 1994-1995 Apple Computer, Inc.
//	All rights reserved.
//
//	Modification Status
//	YY/MM/DD	Name			Comments
//	95/11/14	Jim Schram		Added CodeWarrior 7 IDE & PPC Universal Headers support, released as 2.0a1
//	94/07/07	Jim Schram		Released C header with Pascal 1.0a3 release
//	94/03/17	Jim Schram		Initial Development
//===========================================================================================

#include <Connections.h>

#ifndef ConnectionCompletionUPP
#define ConnectionCompletionUPP Ptr
#endif

//----------------------------------------
//	CODE RESOURCES
//----------------------------------------
#define cLTCompProcResType			'lama'
#define	cLTCompProcResName_Listen	'LlamaTalkCPListen'
#define	cLTCompProcResName_Open		'LlamaTalkCPOpen'
#define	cLTCompProcResName_Close	'LlamaTalkCPClose'
#define	cLTCompProcResName_Read		'LlamaTalkCPRead'
#define	cLTCompProcResName_Write	'LlamaTalkCPWrite'

//----------------------------------------
//	ERROR CODES
//----------------------------------------
#define	cLTSocketTableFull		-17001					// Socket table full -- no free indexes -- can't open any more connections
#define	cLTBadToolName			-17002					// Illegal or bad Comm Toolbox tool-name encountered
#define	cLTBadConfig			-17003					// Bad socket configuration parameters

//----------------------------------------
//	PACKET TYPES
//----------------------------------------
#define cLTPacketType_Simple	0						// LlamaTalk packet type descriptor.  Currently only type 0 is implemented.

//----------------------------------------
//	cLTBitsPhase... for INTERNAL USE ONLY
//----------------------------------------
#define	cLTBitsPhaseListen	0x80
#define	cLTBitsPhaseOpen 	0x40
#define	cLTBitsPhaseClose 	0x20
#define	cLTBitsPhaseRead 	0x10
#define	cLTBitsPhaseWrite 	0x08

#define	cLTBitsPhaseError 	0x07
#define	cLTBitsPhase6 		0x06
#define	cLTBitsPhase5 		0x05
#define	cLTBitsPhase4 		0x04
#define	cLTBitsPhase3 		0x03
#define	cLTBitsPhase2		0x02;
#define	cLTBitsPhase1		0x01;

#define	cLTStateError		0x8000;
#define	cLTStateDispose		0x4000;
#define	cLTStateIdle		0x2000;
#define	cLTStateListen		0x1000;
#define	cLTStateOpen		0x0800;
#define	cLTStateClose		0x0400;
#define	cLTStateReadWrite	0x0300;

#define	cLTListenPhase1		(cLTBitsPhaseListen + cLTBitsPhase1)
#define	cLTListenPhase2		(cLTBitsPhaseListen + cLTBitsPhase2)
#define	cLTListenPhase3		(cLTBitsPhaseListen + cLTBitsPhase3)
#define	cLTListenPhase4		(cLTBitsPhaseListen + cLTBitsPhase4)
#define	cLTListenPhaseError	(cLTBitsPhaseListen + cLTBitsPhaseError)

#define	cLTOpenPhase1		(cLTBitsPhaseOpen + cLTBitsPhase1)
#define	cLTOpenPhase2		(cLTBitsPhaseOpen + cLTBitsPhase2)
#define	cLTOpenPhase3		(cLTBitsPhaseOpen + cLTBitsPhase3)
#define	cLTOpenPhaseError	(cLTBitsPhaseOpen + cLTBitsPhaseError)

#define	cLTClosePhase1		(cLTBitsPhaseClose + cLTBitsPhase1)
#define	cLTClosePhase2		(cLTBitsPhaseClose + cLTBitsPhase2)
#define	cLTClosePhase3		(cLTBitsPhaseClose + cLTBitsPhase3)
#define	cLTClosePhase4		(cLTBitsPhaseClose + cLTBitsPhase4)
#define	cLTClosePhaseError	(cLTBitsPhaseClose + cLTBitsPhaseError)

#define	cLTReadPhase1		(cLTBitsPhaseRead + cLTBitsPhase1)
#define	cLTReadPhase2		(cLTBitsPhaseRead + cLTBitsPhase2)
#define	cLTReadPhase3		(cLTBitsPhaseRead + cLTBitsPhase3)
#define	cLTReadPhase4		(cLTBitsPhaseRead + cLTBitsPhase4)
#define	cLTReadPhase5		(cLTBitsPhaseRead + cLTBitsPhase5)
#define	cLTReadPhaseError	(cLTBitsPhaseRead + cLTBitsPhaseError)

#define	cLTWritePhase1		(cLTBitsPhaseWrite + cLTBitsPhase1)
#define	cLTWritePhase2		(cLTBitsPhaseWrite + cLTBitsPhase2)
#define	cLTWritePhase3		(cLTBitsPhaseWrite + cLTBitsPhase3)
#define	cLTWritePhase4		(cLTBitsPhaseWrite + cLTBitsPhase4)
#define	cLTWritePhase5		(cLTBitsPhaseWrite + cLTBitsPhase5)
#define	cLTWritePhaseError	(cLTBitsPhaseWrite + cLTBitsPhaseError)

//----------------------------------------
//	MISCELLANEOUS
//----------------------------------------
#define	cLTCheckAsyncErrors	TRUE						// TRUE checks error return value of async calls to CM/Read/Write/Listen/Open/Close
														// This was needed to work around a bug in the Apple Modem Tool 1.5.1 which returns a
														// completely erroneous -1 error on each asynchronous call to CMRead.

//===========================================================================================

typedef	struct {
			long	fMaxElements;						// Maximum elements that the queue can contain (size of fData array)
			long	fNumElements;						// Number of elements currently in the queue
			long	fHead;								// Array index of first element
			long	fTail;								// Array index of last element
			Handle	fData[];
		} LTQueueRec, *LTQueuePtr, **LTQueueHdl;


typedef	struct {										// A status record returned by LTGetSocketStatus describing a connection's current state
			CMErr			fCMErr;						// Error returned by CTB status routine CMStatus - noErr = good status record
			CMStatFlags		fCMStatusFlags;				// Actual CTB status flags - never know when you might need them…
			CMBufferSizes	fCMBufferSizes;				// Array of CTB buffer sizes - see definition of CMBufferSizes for more info…

			Boolean			fIsOpening;					// TRUE if the connection is in the process of opening
			Boolean			fIsOpen;					// TRUE if the connection is currently open
			Boolean			fIsClosing;					// TRUE if the connection is in the process of closing
			Boolean			fIsClosed;					// TRUE if the connection is currently closed

			Boolean			fIsDataInAvail;				// TRUE if there is unread data available
			Boolean			fIsDataOutAvail;			// TRUE if there is unwritten data available

			Boolean			fIsDataReadPending;			// TRUE if there is an asynchronous read pending on the DATA channel
			Boolean			fIsDataWritePending;		// TRUE if there is an asynchronous write pending on the DATA channel

			Boolean			fIsBreakPending;			// TRUE if there is a break pending (on any channel)
			Boolean			fIsListenPending;			// TRUE if there is a listen pending (on any channel)
			Boolean			fIsIncoming;				// TRUE if there is an incoming request to connect (valid only when listening)
		} LTSocketStatusRec;

//----------------------------------------
//	NOTE:	Be sure to recompile the completion
//			procedures if you modify
//			LTSocketRec or LTGlobals!!!
//----------------------------------------
typedef	struct {
			short		fPhase;							// Used by LTIdle state machines

			long		fError;
			ConnHandle	fConnHdl;						// Handle to the Comm Toolbox Connection Record for this connection, or NIL if not being used
			Handle		fAddressConfigHdl;

			short		fListenPhase;
			short		fOpenPhase;
			short		fClosePhase;

			short		fReadPhase;
			short		fReadType;
			long		fReadHeader;
			long		fReadCount;
			Handle		fReadBuffer;
			LTQueueHdl	fReadQueue;

			short		fWritePhase;
			short		fWriteType;
			long		fWriteHeader;
			long		fWriteCount;
			Handle		fWriteBuffer;
			LTQueueHdl	fWriteQueue;
		} LTSocketRec;


typedef struct {										// NOTE:  LTGlobals is a variable sized structure.
			ConnectionCompletionUPP		fCompProcPtr_Listen;
			ConnectionCompletionUPP		fCompProcPtr_Open;
			ConnectionCompletionUPP		fCompProcPtr_Close;
			ConnectionCompletionUPP		fCompProcPtr_Read;
			ConnectionCompletionUPP		fCompProcPtr_Write;

			short						fNumSockets;
			LTSocketRec	fSockets[];						// NOTE:  fSockets[0] is RESERVED for future use!
		} LTGlobals, *LTGlobalsPtr, **LTGlobalsHdl;

//----------------------------------------

pascal	LTQueueHdl	LTNewQueue (long maxElements);
pascal	void		LTDisposeQueue (LTQueueHdl *LTQueueHdl);
pascal	void 		LTFlushQueue (LTQueueHdl q);

pascal	void 		LTEnQueue (LTQueueHdl q, void *data);
pascal	Handle 		LTDeQueue (LTQueueHdl q);

pascal	long 		LTGetQueueSize (LTQueueHdl q);
pascal	long 		LTGetMaxQueueSize (LTQueueHdl q);

//----------------------------------------

pascal	OSErr 		LTOpenLlamaTalk (short	maxSockets, LTGlobalsHdl *globals);
pascal	void 		LTCloseLlamaTalk (LTGlobalsHdl globals);

pascal	void 		LTIdle (LTGlobalsHdl globals);

pascal	OSErr 		LTNewSocket (LTGlobalsHdl globals, Str255 toolName, Handle socketConfigHdl, Handle addressConfigHdl, short maxReadQueue, short maxWriteQueue, short *socket);
pascal	void 		LTDisposeSocket (LTGlobalsHdl globals, short socket);

pascal	Boolean 	LTIsValidSocket (LTGlobalsHdl globals, short socket);
pascal	long	 	LTGetSocketState (LTGlobalsHdl globals, short socket);
pascal	void 		LTGetSocketStatus (LTGlobalsHdl globals, short socket, LTSocketStatusRec *status );

pascal	void 		LTListen (LTGlobalsHdl globals, short socket);
pascal	void 		LTOpen (LTGlobalsHdl globals, short socket);
pascal	void 		LTClose (LTGlobalsHdl globals, short socket);
pascal	Handle 		LTRead (LTGlobalsHdl globals, short socket);
pascal	void 		LTWrite (LTGlobalsHdl globals, short socket, Handle *data);

pascal	Boolean 	LTChoose (Str255 *toolName, Handle *configHdl);

//===========================================================================================
