[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ns] Re: Unable to send packets downstream




hi,

Iam sending the test TCL script which i wrote and also the new RTP and
RTCP Agents that i have created...

Test TCL Script : rtcptest.tcl
Modified Agent Code : modify_rtp.{cc, h}, modify_rtcp.cc

i will b very grateful if somebody can spend some time to go thru this
and help me in figuring out the problem....

thanks,
Manoj.


> i did some experiments on the RTP and RTCP Agents and found that the
> RTCP Agent can send packtes only in "Multicast mode" and fails to send
> packets when it is in "Unicast mode"....
> 
> In unicast mode, it fails at target_->recv(p,0) line in the
> sendpkt() procedure in rtcp.cc...A "segmentation fault" occurs at this
> point..
> 
> can anybody please explain me the reason behind this and suggest how to
> overcome this problem...
> 
> thanks in advance,
> 
> Manoj Kumar.
> 
> problem and found On Thu, 22 Nov 2001, Manoj Kumar Chinnakotla wrote:
> 
> > hi,
> > 
> > I have an RTP Agent(Sender) which transmits packets to an RTCP  
> > Agent(receiver). The RTCP Agent sends receiver reports(packets) once in a  
> > fixed interval.
> > 
> > The Actual Problem :
> > 
> > Iam able to send the packets from the RTP Agent to the RTCP Agent but not
> > in the reverse direction...I mean, the RTCP Agent is not able to send
> > report packets back to the RTP Agent. It is failing at
> > target_->recv(p.0)..at this point "Segmentation Fault" Occurs.
> > 
> > I have checked the Destination Address in the IP header. it is correct.
> > 
> > Anyone please help me....
> > 
> > thanks,
> > Manoj.

rtcptest.tcl


#ifndef ns_rtpmm_h
#define ns_rtpmm_h

#include "config.h"
#include "object.h"
#include "agent.h"
#include "timer-handler.h"
#include "rtp.h"

#define RTP_M 0x0080 // marker for significant events

/* rtp packet.  For now, just have srcid + seqno. --- I have added the timestamp*/

struct hdr_rtp_mm { 
	u_int16_t packet_type_; // 0 - Data Packet, 1 - Sender Report, 2 - Recv Report
	u_int32_t srcid_;
	u_int16_t seqno_;
	double timestamp_;
	double fraction_lost_;	// Recv Reports - fraction of packets during the previous interval
	u_int32_t cumul_lost_;	// cumulative number of packets lost from the beginning of the session
	u_int16_t highest_seq_;	// the highest seq number packet received 
	double last_sr_timestamp_;	// the timestamp of the last SR received
	double delay_sr_;	// delay between SR and RR
	u_int32_t no_of_packets_;	// SR Number of packets sent till now
	
	//rtp flags indicating significant event(begining of talkspurt)
	u_int16_t flags_; 

	static int offset_;
	inline static int& offset() { return offset_; }
	inline static hdr_rtp_mm* access(const Packet* p) {
		return (hdr_rtp_mm*) p->access(offset_);
	}

	/* per-field member functions */
	u_int16_t& packet_type() { return (packet_type_); }
	u_int32_t& srcid() { return (srcid_); }
	u_int16_t& seqno() { return (seqno_); }
	double& timestamp(){ return (timestamp_); }
	double& fraction_lost(){ return(fraction_lost_); }
	u_int32_t& cumul_lost(){ return(cumul_lost_); }
	u_int16_t& highest_seq(){ return(highest_seq_); } 
	double& last_sr_timestamp(){ return(last_sr_timestamp_); }
	double& delay_sr(){ return(delay_sr_); }
	u_int32_t& no_of_packets(){ return(no_of_packets_); }
	u_int16_t& flags() { return (flags_); }
	
};

/*
 
class RTPSource : public TclObject {
public:
	RTPSource* next;

	RTPSource(u_int32_t srcid);
	inline u_int32_t srcid() { return (srcid_); }
	inline int np() { return (np_); }
	inline int snp() { return (snp_); }
	inline int ehsr() { return (ehsr_); }

	inline void np(int n) { np_ += n; }
	inline void snp(int n) { snp_ = n; }
	inline void ehsr(int n) { ehsr_ = n; }
protected:
	u_int32_t srcid_;
	int np_;
	int snp_;
	int ehsr_;
};


class RTPSession : public NsObject {
public:
	RTPSession();
	~RTPSession();
	virtual void recv(Packet* p, Handler*);
	virtual void recv_ctrl(Packet* p);
	int command(int argc, const char*const* argv);
	inline u_int32_t srcid() { return (localsrc_->srcid()); }
	int build_report(int bye);
	void localsrc_update(int);
protected:
	RTPSource* allsrcs_;
	RTPSource* localsrc_;
	int build_sdes();
	int build_bye();
	RTPSource* lookup(u_int32_t);
	void enter(RTPSource*);
	int last_np_;
};

*/

class RTPMMAgent;

class RTPMMTimer : public TimerHandler {
public: 
        RTPMMTimer(RTPMMAgent *a) : TimerHandler() { a_ = a; }
protected:
        virtual void expire(Event *e);
        RTPMMAgent *a_;
};

class SRTimer : public TimerHandler {
	public :
		SRTimer(RTPMMAgent *a):TimerHandler(){ a_ = a; }
	protected :
		virtual void expire(Event *e);
		RTPMMAgent *a_;
};

class RTPMMAgent : public Agent {
 public:
        RTPMMAgent();
        virtual void rtp_timeout(int);
	virtual void sr_timeout(int);
        virtual void recv(Packet* p, Handler*);
        virtual int command(int argc, const char*const* argv);
        void advanceby(int delta);
        virtual void sendmsg(int nbytes, const char *flags = 0);
 protected:
        virtual void sendpkt();
	virtual void makepkt(Packet*);
        void rate_change();
        virtual void start();
        virtual void stop();
        virtual void finish();
        double lastpkttime_;
        int seqno_;
	double timestamp_;
        int running_;
        int random_;
        int maxpkts_;
        double interval_;
	double rtcp_interval_;
        RTPMMTimer rtp_timer_;
	SRTimer sr_timer_;
};


#endif

#ifndef lint
static const char rcsid[] =
    "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/rtp.cc,v 1.26 2000/08/18 18:34:01 haoboy Exp $";
#endif


#include <stdlib.h>
#include "config.h"
#include "agent.h"
#include "packet.h"
#include "address.h"
#include "random.h"
#include "ip.h"
#include "modify_rtp.h"

int hdr_rtp_mm::offset_;

class RTPMMHeaderClass : public PacketHeaderClass {
public: 
        RTPMMHeaderClass() : PacketHeaderClass("PacketHeader/RTPMM",
					     sizeof(hdr_rtp_mm)) {
		bind_offset(&hdr_rtp_mm::offset_);
	}
}; 

static class RTPMMAgentClass : public TclClass {
public:
	RTPMMAgentClass() : TclClass("Agent/RTPMM") {}
	TclObject* create(int, const char*const*) {
		return (new RTPMMAgent());
	}
} class_rtp_mm_agent;

RTPMMAgent::RTPMMAgent() : Agent(PT_RTP_MM), lastpkttime_(-1e6), 
    running_(0), rtp_timer_(this), sr_timer_(this)
{
	bind("seqno_", &seqno_);
	bind_time("timestamp_", &timestamp_);
	bind_time("interval_", &interval_);
	bind_time("rtcp_interval_",&rtcp_interval_);
	bind("packetSize_", &size_);
	bind("maxpkts_", &maxpkts_);
	bind("random_", &random_);
}

void RTPMMAgent::start()
{
        running_ = 1;
	sendpkt();
        rtp_timer_.resched(interval_);
	sr_timer_.resched(rtcp_interval_);
}

void RTPMMAgent::stop()
{
        rtp_timer_.force_cancel();
	sr_timer_.force_cancel();
        finish();
}

void RTPMMAgent::sendmsg(int nbytes, const char* /*flags*/)
{
        Packet *p;
        int n;
	

        if (++seqno_ < maxpkts_) {
                if (size_)
                        n = nbytes / size_;
                else
                        printf("Error: RTPMMAgent size = 0\n");

                if (nbytes == -1) {
                        start();
                        return;
                }
                while (n-- > 0) {
                        p = allocpkt();
                        hdr_rtp_mm* rh = hdr_rtp_mm::access(p);
                        rh->seqno() = seqno_;
			rh->timestamp() = timestamp_;
                        target_->recv(p);
                }
                n = nbytes % size_;
                if (n > 0) {
                        p = allocpkt();
                        hdr_rtp_mm* rh = hdr_rtp_mm::access(p);
                        rh->seqno() = seqno_;
			rh->timestamp() = timestamp_;
			
			struct hdr_ip *ih = HDR_IP(p);

			int src = Address::instance().get_nodeaddr(ih->saddr());
			int dst = Address::instance().get_nodeaddr(ih->daddr());
	
			Tcl::instance().evalf("puts stdout \"In the sendpkt procedure part src=%d, and dst=%d\"", src, dst);
			fflush(stdout);

                        target_->recv(p);
                }
                idle();
        } else {
                finish();
                // xxx: should we deschedule the timer here? */
        };
}

void RTPMMAgent::rtp_timeout(int) 
{
	if (running_) {
		sendpkt();
		/* if (session_)
			session_->localsrc_update(size_); */
		double t = interval_;
		if (random_)
			/* add some zero-mean white noise */
			t += interval_ * Random::uniform(-0.5, 0.5);
		rtp_timer_.resched(t);
	}
}

void RTPMMAgent::sr_timeout(int)
{
	if(running_) {
		Tcl::instance().evalc("puts stdout \"I timed out and sent the report\"");
		sendpkt();
		sr_timer_.resched(rtcp_interval_);
	}
}

/*
 * finish() is called when we must stop (either by request or because
 * we're out of packets to send.
 */
void RTPMMAgent::finish()
{
        running_ = 0;
        Tcl::instance().evalf("%s done", this->name());
}

void RTPMMAgent::advanceby(int delta)
{
        maxpkts_ += delta;
        if (seqno_ < maxpkts_ && !running_)
                start();
}               


void RTPMMAgent::recv(Packet* p, Handler*)
{
	/* if (session_)
		session_->recv(p, 0); 
	else */
        Tcl::instance().evalf("I have recieved the packet");
	Packet::free(p);
}

int RTPMMAgent::command(int argc, const char*const* argv)
{
	if (argc == 2) {
		if (strcmp(argv[1], "rate-change") == 0) {
			rate_change();
			return (TCL_OK);
		} else if (strcmp(argv[1], "start") == 0) {
                        start();
                        return (TCL_OK);
                } else if (strcmp(argv[1], "stop") == 0) {
                        stop();
                        return (TCL_OK);
                }
	} else if (argc == 3) {
		if (strcmp(argv[1], "session") == 0) {
			/* session_ = (RTPSession*)TclObject::lookup(argv[2]); */
			return (TCL_OK);
		} else if (strcmp(argv[1], "advance") == 0) {
                        int newseq = atoi(argv[2]);
                        advanceby(newseq - seqno_);
                        return (TCL_OK); 
                } else if (strcmp(argv[1], "advanceby") == 0) {
                        advanceby(atoi(argv[2]));
                        return (TCL_OK);
                }       
	}
	return (Agent::command(argc, argv));
}

/* 
 * We modify the rate in this way to get a faster reaction to the a rate
 * change since a rate change from a very low rate to a very fast rate may 
 * take an undesireably long time if we have to wait for timeout at the old
 * rate before we can send at the new (faster) rate.
 */
void RTPMMAgent::rate_change()
{
	rtp_timer_.force_cancel();
	
	double t = lastpkttime_ + interval_;
	
	double now = Scheduler::instance().clock();
	if ( t > now)
		rtp_timer_.resched(t - now);
	else {
		sendpkt();
		rtp_timer_.resched(interval_);
	}
}

void RTPMMAgent::sendpkt()
{
	Packet* p = allocpkt();
	lastpkttime_ = Scheduler::instance().clock();
	makepkt(p);
	(target_)->recv(p, (Handler*)0);
}

void RTPMMAgent::makepkt(Packet* p)
{
	hdr_rtp_mm *rh = hdr_rtp_mm::access(p);
	/* Fill in srcid_ and seqno */
	rh->seqno() = seqno_++;
	rh->timestamp() = Scheduler::instance().clock();
	rh->srcid() = 0; /* SSRC identfier is expected here */
}

void RTPMMTimer::expire(Event* /*e*/) {
        a_->rtp_timeout(0);
}

void SRTimer::expire(Event *e) {
	a_->sr_timeout(0);
}

#ifndef lint
static const char rcsid[] =
    "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/rtcp.cc,v 1.17 2000/09/01 03:04:06 haoboy Exp $";
#endif

#include <stdlib.h>

#include "config.h"
#include "agent.h"
#include "random.h"
#include "ip.h"
#include "packet.h"
#include "modify_rtp.h"
#include "address.h"

class RTCPMMAgent;

class RTCPMM_Timer : public TimerHandler {
public: 
	RTCPMM_Timer(RTCPMMAgent *a) : TimerHandler() { a_ = a; }
protected:
	virtual void expire(Event *e);
	RTCPMMAgent *a_;
};

class RTCPMMAgent : public Agent {
public:
	RTCPMMAgent();
	virtual void timeout(int);
	virtual void recv(Packet* p, Handler* h);
	int command(int argc, const char*const* argv);
protected:
	void start();
	void stop();
	void sendpkt();

	int running_;
	int random_;
	u_int16_t seqno_;
	double rtcp_interval_;
	// RTPSession* session_;

	RTCPMM_Timer rtcpmm_timer_;
};

static class RTCPMMAgentClass : public TclClass {
public:
	RTCPMMAgentClass() : TclClass("Agent/RTCPMM") {}
	TclObject* create(int, const char*const*) {
		return (new RTCPMMAgent());
	}
} class_rtcpmm_agent;

/* XXX Could perhaps derive this from CBR.  If so, use cbr_timer_ */
RTCPMMAgent::RTCPMMAgent()
	: Agent(PT_RTP_MM), rtcpmm_timer_(this)
{
	size_ = 128;
	bind_time("rtcp_interval_", &rtcp_interval_);
	bind("random_", &random_);
	bind("seqno_", &(unsigned int )seqno_);
	running_ = 0;
}

void RTCPMMAgent::start()
{
	
	Tcl::instance().evalc("puts stdout \"In the START procedure part......---1\"");
	fflush(stdout);
	running_ = 1;
	rtcpmm_timer_.resched(rtcp_interval_);
}

void RTCPMMAgent::stop()
{
	rtcpmm_timer_.cancel();
	running_ = 0;
}

void RTCPMMAgent::recv(Packet* p, Handler*)
{
	Tcl::instance().evalc("puts stdout \"I received a packet\"");
	
	Packet::free(p);
	// session_->recv_ctrl(p);
}

void RTCPMMAgent::sendpkt()
{
	Packet* p = allocpkt();
	if(p)
	{
	hdr_rtp_mm* rh = hdr_rtp_mm::access(p);

	Tcl::instance().evalc("puts stdout \"In the sendpkt procedure part......---1\"");
	/* Fill in srcid_ and seqno */
	rh->seqno() = seqno_++;
	rh->srcid() = 0; 		// session_->srcid();
	Tcl::instance().evalc("puts stdout \"In the sendpkt procedure part......---2\"");
	struct hdr_ip *ih = HDR_IP(p);
	
	int src = Address::instance().get_nodeaddr(ih->saddr());
	int dst = Address::instance().get_nodeaddr(ih->daddr());
	
	Tcl::instance().evalf("puts stdout \"In the sendpkt procedure part src=%d, and dst=%d\"", src, dst);
	fflush(stdout);
	
	target_->recv(p,(Handler *)0);
	Tcl::instance().evalc("puts stdout \"In the sendpkt procedure part......---3\"");
	
	}
}

void RTCPMMAgent::timeout(int)
{
	Tcl::instance().evalc("puts stdout \"In the timeout procedure part......\"");
	if (running_) {
		size_ = 20; 	//session_->build_report(0)
		sendpkt();
		double t = rtcp_interval_;
		if (random_)
			/* add some zero-mean white noise */
			t += rtcp_interval_ * Random::uniform(-0.5, 0.5);	
		rtcpmm_timer_.resched(t);
		/* XXX */
		// Tcl::instance().evalf("%s rtcp_timeout", session_->name());
	}
}

int RTCPMMAgent::command(int argc, const char*const* argv)
{
	if (argc == 2) {
		if (strcmp(argv[1], "start") == 0) {
			Tcl::instance().evalc("puts stdout \"In the C++ command executing part......\"");
			fflush(stdout);
			start();
			return (TCL_OK);
		}
		if (strcmp(argv[1], "stop") == 0) {
			stop();
			return (TCL_OK);
		}
		if (strcmp(argv[1], "bye") == 0) {
			size_ = 20;		// session_->build_report(1);
			sendpkt();
			stop();
			return (TCL_OK);
		}
	} else if (argc == 3) {
			/* if (strcmp(argv[1], "session") == 0) {
			session_ = (RTPSession*)TclObject::lookup(argv[2]); */
			return (TCL_OK);
		}

	return (Agent::command(argc, argv));
}

void RTCPMM_Timer::expire(Event* /*e*/) {
	a_->timeout(0);
}