diff -uNr ns-2.1b9a/Makefile.in ns-2.1b9a_sip/Makefile.in --- ns-2.1b9a/Makefile.in Fri Jun 7 07:37:57 2002 +++ ns-2.1b9a_sip/Makefile.in Fri Sep 5 11:37:36 2003 @@ -163,6 +163,7 @@ tcp/tcp-asym-fs.o \ tcp/tcp-int.o tcp/chost.o tcp/tcp-session.o \ tcp/nilist.o \ + sip/sip.o sip/sip_server.o sip/sip_tg.o \ tools/integrator.o tools/queue-monitor.o \ tools/flowmon.o tools/loss-monitor.o \ queue/queue.o queue/drop-tail.o \ diff -uNr ns-2.1b9a/apps/app.h ns-2.1b9a_sip/apps/app.h --- ns-2.1b9a/apps/app.h Tue Sep 28 12:46:27 1999 +++ ns-2.1b9a_sip/apps/app.h Fri Nov 22 01:12:23 2002 @@ -50,6 +50,7 @@ Application(); virtual void send(int nbytes); virtual void recv(int nbytes); + virtual void recv_msg(int nbytes, const char *msg = 0) {}; virtual void resume(); protected: diff -uNr ns-2.1b9a/common/agent.cc ns-2.1b9a_sip/common/agent.cc --- ns-2.1b9a/common/agent.cc Fri Jun 21 07:26:13 2002 +++ ns-2.1b9a_sip/common/agent.cc Sat Dec 28 04:32:00 2002 @@ -367,6 +367,14 @@ } /* + * SIP Registration + */ +int Agent::Register() +{ + return 0; +} + +/* * Assign application pointer for callback purposes */ void Agent::attachApp(Application *app) @@ -523,3 +531,16 @@ return(p); } + +/* SIP function */ +void +Agent::set_tusername(const char* username) +{ + /* real implementaion is located SIPAgent::set_tusrname */ +} + +void +Agent::set_turl(const char* url) +{ + /* real implementaion is located SIPAgent::set_turl */ +} diff -uNr ns-2.1b9a/common/agent.h ns-2.1b9a_sip/common/agent.h --- ns-2.1b9a/common/agent.h Fri Mar 22 03:42:10 2002 +++ ns-2.1b9a_sip/common/agent.h Sat Dec 28 04:30:41 2002 @@ -80,6 +80,8 @@ void send(Packet* p, Handler* h) { target_->recv(p, h); } virtual void timeout(int tno); + // SIP registeration call + virtual int Register(); virtual void sendmsg(int sz, AppData*, const char* flags = 0); virtual void send(int sz, AppData *data) { sendmsg(sz, data, 0); } virtual void sendto(int sz, AppData*, const char* flags, @@ -92,6 +94,8 @@ virtual void close(); virtual void listen(); virtual void attachApp(Application* app); + virtual void set_tusername(const char* username); + virtual void set_turl(const char* username); virtual int& size() { return size_; } inline nsaddr_t& addr() { return here_.addr_; } inline nsaddr_t& port() { return here_.port_; } diff -uNr ns-2.1b9a/common/packet.h ns-2.1b9a_sip/common/packet.h --- ns-2.1b9a/common/packet.h Fri Jun 21 07:26:13 2002 +++ ns-2.1b9a_sip/common/packet.h Fri Nov 22 00:22:39 2002 @@ -147,6 +147,7 @@ PT_PGM, #endif //STL + PT_SIP, // Session Initiation Protocol // insert new packet types here PT_NTYPE // This MUST be the LAST one }; @@ -226,7 +227,7 @@ // for PGM name_[PT_PGM] = "PGM"; #endif - + name_[PT_SIP] = "SIP"; name_[PT_NTYPE]= "undefined"; } const char* name(packet_t p) const { diff -uNr ns-2.1b9a/sip/readme ns-2.1b9a_sip/sip/readme --- ns-2.1b9a/sip/readme Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/sip/readme Thu Sep 4 20:24:29 2003 @@ -0,0 +1,49 @@ +readme - README file for NS-2 SIP module + + Jin-Woo Jung + +Please submit bug reports to jjw@kore.ac.kr + +----------------------------------------------------------------------- + +INSTALLTION: + +1. For first installs only: + + a. dowload ns-allinone-2.1b9a from + http://www.isi.edu/nsnam/dist/ns-allinone-2.1b9a.tar.gz + + b. untar the file by doing: + tar xvzf ns-allinone-2.19a.tar.gz + +2. Download the patch file for supporting SIP + + a. ns-allinone-2.1b9a.sip.patch + +3. At the parent directory of the untar'd source, do: + + patch -p0 < ns-allinone-2.1b9a.sip.patch + +4. Compile ns-2 + +5. For first installs : add ns-allinone-2.1b9a/bin to your path + +------------------------------------------------------------------------ + + +Example Script + +For three cases, we supports Example scripts. + + - Peer-To-Peer Communication between caller and callee + ( ../ns-2.1b9a/tcl/sip/normal_test.tcl) + + - Peer-To-Peer Communication in Proxy Mode + (../ns-2.1b9a/tcl/sip/proxy_test.tcl) + + - Peer-To-Peer Communication in Redirect Mode + (../ns-2.1b9a/tcl/sip/redirect_test.tcl) + + +--------------------------------------------------------------------------- + \ No newline at end of file diff -uNr ns-2.1b9a/sip/sip.cc ns-2.1b9a_sip/sip/sip.cc --- ns-2.1b9a/sip/sip.cc Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/sip/sip.cc Thu Sep 4 18:58:19 2003 @@ -0,0 +1,851 @@ +// +// This software was developed at the National Institute of Standards and +// Technology by employees of the Federal Goverment in the course of their +// official duties. This software is an experimental objects. NIST assumes +// no responsibility whatsoever for its use by other parties, and makes no +// guarantees, expressed or implied, about its quality, reliability, or any +// other characteristic. We would appreicate acknowledgement if the software +// is used. + +// This software can be redistributed and/or modified freely. We respect +// that any derivative works bear some notice that they are derived from it, +// any any modified versions bear some notice that they have been modified. + +// Jin-Woo Jung, jjw@korea.ac.kr + +#include "sip.h" +#include "rtp.h" +#include "udp.h" +#include "random.h" +#include "time.h" + + // SIP + + int hdr_SIP::offset_; + + // SIP Header Class + static class SIPHeaderClass : public PacketHeaderClass { + public: + SIPHeaderClass() : PacketHeaderClass("PacketHeader/SIP", sizeof(hdr_SIP)) { + bind_offset(&hdr_SIP::offset_); + } + } class_SIPhdr; + + +static class SIPAgentClass : public TclClass { + public: + SIPAgentClass() : TclClass("Agent/SIP") {} + TclObject* create(int argc, const char*const* argv) { + if(argc == 6) + { + return (new SIPAgent(argv[4],argv[5])); + } else { + printf("ERROR : Bad Argument\n"); + printf("Usage : set variable [new Agent/SIP username URL]\n"); + return (new SIPAgent(argv[4],argv[5])); + } + + } +} class_SIP_agent; + + +SIPAgent::SIPAgent(const char* username, const char* url) : Agent(PT_SIP), seqno_(1), present_seq(0), present_CSeq(0), inv_list_head(0), inv_list_tail(0), reg_list_head(0), reg_list_tail(0), +ok_list_head(0), ok_list_tail(0) // why not Agent(PT_UDP) +{ + + bind("packetSize_", &size_); // setup SIP message size using Otcl script + bind("print_", &print_log_); // for tracing message flow + bind("Registrar_", &Registrar_); // + bind("Server_", &Server_); + bind("Lifetime_",&Lifetime_); + bind("Mode_",&Mode_); + strcpy(usrid_,username); + strcpy(url_,url); + set_username(usrid_); // setup User Name or User ID + set_url(url_); // setup node's URL + ua_state_.callSetComplete = 0; // if call setup is completed, its value is non-zero +} + +SIPAgent::SIPAgent(packet_t type) : Agent(type), present_seq(0), present_CSeq(0), inv_list_head(0), inv_list_tail(0), reg_list_head(0),reg_list_tail(0), ok_list_head(0), ok_list_tail(0) +{ + bind("packetSize_", &size_); + bind("print_", &print_log_); + bind("Registrar_", &Registrar_); + bind("Server_", &Server_); + bind("Lifetime_",&Lifetime_); + bind("Mode_",&Mode_); + ua_state_.callSetComplete = 0; + set_username(usrid_); + set_url(url_); + +} + +void SIPAgent::recv(Packet* p, Handler *) +{ + Tcl& tcl = Tcl::instance(); + char *objname = NULL; + NsObject *obj = NULL; + hdr_ip *iph = hdr_ip::access(p); + hdr_cmn *ch = hdr_cmn::access(p); + hdr_SIP* sh = hdr_SIP::access(p); + hdr_SIP sh_buf; + memcpy(&sh_buf, sh, sizeof(hdr_SIP)); + hdr_SIP sh_buf_send; + sh_buf_send.seq = sh->seq; + struct sip_address toaddr_; + + + int nodeaddr = Address::instance().get_nodeaddr(addr()); + + if(sh->type == SIP_MSG_INVITE) { + ua_state_.LastCallID = sh->callID; + + strcpy(ua_state_.tusrname,sh->usrname); + strcpy(ua_state_.turl,sh->url); + ua_state_.callee_location.node_ = iph->saddr(); + ua_state_.callee_location.port_ = iph->sport(); + + ok_list* listp = del_ok_item(sh_buf_send.seq); + toaddr_.node_ = iph->saddr(); + toaddr_.port_ = iph->sport(); + if(!listp) { + send_sip_response(sh->seq, sh->type, SIP_RSP_TRYING,toaddr_); // send 100-TRYING + send_sip_response(sh->seq, sh->type, SIP_RSP_RINGING,toaddr_); // send 180-RINGING + } else { + listp->timer->cancel(); + delete listp; + } + send_sip_response(sh->seq, sh->type, SIP_RSP_SUCCESS,toaddr_); + OkTimer* ok_tmr = new OkTimer(this); + ok_tmr->seq = sh_buf_send.seq; + ok_tmr->retrans = 0; + ok_tmr->method = sh->type; + ok_tmr->resched(0.5); + + ok_list* ok_list_ptr = new ok_list; + ok_list_ptr->seq = sh_buf_send.seq; + ok_list_ptr->method = sh->type; + ok_list_ptr->timer = ok_tmr; + ok_list_ptr->next = 0; + + if(!ok_list_head) { + ok_list_head = ok_list_ptr; + ok_list_tail = ok_list_ptr; + } else { + ok_list_tail->next = ok_list_ptr; + ok_list_tail = ok_list_ptr; + } + } else if (sh->type == SIP_RSP_TRYING) { + invite_list* listp = del_inv_item(sh->seq); + if(listp) { + listp->timer->cancel(); + delete listp; + } + if(print_log_) + printf("SIP/2.0 100 Trying %d %d \t CSeq = %d 100-TRYING\n", sh->ContactID.node_, sh->ContactID.port_,sh->seq); + } else if (sh->type == SIP_RSP_RINGING) { + invite_list* listp = del_inv_item(sh->seq); + if(listp) { + listp->timer->cancel(); + delete listp; + } + + if(print_log_) + printf("SIP/2.0 180-RINGING CSeq = %d \n", sh->seq); + } else if (sh->type == SIP_RSP_SUCCESS) { + if(sh->method == SIP_MSG_INVITE) { + invite_list* listp = del_inv_item(sh->seq); + if(listp) { + listp->timer->cancel(); + delete listp; + } + if(print_log_) + printf("SIP/2.0 INVITE 200-OK CSeq = %d \n", sh->seq); + toaddr_.node_ = iph->saddr(); + toaddr_.port_ = iph->sport(); + ua_state_.callee_location.node_ = sh->ContactID.node_; + ua_state_.callee_location.port_ = sh->ContactID.port_; + toaddr_.node_ = ua_state_.callee_location.node_; + toaddr_.port_ = ua_state_.callee_location.port_; + send_sip_request(sh->seq,SIP_RSP_SUCCESS, SIP_MSG_ACK,toaddr_); + ua_state_.callSetComplete = SET_COMPLETE; + app_->send(size_); + } else if (sh->method == SIP_MSG_REGISTER) { + register_list* reg_listp_ = del_reg_item(sh->seq); + if(reg_listp_) { + reg_listp_->timer->cancel(); + delete reg_listp_; + } + + } + } else if (sh->type == SIP_MSG_ACK) { + ua_state_.callee_location.node_ = sh->ContactID.node_; + ua_state_.callee_location.port_ = sh->ContactID.port_; + iph->saddr() = toaddr_.node_; + iph->sport() = toaddr_.port_; + ok_list* listp = del_ok_item(sh->seq); + if(listp) { + listp->timer->cancel(); + delete listp; + } + if(print_log_) + printf("SIP/2.0 ACK \t CSeq = %d \n", sh->seq); + } else if (sh->type == SIP_MSG_BYE) { + toaddr_.node_ = ua_state_.callee_location.node_; + toaddr_.port_ = ua_state_.callee_location.port_; + send_sip_response(sh->seq, SIP_MSG_BYE,SIP_RSP_SUCCESS,toaddr_); + if(print_log_) + printf("SIP/2.0 BYE \t CSeq = %d BYE \n", sh->seq); + ua_state_.callSetComplete =0; + } else if (sh->type == SIP_MSG_REGISTER) { + if(print_log_) + printf("Received SIP message \t CSeq = %d REGISTER \n", sh->seq); + //send_sip_response(sh->seq,SIP_MSG_REGISTER, SIP_RSP_SUCCESS); + + } else if (sh->type == SIP_RSP_TMOVED && Mode_ == 1){ /* Temporary Moving */ + ua_state_.callee_location.node_ = sh->ContactID.node_; + ua_state_.callee_location.port_ = sh->ContactID.port_; + toaddr_.node_ = Server_; + toaddr_.port_ = 0; + send_sip_request(sh->seq,SIP_RSP_TMOVED,SIP_MSG_ACK,toaddr_); + /* deleting inv item in list */ + invite_list* listp = del_inv_item(sh->seq); + if(listp) { + listp->timer->cancel(); + delete listp; + } + + ua_state_.location_expire = sh->Expires + Scheduler::instance().clock(); + send_sip_request(sh->seq,SIP_RSP_TMOVED, SIP_MSG_INVITE, toaddr_); + + InviteTimer* inv_tmr = new InviteTimer(this); + inv_tmr->seq = present_CSeq -1; + inv_tmr->retrans = 0; + inv_tmr->resched(0.5); + + invite_list* inv_listp_ = new invite_list; + inv_listp_->seq = present_CSeq -1; + inv_listp_->timer = inv_tmr; + inv_listp_->next = 0; + + if(!inv_list_head){ + inv_list_head = inv_listp_; + inv_list_tail = inv_listp_; + } else { + inv_list_tail->next = inv_listp_; + inv_list_tail = inv_listp_; + } + + } else if (sh->type == SIP_RSP_PMOVED && Mode_ == 1){ /* Permanet Moving */ + ua_state_.callee_location.node_ = sh->ContactID.node_; + ua_state_.callee_location.node_ = sh->ContactID.port_; + ua_state_.location_expire = Scheduler::instance().clock() + 720000; + if(print_log_) + printf("Received Permanent Moved Message \n"); + + } else { + + } +} + + +void SIPAgent::timeout(int) +{ + + hdr_SIP sh_buf; + sh_buf.type = SIP_MSG_INVITE; + sh_buf.seq = present_seq; + sh_buf.method = SIP_MSG_INVITE; + + + send_sip_request(sh_buf.seq, SIP_MSG_INVITE, SIP_MSG_INVITE, ua_state_.callee_location); + + InviteTimer* inv_tmr = new InviteTimer(this); + inv_tmr->seq = present_CSeq -1; + inv_tmr->retrans = 0; + inv_tmr->resched(0.5); + + invite_list* inv_listp_ = new invite_list; + inv_listp_->seq = present_CSeq -1; + inv_listp_->timer = inv_tmr; + inv_listp_->next = 0; + + if(!inv_list_head){ + inv_list_head = inv_listp_; + inv_list_tail = inv_listp_; + } else { + inv_list_tail->next = inv_listp_; + inv_list_tail = inv_listp_; + } + +} + +void SIPAgent::send_sip_register(int CSeq, int request_type) +{ + struct sip_address toaddr_; + toaddr_.node_ = Server_; + toaddr_.port_ = 0; + send_sip_request(CSeq, SIP_MSG_REGISTER, SIP_MSG_REGISTER,toaddr_); + RegisterTimer* reg_tmr = new RegisterTimer(this); + reg_tmr->seq = present_CSeq - 1; + reg_tmr->retrans = 0; + reg_tmr->resched(0.5); + + register_list* reg_listp_ = new register_list; + reg_listp_->seq = present_CSeq-1; + reg_listp_->timer = reg_tmr; + reg_listp_->next = 0; + + if(!reg_list_head){ + reg_list_head = reg_listp_; + reg_list_tail = reg_listp_; + } else { + reg_list_tail->next = reg_listp_; + reg_list_tail = reg_listp_; + + } +// present_seq++; + +} + + +void SIPAgent::send_sip_request(int CSeq, int method, int request_type, struct sip_address toaddr_) +{ + Tcl& tcl = Tcl::instance(); + Packet *p = allocpkt(); + hdr_ip *iph = hdr_ip::access(p); + // iph->daddr() = + // iph->dport() = 0; + // iph->saddr() = Address::instance().get_nodeaddr(addr()); + hdr_SIP *sh = hdr_SIP::access(p); + + if(request_type) { + + switch(request_type) { + case SIP_MSG_INVITE: + srand((unsigned)time(NULL)); + ua_state_.LastCallID = rand(); + strcpy(sh->tusrname,ua_state_.tusrname); + strcpy(sh->turl,ua_state_.turl); + strcpy(sh->usrname,ua_state_.usrname); + strcpy(sh->url,ua_state_.url); + sh->type = request_type; + sh->callID = ua_state_.LastCallID; + sh->UserID = Address::instance().get_nodeaddr(addr());; + sh->ToUserID = iph->dst_.addr_; + sh->FromUserID = Address::instance().get_nodeaddr(addr()); + sh->ContactID.node_ = Address::instance().get_nodeaddr(addr()); + sh->ContactID.port_ = Address::instance().get_nodeaddr(port()); + sh->Expires = Lifetime_; + if(method == SIP_RSP_TMOVED || method == SIP_RSP_PMOVED) { + sh->seq = CSeq; + iph->dst_.addr_ = ua_state_.callee_location.node_; + iph->dst_.port_ = ua_state_.callee_location.port_; + if(print_log_) + printf("INVITE[TMOVED|PMOVED] sip:%d@%d SIP/2.0 CSeq = %d\n",ua_state_.callee_location.node_, + ua_state_.callee_location.port_,sh->seq); + + } else { + sh->seq = present_CSeq++; + if(print_log_) + printf("INVITE sip:%s@%s SIP/2.0 CSeq = %d\n",sh->tusrname,sh->turl,sh->seq); + iph->dst_.addr_ = Server_; + iph->dst_.port_ = 0; + } + sh->method = SIP_MSG_INVITE; + CSeq = CSeq; + send(p,0); + break; + case SIP_MSG_OK: + sh->seq = CSeq; + sh->callID = ua_state_.LastCallID; + sh->type = request_type; + send(p,0); + break; + case SIP_MSG_BUSY: + sh->seq = CSeq; + sh->callID = ua_state_.LastCallID; + sh->type = request_type; + send(p,0); + break; + case SIP_MSG_ACK: + strcpy(sh->turl,ua_state_.turl); + strcpy(sh->tusrname,ua_state_.tusrname); + iph->daddr() = toaddr_.node_; + iph->dport() = toaddr_.port_; + sh->ContactID.node_ = Address::instance().get_nodeaddr(addr()); + sh->ContactID.port_ = Address::instance().get_nodeaddr(port()); + sh->seq = CSeq; + sh->callID = ua_state_.LastCallID; + sh->type = request_type; + sh->method = method; + send(p,0); + if(print_log_) + printf("ACK message <== From %d %d to %d %d\n", ua_state_.caller_location.node_, + ua_state_.caller_location.port_,ua_state_.callee_location.node_,ua_state_..callee_location.port_); + break; + case SIP_MSG_BYE: + iph->daddr() = toaddr_.node_; + iph->dport() = toaddr_.port_; + sh->seq = present_CSeq++; + sh->callID = ua_state_.LastCallID; + sh->type = request_type; + sh->method = SIP_MSG_BYE; + send(p,0); + break; + case SIP_MSG_REGISTER: + iph->saddr() = Address::instance().get_nodeaddr(addr()); + srand((unsigned)time(NULL)); + sh->type = request_type; + strcpy(sh->usrname,ua_state_.usrname); + strcpy(sh->url,ua_state_.url); + strcpy(sh->tusrname,ua_state_.usrname); + strcpy(sh->turl,ua_state_.url); + sh->callID = rand(); + sh->seq = present_CSeq++; + sh->UserID = UserID_; + sh->FromUserID = UserID_; + sh->ContactID.node_ = Address::instance().get_nodeaddr(addr()); + sh->ContactID.port_ = Address::instance().get_nodeaddr(port()); + sh->ToUserID = CalleeID_; + iph->dst_.addr_ = Server_; + iph->dst_.port_ = 0; + sh->method = SIP_MSG_REGISTER; + if(print_log_) + printf("REGISTER sip:%d SIP/2.0 Cseq = %d\n",Server_, sh->seq); + + send(p,0); + break; + default: + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n", request_type); + } + } + else { + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n", request_type); + } +} + + +void SIPAgent::send_sip_response(int CSeq, int method, int response_type, struct sip_address toaddr) +{ + Tcl& tcl = Tcl::instance(); + Packet *p = allocpkt(); + hdr_ip *iph = hdr_ip::access(p); + iph->daddr() = toaddr.node_; + iph->dport() = toaddr.port_; + // iph->saddr() = Address::instance().get_nodeaddr(addr()); + hdr_SIP *sh = hdr_SIP::access(p); + sh->callID = ua_state_.LastCallID; + + if(response_type) { + + switch(response_type) { + case SIP_RSP_TRYING: + strcpy(sh->turl,ua_state_.turl); + strcpy(sh->tusrname,ua_state_.tusrname); + sh->seq = CSeq; + sh->type = response_type; + sh->method = method; + send(p,0); + break; + case SIP_RSP_RINGING: + strcpy(sh->turl,ua_state_.turl); + strcpy(sh->tusrname,ua_state_.tusrname); + sh->seq = CSeq; + sh->type = response_type; + sh->method = method; + send(p,0); + break; + case SIP_RSP_SUCCESS: + strcpy(sh->turl,ua_state_.turl); + strcpy(sh->tusrname,ua_state_.tusrname); + sh->ContactID.node_ = Address::instance().get_nodeaddr(addr()); + sh->ContactID.port_ = Address::instance().get_nodeaddr(port()); + sh->seq = CSeq; + sh->type = response_type; + sh->method = method; + send(p,0); + if(print_log_) + printf("Success Message <== From %d %d to %d %d\n", ua_state_.caller_location.node_, + ua_state_.caller_location.port_,ua_state_.callee_location.node_,ua_state_..callee_location.port_); + break; + case SIP_RSP_PMOVED: + sh->seq = CSeq; + sh->type = response_type; + sh->method = method; + send(p,0); + break; + case SIP_RSP_TMOVED: + sh->seq = CSeq; + sh->type = response_type; + sh->method = method; + send(p,0); + break; + default: + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n", response_type); + } + } + else { + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n", response_type); + } + +} + +void SIPAgent::sendmsg(int nbytes, const char* flags) +{ + Packet *p; + int n; + + + if(ua_state_.callSetComplete != SET_COMPLETE) { + if(ua_state_.callSetComplete == 0) { + ua_state_.callSetComplete = SET_DOING; + //connect(0); + } + return; + } + + if(flags && (0 == strcmp(flags,"END_DATA"))) { + if(print_log_) + printf("STOP signal is accepted \n"); + close(); + } + + + if(size_) + n = nbytes / size_; + else { + if(print_log_) + printf("Error: UDP size = 0\n"); + } + if(nbytes == -1) { + if(print_log_) + printf("Error: sendmsg() for UDP should not be -1\n"); + return; + + } + + double local_time = Scheduler::instance().clock(); + + while(n-- > 0) { + p = allocpkt(); + hdr_rtp* rh = hdr_rtp::access(p); + rh->flags() = 0; + rh->seqno() = ++seqno_; + hdr_cmn::access(p)->timestamp() = + (u_int32_t)(SAMPLERATE*local_time); + + + hdr_SIP* sh = hdr_SIP::access(p); + hdr_ip* ih = hdr_ip::access(p); + ih->daddr() = ua_state_.callee_location.node_; + ih->dport() = ua_state_.callee_location.port_; + ih->prio_ = 15; + memcpy(sh, flags, sizeof(hdr_SIP)); + + if(flags && (0 == strcmp(flags, "NEW_BURST"))) + rh->flags() |= RTP_M; + target_->recv(p); + } + + n = nbytes % size_; + + if (n > 0) { + + p = allocpkt(); + hdr_cmn::access(p)->size() = n; + hdr_rtp* rh = hdr_rtp::access(p); + rh->flags() = 0; + rh->seqno() = ++seqno_; + hdr_cmn::access(p)->timestamp() = + (u_int32_t)(SAMPLERATE*local_time); + + + hdr_SIP* sh = hdr_SIP::access(p); + hdr_ip* ih = hdr_ip::access(p); + ih->daddr() = ua_state_.callee_location.node_; + ih->dport() = ua_state_.callee_location.port_; + ih->prio_ = 15; + memcpy(sh, flags, sizeof(hdr_SIP)); + + if(flags && (0 == strcmp(flags, "NEW_BURST"))) + rh->flags() |= RTP_M; + target_->recv(p); + } + idle(); +} + +int SIPAgent::command(int argc, const char*const* argv) +{ + Tcl& tcl = Tcl::instance(); + + if(argc == 3) { + if(strcmp(argv[1], "register") == 0) { + Register(); + return TCL_OK; + } else if (strcmp(argv[1], "bcast-target") == 0) { + return TCL_OK; + } + // else if(strcmp(argv[1], "register") == 0) { + // Register(); + // return TCL_OK; + // } + + } + if(argc == 2) { + if(strcmp(argv[1], "start") == 0) { + connect(0); + return TCL_OK; + } else if (strcmp(argv[1], "stop") == 0){ + close(); + return TCL_OK; + } + } + return (Agent::command(argc, argv)); +} + +void SIPAgent::connect(nsaddr_t addr) +{ + timeout(0); /* first SIP iniviation is started */ + +} +/* +void SIPAgent::connect(nsaddr_t addr) +{ + Register(); + +} +*/ +int SIPAgent::Register() +{ + Tcl& tcl = Tcl::instance(); + Packet* p = allocpkt(); + ua_state_.caller_location.node_ = Address::instance().get_nodeaddr(addr()); + ua_state_.caller_location.port_ = Address::instance().get_nodeaddr(port()); + hdr_ip* iph = hdr_ip::access(p); + UserID_ = Address::instance().get_nodeaddr(addr()); + send_sip_register(0, SIP_MSG_REGISTER); + CalleeID_ = Address::instance().get_nodeaddr(iph->daddr()); + return 1; +} + +void SIPAgent::close() +{ + // Send Bye message + send_sip_request(0, SIP_MSG_BYE, SIP_MSG_BYE,ua_state_.callee_location); +} + + +register_list* SIPAgent::del_reg_item(int recvd_seq) +{ + register_list* listp_ = reg_list_head; + register_list* listp__prev; + int count = 0; + + while(listp_) { + count++; + if(recvd_seq == listp_->seq) { + if(listp_ == reg_list_head) { + if(reg_list_head == reg_list_tail) { + reg_list_head = 0; + reg_list_tail = 0; + } else { + reg_list_head = listp_->next; + } + } else if (listp_ == reg_list_tail) { + reg_list_tail = listp__prev; + listp__prev->next =0; + } else { + listp__prev -> next = listp_->next; + } + + + return listp_; + break; + } else { + listp__prev = listp_; + listp_ = listp_->next; + } + } + return 0; +} + +invite_list* SIPAgent::del_inv_item(int recvd_seq) +{ + invite_list* listp_ = inv_list_head; + invite_list* listp__prev; + int count = 0; + + while(listp_) { + count++; + if(recvd_seq == listp_->seq) { + if(listp_ == inv_list_head) { + if(inv_list_head == inv_list_tail) { + inv_list_head = 0; + inv_list_tail = 0; + } else { + inv_list_head = listp_->next; + } + } else if (listp_ == inv_list_tail) { + inv_list_tail = listp__prev; + listp__prev->next =0; + } else { + listp__prev -> next = listp_->next; + } + + + return listp_; + break; + } else { + listp__prev = listp_; + listp_ = listp_->next; + } + } + return 0; +} + + +ok_list* SIPAgent::del_ok_item(int recvd_seq) +{ + ok_list* listp_ = ok_list_head; + ok_list* listp__prev; + int count = 0; + + while(listp_) { + count++; + if(recvd_seq == listp_->seq) { + if(listp_ == ok_list_head) { + if(ok_list_head == ok_list_tail) { + ok_list_head = 0; + ok_list_tail = 0; + } else { + ok_list_head = listp_->next; + } + } else if (listp_ == ok_list_tail) { + ok_list_tail = listp__prev; + listp__prev->next =0; + } else { + listp__prev -> next = listp_->next; + } + + return listp_; + break; + } else { + listp__prev = listp_; + listp_ = listp_->next; + } + } + if(print_log_) + printf("NOT FOUND: ok List lentgh = %d\n",count); + return 0; +} + + +void OkTimer::expire(Event*) +{ + struct sip_address toaddr_; + switch(retrans++) { + case 0: + resched(1.0); + break; + case 1: + resched(2.0); + break; + case 2: + resched(4.0); + break; + case 3: + resched(8.0); + break; + case 4: + resched(16.0); + break; + default: + ok_list* listp_ = t_->del_ok_item(this->seq); + if (listp_) delete listp_; + } + toaddr_.node_ = t_->ua_state_.callee_location.node_; + toaddr_.node_ = t_->ua_state_.callee_location.port_; + t_->send_sip_response(this->seq, this->method, SIP_RSP_SUCCESS,toaddr_); // retransmission of SIP OK message +} + +void RegisterTimer::expire(Event*) +{ + switch(retrans++) { + case 0: + resched(1.0); + break; + case 1: + resched(2.0); + break; + case 2: + resched(4.0); + break; + case 3: + resched(8.0); + break; + case 4: + resched(16.0); + break; + default: + register_list* listp_ = t_->del_reg_item(this->seq); + if (listp_) delete listp_; + } + struct sip_address toaddr_; + toaddr_.node_ = t_->Server_; + toaddr_.port_ = 0; + + t_->send_sip_request(this->seq, SIP_MSG_REGISTER, SIP_MSG_REGISTER,toaddr_); // retransmission of SIP OK message +} + +void InviteTimer::expire(Event*) +{ + switch(retrans++) { + case 0: + resched(1.0); + break; + case 1: + resched(2.0); + break; + case 2: + resched(4.0); + break; + case 3: + resched(8.0); + break; + case 4: + resched(16.0); + break; + default: + invite_list* listp_ = t_->del_inv_item(this->seq); + if (listp_) delete listp_; + } + + t_->send_sip_request(this->seq, SIP_MSG_INVITE, SIP_MSG_INVITE,t_->ua_state_.callee_location); // retransmission of SIP INVITE message +} + +void SIPAgent::set_username(const char* username) +{ + strcpy(ua_state_.usrname,username); +} + +void SIPAgent::set_url(const char* url) +{ + strcpy(ua_state_.url,url); + +} + +void SIPAgent::set_tusername(const char* username) +{ + strcpy(ua_state_.tusrname,username); +} + +void SIPAgent::set_turl(const char* url) +{ + strcpy(ua_state_.turl,url); + +} diff -uNr ns-2.1b9a/sip/sip.h ns-2.1b9a_sip/sip/sip.h --- ns-2.1b9a/sip/sip.h Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/sip/sip.h Thu Sep 4 18:36:04 2003 @@ -0,0 +1,236 @@ +// +// This software was developed at the National Institute of Standards and +// Technology by employees of the Federal Goverment in the course of their +// official duties. This software is an experimental objects. NIST assumes +// no responsibility whatsoever for its use by other parties, and makes no +// guarantees, expressed or implied, about its quality, reliability, or any +// other characteristic. We would appreicate acknowledgement if the software +// is used. + +// This software can be redistributed and/or modified freely. We respect +// that any derivative works bear some notice that they are derived from it, +// any any modified versions bear some notice that they have been modified. + +// Jin-Woo Jung, jjw@korea.ac.kr + + +#ifndef ns_sip_h +#define ns_sip_h + +#include "agent.h" +#include "tclcl.h" +#include "packet.h" +#include "address.h" +#include "ip.h" + +/* To identify different SIP messages */ +#define SIP_MSG_NONE 0 +#define SIP_MSG_INVITE 1 +#define SIP_MSG_OK 2 +#define SIP_MSG_BUSY 3 +#define SIP_MSG_ACK 4 +#define SIP_MSG_BYE 5 +#define SIP_MSG_REGISTER 6 + +/* To identify different SIP Responses Classes */ +/* 1XX informational */ +#define SIP_RSP_TRYING 100 +#define SIP_RSP_RINGING 180 + +/* 2XX Success: request has succeeded */ +#define SIP_RSP_SUCCESS 200 /* 200-OK */ + +/* 3XX Redirection: server has returned possible locations */ +#define SIP_RSP_PMOVED 301 // Moved Permanently +#define SIP_RSP_TMOVED 302 // Moved Temporarily + +/* 4XX Client error: the request has failed due to an error by the client */ +#define SIP_RSP_BAD 400 // 400 Bad request +#define SIP_RSP_UNAUTHORIZED 401 +#define SIP_RSP_PAY 402 // 402 Payment Required +#define SIP_RSP_FORBIDDEN 403 +#define SIP_RSP_NOTFOUND 404 // Not Found + +/* 5XX Server failure: the request has failed due to an error by the server */ + +/* 6XX Global failure: the request has failed */ +#define SIP_RSP_BUSY 600 // Busy Everywhere +#define SIP_RSP_DECLIE 603 // Decline + + +/* Operation Mode */ +#define SIP_PROXY_MODE 0 +#define SIP_REDIRECT_MODE 1 + +/* Maximum User ID length & Maximum URL length */ +#define USRID_MAXLEN 10 +#define SIP_URLMAXLEN 20 + +/* XXX DNS */ +#define DNS_QUERY 1111 +#define DNS_REPLY 2222 +#define DNS_NOT_FOUND 3333 + + +/* ------------------------- DEFINITION OF STRUCTURES ----------------------------------*/ + +struct sip_address { + int port_; + int node_; +}; + + +/* Structure for SIP message to be embedded in packets */ + +struct hdr_SIP { + int type; /* type of message */ + char tusrname[USRID_MAXLEN]; /* Username part of Request URI, To field in SIP header */ + char turl[SIP_URLMAXLEN]; /* URL part of Request URI , To field in SIP header */ + char usrname[USRID_MAXLEN]; /* Caller Username , From filed in SIP header */ + char url[SIP_URLMAXLEN]; /* Calleer URL , From field in SIP header */ + int seq; /* SIP sequence number */ + int method; /* related Method */ + double callID; + sip_address ContactID; /* Contact field in SIP message , future requests should be sent */ + int UserID; /* Unique User ID */ + int ToUserID; /* To field in SIP message , logical destination of the request*/ + + int FromUserID; /* From field in SIP message */ + double Expires; /* Registration Expire time , minitue*/ + + /* Packet header access functions */ + static int offset_; // required by PacketHeaderManager + inline static int& offset() { return offset_; } + inline static hdr_SIP* access(const Packet *p) { + return (hdr_SIP*) p->access(offset_); + } +}; + +class SIPAgent; +/* structure for maintaining state information by the SIP user agent. */ + +typedef struct +{ + int callSetComplete; + struct sip_address callee_location; + struct sip_address caller_location; + char usrname[USRID_MAXLEN]; + char url[SIP_URLMAXLEN]; + char tusrname[USRID_MAXLEN]; + char turl[SIP_URLMAXLEN]; + double LastCallID; /* The last received/sent Call-ID, primary identifier for the call */ + int LastOutCSeqNum; /* The last sent request command sequence num */ + int iLastOutMsgStatus; /* Status of the last sent msg - used to decide on retransmitting the message */ + int iNumTimesSent; /* Number of times the last msg has been sent on the whole (count of retransmissions) */ + double location_expire; /* valid callee_ location for limited duration, as indicated by the Exprires filed */ +} sip_ua_state; + +#define SET_COMPLETE 0x0008 +#define SET_DOING 0x0004 + +class InviteTimer : public TimerHandler { + public: + InviteTimer(SIPAgent* t) : TimerHandler(), t_(t) {} + inline virtual void expire(Event *); + int seq; + int retrans; + protected: + SIPAgent* t_; +}; + +class RegisterTimer : public TimerHandler { + public: + RegisterTimer(SIPAgent* t) : TimerHandler(), t_(t) {} + inline virtual void expire(Event *); + int seq; + int retrans; + protected: + SIPAgent* t_; +}; + +class OkTimer : public TimerHandler { + public: + OkTimer(SIPAgent* t) : TimerHandler(), t_(t) {} + inline virtual void expire(Event *); + int seq; + int method; + int retrans; + protected: + SIPAgent* t_; +}; + + +struct invite_list { + int seq; + InviteTimer* timer; + invite_list* next; +}; + +struct register_list { + int seq; + RegisterTimer* timer; + register_list* next; +}; + +struct ok_list { + int seq; + int method; + OkTimer* timer; + ok_list* next; +}; + + +// SIP User Agent Class Definition +class SIPAgent : public Agent { + public: + sip_ua_state ua_state_; + int Server_; /* Server Node ID */ + char usrid_[USRID_MAXLEN]; /* User name */ + char url_[SIP_URLMAXLEN]; /* User URL */ + char tusrid_[USRID_MAXLEN]; /* Target User ID */ + char turl_[SIP_URLMAXLEN]; /* Target URL */ + SIPAgent(const char* username, const char* url); + SIPAgent(packet_t); + virtual void connect(nsaddr_t addr); + virtual void recv(Packet *, Handler *); + virtual void sendmsg(int nbytes, const char *flags =0); + void send_sip_register(int CSeq, int request_type); // sned SIP register message + void send_sip_request(int CSeq,int method, int request_type, struct sip_address toaddr); // send SIP request message + void send_sip_response(int CSeq, int method, int response_type, struct sip_address toaddr); // send SIP response message + virtual void timeout(int); + register_list* del_reg_item(int seqToSend); + invite_list* del_inv_item(int seqToSend); + ok_list* del_ok_item(int recvd_seq); + + virtual void close(); + virtual int Register(); + void set_username(const char* username); + void set_url(const char* url); + virtual void set_tusername(const char* username); + virtual void set_turl(const char* url); + protected: + int seqno_; + int size_; + int print_log_; + int Registrar_; + int Lifetime_; + + int UserID_; + int CalleeID_; + int Mode_; // For mobility support, this version doest not support mobility, its value is ignored + int command(int argc, const char*const*argv); + NsObject *caller_; // where to send reg-replies to caller */ + private: + int present_CSeq; + int present_seq; + invite_list* inv_list_head; + invite_list* inv_list_tail; + register_list* reg_list_head; + register_list* reg_list_tail; + ok_list* ok_list_head; + ok_list* ok_list_tail; +}; + + + +#endif diff -uNr ns-2.1b9a/sip/sip_server.cc ns-2.1b9a_sip/sip/sip_server.cc --- ns-2.1b9a/sip/sip_server.cc Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/sip/sip_server.cc Thu Sep 4 19:03:15 2003 @@ -0,0 +1,790 @@ +// +// This software was developed at the National Institute of Standards and +// Technology by employees of the Federal Goverment in the course of their +// official duties. This software is an experimental objects. NIST assumes +// no responsibility whatsoever for its use by other parties, and makes no +// guarantees, expressed or implied, about its quality, reliability, or any +// other characteristic. We would appreicate acknowledgement if the software +// is used. + +// This software can be redistributed and/or modified freely. We respect +// that any derivative works bear some notice that they are derived from it, +// any any modified versions bear some notice that they have been modified. + +// Jin-Woo Jung, jjw@korea.ac.kr + +#include "sip_server.h" +#include "rtp.h" +#include "udp.h" +#include "random.h" + +/* + * ========================================== Domain Name System ============================================== + * + */ + + static class DNSAgentClass : public TclClass { + public: + DNSAgentClass() : TclClass("Agent/DNSAgent") {} + TclObject* create(int argc, const char*const* argv) { + return (new DNSAgent()); + } +} class_dns_agent; + +DNSAgent :: DNSAgent() : Agent(PT_SIP), recordList_head(0), recordList_tail(0) +{ + bind("print_",&print_log_); +} + +void DNSAgent::recv(Packet* p, Handler *) +{ + Tcl& tcl = Tcl::instance(); + char *objname = NULL; + NsObject *obj = NULL; + hdr_ip *iph = hdr_ip::access(p); + hdr_cmn *ch = hdr_cmn::access(p); + hdr_SIP* sh = hdr_SIP::access(p); + hdr_SIP sh_buf; + memcpy(&sh_buf, sh, sizeof(hdr_SIP)); + struct sip_address request_addr; + request_addr.node_ = iph->saddr(); + request_addr.port_ = iph->sport(); + + if(print_log_) + printf("ContactID = %d %d \t trul = %s\n",sh->ContactID.node_,sh->ContactID.port_,sh->turl); + + if(sh->type == SIP_MSG_REGISTER) { + _recordList* add_record_ptr = new _recordList; + add_record_ptr->NodeID.node_ = sh->ContactID.node_; + add_record_ptr->NodeID.port_ = sh->ContactID.port_; + strcpy(add_record_ptr->url,sh->turl); + add_record_ptr->next = 0; + + if(!recordList_head) { + recordList_head = add_record_ptr; + recordList_tail = add_record_ptr; + } else { + recordList_tail->next = add_record_ptr; + recordList_tail = add_record_ptr; + } + if(print_log_) + printf("%s registers its location[%d %d] with DNS\n",sh->turl, sh->ContactID.node_,sh->ContactID.port_); + } else if(sh->type == DNS_QUERY) { + _recordList* recordListptr = find_record(sh->turl); + + if(recordListptr) + { + + sh->type = DNS_REPLY; + if(print_log_) + printf("dst %d %d\n",iph->saddr(),iph->sport()); + iph->daddr() = iph->saddr(); + iph->dport() = iph->sport(); + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + strcpy(sh->turl, sh_buf.turl); + strcpy(sh->tusrname, sh_buf.tusrname); + strcpy(sh->url, sh_buf.url); + strcpy(sh->usrname, sh_buf.usrname); + sh->callID = sh_buf.callID; + sh->seq = sh_buf.seq; + sh->method = sh_buf.method; + sh->ToUserID = sh_buf.ToUserID; + sh->FromUserID = sh_buf.FromUserID; + sh->ContactID.node_ = recordListptr->NodeID.node_; + sh->ContactID.port_ = recordListptr->NodeID.port_; + send(p,0); + + } else { + sh->type = DNS_NOT_FOUND; + strcpy(sh->turl, sh_buf.turl); + strcpy(sh->tusrname, sh_buf.tusrname); + strcpy(sh->url, sh_buf.url); + strcpy(sh->usrname, sh_buf.usrname); + sh->callID = sh_buf.callID; + sh->seq = sh_buf.seq; + iph->daddr() = iph->saddr(); + iph->dport() = iph->sport(); + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + sh->ContactID.node_ = 0; + sh->ContactID.port_ = 0; + send(p,0); + if(print_log_) + printf("DNS Agent does not have location information for %s\n",sh->turl); + } + } + +} + +_recordList* DNSAgent::find_record(const char* url) +{ + _recordList* record_ptr = recordList_head; + _recordList* record_ptr_prev; + int count = 0; + + while(record_ptr) { + count++; + if(!strcmp(url,record_ptr->url)) { + return record_ptr; + break; + + } else { + + } + record_ptr_prev = record_ptr; + record_ptr = record_ptr->next; + + } + return NULL; +} + + + + +/* ========================================== Redirect Agent ==================================================*/ +/* + * Redirect Agent + */ + +static class SIPRedirectClass : public TclClass { + public: + SIPRedirectClass() : TclClass("Agent/SIPRedirect") {} + TclObject* create(int argc, const char*const* argv) { + if(argc == 5) return (new SIPRedirectAgent(argv[4])); + else { + printf("ERROR: [usage] set variable [new Agent/SIPRedirect URL]\n"); + } + } +} class_sipredirect_agent; + +SIPRedirectAgent::SIPRedirectAgent(const char* url) : Agent(PT_SIP), userList_head(0), userList_tail(0), userList_timer_(this) +{ + bind("print_", &print_log_); + strcpy(url_,url); +} + +void SIPRedirectAgent::recv(Packet* p, Handler *) +{ + Tcl& tcl = Tcl::instance(); + char *objname = NULL; + NsObject *obj = NULL; + hdr_ip *iph = hdr_ip::access(p); + hdr_cmn *ch = hdr_cmn::access(p); + hdr_SIP* sh = hdr_SIP::access(p); + hdr_SIP sh_buf; + memcpy(&sh_buf, sh, sizeof(hdr_SIP)); + hdr_SIP sh_buf_send; + sh_buf_send.seq = sh->seq; + + int nodeaddr = Address::instance().get_nodeaddr(addr()); + struct sip_address request_addr; + request_addr.node_ = iph->saddr(); + request_addr.port_ = iph->sport(); + + if(sh->type == SIP_MSG_INVITE) { + + _userList* userListptr = find_user(sh->tusrname,sh->turl); + + if(userListptr) + { + if(userListptr->permanent) { + send_sip_reply(sh_buf, SIP_RSP_PMOVED, userListptr->ContactID,request_addr); + if(print_log_) + printf("301 Moved Permanetly SIP/2.0 Contact:%d %d\n",userListptr->ContactID.node_,userListptr->ContactID.port_); + } else { + send_sip_reply(sh_buf, SIP_RSP_TMOVED, userListptr->ContactID, request_addr); + if(print_log_) + printf("302 Moved Temporarily SIP/2.0 Contact:%d %d\n",userListptr->ContactID.node_,userListptr->ContactID.port_); + } + + } + else + { + if(print_log_) + printf("DNS Server = %d\n",DNS_Server); + iph->daddr() = DNS_Server; + iph->dport() = 0; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + if(print_log_) + printf("Node Addr = %d %d\n",iph->saddr(),iph->sport()); + strcpy(sh->tusrname,sh_buf.tusrname); + strcpy(sh->turl,sh_buf.turl); + sh->FromUserID = sh_buf.FromUserID; + sh->callID = sh_buf.callID; + sh->type = DNS_QUERY; + send(p,0); + } + } else if(sh->type == SIP_MSG_REGISTER) { + + _userList* add_user_ptr = new _userList; + add_user_ptr->UserID = sh->UserID; + add_user_ptr->callID = sh->callID; + add_user_ptr->ContactID.node_ = sh->ContactID.node_; + add_user_ptr->ContactID.port_ = sh->ContactID.port_; + add_user_ptr->location.node_ = sh->ContactID.node_; + add_user_ptr->location.port_ = sh->ContactID.port_; + strcpy(add_user_ptr->usrname,sh->tusrname); + strcpy(add_user_ptr->url,sh->turl); + add_user_ptr->next_ = 0; + if(sh->Expires == 720000) add_user_ptr->permanent = PERMANENT_MOVED; + else add_user_ptr->permanent = TEMPORARY_MOVED; + add_user_ptr->expire_time_ = Scheduler::instance().clock() + sh->Expires; + + if(!userList_head) { + userList_head = add_user_ptr; + userList_tail = add_user_ptr; + } else { + userList_tail->next_ = add_user_ptr; + userList_tail = add_user_ptr; + } + send_sip_response(sh->seq, sh_buf, SIP_RSP_SUCCESS, request_addr); + + if(print_log_) + printf("SIP/2.0 200 OK node = %d, port = %d\n",sh->ContactID.node_,sh->ContactID.port_); + + } else if(sh->type == SIP_MSG_ACK && sh->method == SIP_RSP_TMOVED){ + + } else if(sh->type == DNS_NOT_FOUND) { + send_sip_response(sh->seq, sh_buf, SIP_RSP_NOTFOUND, request_addr); + } else if(sh->type == DNS_REPLY) { + sh->type = SIP_MSG_INVITE; + iph->daddr() = sh->ContactID.node_; + iph->dport() = sh->ContactID.port_; + if(print_log_) + printf("finded address = %d %d \n",sh->ContactID.node_,sh->ContactID.port_); + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->saddr() = Address::instance().get_nodeaddr(port()); + send(p,0); + } else if(sh->type == SIP_RSP_TMOVED || sh->type == SIP_RSP_PMOVED) { + iph->daddr() = sh->FromUserID; + iph->dport() = 0; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->saddr() = Address::instance().get_nodeaddr(port()); + send(p,0); + } + + + + +} + +void SIPRedirectAgent::send_sip_reply(hdr_SIP sip_hdr_, int reply_code, struct sip_address ContactID,struct sip_address request_addr) +{ + Tcl& tcl = Tcl::instance(); + Packet *p = allocpkt(); + hdr_ip *iph = hdr_ip::access(p); + hdr_SIP *sh = hdr_SIP::access(p); + iph->daddr() = request_addr.node_; + iph->dport() = request_addr.port_; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->saddr() = Address::instance().get_nodeaddr(port()); + sh->seq = sip_hdr_.seq; + sh->callID = sip_hdr_.callID; + sh->type = reply_code; + sh->method = sip_hdr_.type; + sh->ContactID.node_ = ContactID.node_; + sh->ContactID.port_ = ContactID.port_; + send(p,0); +} + + +void SIPRedirectAgent::send_sip_response(int CSeq, hdr_SIP sip_hdr_, int response_type, struct sip_address request_addr) +{ + Tcl& tcl = Tcl::instance(); + Packet *p = allocpkt(); + hdr_ip *iph = hdr_ip::access(p); + iph->daddr() = request_addr.node_; + iph->dport() = request_addr.port_; + hdr_SIP *sh = hdr_SIP::access(p); + + if(response_type) { + switch(response_type) { + + case SIP_RSP_SUCCESS: + sh->seq = CSeq; + sh->type = SIP_RSP_SUCCESS; + sh->callID = sip_hdr_.callID; + sh->method = sip_hdr_.type; + send(p,0); + break; + + case SIP_RSP_NOTFOUND: + sh->seq = CSeq; + sh->type = SIP_RSP_NOTFOUND; + sh->callID = sip_hdr_.callID; + sh->method = sip_hdr_.type; + send(p,0); + break; + + default: + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n", response_type); + } + } + else { + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n",response_type); + } +} + +int SIPRedirectAgent::command(int argc, const char*const* argv) +{ + Tcl& tcl = Tcl::instance(); + + if(argc == 3) { + if(strcmp(argv[1], "register") == 0) { + DNS_Server = atoi(argv[2]); + Register(); + return TCL_OK; + } + + } + return (Agent::command(argc, argv)); +} + +int SIPRedirectAgent::Register() +{ + Tcl& tcl = Tcl::instance(); + Packet* p = allocpkt(); + hdr_ip* iph = hdr_ip::access(p); + hdr_SIP *sh = hdr_SIP::access(p); + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + iph->daddr() = DNS_Server; + iph->dport() = 0; + strcpy(sh->turl,url_); + sh->type = SIP_MSG_REGISTER; + sh->ContactID.node_ = iph->saddr(); + sh->ContactID.port_ = iph->sport(); + send(p,0); + +} + +_userList* SIPRedirectAgent::find_user(const char* usrname, const char* url) +{ + _userList* user_ptr = userList_head; + _userList* user_ptr_prev; + int count = 0; + + while(user_ptr) { + count++; + if(!strcmp(usrname,user_ptr->usrname)){ + if(!strcmp(url,user_ptr->url)) { + return user_ptr; + break; + } + } else { + + } + user_ptr_prev = user_ptr; + user_ptr = user_ptr->next_; + + } + return NULL; +} + +void SIPRedirectAgent::timeout(int tno) +{ + switch(tno) { + case REGISTRAR_TIMER_LIST: + { + double now = Scheduler::instance().clock(); + _userList *user_ptr = userList_head; + _userList *user_ptr_prev; + + while(user_ptr) { + if(user_ptr->expire_time_ < now) { + if(user_ptr == userList_head) { + if(userList_head == userList_tail) { + userList_head =0; + userList_tail =0; + } else { + userList_head = user_ptr->next_; + } + } else if (user_ptr == userList_tail) { + userList_head = user_ptr_prev; + user_ptr_prev->next_ =0; + } else { + user_ptr_prev->next_ = user_ptr->next_; + } + break; + } else { + user_ptr_prev = user_ptr; + user_ptr = user_ptr->next_; + } + } + } + } +} + +/* + * Registrar + * + */ + +void UserListTimer::expire(Event *) { + r_->timeout(REGISTRAR_TIMER_LIST); +} + +/* ========================================== Proxy Agent ==================================================*/ +/* + * Proxy Agent + */ + +static class SIPProxyClass : public TclClass { + public: + SIPProxyClass() : TclClass("Agent/SIPProxy") {} + TclObject* create(int argc, const char*const* argv) { + if(argc == 5) return (new SIPProxyAgent(argv[4])); + else { + printf("ERROR: [usage] set variable [new Agent/SIPProxy URL]\n"); + } + } +} class_sipProxy_agent; + +SIPProxyAgent::SIPProxyAgent(const char* url) : Agent(PT_SIP), userList_head(0), userList_tail(0), userList_timer_(this) +{ + bind("print_", &print_log_); + strcpy(url_,url); +} + +void SIPProxyAgent::recv(Packet* p, Handler *) +{ + Tcl& tcl = Tcl::instance(); + char *objname = NULL; + NsObject *obj = NULL; + hdr_ip *iph = hdr_ip::access(p); + hdr_cmn *ch = hdr_cmn::access(p); + hdr_SIP* sh = hdr_SIP::access(p); + hdr_SIP sh_buf; + memcpy(&sh_buf, sh, sizeof(hdr_SIP)); + hdr_SIP sh_buf_send; + sh_buf_send.seq = sh->seq; + + int nodeaddr = Address::instance().get_nodeaddr(addr()); + struct sip_address request_addr; + request_addr.node_ = iph->saddr(); + request_addr.port_ = iph->sport(); + + if(sh->type == SIP_MSG_INVITE) { + + _userList* userListptr = find_user(sh->tusrname,sh->turl); + + if(userListptr) + { + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + iph->daddr() = userListptr->ContactID.node_; + iph->dport() = userListptr->ContactID.port_; + send(p,0); + if(print_log_) + printf("From Proxy: SIP/2.0 INVITE %s@%s Contact:%d %d\n",sh->tusrname,sh->turl,userListptr->ContactID.node_,userListptr->ContactID.port_); + + + } + else + { + iph->daddr() = DNS_Server; + iph->dport() = 0; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + strcpy(sh->tusrname,sh_buf.tusrname); + strcpy(sh->turl,sh_buf.turl); + strcpy(sh->usrname,sh_buf.usrname); + strcpy(sh->url,sh_buf.url); + sh->seq = sh_buf.seq; + sh->ToUserID = sh_buf.ToUserID; + sh->FromUserID = sh_buf.FromUserID; + sh->callID = sh_buf.callID; + sh->method = SIP_MSG_INVITE; + sh->type = DNS_QUERY; + send(p,0); + } + send_sip_reply(sh_buf, SIP_RSP_TRYING, request_addr, request_addr); + + } else if(sh->type == SIP_MSG_REGISTER) { + + _userList* add_user_ptr = new _userList; + add_user_ptr->UserID = sh->UserID; + add_user_ptr->callID = sh->callID; + add_user_ptr->ContactID.node_ = sh->ContactID.node_; + add_user_ptr->ContactID.port_ = sh->ContactID.port_; + add_user_ptr->location.node_ = sh->ContactID.node_; + add_user_ptr->location.port_ = sh->ContactID.port_; + strcpy(add_user_ptr->usrname,sh->tusrname); + strcpy(add_user_ptr->url,sh->turl); + add_user_ptr->next_ = 0; + if(sh->Expires == 720000) add_user_ptr->permanent = PERMANENT_MOVED; + else add_user_ptr->permanent = TEMPORARY_MOVED; + add_user_ptr->expire_time_ = Scheduler::instance().clock() + sh->Expires; + + if(!userList_head) { + userList_head = add_user_ptr; + userList_tail = add_user_ptr; + } else { + userList_tail->next_ = add_user_ptr; + userList_tail = add_user_ptr; + } + send_sip_response(sh->seq, sh_buf, SIP_RSP_SUCCESS, request_addr); + if(print_log_) + printf("SIP/2.0 200 OK node = %d, port = %d\n",sh->ContactID.node_,sh->ContactID.port_); + } else if(sh->type == SIP_MSG_ACK && sh->method == SIP_RSP_TMOVED){ + } else if(sh->type == DNS_NOT_FOUND) { + if(print_log_) + printf("%d %d does not have location information for %s@%s\n\n",Address::instance().get_nodeaddr(addr()),Address::instance().get_nodeaddr(port()), sh->turl,sh->tusrname); + send_sip_response(sh->seq, sh_buf, SIP_RSP_NOTFOUND, request_addr); + } else if(sh->type == DNS_REPLY && sh->method == SIP_MSG_INVITE) { + sh->type = SIP_MSG_INVITE; + strcpy(sh->turl, sh_buf.turl); + strcpy(sh->tusrname, sh_buf.tusrname); + strcpy(sh->url, sh_buf.url); + strcpy(sh->usrname, sh_buf.usrname); + sh->callID = sh_buf.callID; + sh->seq = sh_buf.seq; + sh->ToUserID = sh_buf.ToUserID; + sh->FromUserID = sh_buf.FromUserID; + iph->daddr() = sh->ContactID.node_; + iph->dport() = sh->ContactID.port_; + sh->ContactID.node_ = sh->FromUserID; + sh->ContactID.port_ = 0; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->saddr() = Address::instance().get_nodeaddr(port()); + send(p,0); + } else if(sh->type == DNS_REPLY && (sh->method == SIP_RSP_TRYING || sh->method == SIP_RSP_RINGING || sh->method == SIP_RSP_SUCCESS)){ + sh->type = sh->method; + strcpy(sh->turl, sh_buf.turl); + strcpy(sh->tusrname, sh_buf.tusrname); + strcpy(sh->url, sh_buf.url); + strcpy(sh->usrname, sh_buf.usrname); + sh->callID = sh_buf.callID; + sh->seq = sh_buf.seq; + sh->ToUserID = sh_buf.ToUserID; + sh->FromUserID = sh_buf.FromUserID; + iph->daddr() = sh->ContactID.node_; + iph->dport() = sh->ContactID.port_; + sh->ContactID.node_ = sh->FromUserID; + sh->ContactID.port_ = 0; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->saddr() = Address::instance().get_nodeaddr(port()); + send(p,0); + }else if(sh->type == SIP_RSP_TRYING || sh->type == SIP_RSP_RINGING || sh->type == SIP_RSP_SUCCESS) { + _userList* userListptr = find_user(sh->tusrname,sh->turl); + + if(userListptr) + { + iph->daddr() = userListptr->ContactID.node_; + iph->dport() = userListptr->ContactID.port_; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->saddr() = Address::instance().get_nodeaddr(port()); + send(p,0); + if(print_log_) { + if(sh->type == SIP_RSP_TRYING) + printf("From Proxy: SIP/2.0 100 TRYING %s@%s Contact:%d %d\n",sh->tusrname,sh->turl,userListptr->ContactID.node_,userListptr->ContactID.port_); + else if(sh->type == SIP_RSP_RINGING) + printf("From Proxy: SIP/2.0 180 RINGING %s@%s Contact:%d %d\n",sh->tusrname,sh->turl,userListptr->ContactID.node_,userListptr->ContactID.port_); + else if(sh->type == SIP_RSP_SUCCESS) + printf("From Proxy: SIP/2.0 200 OK %s@%s Contact:%d %d\n",sh->tusrname,sh->turl,userListptr->ContactID.node_,userListptr->ContactID.port_); + } + } + else + { + iph->daddr() = DNS_Server; + iph->dport() = 0; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + if(print_log_) + printf("Node Addr = %d %d\n",iph->saddr(),iph->sport()); + strcpy(sh->tusrname,sh_buf.tusrname); + strcpy(sh->turl,sh_buf.turl); + strcpy(sh->usrname,sh_buf.usrname); + strcpy(sh->url,sh_buf.url); + sh->seq = sh_buf.seq; + sh->ToUserID = sh_buf.ToUserID; + sh->FromUserID = sh_buf.FromUserID; + sh->callID = sh_buf.callID; + sh->method = sh->type; + sh->type = DNS_QUERY; + send(p,0); + } + } + + +} + +void SIPProxyAgent::send_sip_reply(hdr_SIP sip_hdr_, int reply_code, struct sip_address ContactID,struct sip_address request_addr) +{ + Tcl& tcl = Tcl::instance(); + Packet *p = allocpkt(); + hdr_ip *iph = hdr_ip::access(p); + hdr_SIP *sh = hdr_SIP::access(p); + if(reply_code == SIP_RSP_TRYING) { + + sh->seq = sip_hdr_.seq; + sh->type = SIP_RSP_TRYING; + sh->method = SIP_MSG_INVITE; + iph->daddr() = request_addr.node_; + iph->dport() = request_addr.port_; + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->saddr() = Address::instance().get_nodeaddr(port()); + sh->seq = sip_hdr_.seq; + sh->callID = sip_hdr_.callID; + sh->type = reply_code; + sh->ContactID.node_ = ContactID.node_; + sh->ContactID.port_ = ContactID.port_; + send(p,0); + } +} + + +void SIPProxyAgent::send_sip_response(int CSeq, hdr_SIP sip_hdr_, int response_type, struct sip_address request_addr) +{ + Tcl& tcl = Tcl::instance(); + Packet *p = allocpkt(); + hdr_ip *iph = hdr_ip::access(p); + iph->daddr() = request_addr.node_; + iph->dport() = request_addr.port_; + hdr_SIP *sh = hdr_SIP::access(p); + + if(response_type) { + switch(response_type) { + + case SIP_RSP_SUCCESS: + sh->seq = CSeq; + sh->type = SIP_RSP_SUCCESS; + sh->callID = sip_hdr_.callID; + sh->method = sip_hdr_.type; + send(p,0); + break; + + case SIP_RSP_NOTFOUND: + sh->seq = CSeq; + sh->type = SIP_RSP_NOTFOUND; + sh->callID = sip_hdr_.callID; + sh->method = sip_hdr_.type; + send(p,0); + break; + + default: + if(print_log_) + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n", response_type); + } + } + else { + if(print_log_) + printf("*** ERROR REQUEST MESSAGE *** : unknown message : type = %d\n",response_type); + } +} + +int SIPProxyAgent::command(int argc, const char*const* argv) +{ + Tcl& tcl = Tcl::instance(); + + if(argc == 3) { + if(strcmp(argv[1], "register") == 0) { + DNS_Server = atoi(argv[2]); + Register(); + return TCL_OK; + } + + } + return (Agent::command(argc, argv)); +} + +void SIPProxyAgent::send_request(hdr_SIP sip_hdr_, int request_code, struct sip_address ContactID, struct sip_address request_addr) +{ + Tcl& tcl = Tcl::instance(); + Packet* p = allocpkt(); + hdr_ip* iph = hdr_ip::access(p); + hdr_SIP* sh = hdr_SIP::access(p); + +} + +int SIPProxyAgent::Register() +{ + Tcl& tcl = Tcl::instance(); + Packet* p = allocpkt(); + hdr_ip* iph = hdr_ip::access(p); + hdr_SIP *sh = hdr_SIP::access(p); + iph->saddr() = Address::instance().get_nodeaddr(addr()); + iph->sport() = Address::instance().get_nodeaddr(port()); + iph->daddr() = DNS_Server; + iph->dport() = 0; + strcpy(sh->turl,url_); + sh->type = SIP_MSG_REGISTER; + sh->ContactID.node_ = iph->saddr(); + sh->ContactID.port_ = iph->sport(); + send(p,0); + return 0; + +} + +_userList* SIPProxyAgent::find_user(const char* usrname, const char* url) +{ + _userList* user_ptr = userList_head; + _userList* user_ptr_prev; + int count = 0; + + while(user_ptr) { + count++; + if(!strcmp(usrname,user_ptr->usrname)){ + if(!strcmp(url,user_ptr->url)) { + return user_ptr; + break; + } + } else { + + } + user_ptr_prev = user_ptr; + user_ptr = user_ptr->next_; + + } + + return NULL; +} + +void SIPProxyAgent::timeout(int tno) +{ + switch(tno) { + case REGISTRAR_TIMER_LIST: + { + double now = Scheduler::instance().clock(); + _userList *user_ptr = userList_head; + _userList *user_ptr_prev; + + while(user_ptr) { + if(user_ptr->expire_time_ < now) { + if(user_ptr == userList_head) { + if(userList_head == userList_tail) { + userList_head =0; + userList_tail =0; + } else { + userList_head = user_ptr->next_; + } + } else if (user_ptr == userList_tail) { + userList_head = user_ptr_prev; + user_ptr_prev->next_ =0; + } else { + user_ptr_prev->next_ = user_ptr->next_; + } + break; + } else { + user_ptr_prev = user_ptr; + user_ptr = user_ptr->next_; + } + } + } + } +} + + +/* + * Registrar + * + */ + +void PUserListTimer::expire(Event *) { + r_->timeout(REGISTRAR_TIMER_LIST); +} diff -uNr ns-2.1b9a/sip/sip_server.h ns-2.1b9a_sip/sip/sip_server.h --- ns-2.1b9a/sip/sip_server.h Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/sip/sip_server.h Thu Sep 4 18:37:18 2003 @@ -0,0 +1,137 @@ +// +// This software was developed at the National Institute of Standards and +// Technology by employees of the Federal Goverment in the course of their +// official duties. This software is an experimental objects. NIST assumes +// no responsibility whatsoever for its use by other parties, and makes no +// guarantees, expressed or implied, about its quality, reliability, or any +// other characteristic. We would appreicate acknowledgement if the software +// is used. + +// This software can be redistributed and/or modified freely. We respect +// that any derivative works bear some notice that they are derived from it, +// any any modified versions bear some notice that they have been modified. + +// Jin-Woo Jung, jjw@korea.ac.kr + + #ifndef ns_sip_server_h + #define ns_sip_server_h + + #include "sip.h" + + #define REGISTRAR_TIMER_LIST 1 + + #define TEMPORARY_MOVED 0 + #define PERMANENT_MOVED 1 + + + typedef struct _userList{ + int UserID; /* unique user ID */ + char usrname[USRID_MAXLEN]; /* user name */ + char url[SIP_URLMAXLEN]; /* Domain */ + double expire_time_; /* registration lifetime */ + double lifetime_; + double callID; + struct sip_address ContactID; /* future request should be sent */ + struct sip_address location; /* current location of user */ + int status; /* state of UA */ + int permanent; + int serverid; + char servername[SIP_URLMAXLEN]; + struct _userList *next_; +}; + +typedef struct _recordList { + struct sip_address NodeID; + char url[SIP_URLMAXLEN]; + struct _recordList *next; +}; + +/* + * Domain Name System + */ + +class DNSAgent; + +class DNSAgent:public Agent{ + public: + void recv(Packet* , Handler *); + DNSAgent(); + protected: + int print_log_; + _recordList* find_record(const char* url); + _recordList* recordList_head; + _recordList* recordList_tail; +}; + +/* + * Redirect Agent (coupled with Location Server) + */ +class SIPRedirectAgent; + +class UserListTimer : public TimerHandler { + public: + UserListTimer(SIPRedirectAgent *r):TimerHandler(){ r_ = r; } + protected: + void expire(Event *e); + SIPRedirectAgent *r_; +}; + + +class SIPRedirectAgent : public Agent { + public: + int DNS_Server; + char url_[SIP_URLMAXLEN]; + int EntrySize; + SIPRedirectAgent(const char* url); + void send_sip_reply(hdr_SIP sip_hdr_, int reply_code, struct sip_address ContactID, struct sip_address request_addr); // send SIP request message + void send_sip_response(int CSeq, hdr_SIP sip_hdr_, int request_type, struct sip_address request_address); + virtual int Register(); + void recv(Packet *, Handler *); + // _userList* add_user(int UserID); + _userList* find_user(const char * usrname, const char* url); // simply + UserListTimer userList_timer_; + void timeout(int); + protected: + int print_log_; + _userList* userList_head; + _userList* userList_tail; + int command(int argc, const char*const* argv); +}; + +class SIPProxyAgent; + +class PUserListTimer : public TimerHandler { + public: + PUserListTimer(SIPProxyAgent *r):TimerHandler(){ r_ = r; } + protected: + void expire(Event *e); + SIPProxyAgent *r_; +}; +/* + * Proxy Agent + */ +class SIPProxyAgent : public Agent { + public: + int DNS_Server; + char url_[SIP_URLMAXLEN]; + int EntrySize; + SIPProxyAgent(const char* url); + void send_sip_reply(hdr_SIP sip_hdr_, int reply_code, struct sip_address ContactID, struct sip_address request_addr); // send SIP request message + void send_sip_response(int CSeq, hdr_SIP sip_hdr_, int request_type, struct sip_address request_address); + void send_request(hdr_SIP sip_hdr_, int request_code, struct sip_address ContactID, struct sip_address request_addr); // send request message insted of SIP UA + virtual int Register(); + void recv(Packet *, Handler *); + // _userList* add_user(int UserID); + _userList* find_user(const char * usrname, const char* url); // simply + PUserListTimer userList_timer_; + void timeout(int); + protected: + int print_log_; + _userList* userList_head; + _userList* userList_tail; + int command(int argc, const char*const* argv); +}; + + + +#endif diff -uNr ns-2.1b9a/sip/sip_tg.cc ns-2.1b9a_sip/sip/sip_tg.cc --- ns-2.1b9a/sip/sip_tg.cc Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/sip/sip_tg.cc Thu Sep 4 18:54:37 2003 @@ -0,0 +1,121 @@ +/* + * Author: Jae Chung + * File: 07/17/99 + * Modified: 12/23/2002 by Jin-Woo Jung + */ + + #include "random.h" + #include "sip_tg.h" + + // SIP_UA OTcl linkage class +static class SIPTrafficClass : public TclClass { + public: + SIPTrafficClass() : TclClass("Application/SIPTraffic") {} + TclObject* create(int, const char*const*) { + return (new SIP_Traffic()); + } +} class_sip_traffic; + +// When snd_timer_expires call SIP_Traffic::send_pkt() +void SendTimer::expire(Event *) +{ + t_->send_pkt(); +} + +SIP_Traffic::SIP_Traffic() : running_(0), snd_timer_(this) +{ + bind_bw("rate_", &rate_); + bind("packetSize_", &pktsize_); + bind_bool("random_", &random_); +} + + +// Otcl command interpreter +int SIP_Traffic::command(int argc, const char*const* argv) +{ + Tcl& tcl = Tcl::instance(); + if(argc == 2) { + if(strcmp(argv[1], "stop") == 0) { + agent_->close(); + } + return(TCL_OK); + } + if(argc == 3) { + if(strcmp(argv[1], "attach-agent") == 0) { + agent_ = (Agent*) TclObject::lookup(argv[2]); + if(agent_ == 0) { + printf("no such agent %s", argv[2]); + return(TCL_ERROR); + } + agent_->attachApp(this); + return(TCL_OK); + } + } + if(argc == 4) { + if(strcmp(argv[1], "start") == 0) { + agent_->set_tusername(argv[2]); + agent_->set_turl(argv[3]); + agent_->connect(0); + //start(); + } + return(TCL_OK); + } + return (Application::command(argc, argv)); +} + +void SIP_Traffic::init() +{ + seq_ = 0; // sequence number (start from 0) + interval_ = (double)(pktsize_ << 3)/(double)rate_; + +} + +void SIP_Traffic::start() +{ + init(); + running_ = 1; + send_pkt(); +} + +void SIP_Traffic::stop() +{ + running_ =0; +} + +void SIP_Traffic::send(int nbytes) +{ + start(); +} +// Send application data packet +void SIP_Traffic::send_pkt() +{ + hdr_SIP mh_buf; + + if(running_) { + // the below info is passed to SIP agent, which will write it to RTP header after packet creation, + // This is a RTP packet header (ack, sequence, nbyte(size of packet, not udp packet size) + agent_->sendmsg(pktsize_, (char*) &mh_buf); // send to UDP + + // Reschedule the send_pkt timer + double next_time_ = next_snd_time(); + if(next_time_ > 0) snd_timer_.resched(next_time_); + } + } + + // Schedule next data packet transmission time + double SIP_Traffic::next_snd_time() + { + // Recompute interval in case rate or size changes + double next_time_ = interval_; + if(random_) + next_time_ += interval_ * Random::uniform(-0.5, 0.5); + return next_time_; +} + + +double SIP_Traffic::next_interval(int& size) +{ + + +} + diff -uNr ns-2.1b9a/sip/sip_tg.h ns-2.1b9a_sip/sip/sip_tg.h --- ns-2.1b9a/sip/sip_tg.h Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/sip/sip_tg.h Thu Sep 4 18:48:55 2003 @@ -0,0 +1,86 @@ +/* + * Author: Jae Chung + * File: 07/17/99 + * Modified: 12/23/2002 by Jin-Woo Jung + */ + + +#ifndef ns_sip_tg_h +#define ns_sip_tg_h + +#include "timer-handler.h" +#include "packet.h" +#include "app.h" +#include "sip.h" +#include "classifier-addr.h" +#include "random.h" +#include "trafgen.h" +#include "ranvar.h" + +/* This is used for receiver's received packet accounting */ + +class SIP_Traffic; + +// Sender uses this timer to schedule next app data packet transmission time + +class SendTimer : public TimerHandler { + public: + SendTimer(SIP_Traffic* t) : TimerHandler(), t_(t) {} + inline virtual void expire(Event*); + protected: + SIP_Traffic* t_; +}; + +class SIP_Traffic : public TrafficGenerator { + public: + SIP_Traffic(); + virtual void send(int nbytes); + void send_pkt(); // called by SendTimer:expire (Sender) + virtual double next_interval(int &); +/* int loadCDF(const char* filename); + int lookup(double u); + virtual double value(); + virtual double interpolate(double u, double x1, double y1, double x2,, double y2); + virtual double next_interval(int &); +*/ + + protected: + int command(int argc, const char*const* argv); + virtual void start(); // Start sending data packets (Sender) + virtual void stop(); // Stop sending data packets (Sender) + + double rate_; // Transmission rates associated to scale values + double interval_; // application data packet transmission interval + int pktsize_; // Application data packet size + int random_; // If 1 add randomness to the interval + int running_; // If 1 application is running +/* void init(); + double ontime_; // average length of burst (sec) + double offtime_; // average idle period (sec) + double rate_; // send rate during burst (bps) + double interval_; // inter-packet time at burst rate + double burstlen_; // average # packet/burst + unsigned int rem_; // number of packets remaining in current burst + double minCDF_; // min value of the CDF(Cumulative Distribution function) (default to 0) + double maxCDF_; // max value of the CDF (default to 1) + int interpolation_; // how to interpolate data (INTER_DISCRETE...) + int numEntry_; // number of entries in the CDF table + CDFentry* table_; // CDF table of (val_, cdf_) + RNG* rng_; +*/ + private: + void init(); + inline double next_snd_time(); // (Sender) +/* virtual void recv_msg(int nbytes, const char *msg =0); // (Sender/Receiver) + this received message needed implementaion */ + + int seq_; // Application data packet sequence number + SendTimer snd_timer_; // SendTimer +}; + + + +#endif + + + diff -uNr ns-2.1b9a/tcl/lib/ns-default.tcl ns-2.1b9a_sip/tcl/lib/ns-default.tcl --- ns-2.1b9a/tcl/lib/ns-default.tcl Fri Jun 21 07:26:18 2002 +++ ns-2.1b9a_sip/tcl/lib/ns-default.tcl Wed Jan 1 02:18:19 2003 @@ -439,6 +439,12 @@ Application/Traffic/CBR set random_ 0 Application/Traffic/CBR set maxpkts_ 268435456; # 0x10000000 +# SIP Traffic Generation +Application/SIPTraffic set packetSize_ 500 +Application/SIPTraffic set random_ 0 +Application/SIPTraffic set rate_ 1mb + + Application/Telnet set interval_ 1.0 RandomVariable/Uniform set min_ 0.0 @@ -1034,6 +1040,22 @@ Agent/LossMonitor/PLM set fid_PP_ 0 Agent/LossMonitor/PLM set seqno_ 0 +# Session Initiation Protocol agent [SIP] +Agent/SIP set packetSize_ 64 +Agent/SIP set print_ 1 +Agent/SIP set Registrar_ 2 +Agent/SIP set Server_ 3 +Agent/SIP set Lifetime_ 720000 +Agent/SIP set Mode_ 0 ;#Default operation mode is Proxy + +# DNS for Session Initiation Protocol +Agent/DNSAgent set print_ 1 +# Session Initiation Protocol Redirect Server agent [SIP] +Agent/SIPRedirect set print_ 1 + +#Session Initiation protocol Proxy Server agent [SIP] +Agent/SIPProxy set print_ 1 + # MPLS Label Distribution Protocol agent Agent/LDP set trace_ldp_ 0 diff -uNr ns-2.1b9a/tcl/lib/ns-packet.tcl ns-2.1b9a_sip/tcl/lib/ns-packet.tcl --- ns-2.1b9a/tcl/lib/ns-packet.tcl Tue Jan 15 06:02:34 2002 +++ ns-2.1b9a_sip/tcl/lib/ns-packet.tcl Fri Nov 22 00:17:35 2002 @@ -146,6 +146,7 @@ SRM SRMEXT Snoop + SIP TCP TCPA TFRC diff -uNr ns-2.1b9a/tcl/sip/normal_test.tcl ns-2.1b9a_sip/tcl/sip/normal_test.tcl --- ns-2.1b9a/tcl/sip/normal_test.tcl Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/tcl/sip/normal_test.tcl Fri Sep 5 13:23:28 2003 @@ -0,0 +1,114 @@ +# +# This software was developed at the National Institute of Standards and +# Technology by employees of the Federal Goverment in the course of their +# official duties. This software is an experimental objects. NIST assumes +# no responsibility whatsoever for its use by other parties, and makes no +# guarantees, expressed or implied, about its quality, reliability, or any +# other characteristic. We would appreicate acknowledgement if the software +# is used. + +# This software can be redistributed and/or modified freely. We respect +# that any derivative works bear some notice that they are derived from it, +# any any modified versions bear some notice that they have been modified. + +# Jin-Woo Jung, jjw@korea.ac.kr + + +#initilizations +set ns [new Simulator] +set tf [open out_sip_test.tr w] + +$ns namtrace-all $tf + +set n0 [$ns node] +set n1 [$ns node] +set n2 [$ns node] +set n3 [$ns node] +set n4 [$ns node] +set n5 [$ns node] + +$ns duplex-link $n4 $n5 1Mb 10ms DropTail +$ns duplex-link-op $n4 $n5 orient right + +$ns duplex-link $n0 $n4 1Mb 10ms DropTail +$ns duplex-link-op $n0 $n4 orient down-right + +$ns duplex-link $n5 $n1 1Mb 10ms DropTail +$ns duplex-link-op $n5 $n1 orient up-right + +$ns duplex-link $n2 $n4 1Mb 10ms DropTail +$ns duplex-link-op $n2 $n4 orient up-right + +$ns duplex-link $n3 $n5 1Mb 10ms DropTail +$ns duplex-link-op $n3 $n5 orient up-left + + +set serverid [$n3 id] +set serverid1 [$n2 id] +set dnsid [$n5 id] + + +# agents +set sipA [new Agent/SIP jwjung www.nist.gov] +$sipA set packetSize_ 1000 +$sipA set print_ 0 ;# if set 1 , display message flow on screen +$sipA set Server_ $serverid +$sipA set Lifetime_ 120 +$sipA set Mode_ 1 +$ns attach-agent $n0 $sipA + +set sipB [new Agent/SIP bykim www.nist.gov] +$sipB set packetSize_ 1000 +$sipB set print_ 0 +$sipB set Server_ $serverid +$sipB set Mode_ 1 +$sipB set Lifetime_ 120 +$ns attach-agent $n1 $sipB + +set dnsServer [new Agent/DNSAgent] +$dnsServer set print_ 0 +$ns attach-agent $n5 $dnsServer + + +set sipC [new Agent/SIPRedirect www.nist.gov] +$sipC set packetSize_ 1000 +$sipC set print_ 0 +$ns attach-agent $n3 $sipC + +set sipD [new Agent/SIPRedirect www.antd.gov] +$sipD set packetSize_ 1000 +$sipD set print_ 0 +$ns attach-agent $n2 $sipD + +#$ns connect $sipA $sipB + +#Setup a RTP traffic over SIP connection +set st [new Application/SIPTraffic] +$st attach-agent $sipA +#$cbr set type_ CBR +$st set packetSize_ 500 +$st set rate_ 1mb +$st set random_ false + + +#finish procedure +proc finish {} { + global ns tf + $ns flush-trace + close $tf + puts "Running NS-simulation" +# exec nam out_sip_test.nam & + exit 0 + } + +$ns at 1.0 "$sipA register $serverid" ;# register its location with proxy or redirect server +$ns at 1.2 "$sipB register $serverid1" ;# register its location with protyx or redirect server +$ns at 1.4 "$sipC register $dnsid" +$ns at 1.4 "$sipD register $dnsid" +$ns at 2.0 "$st start bykim www.nist.gov" +$ns at 4.0 "$st send" + +$ns at 8.0 "$st stop" +$ns at 10.0 "finish" + +$ns run diff -uNr ns-2.1b9a/tcl/sip/proxy_test.tcl ns-2.1b9a_sip/tcl/sip/proxy_test.tcl --- ns-2.1b9a/tcl/sip/proxy_test.tcl Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/tcl/sip/proxy_test.tcl Fri Sep 5 12:55:52 2003 @@ -0,0 +1,119 @@ +# This software was developed at the National Institute of Standards and +# Technology by employees of the Federal Goverment in the course of their +# official duties. This software is an experimental objects. NIST assumes +# no responsibility whatsoever for its use by other parties, and makes no +# guarantees, expressed or implied, about its quality, reliability, or any +# other characteristic. We would appreicate acknowledgement if the software +# is used. + +# This software can be redistributed and/or modified freely. We respect +# that any derivative works bear some notice that they are derived from it, +# any any modified versions bear some notice that they have been modified. + +# Jin-Woo Jung, jjw@korea.ac.kr + + +#initilizations +set ns [new Simulator] +set tf [open out_sip_test.tr w] + +$ns namtrace-all $tf + +set n0 [$ns node] +set n1 [$ns node] +set n2 [$ns node] +set n3 [$ns node] +set n4 [$ns node] +set n5 [$ns node] + +$ns duplex-link $n4 $n5 1Mb 10ms DropTail +$ns duplex-link-op $n4 $n5 orient right + +$ns duplex-link $n0 $n4 1Mb 10ms DropTail +$ns duplex-link-op $n0 $n4 orient down-right + +$ns duplex-link $n5 $n1 1Mb 10ms DropTail +$ns duplex-link-op $n5 $n1 orient up-right + +$ns duplex-link $n2 $n4 1Mb 10ms DropTail +$ns duplex-link-op $n2 $n4 orient up-right + +$ns duplex-link $n3 $n5 1Mb 10ms DropTail +$ns duplex-link-op $n3 $n5 orient up-left + + +set serverid [$n3 id] +set serverid1 [$n2 id] +set dnsid [$n5 id] + + +# agents +set sipA [new Agent/SIP jwjung www.nist.gov] +$sipA set packetSize_ 1000 +$sipA set print_ 0 +$sipA set Server_ $serverid +$sipA set Lifetime_ 120 +$sipA set Mode_ 1 ;# if mode_ set 1, means Mobility Support, currently not used +$ns attach-agent $n0 $sipA + +set sipB [new Agent/SIP bykim www.antd.gov] +$sipB set packetSize_ 1000 +$sipB set print_ 0 +$sipB set Server_ $serverid1 +$sipB set Mode_ 1 +$sipB set Lifetime_ 120 +$ns attach-agent $n1 $sipB + +#set sipC[new Agent/SIP culkim www.antd.gov] + + +set dnsServer [new Agent/DNSAgent] +$dnsServer set print_ 0 +$ns attach-agent $n5 $dnsServer + + +set sipC [new Agent/SIPProxy www.nist.gov] +$sipC set packetSize_ 1000 +$sipC set print_ 0 +$ns attach-agent $n3 $sipC + +set sipD [new Agent/SIPProxy www.antd.gov] +$sipD set packetSize_ 1000 +$sipD set print_ 0 +$ns attach-agent $n2 $sipD + +#$ns connect $sipA $sipB + + +#Setup a RTP traffic over SIP connection +set st [new Application/SIPTraffic] +$st attach-agent $sipA +#$cbr set type_ CBR +$st set packetSize_ 500 +$st set rate_ 1mb +$st set random_ false + + +#finish procedure +proc finish {} { + global ns tf + $ns flush-trace + close $tf + puts "Running NS-simulation" +# exec nam out_sip_test.nam & + exit 0 + } + +#$ns at 1.0 "$sipA start" +#$ns at 0.5 "$st register 10" +$ns at 1.0 "$sipA register $serverid" ;# register its location with proxy or redirect server +$ns at 1.2 "$sipB register $serverid1" ;# register its location with protyx or redirect server +$ns at 1.4 "$sipC register $dnsid" +$ns at 1.4 "$sipD register $dnsid" +$ns at 2.0 "$st start bykim www.antd.gov" +$ns at 4.0 "$st send" + +$ns at 8.0 "$st stop" +$ns at 10.0 "finish" + +$ns run diff -uNr ns-2.1b9a/tcl/sip/redirect_test.tcl ns-2.1b9a_sip/tcl/sip/redirect_test.tcl --- ns-2.1b9a/tcl/sip/redirect_test.tcl Thu Jan 1 09:00:00 1970 +++ ns-2.1b9a_sip/tcl/sip/redirect_test.tcl Fri Sep 5 12:56:02 2003 @@ -0,0 +1,119 @@ +# This software was developed at the National Institute of Standards and +# Technology by employees of the Federal Goverment in the course of their +# official duties. This software is an experimental objects. NIST assumes +# no responsibility whatsoever for its use by other parties, and makes no +# guarantees, expressed or implied, about its quality, reliability, or any +# other characteristic. We would appreicate acknowledgement if the software +# is used. + +# This software can be redistributed and/or modified freely. We respect +# that any derivative works bear some notice that they are derived from it, +# any any modified versions bear some notice that they have been modified. + +# Jin-Woo Jung, jjw@korea.ac.kr + + +#initilizations +set ns [new Simulator] +set tf [open out_sip_test.tr w] + +$ns namtrace-all $tf + +set n0 [$ns node] +set n1 [$ns node] +set n2 [$ns node] +set n3 [$ns node] +set n4 [$ns node] +set n5 [$ns node] + +$ns duplex-link $n4 $n5 1Mb 10ms DropTail +$ns duplex-link-op $n4 $n5 orient right + +$ns duplex-link $n0 $n4 1Mb 10ms DropTail +$ns duplex-link-op $n0 $n4 orient down-right + +$ns duplex-link $n5 $n1 1Mb 10ms DropTail +$ns duplex-link-op $n5 $n1 orient up-right + +$ns duplex-link $n2 $n4 1Mb 10ms DropTail +$ns duplex-link-op $n2 $n4 orient up-right + +$ns duplex-link $n3 $n5 1Mb 10ms DropTail +$ns duplex-link-op $n3 $n5 orient up-left + + +set serverid [$n3 id] +set serverid1 [$n2 id] +set dnsid [$n5 id] + + +# agents +set sipA [new Agent/SIP jwjung www.nist.gov] +$sipA set packetSize_ 1000 +$sipA set print_ 0 +$sipA set Server_ $serverid +$sipA set Lifetime_ 120 +$sipA set Mode_ 1 +$ns attach-agent $n0 $sipA + +set sipB [new Agent/SIP bykim www.antd.gov] +$sipB set packetSize_ 1000 +$sipB set print_ 0 +$sipB set Server_ $serverid1 +$sipB set Mode_ 1 +$sipB set Lifetime_ 120 +$ns attach-agent $n1 $sipB + +#set sipC[new Agent/SIP culkim www.antd.gov] + + +set dnsServer [new Agent/DNSAgent] +$dnsServer set print_ 0 +$ns attach-agent $n5 $dnsServer + + +set sipC [new Agent/SIPRedirect www.nist.gov] +$sipC set packetSize_ 1000 +$sipC set print_ 0 +$ns attach-agent $n3 $sipC + +set sipD [new Agent/SIPRedirect www.antd.gov] +$sipD set packetSize_ 1000 +$sipD set print_ 0 +$ns attach-agent $n2 $sipD + +#$ns connect $sipA $sipB + + +#Setup a RTP traffic over SIP connection +set st [new Application/SIPTraffic] +$st attach-agent $sipA +#$cbr set type_ CBR +$st set packetSize_ 500 +$st set rate_ 1mb +$st set random_ false + + +#finish procedure +proc finish {} { + global ns tf + $ns flush-trace + close $tf + puts "Running NS-simulation" +# exec nam out_sip_test.nam & + exit 0 + } + +#$ns at 1.0 "$sipA start" +#$ns at 0.5 "$st register 10" +$ns at 1.0 "$sipA register $serverid" ;# register its location with proxy or redirect server +$ns at 1.2 "$sipB register $serverid1" ;# register its location with protyx or redirect server +$ns at 1.4 "$sipC register $dnsid" +$ns at 1.4 "$sipD register $dnsid" +$ns at 2.0 "$st start bykim www.antd.gov" +$ns at 4.0 "$st send" + +$ns at 8.0 "$st stop" +$ns at 10.0 "finish" + +$ns run