modules/up/src/Core/network/Mtrace.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- mtraceTimerHandler
- Mtrace
- Mtrace
- send
- handleTimer
- receive
- Response
- Response
//
// $Id: Mtrace.cc,v 1.1.1.1 2000/03/10 16:32:19 engin Exp $
//
// Author(s): Ramesh Govindan
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "util/Types.hh"
#include "util/Trail.hh"
#include "util/Handler.hh"
#include "util/Buffer.hh"
#include "sys/File.hh"
#include "sys/Pipe.hh"
#include "sys/Time.hh"
#include "sched/Timer.hh"
#include "sched/Dispatcher.hh"
#include "network/Mtrace.hh"
#include "network/Headers.hh"
#include "network/Network.hh"
// Constants
static const U8 MaxUnicastTtl = 255;
static const U8 MaxMulticastTtl = 192;
// Locals
static TraceCode traceMtrace("network");
static TimeShort maxWait(10, 0);
static int mtraceSequence = 0;
static void
mtraceTimerHandler(void* ptr,
/* [<][>][^][v][top][bottom][index][help] */
void*)
{
((Mtrace*) ptr)->handleTimer();
}
Mtrace::Mtrace(const Address* s,
/* [<][>][^][v][top][bottom][index][help] */
const Address* g,
const Address* r,
const Address* R,
const Address* t,
int h,
const Handler& cb)
: ListNode()
{
done = cb;
source = *s;
group = *g;
multicastSocket = NULL;
if (r) {
replyTo = *r;
ASSERT(!IN_MULTICAST(replyTo.get()));
} else {
replyTo.set(MtraceMulticast);
}
if (R) {
receiver = *R;
} else {
receiver.set((network->interfaces.head())->address.get());
}
if (t) {
target = *t;
} else {
target.set(AllRoutersMulticast);
}
nhops = h;
timer = NULL;
network->pendingMtraces.append(this);
}
Mtrace::~Mtrace()
/* [<][>][^][v][top][bottom][index][help] */
{
if (timer) {
delete timer;
}
if (multicastSocket) {
delete multicastSocket;
}
responses.clear();
network->pendingMtraces.remove(this);
}
void
Mtrace::send()
/* [<][>][^][v][top][bottom][index][help] */
{
Handler th(mtraceTimerHandler, this);
Handler nh(NULL, NULL);
Buffer* buf;
IP* ip;
IGMP* igmp;
IGMPTrace* trace;
RawSocket* raw;
TimeLong at;
Address addr;
raw = new RawSocket(nh, nh, RawSocketIGMP);
buf = new Buffer(sizeof(IP) + sizeof(IGMP) + sizeof(IGMPTrace));
ip = (IP*) buf->contents;
ip->headerLength = sizeof(IP) >> 2;
ip->version = 4;
ip->typeOfService = 0;
ip->totalLength = sizeof(IP) + sizeof(IGMP) + sizeof(IGMPTrace);
ip->identifier = 0;
ip->fragmentOffset = 0;
ip->timeToLive = 0xff;
ip->protocol = IPPROTO_IGMP;
ip->source = (network->interfaces.head())->address.get();
ip->destination = target.get();
ip->hton();
ip->checksum = 0;
ip->checksum = htons(network->cksum((U16*) ip, sizeof(IP)));
igmp = (IGMP*) (ip + 1);
igmp->type = IGMPMtrace;
igmp->code = nhops;
igmp->group = group.get();
igmp->hton();
trace = (IGMPTrace*) (igmp + 1);
trace->source = source.get();
trace->destination = receiver.get();
trace->responseAddress = replyTo.get();
trace->timeToLive =
IN_MULTICAST(trace->destination) ?
MaxMulticastTtl : MaxUnicastTtl;
// identifier = ++mtraceSequence;
identifier = random() >> 8;
trace->queryId = identifier;
trace->hton();
igmp->checksum = 0;
igmp->checksum = network->cksum((U16*) igmp,
sizeof(IGMP) + sizeof(IGMPTrace));
addr.set(AllRoutersMulticast);
raw->sendTo(buf->contents, buf->size, addr, 0);
TRACE(traceMtrace, "mtrace sent to %s\n", group.name());
delete raw;
delete buf;
if (timer) {
delete timer;
}
at = dispatcher.systemClock;
at = at + maxWait;
timer = new Timer(th, at);
return;
}
void
Mtrace::handleTimer()
/* [<][>][^][v][top][bottom][index][help] */
{
TRACE(traceMtrace, "mtrace failed to %s\n", group.name());
timer = NULL;
done.callBack((void*) this);
return;
}
void
Mtrace::receive(const IGMPTrace *trace, int length)
/* [<][>][^][v][top][bottom][index][help] */
{
IGMPTraceResponse* resp;
// Save the response
resp = (IGMPTraceResponse*) (trace + 1);
for (int i = 0; i < (length / sizeof(IGMPTraceResponse)); i++) {
Mtrace::Response* response;
response = new Mtrace::Response(resp);
response->ntoh();
responses.append(response);
resp++;
}
done.callBack((void*) this);
return;
}
Mtrace::Response::Response(IGMPTraceResponse* r)
/* [<][>][^][v][top][bottom][index][help] */
: ListNode()
{
response = *r;
}
Mtrace::Response::~Response()
/* [<][>][^][v][top][bottom][index][help] */
{
// Empty
}
// Copyright (c) 1994 by the University of Southern California.
// All rights reserved.
//
// Permission to use, copy, modify, and distribute this software and
// its documentation in source and binary forms for lawful
// non-commercial purposes and without fee is hereby granted, provided
// that the above copyright notice appear in all copies and that both
// the copyright notice and this permission notice appear in supporting
// documentation, and that any documentation, advertising materials,
// and other materials related to such distribution and use acknowledge
// that the software was developed by the University of Southern
// California and/or Information Sciences Institute.
// The name of the University of Southern California may not
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
// ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
// PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
// NON-INFRINGEMENT.
//
// IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
// SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
// TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
// THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Questions concerning this software should be directed to
// scan@isi.edu.
//