[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_", ×tamp_);
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);
}