• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: bootp example
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: bootp example


  • Subject: Re: bootp example
  • From: Quinn <email@hidden>
  • Date: Wed, 9 Jul 2003 10:47:16 +0100

At 10:50 -0400 25/6/03, Matt Mashyna wrote:
I need to implement a bootp server for carbon (yes 9 & X) so I can listen for a router reboot. Can anyone point me to some example code ?

I don't know of any official UDP broadcast send/received samples. However, my experience is that this isn't particularly tricky. The most common gotchas associated with UDP broadcast reception are covered by DTS Q&A NW 53.

<http://developer.apple.com/qa/nw/nw53.html>

I also dug through my archive of snippets written for developers and found some code that might be useful. It contains too many ugly experiments to post as a whole, but I've included some relevant routines at the end of this email.

Note that this was written for traditional Mac OS (pre-Carbon). I decided not to update it for Carbon because we're no longer encouraging developers to use the OT API for new code.

S+E
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Technical Support * Networking, Communications, Hardware


static OSStatus BindEndpoint(EndpointRef ep, InetHost host, InetPort port)
{
OSStatus err;
TBind bindRequest;
InetAddress requestAddr;
TBind bindResponse;
InetAddress responseAddr;

// Set up to bind the endpoint. Because we're listening for broadcasts,
// we have to request kOTAnyInetAddress.
OTInitInetAddress(&requestAddr, port, host);
OTMemzero(&bindRequest, sizeof(TBind));
bindRequest.addr.buf = (UInt8 *) &requestAddr;
bindRequest.addr.len = sizeof(InetAddress);

// Because the port might be in use, we have to check that XTI
// has not given us another port (XTI is kinda lame in this respect).
// So we set up bindResponse to collect the bound address.
OTMemzero(&bindResponse, sizeof(TBind));
bindResponse.addr.buf = (UInt8 *) &responseAddr;
bindResponse.addr.maxlen = sizeof(InetAddress);
// Do the bind and check that we got what we wanted.
err = OTBind(ep, &bindRequest, &bindResponse);
if (err == noErr) {
if ( requestAddr.fPort != responseAddr.fPort ) {
err = kEADDRINUSEErr;
}
}
return err;
}

static pascal OSStatus EchoThread(void *junkParam)
{
#pragma unused(junkParam)
OSStatus err;
OSStatus junk;
OTResult result;
EndpointRef ep;
TEndpointInfo epInfo;
UInt8 *dataBuffer;
UInt8 *addrBuffer;
TUnitData rcvRequest;
OTFlags junkFlags;
InetAddress *sourceAddr;
dataBuffer = nil;
addrBuffer = nil;
ep = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, nil, &err);

// If the endpoint opens successfully...
if (err == noErr) {
SetupEndpointForThreads(ep);

junk = OTGetEndpointInfo(ep, &epInfo);
OTAssert("EchoThread: OTGetEndpointInfo failed", junk == noErr);
dataBuffer = OTAllocMem(epInfo.tsdu);
if (dataBuffer == nil) {
err = kENOMEMErr;
}
addrBuffer = OTAllocMem(epInfo.addr);
if (dataBuffer == nil) {
err = kENOMEMErr;
}
}
// Now bind the endpoint.
if (err == noErr) {
result = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, 1);
if (result > 0) {
err = kENXIOErr;
} else {
err = result;
}
}
if (err == noErr) {
err = BindEndpoint(ep, kOTAnyInetAddress, kTestPort);
}
if (err == noErr) {

// Tell the sending thread that we're bound and waiting for
// packets to echo. We do this because we want to make sure
// that we bind before it does.
gEchoThreadBound = true;
// Repeatedly get data from the endpoint and echo it to
// stdout.
do {
OTMemzero(&rcvRequest, sizeof(TUnitData));
rcvRequest.addr.buf = addrBuffer;
rcvRequest.addr.maxlen = epInfo.addr;
rcvRequest.udata.buf = dataBuffer;
rcvRequest.udata.maxlen = epInfo.tsdu;
err = OTRcvUData(ep, &rcvRequest, &junkFlags);
if (err == noErr) {
sourceAddr = (InetAddress *) addrBuffer;

printf("EchoThread: Got a packet!\n");
printf(" size = %ld.\n", rcvRequest.addr.len);
if ( sourceAddr->fAddressType == AF_INET ) {
printf(" source addr = %d.%d.%d.%d, source port = %d\n",
(int) ((sourceAddr->fHost >> 24) & 0x00FF),
(int) ((sourceAddr->fHost >> 16) & 0x00FF),
(int) ((sourceAddr->fHost >> 8) & 0x00FF),
(int) ((sourceAddr->fHost >> 0) & 0x00FF),
sourceAddr->fPort);
} else {
printf(" unknown (fAddressType = %d)\n", ((InetAddress *) addrBuffer)->fAddressType);
}
} else if (err == kOTLookErr) {
OTResult look;
look = OTLook(ep);
switch ( look ) {
case T_UDERR:
err = OTRcvUDErr(ep, nil);
break;
default:
printf("EchoThread: Got a kOTLookErr, look = %ld\n", look);
// leave err set to kOTLookErr
break;
}
}
// fflush(stdout);
} while (err == noErr);
}
// Clean up.
if (addrBuffer != nil) {
OTFreeMem(dataBuffer);
}
if (dataBuffer != nil) {
OTFreeMem(addrBuffer);
}
if (ep != kOTInvalidEndpointRef) {
junk = OTCloseProvider(ep);
OTAssert("EchoThread: OTCloseProvider failed", junk == noErr);
}
if (err == noErr || err == userCanceledErr) {
printf("EchoThread: Successful termination.\n");
} else {
printf("EchoThread: Terminated with error %d.\n", err);
}
return noErr;
}

static UInt32 gPacketsToSend = 0;

static UInt32 gCurrentPacketNumber = 0;

static pascal OSStatus SendThread(void *junkParam)
{
#pragma unused(junkParam)
OSStatus err;
OSStatus junk;
EndpointRef ep;
OTResult result;
TUnitData sndRequest;
InetAddress destAddr;
OTResult look;
char dataString[256];
ep = kOTInvalidEndpointRef;
// Start by waiting for the echo thread to start up successfully.
err = noErr;
while ( err == noErr && ! gEchoThreadBound ) {
err = MyYieldToAnyThread();
}
// Create the endpoint, set it up for threaded execution, set
// up the IP_REUSEADDR option, and then bind it to one of the
// interfaces.
if (err == noErr) {
ep = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, nil, &err);
}
if (err == noErr) {
SetupEndpointForThreads(ep);
result = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, 1);
if (result > 0) {
err = kENXIOErr;
} else {
err = result;
}
}
if (err == noErr) {
err = BindEndpoint(ep, kOTAnyInetAddress, kTestPort);
}
if (err == noErr) {
do {
if (gPacketsToSend == 0) {
err = MyYieldToAnyThread();
} else {
OTInitInetAddress(&destAddr, kTestPort, 0xFFFFFFFF);

gCurrentPacketNumber += 1;
sprintf(dataString, "Broadcast Message %ld", gCurrentPacketNumber);
OTMemzero(&sndRequest, sizeof(TUnitData));
sndRequest.addr.buf = (UInt8 *) &destAddr;
sndRequest.addr.len = sizeof(InetAddress);
sndRequest.udata.buf = (UInt8 *) dataString;
sndRequest.udata.len = OTStrLength(dataString);
err = OTSndUData(ep, &sndRequest);
if (err == kOTLookErr) {
look = OTLook(ep);
switch ( look ) {
case T_UDERR:
err = OTRcvUDErr(ep, nil);
break;
case T_DATA:
printf("SendThread: Got a T_DATA\n");
// leave err set to kOTLookErr
break;
default:
printf("SendThread: Got a kOTLookErr, look = %ld\n", look);
// leave err set to kOTLookErr
break;
}
}
// fflush(stdout);
gPacketsToSend -= 1;
}
} while (err == noErr);
}
// Clean up.
if (ep != kOTInvalidEndpointRef) {
junk = OTCloseProvider(ep);
OTAssert("SendThread: OTCloseProvider failed", junk == noErr);
}
if (err == noErr || err == userCanceledErr) {
printf("SendThread: Successful termination.\n");
} else {
printf("SendThread: Terminated with error %d.\n", err);
}
return noErr;
}
_______________________________________________
macnetworkprog mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/macnetworkprog
Do not post admin requests to the list. They will be ignored.
  • Prev by Date: Re: Help for Network Configuration
  • Next by Date: Re: NSLStartNeighborhoodLookup in Jaguar
  • Previous by thread: Re: Help for Network Configuration
  • Next by thread: Authenticating
  • Index(es):
    • Date
    • Thread