Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
LocalServerTCP/LocalServerClient/TCPPitchSample.cp
/* |
File: TCPPitchSample.cp |
Contains: Tcp pitch sample. |
Copyright: © 1993-1997, 2000 by Apple Computer, Inc., all rights reserved. |
*/ |
// OT TCP Pitch Test Program (as an SIOW app) |
#include <OpenTransport.h> |
#include <OpenTransportProviders.h> |
#include <Processes.h> |
#include <stdio.h> |
#include <StdLib.h> |
#include "ServerInfo.h" |
#include <AppleEvents.h> |
#ifndef T_DISCON_IND |
#define T_DISCON_IND 128 |
#endif |
/******************************************************************************* |
** GLOBAL VARIABLES |
********************************************************************************/ |
InetPort gCatchPort = 0; |
InetHost gCatchIpAddr = 0; |
InetPort gPitchPort = 0; |
InetHost gPitchIpAddr = 0; |
unsigned short gBindCompleted = 0; |
unsigned short gCallRcvOrdDiscon = 0; |
static OTNotifyUPP gNotifier = nil; |
struct InetAddress gCatchAddr, rcvsin, reqsin, retsin; |
/******************************************************************************* |
** Function Prototypes |
********************************************************************************/ |
void Inits(); |
OSErr GetServerInfo(); |
void CleanUp(); |
void Idle(); |
void DoIt(); |
OSErr FindProcessBySignature( const OSType targetType, |
const OSType targetCreator, |
ProcessSerialNumberPtr psnPtr ); |
OTResult SetFourByteOption(EndpointRef ep, |
OTXTILevel level, |
OTXTIName name, |
UInt32 value); |
/******************************************************************************* |
** main function |
********************************************************************************/ |
void main() |
{ |
printf ("Hello World\n"); |
Inits(); |
if (GetServerInfo() == noErr) |
{ |
DoIt(); |
} |
else |
printf ("GetServerInfo returned an error\n"); |
CleanUp(); |
} |
/******************************************************************************* |
** Initialize Quickdraw and ASLM |
********************************************************************************/ |
void Inits() |
{ |
if (InitOpenTransport() != kOTNoError) |
{ |
fprintf(stderr, "OTTcpPitch: Could not initialize ASLM, exiting\n"); |
exit(1); |
} |
} |
/******************************************************************************* |
The FindProcessBySignature function returns a ProcessSerialNumber |
for a process whose signature (type and creator) matches the input values. |
The ProcessSerialNumber will be kNoProcess is the requested process cannot |
be found. |
targetType input: The file type of the process to be found. |
targetCreator input: The creator type of the process to be found. |
psnPtr input: Pointer to a ProcessSerialNumber where the |
process serial number is returned. |
output: Process serial number. |
RESULT CODES |
____________ |
noErr 0 No error |
procNotFound Ð600 No eligible process with specified descriptor |
____________ |
********************************************************************************/ |
OSErr FindProcessBySignature( const OSType targetType, |
const OSType targetCreator, |
ProcessSerialNumberPtr psnPtr ) |
{ |
OSErr anErr = noErr; |
Boolean foundTheProcess = false; |
ProcessInfoRec infoRec; |
infoRec.processInfoLength = sizeof( ProcessInfoRec ); |
infoRec.processName = nil; |
infoRec.processLocation = nil; |
infoRec.processAppSpec = nil; |
psnPtr->lowLongOfPSN = kNoProcess; |
psnPtr->highLongOfPSN = kNoProcess; |
while ( !foundTheProcess && (anErr == noErr) ) |
{ |
anErr = GetNextProcess( psnPtr ); |
if ( anErr == noErr ) |
{ |
anErr = GetProcessInformation( psnPtr, &infoRec ); |
if ( ( anErr == noErr ) |
&& ( infoRec.processType == targetType ) |
&& ( infoRec.processSignature == targetCreator ) ) |
{ |
foundTheProcess = true; |
} |
} |
} |
return anErr; |
}//end FindProcessBySignature |
/******************************************************************************* |
** Send an Apple Event to find out if the server is up and running |
** which will return the address to send the event to |
********************************************************************************/ |
OSErr GetServerInfo() |
{ |
AppleEvent reqEvent = { typeNull, nil }; |
AppleEvent retEvent = { typeNull, nil }; |
DescType typeCode; |
OSErr err; |
ProcessSerialNumber psn = { kNoProcess, kNoProcess }; |
AEDesc targetAppDesc = { typeNull, nil }; |
Size size; |
char mystr[255]; |
UInt32 dummy; |
err = FindProcessBySignature(kApplicationFileType, kPassServerSignature, &psn); |
if (err == noErr) |
{ |
err = AECreateDesc (typeProcessSerialNumber, &psn, sizeof( ProcessSerialNumber ), &targetAppDesc); |
if ( err == noErr ) |
{ |
err = AECreateAppleEvent( kPassServerInfoClass, kPassServerInfoEvent, &targetAppDesc, |
kAutoGenerateReturnID, kAnyTransactionID, &reqEvent); |
if (err) |
printf("AECreateAppleEvent returned error %d\n", err); |
} |
else |
printf("AECreateDesc returned error %d\n", err); |
AEDisposeDesc( &targetAppDesc ); |
} |
else |
printf("FindProcessBySignature returned error %d\n", err); |
if (err == noErr) |
{ |
// we have to insert a dummy in the outgoing AppleEvent list which the |
// LocalServer is expecting, but will not do anything with. Just doing this |
// for kicks |
err = AEPutParamPtr(&reqEvent, keyDirectObject, typeLongInteger, &dummy, |
sizeof(dummy) ); |
} |
if (err == noErr) |
{ |
err = AESend(&reqEvent, &retEvent, kAEWaitReply+kAENeverInteract, kAENormalPriority, |
kAEDefaultTimeout, nil, nil); |
if (err != noErr) |
{ |
printf("Error calling AESend = %d\n", err); |
} |
else |
{ |
// get the apple event object |
err = AEGetParamPtr(&retEvent, keyDirectObject, kPassServerType, &typeCode, |
&gCatchAddr, sizeof (struct InetAddress), &size ); |
if (err != noErr) |
printf("Error calling AEGetParamDesc to get the catch address %d\n", err); |
// dispose of the returned apple event |
AEDisposeDesc(&retEvent); |
} |
AEDisposeDesc(&reqEvent); |
} |
if (err == noErr) |
{ |
OTInetHostToString(gCatchAddr.fHost, mystr); |
printf("LocalServer found at %s, port %d.\n", mystr, gCatchAddr.fPort); |
} |
return err; |
} |
/******************************************************************************* |
** Clean up at the end |
********************************************************************************/ |
void CleanUp() |
{ |
CloseOpenTransport(); |
} |
/******************************************************************************* |
** Idle |
********************************************************************************/ |
void Idle() |
{ |
EventRecord theEvent; |
WaitNextEvent(everyEvent, &theEvent, 1, nil); |
} |
/******************************************************************************* |
** EventHandler |
********************************************************************************/ |
pascal void EventHandler(void*, OTEventCode event, OTResult, void*) |
{ |
OTEventCode tempevent = 0; |
switch ( event ) |
{ |
case T_BINDCOMPLETE: |
gBindCompleted = 1; |
break; |
case T_ORDREL: |
case T_DISCONNECTCOMPLETE: |
gCallRcvOrdDiscon = 1; |
break; |
case T_CONNECT: |
printf("T_CONNECT event occurred\n"); |
break; |
case T_DATA: |
printf("T_DATA event occurred\n"); |
break; |
case T_DISCONNECT: |
printf("T_DISCONNECT event occurred\n"); |
break; |
case T_ERROR: |
printf("T_ERROR event occurred\n"); |
break; |
default: |
printf("TCP EventHandler got unexpected event %d", event); |
break; |
} |
return; |
} |
/******************************************************************************* |
** DoIt |
********************************************************************************/ |
void DoIt() |
{ |
TEndpoint* ep = NULL; |
TEndpointInfo info; |
TBind req, ret; |
TCall sndcall, rcvcall; |
OSStatus err = kOTNoError; |
OTResult result; |
long myport = 0; |
InetHost myaddr = 0; |
char mystr[255]; |
long bytes = 0; |
OTFlags flags = 0; |
OTTimeStamp time; |
OTTimeStamp end, *begin, diff; |
UInt32 diffInMsec; |
UInt32 i, j; |
UInt8 *ptr; |
UInt8 buffer[32]; |
myport = 0; |
gPitchPort =(InetPort) myport; |
gPitchIpAddr = gCatchAddr.fHost; |
OTMemset(&rcvsin, 0, sizeof(struct InetAddress)); |
OTMemset(&sndcall, 0, sizeof(TCall)); |
OTMemset(&rcvcall, 0, sizeof(TCall)); |
OTMemset(&reqsin, 0, sizeof(struct InetAddress)); |
OTMemset(&rcvsin, 0, sizeof(struct InetAddress)); |
OTMemset(&req, 0, sizeof(TBind)); |
OTMemset(&ret, 0, sizeof(TBind)); |
do |
{ |
// |
// Now create a TCP |
// |
ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &info, &err); |
if ( ep == NULL || err != kOTNoError ) |
{ |
ep = NULL; |
fprintf(stderr,"ERROR: OpenEndpoint(\"TCP\") failed with %d\n", err); |
break; |
} |
// since we are going to send very small packet in this example, we need to |
// set the TCP NO_DELAY option, otherwise performance will be very poor |
// due to the Nagle Algorithm, where TCP optimizes small sends by waiting |
// for multiple requests to bundle the sends into a single larger packet. |
err = SetFourByteOption(ep, INET_TCP, TCP_NODELAY, 1); |
err = ep->SetSynchronous(); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: SetSynchronous() failed with %d\n", err); |
break; |
} |
// |
// Install notifier we're going to use for testing |
// |
gNotifier = NewOTNotifyUPP(EventHandler); |
err = ep->InstallNotifier(gNotifier, 0); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: InstallNotifier() failed with %d\n", err); |
break; |
} |
// |
// Try to bind |
// |
gPitchIpAddr = 0; |
OTInitInetAddress(&reqsin, gPitchPort, gPitchIpAddr); |
req.addr.len = sizeof(struct InetAddress); |
req.addr.buf = (unsigned char *) &reqsin; |
req.qlen = 0; // don't care for tcp |
ret.addr.maxlen = sizeof(struct InetAddress); |
ret.addr.buf = (unsigned char *) &retsin; |
OTInetHostToString(retsin.fHost, mystr); |
printf("Trying to bind at %s, port %d.\n", mystr, gPitchPort); |
// bind TCP to current address and port |
err = ep->Bind(&req, &ret); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: Bind() failed with %d\n", err); |
break; |
} |
OTInetHostToString(retsin.fHost, mystr); |
printf("Bound ep to %s, port %d.\n", mystr, retsin.fPort); |
err = ep->SetSynchronous(); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: SetSynchronous() failed with %d\n", err); |
break; |
} |
sndcall.addr.len = sizeof(struct InetAddress); |
sndcall.addr.buf = (unsigned char *) &gCatchAddr; |
rcvcall.addr.maxlen = sizeof(struct InetAddress); |
rcvcall.addr.buf = (unsigned char *) &rcvsin; |
err = ep->Connect(&sndcall, &rcvcall); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: Connect() failed with %d\n", err); |
break; |
} |
for (i = 0; i < 50; i++) |
{ |
OTGetTimeStamp(&time); |
bytes = ep->Snd(&time, sizeof(time), flags); |
if ( bytes >= 0 ) |
{ |
// the server will return the byte sent |
result = ep->Rcv(&buffer, sizeof(buffer), &flags); |
// get a timestamp |
OTGetTimeStamp(&end); |
fprintf(stderr, "Sent bytes: <%d> data\n", bytes); |
// print out the bytes of the time stamp |
if (result > 0) |
{ |
fprintf(stderr, "Rcv'd nbytes: <%d> data\n", result); |
begin = (OTTimeStamp*)&buffer; |
OTSubtractTimeStamps(&diff, begin, &end); |
diffInMsec = OTTimeStampInMilliseconds(&diff); |
printf("%ld bytes received - %ld milliseconds\n", result, diffInMsec); |
ptr = (UInt8*) &buffer; |
for (j = 0; j < result; j++) |
fprintf(stderr, "%X ", *ptr++); |
fprintf(stderr, "\n"); |
} |
else |
fprintf(stderr, "OTRcv'd error %d\n", result); |
} |
else |
{ |
fprintf(stderr, "ERROR: Snd() failed with %d\n", bytes); |
break; |
} |
Idle(); |
fflush(stderr); |
} |
} while (false); |
if ( ep != NULL ) |
{ |
err = ep->SetSynchronous(); |
err = ep->SndOrderlyDisconnect(); |
if ( err != kOTNoError ) |
{ |
if ( err == kOTLookErr ) |
fprintf(stderr, "SndOrderlyDisconnect() returns %d\n", err); |
else |
fprintf(stderr, "ERROR: SndOrderlyDisconnect() failed with %d\n", err); |
} |
else |
fprintf(stderr, "Orderly Disconnect sent successfully\n"); |
err = ep->RcvOrderlyDisconnect(); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: RcvOrderlyDisconnect() failed with %d\n", err); |
} |
// |
// Remove notifier |
// |
ep->RemoveNotifier(); |
// |
// Try to Unbind |
// |
err = ep->Unbind(); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: Unbind() returned %d\n", err); |
} |
// |
// Get rid of endpoint. |
// |
err = OTCloseProvider(ep); |
if ( err != kOTNoError ) |
{ |
fprintf(stderr, "ERROR: CloseEndpoint() failed with %d\n", err); |
} |
} |
fprintf(stderr, "Bye\n"); |
} |
OTResult SetFourByteOption(EndpointRef ep, |
OTXTILevel level, |
OTXTIName name, |
UInt32 value) |
{ |
OTResult err; |
TOption option; |
TOptMgmt request; |
TOptMgmt result; |
/* Set up the option buffer to specify the option and value to |
set. */ |
option.len = kOTFourByteOptionSize; |
option.level= level; |
option.name = name; |
option.status = 0; |
option.value[0] = value; |
/* Set up request parameter for OTOptionManagement */ |
request.opt.buf= (UInt8 *) &option; |
request.opt.len= sizeof(option); |
request.flags = T_NEGOTIATE; |
/* Set up reply parameter for OTOptionManagement. */ |
result.opt.buf = (UInt8 *) &option; |
result.opt.maxlen = sizeof(option); |
err = OTOptionManagement(ep, &request, &result); |
if (err == noErr) { |
if (option.status != T_SUCCESS) |
err = option.status; |
} |
return (err); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-30