MACINTOSH documentation - MACINTOSH documentation - MACINTOSH documentation
______________________________________________________________________________

LlamaTalkLib
by Jim Schram
Copyright 1994-1995 by Apple Computer, Inc. All rights reserved
Version 2.0a1 - Nov 14, 1995


What is LlamaTalk?
1.)  n. Oral grunts forming a system of communication between two or more Llamas.
2.)  n. An interrogative shouted by small children when grunted at by Llamas.
3.)  n. A client-server protocol used for Newton-to-Macintosh communication.

The LlamaTalk protocol is a two-way context-free framed transaction protocol
used for communication between a Newton and a Macintosh.  The protocol is
based on a reliable, error-free delivery system such as ADSP or MNP.  This
document will describe the basic transaction delivery system for simple,
unacknowledged transaction packets.  The reader is encouraged to implement
higher-level protocols as appropriate.

A LlamaTalk transaction packet is a variable non-zero sized Handle containing
context-independent data.  The transaction is generally, but not necessarily,
assembled as a stream; data is written serially into an expanding Handle
until complete, and then sent as a single LlamaTalk packet.  Due to the
limited amount of memory available in the Newton, individual transactions
should therefore be kept to a reasonable size.

Currently only a simple transport packet type is implemented.  However, the
protocol allows for future enhancements such as encryption, control packets,
and message priority.  Compression is assumed to be handled by the underlying
transport (e.g. MNP).

LlamaTalk is implemented on the Macintosh as a wrapper library for the
communications toolbox.  The code is structured in such a way that
non-applications (i.e. 4th Dimension externals, CDEVs, etc.) can make use of
the protocol code.  The design is object oriented, but not object
implemented.

The basic server system is implemented something like this:

Initialize all toolbox managers, etc.
LTOpenLlamaTalk(...)

socket := 0;
main event loop:
    LTIdle(...);

    socket := (socket + 1) mod N;
    if LTIsValidSocket(...) then
        dataHdl := LTRead(...);
        if dataHdl <> nil then
            <process the data>
            LTWrite(...);  <if appropriate>

        if LTGetSocketState(...) = cLTStateError then
            LTDisposeSocket(...);
        else
    else
        LTNewSocket(...);
        LTListen(...);

LTCloseLlamaTalk(...);

Note:  Socket references go from 1 to N and are reused as often as possible.

==========

The following files are included in the Macintosh LlamaTalk 2.0a1 package:

LlamaTalk.h             C LlamaTalk headers.
LlamaTalk.p             Main protocol source and data structures.
LlamaTalkCPListen.p     Completion procedure source for CMListen.
LlamaTalkCPOpen.p       Completion procedure source for CMOpen.
LlamaTalkCPClose.p      Completion procedure source for CMClose.
LlamaTalkCPRead.p       Completion procedure source for CMRead.
LlamaTalkCPWrite.p      Completion procedure source for CMWrite.

LlamaTalkCPListen.proj  Think Pascal project used to build LlamaTalkCPListen in LlamaTalkCPListen.rsrc.
LlamaTalkCPOpen.proj    Think Pascal project used to build LlamaTalkCPOpen in LlamaTalkCPOpen.rsrc.
LlamaTalkCPClose.proj   Think Pascal project used to build LlamaTalkCPClose in LlamaTalkCPClose.rsrc.
LlamaTalkCPRead.proj    Think Pascal project used to build LlamaTalkCPRead in LlamaTalkCPRead.rsrc.
LlamaTalkCPWrite.proj   Think Pascal project used to build LlamaTalkCPWrite in LlamaTalkCPWrite.rsrc.

LlamaTalkCPListen.µ     CodeWarrior project used to build LlamaTalkCPListen in LlamaTalkCPAll.rsrc.
LlamaTalkCPOpen.µ       CodeWarrior project used to build LlamaTalkCPOpen in LlamaTalkCPAll.rsrc.
LlamaTalkCPClose.µ      CodeWarrior project used to build LlamaTalkCPClose in LlamaTalkCPAll.rsrc.
LlamaTalkCPRead.µ       CodeWarrior project used to build LlamaTalkCPRead in LlamaTalkCPAll.rsrc.
LlamaTalkCPWrite.µ      CodeWarrior project used to build LlamaTalkCPWrite in LlamaTalkCPAll.rsrc.

LlamaTalkCPListen.rsrc  Contains Think Pascal LlamaTalkCPListen 'lama' resource.
LlamaTalkCPOpen.rsrc    Contains Think Pascal LlamaTalkCPOpen 'lama' resource.
LlamaTalkCPClose.rsrc   Contains Think Pascal LlamaTalkCPClose 'lama' resource.
LlamaTalkCPRead.rsrc    Contains Think Pascal LlamaTalkCPRead 'lama' resource.
LlamaTalkCPWrite.rsrc   Contains Think Pascal LlamaTalkCPWrite 'lama' resource.

LlamaTalkCPAll.rsrc     Contains CodeWarrior LlamaTalkCPListen, LlamaTalkCPOpen, LlamaTalkCPClose,
                        LlamaTalkCPRead, and LlamaTalkCPWrite 'lama' resources.

LlamaTalkA4.p           CodeWarrior prefix file for LlamaTalkA4.µ for building LlamaTalkA4.lib.
LlamaTalkA5.p           CodeWarrior prefix file for LlamaTalkA5.µ for building LlamaTalkA5.lib.
LlamaTalkPPC.p          CodeWarrior prefix file for LlamaTalkPPC.µ for building LlamaTalkPPC.lib.

LlamaTalkA4.µ           CodeWarrior project used to build LlamaTalkA4.lib.
LlamaTalkA5.µ           CodeWarrior project used to build LlamaTalkA5.lib.
LlamaTalkPPC.µ          CodeWarrior project used to build LlamaTalkPPC.lib.

LlamaTalkA4.lib         68k A4-relative library which loads completion routines from 'lama' resources.
LlamaTalkA5.lib         68k A5-relative library which includes its own completion routines.
LlamaTalkPPC.lib        PPC library which includes its own completion routines.

LlamaTalkEchoApp.p      Main application source for LlamaTalkEchoApp.
LlamaTalkEchoApp.rsrc   Socket config resources.  These resources are linked into the compiled app.
                        The 'LAMA' resources are example socket configuration and address settings.
LlamaTalkEchoApp.proj   Think Pascal project used to build LlamaTalkEchoApp ADSP.
LlamaTalkEchoApp68k.µ   CodeWarrior project used to build LlamaTalkEchoApp 68k ADSP.
LlamaTalkEchoAppPPC.µ   CodeWarrior project used to build LlamaTalkEchoApp PPC ADSP.

Note:  LlamaTalkEchoApp 68k MNP and LlamaTalkEchoApp PPC MNP are nothing more than ResEdit modifications to
       LlamaTalkEchoApp 68k ADSP and LlamaTalkEchoApp PPC ADSP to modify the 'LAMA' resources accordingly.

The following units are required to build LlamaTalk.p:
Traps, Errors, Resources, AppleTalk, TextUtils,
CTBUtilities, Connections, CommResources, LlamaTalk


==========  Public Functions

The following functions are to be used when interacting with the LlamaTalk
driver.  All other structures and functions are considered private and are
subject to change in future implementations.

-----------

Function LTOpenLlamaTalk (maxSockets: Short; Var globals: LTGlobalsHdl):
OSErr;

Opens the LlamaTalk driver for a maximum of maxSockets simultaneous
connections.  This routine loads asynchronous completion routines from the
current resource file if compiler directive LT_UsingGlobals = 0, otherwise
completion procs in main code segment are used.  Call once at server startup.

The following 68k completion routine resources are loaded (by name, NOT by ID,
when LT_UsingGlobals = 0 or when using the LlamaTalkA4.lib library file):

  TYPE    NAME
  lama    LlamaTalkCPClose
  lama    LlamaTalkCPListen
  lama    LlamaTalkCPOpen
  lama    LlamaTalkCPRead
  lama    LlamaTalkCPWrite

-----------

Procedure LTCloseLlamaTalk (globals: LTGlobalsHdl);

Closes the LlamaTalk driver and any still-open connections.  Call once at
server shutdown.  Due to the way connection memory is allocated by the
communications toolbox, you MUST be certain to call this procedure before
exiting the application.  Failure to do so will very likely crash the
Macintosh.

-----------

Function LTChoose (Var toolName: Str255; Var configHdl: Handle): Boolean;

Provided mainly for convenience, this function will display the standard CTB
chooser and return the selected tool and it's configuration string. 
Initialize toolName to the name of the tool you wish to default to on open. 
The configHdl is a newly-allocated handle containing the C-string
configuration data for this tool.  You may save it as a data resource for use
with LTNewSocket.  It is up to the caller to dispose of configHdl.

-----------

Procedure LTIdle (globals: LTGlobalsHdl);

The "heartbeat" of the LlamaTalk driver, this method must be called at least
once during each pass through the main event loop.  It clocks all state
machines for all sockets, as well as the CTB internal machines.

-----------

Function LTNewSocket (globals: LTGlobalsHdl; toolName: Str255;
socketConfigHdl, addressConfigHdl: Handle; maxReadQueue, maxWriteQueue:
Short; Var socket: Short): OSErr;

Allocates and configures a new socket and returns its LlamaTalk socket
reference.

The toolName and socketConfigHdl parameters are only used during initial
socket creation, and may be attached non-purgeable resources.  The
addressConfigHdl is used when the socket is told to listen for or open a
connection, and can be an attached non-purgeable resource so long as the
resource handle is valid at the time of the actual listen or open.  Neither
handle will be modified or disposed, but will become unlocked.  You may pass
NIL for addressConfigHdl if desired.

maxReadQueue and maxWriteQueue set the maximum size of the I/O queues used to
send and receive data.  Attempts to enqueue more than the maximum number of
entries will dispose of the data instead of enqueueing it.  A future
enhancement will provide some type of error handling or prevention mechanism
for this.

-----------

Procedure LTDisposeSocket (globals: LTGlobalsHdl; socket: Short);

Deallocates a socket, abruptly closing the connection if still open at the
time of call.  If an error occurs on a socket, the socket state machine will
remain in the error state until it is disposed of.  This is by design.

-----------

Function LTIsValidSocket (globals: LTGlobalsHdl; socket: Short): Boolean;

Returns TRUE if socket is a valid socket.  The socket may be in any state: 
listen, open, close, read, write, idle, error, dispose, etc.  To determine
the health and activity of a valid socket, call LTGetSocketStatus.

-----------

Fuction LTGetSocketState (globals: LTGlobalsHdl; socket: Short): Long;

Returns a long describing the state of the socket.  This is used to determine
if a socket error has occurred, etc.  It is actually a value which indicates
which state machine the socket is currently running.  Zero is an invalid
state.

-----------

Procedure LTGetSocketStatus (globals: LTGlobalsHdl; socket: Short; Var
status: LTSocketStatusRec);

Returns a structure describing the health of the socket.  This is used to
determine if a socket error has occurred, etc.

-----------

Function LTRead (globals: LTGlobalsHdl; socket: Short): Handle;

Returns an incoming LlamaTalk transaction, or NIL if there is no input data
available.  Poll the socket often using this function to process incoming
data.  The maximum number of incoming packets that can be queued is
determined at LTNewSocket time.  It is the caller's responsibility to dispose
of the returned handle.

-----------

Procedure LTWrite (globals: LTGlobalsHdl; socket: Short; Var data: Handle);

Enqueues a LlamaTalk transaction for output.  The data handle will become the
properly of the LlamaTalk driver, and the parameter will be set to NIL to
assist with the takeover.



============  State Transition Procedures

The following procedures are designed as simple state transitioners for a
given socket.  Generally speaking, the socket should be in an IDLE state when
one of the following routines is called.  This is because, currently, socket
transitions are immediate rather than queued, and so an out-of-sequence
transition (especially to another state system) would likely prove disastrous
for that socket.

-----------

Procedure LTListen (globals: LTGlobalsHdl; socket: Short);

Tells the socket to enter the listen state machine.  More than one socket can
be running a listen machine simultaneously (they will arbitrate among
themselves which is allowed to publish the actual NBP listener and when). 
The socket should be in an idle phase when told to enter this machine.

-----------

Procedure LTOpen (globals: LTGlobalsHdl; socket: Short);

Tells the socket to enter the open state machine.  More than one socket can
be running an open machine simultaneously.  The socket should be in an idle
phase when told to enter this machine.

-----------

Procedure LTClose (globals: LTGlobalsHdl; socket: Short);

Tells the socket to enter the close state machine.  More than one socket can
be running a close machine simultaneously.  The socket should be in an idle
or error phase when told to enter this machine.


==============================================================================

Changes in 2.0a1
----------------
Added CodeWarrior 7 IDE and Universal Headers support.
Now compiles for both 68k and PPC native.

There is an obscure problem with libraries built using Think Pascal 4.0.2
regarding capitalization of the library routines.  Pascal routine names should
exist in the library in all caps but Think Pascal was building them using
mixed case as in the sources.  The CodeWarrior C/C++ and Symantec C/C++ build
systems found it rather difficult to deal with this, therefore the LlamaTalk
libraries are now built using CodeWarrior 7 which properly capitalizes all
Pascal library routine names.

PPC and A5 libraries use CommToolBox completion routines within the
LlamaTalk.p source file.  The A4 library uses CommToolBox completion routines
contained in resources of type 'lama' (see the documentation on
LTOpenLlamaTalk above for more information).

CommToolBox connection handles are now explicitly locked during use.

------------------------------------------------------------------------------

Changes in 1.0a4
----------------
Add {$MAIN} directive in front of Main procedure in Interface section of all
code resource sources for MetroWerks Pascal 1.0b5 compiler.

Changed TextToHex routine to use a local string variable instead of
a local string constant.  MetroWerks Pascal 1.0b5 compiler was generating
bad code for the constant case.

Added LT_UsingGlobals compiler directive.  Now LlamaTalk can be built to load
asynchronous completion routines from code resources, as in the case of XCMDs,
4D externals, etc. or from procedures located in the $Main code segment, as
in applications.  See LTOpenLlamaTalk for details.

------------------------------------------------------------------------------

Initial release 1.0a3

==============================================================================

No part of this document or the software described in it may be altered in
any way and subsequently distributed as original material without prior
written permission of Apple Computer, Inc.  No licenses, express or implied,
are granted with respect to any of the technology described therein.  This
document and the accompanying software are intended to assist application
developers to develop applications only for licensed Newton platforms.  Apple
makes no warranty or representation either express or implied of the
aforementioned technology with respect to the quality, accuracy,
merchantability, or fitness for a particular purpose.  As a result, this
material is distributed "as is" and you, the reader, are assuming the entire
risk as to its quality and accuracy.  It's sample code, darn it.

