home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
clintsrc.sit
/
DAtcp.c
< prev
next >
Wrap
Text File
|
1990-02-13
|
14KB
|
598 lines
/*========================================================================
=== DAtcp.c
===
=== Greg Anderson
=== 29 Kerr Hall
=== Social Sciences Computing
=== University of California at Santa Cruz
=== Santa Cruz CA 95062
===
=== (408) 459-2658
=== sirkm@ssyx.ucsc.edu
===
=== TCP/IP portion of client DA.
===
========================================================================*/
#include <MacTCPCommontypes.h>
#include <TCPPB.h>
#include <AddressXlation.h>
#include <types.h>
#include <osutils.h>
#include <memory.h>
#include <devices.h>
#include <events.h>
#include <quickdraw.h>
#include <fonts.h>
#include <windows.h>
#include <files.h>
#include <errors.h>
#include <toolutils.h>
#include <packages.h>
#include <Limits.h>
#include <Controls.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Desk.h>
#include <Scrap.h>
#include <Traps.h>
#include <Lists.h>
#include <Resources.h>
#include "unixDA.h"
#include "DA.h"
void itoa(int var,char **str);
void myAddrToStr(long a, char *str);
/*----------------------------------------------------------------------
| Translate a TCP error code into an index into the str# resource
----------------------------------------------------------------------*/
short getTCPErrorStr(OSErr err)
{
if( err == connectionClosing ) return(eClosing);
if( err == connectionExists ) return(eConExists);
if( err == connectionDoesntExist ) return(eConNoExist);
if( err == connectionTerminated ) return(eConTerm);
if( err == invalidStreamPtr ) return(eBadStream);
if( err == streamAlreadyOpen ) return(eStreamOpen);
if( err == openFailed ) return(eBadOpen);
if( err == commandTimeout ) return(eTimeOut);
if( err == duplicateSocket ) return(eSocUsed);
if( err == ipDestDeadErr) return(eDestDead);
return(eUnknownErr);
}
#define add_dot(str) *str++ = '.'; *str = 0;
#define add_cr(str) *str++ = '\n'; *str = 0;
/*----------------------------------------------------------------------
| Integer to ascii--takes a var pointer, which is advanced as the
| integer is converted to a string.
----------------------------------------------------------------------*/
void myItoa(int var,char **text)
{
char *str = *text;
int i,
m = 1;
if(var < 0)
{
var = -var;
*(str++) = '-';
++(*text);
}
*str = 0;
do
{
for(i=m;i>0;--i)
str[i] = str[i-1];
str[0] = '0' + (var % 10);
++m;
++(*text);
var /= 10;
} while(var);
}
/*----------------------------------------------------------------------
| Convert an ascii number to an integer.
----------------------------------------------------------------------*/
int myAtoI(char **str)
{
char c;
int result = 0;
while( ((c = **str) >= '0') && (c <= '9') )
{
result = result * 10 + c - '0';
++(*str);
}
++(*str);
return( result );
}
/*----------------------------------------------------------------------
| Convert an internet address to ascii.
----------------------------------------------------------------------*/
void myAddrToStr(long inet_addr,char *str)
{
int a1 = (inet_addr >> 24) & 0xFF,
a2 = (inet_addr >> 16) & 0xFF,
a3 = (inet_addr >> 8) & 0xFF,
a4 = (inet_addr ) & 0xFF;
myItoa(a1,&str);
add_dot(str);
myItoa(a2,&str);
add_dot(str);
myItoa(a3,&str);
add_dot(str);
myItoa(a4,&str);
}
/*----------------------------------------------------------------------
| Convert an ascii dot-notation internet address to a long address.
----------------------------------------------------------------------*/
void myStrToAddr(char *lookupName,long *inet_addr)
{
char *str = lookupName;
int a1,
a2,
a3,
a4;
a1 = myAtoI(&str);
a2 = myAtoI(&str);
a3 = myAtoI(&str);
a4 = myAtoI(&str);
*inet_addr = (a1 << 24) + (a2 << 16) + (a3 << 8) + a4;
}
void showBounds( DCtlPtr dCtl )
{
Handle knownHosts;
Rect tempRect;
char msg[80],
*str = msg;
knownHosts = GetResource('STR#',DA_global->rsrcID+1 );
HLock(knownHosts);
addTEstring( dCtl, *knownHosts+2 );
HUnlock(knownHosts);
/*
extern void getScreenRect( Rect *r );
getScreenRect(&tempRect);
myItoa(tempRect.left,&str);
add_dot(str);
myItoa(tempRect.top,&str);
add_dot(str);
myItoa(tempRect.right,&str);
add_dot(str);
myItoa(tempRect.bottom,&str);
addTEstring( dCtl, msg);
*/
}
void PutLongAtOffset(char *base,int offset,long data)
{
long *L_base;
base += offset;
L_base = (long *)base;
*L_base = data;
}
void PutWordAtOffset(char *base,int offset,short data)
{
short *W_base;
base += offset;
W_base = (short *)base;
*W_base = data;
}
void PutByteAtOffset(char *base,int offset,char data)
{
base[offset] = data;
}
long GetLongAtOffset(char *base,int offset)
{
long *L_base;
base += offset;
L_base = (long *)base;
return( *L_base );
}
int GetWordAtOffset(char *base,int offset)
{
short *W_base;
base += offset;
W_base = (short *)base;
return( *W_base );
}
char GetByteAtOffset(char *base,int offset)
{
return( base[offset] );
}
/*----------------------------------------------------------------------
| Zero the PBcontrol structure parameter space.
----------------------------------------------------------------------*/
ZeroIOParams(char *base)
{
int i;
for(i=32; i<TCPCTLSIZE; ++i)
PutByteAtOffset(base,i,0);
}
/*----------------------------------------------------------------------
| Make a TCP stream
----------------------------------------------------------------------*/
OSErr MakeTCPStream( DCtlPtr dCtl )
{
OSErr err = noErr;
int i;
/*
* Get some memory for the TCP control
*/
DA_tcp = (CntrlParam *)NewPtr(TCPCTLSIZE);
if( !DA_tcp )
{
alertUser( dCtl, eNoMemory );
return(-1);
}
/*
* Zero the memory we were just given
*/
for(i=0; i<TCPCTLSIZE; ++i)
PutByteAtOffset(DA_tcpB,i,0);
/*
* Open TCP driver
*/
text(etcpDRVR, DA_global);
if( (err = OpenDriver(DA_global->strBuf,&(DA_tcp->ioCRefNum) )) != noErr)
{
alertUser2( dCtl, eNoDRVR, getTCPErrorStr(err) );
return(err);
}
/*
* Create a stream
*/
DA_tcp->csCode = TCPCreate;
PutLongAtOffset( DA_tcpB, 32, (long)( &(DA_global->tcpBuf)) );
PutLongAtOffset( DA_tcpB, 36, TCPBUFSIZE );
PutLongAtOffset( DA_tcpB, 40, 0L );
PutLongAtOffset( DA_tcpB, 44, (long)dCtl );
err = PBControl( (ParmBlkPtr)DA_tcp, false );
if( err != noErr )
alertUser2( dCtl, eBadCreate, getTCPErrorStr(err) );
return(err);
}
/*----------------------------------------------------------------------
| Kill a TCP stream, releasing its memory.
----------------------------------------------------------------------*/
OSErr KillTCPStream( DCtlPtr dCtl )
{
OSErr err = noErr;
ZeroIOParams(DA_tcpB);
DA_tcp->csCode = TCPRelease;
err = PBControl( (ParmBlkPtr)DA_tcp, false );
if( err != noErr )
alertUser2( dCtl, eBadKill, getTCPErrorStr(err) );
DisposPtr( (Ptr)DA_tcp);
DA_tcp = nil;
DA_global->windButton = eReconnectButton;
drawWInfo( dCtl );
return(err);
}
/*----------------------------------------------------------------------
| Open a TCP connection
----------------------------------------------------------------------*/
OSErr ActiveOpen( DCtlPtr dCtl, long inet_addr, long port )
{
OSErr err = noErr;
DA_global->ignoreUntil = 0;
ZeroIOParams(DA_tcpB);
DA_tcp->csCode = TCPActiveOpen;
/*
* Time out value, in seconds:
*/
PutByteAtOffset( DA_tcpB,32,1);
PutByteAtOffset( DA_tcpB,33,1);
PutByteAtOffset( DA_tcpB,34,0xC0);
PutLongAtOffset( DA_tcpB,36,inet_addr);
PutWordAtOffset( DA_tcpB,40,port);
PutWordAtOffset( DA_tcpB,46,0);
PutByteAtOffset( DA_tcpB,50,0);
PutByteAtOffset( DA_tcpB,51,0);
PutByteAtOffset( DA_tcpB,52,0);
PutByteAtOffset( DA_tcpB,53,0);
PutLongAtOffset( DA_tcpB,94,(long) dCtl);
err = PBControl( (ParmBlkPtr)DA_tcp, false );
if( err != noErr )
alertUser2( dCtl, eBadActiveOpen, getTCPErrorStr(err) );
return(err);
}
/*----------------------------------------------------------------------
| Close a TCP session
----------------------------------------------------------------------*/
OSErr CloseTCP( DCtlPtr dCtl )
{
OSErr err = noErr;
DA_global->windButton = eReconnectButton;
drawWInfo( dCtl );
ZeroIOParams(DA_tcpB);
DA_tcp->csCode = TCPClose;
/*
* Time out, in seconds:
*/
PutByteAtOffset( DA_tcpB,32, 2 );
PutByteAtOffset( DA_tcpB,33, 0 );
PutByteAtOffset( DA_tcpB,34, 0 );
/* PutLongAtOffset( DA_tcpB,35, (long) dCtl); */
err = PBControl( (ParmBlkPtr)DA_tcp, false );
if( err != noErr )
alertUser2( dCtl, eBadKill, getTCPErrorStr(err) );
return(err);
}
/*----------------------------------------------------------------------
| Return the status of a TCP connection & the number of unread bytes
----------------------------------------------------------------------*/
OSErr StatusTCP( DCtlPtr dCtl, char *connection_state, short *unread_data )
{
OSErr err = noErr;
*connection_state = 0;
*unread_data = 0;
if( DA_tcp == nil ) return( noErr );
ZeroIOParams(DA_tcpB);
DA_tcp->csCode = TCPStatus;
PutLongAtOffset( DA_tcpB,98, (long) dCtl);
*unread_data = 0;
err = PBControl( (ParmBlkPtr)DA_tcp, false );
if( err != noErr )
return(err);
*connection_state = GetByteAtOffset(DA_tcpB,52);
*unread_data = GetWordAtOffset(DA_tcpB,60);
return(err);
}
/*----------------------------------------------------------------------
| Return the state of a TCP connection
----------------------------------------------------------------------*/
char connectionState( DCtlPtr dCtl )
{
char connection_state;
short dummy;
StatusTCP( dCtl, &connection_state, &dummy );
return(connection_state);
}
/*----------------------------------------------------------------------
| Send data on a TCP stream
----------------------------------------------------------------------*/
OSErr SendTCP( DCtlPtr dCtl, char *data)
{
OSErr err = noErr;
char WDS[32];
if( !*data ) return(err);
/*
* Build a WDS
*/
PutWordAtOffset(WDS, 0, strlen(data) );
PutLongAtOffset(WDS, 2, (long)(data) );
PutWordAtOffset(WDS, 6, 0 );
ZeroIOParams(DA_tcpB);
DA_tcp->csCode = TCPSend;
PutByteAtOffset( DA_tcpB,32, 30 );
PutByteAtOffset( DA_tcpB,33, 0 );
PutByteAtOffset( DA_tcpB,34, 0 );
PutByteAtOffset( DA_tcpB,35, 0 );
PutByteAtOffset( DA_tcpB,36, 0 );
PutLongAtOffset( DA_tcpB,38, (long) WDS );
PutLongAtOffset( DA_tcpB,48, (long) dCtl);
err = PBControl( (ParmBlkPtr)DA_tcp, false );
if( err != noErr )
alertUser2( dCtl, eBadSend, getTCPErrorStr(err) );
return(err);
}
/*----------------------------------------------------------------------
| Get data from a TCP connection
----------------------------------------------------------------------*/
OSErr GetTCP( DCtlPtr dCtl, char *buf, int max )
{
OSErr err = noErr;
ZeroIOParams(DA_tcpB);
DA_tcp->csCode = TCPRcv;
/*
* Time out, in seconds:
*/
PutByteAtOffset( DA_tcpB,32, 1 );
PutLongAtOffset( DA_tcpB,36, (long) buf );
PutWordAtOffset( DA_tcpB,40, max );
PutLongAtOffset( DA_tcpB,50, (long) dCtl);
err = PBControl( (ParmBlkPtr)DA_tcp, false );
if( (err != noErr) && (err != commandTimeout) )
{
alertUser2( dCtl, eBadGet, getTCPErrorStr(err) );
return(err);
}
buf[ GetWordAtOffset(DA_tcpB,40) ] = 0;
return(err);
}
/*----------------------------------------------------------------------
| Keep getting info until the other side closes the connection
----------------------------------------------------------------------*/
OSErr GetUntilClosed( DCtlPtr dCtl, char *buf, int max )
{
OSErr err = noErr;
short avail;
char state;
int i;
*buf = 0;
while( err == noErr )
{
err = StatusTCP( dCtl, &state, &avail );
if( state != 8 ) return( err );
if( avail )
{
i = strlen(buf);
err = GetTCP( dCtl, buf + i, max - i );
}
}
return( err );
}
/*----------------------------------------------------------------------
| Get all outstanding TCP data & put it into the DA's window.
----------------------------------------------------------------------*/
OSErr GetTCPtoWindow( DCtlPtr dCtl )
{
#define RCVBUFSIZE 2000
OSErr err = noErr;
short avail,
more,
rep = 0;
char state,
buf[RCVBUFSIZE+4],
*bp;
do
{
++rep;
/*
* Are there any characters available?
*/
err = StatusTCP( dCtl, &state, &avail );
if( !avail ) return(err);
if( (more = (avail > RCVBUFSIZE)) )
avail = RCVBUFSIZE;
/*
* Read them.
*/
if( (err = GetTCP( dCtl, buf, avail )) != noErr )
return(err);
/*
* Check if there's anything we want to skip.
*/
bp = buf;
if( DA_global->ignoreUntil )
{
while( *bp != DA_global->ignoreUntil )
{
if( !*bp ) return(noErr);
++bp;
}
DA_global->ignoreUntil = 0;
++bp;
if( !*bp ) return(noErr);
}
addTEstring( dCtl, bp);
} while( more && (rep < 10) );
return(err);
}
/*----------------------------------------------------------------------
| Check the status of a TCP connection & handle periodic stuff
----------------------------------------------------------------------*/
void checkTCP( DCtlPtr dCtl )
{
OSErr err = noErr;
char state;
short avail;
if( (err = StatusTCP( dCtl, &state, &avail )) == noErr )
{
changeMsg( dCtl, eStatClosed + (state >> 1) );
/*
* If the connection has closed, kill the stream.
*/
if( !state || (state == 12) )
{
KillTCPStream( dCtl );
}
/*
* If there is an established connection, read any bytes that
* might be available.
*/
if( (state >= 8) && (avail != 0) )
GetTCPtoWindow( dCtl );
/*
* If there is no data waiting & the server has issued a close,
* shut down our part of the connection too.
*/
else if( state == 14 )
{
CloseTCP( dCtl );
}
}
else
{
changeMsg( dCtl, eStatClosed );
}
}
/*----------------------------------------------------------------------
| Open a connection to the SuperServer & send the specified command
----------------------------------------------------------------------*/
void connectToServer( DCtlPtr dCtl, long inet_addr, char *command )
{
/* showBounds( dCtl ); */
if( MakeTCPStream( dCtl ) == noErr)
{
if( ActiveOpen( dCtl, inet_addr, 3502 ) == noErr )
{
DA_global->ignoreUntil = '\r';
SendTCP( dCtl, command );
}
}
}