📄 nssocket.cc
字号:
/*-------------------------------------------------------------------------*//* NSSocket: a socket interface that wraps the functionalities of SocketTcp*//* Author: Qi He <http://www.cc.gatech.edu/~qhe> 01Aug2003 *//* $Revision:$ $Name:$ $Date:$ *//*-------------------------------------------------------------------------*/#include "peer_agent.h"#include "nssocket.h"#include <stdarg.h>#include <stdlib.h>static class NSSocketClass: public TclClass {public: NSSocketClass(): TclClass("Application/AdvwTcpApplication/NSSocket") {} TclObject* create(int, const char*const*) { return (new Socket()); }}class_socket;/* Applications using the NSSocket interface */static class SockAppClass: public TclClass {public: SockAppClass(): TclClass("SocketApp") {} TclObject* create(int, const char*const* argv) { return (new SocketApp()); }}class_sockapp;static int dcnt=0; //number of messages dropped by sockets#ifdef PDNSextern NsObject* GetLocalIP(ipaddr_t ipaddr);#endifstatic void debug_stat(char *format, ...) { va_list ap; if(getenv("GNUSIM_NOSTAT")==NULL) { va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); } fflush(NULL);};/* TCP socket in NS */NSSocket::NSSocket() { peer_.addr_ = 0; peer_.port_ = -1; bind("addr_", &addr_); bind("port_", &port_); state_ = UNCONNECTED; sec_ = 0; secRcv_ = 0; isPrio_ = FALSE; rate_limit_ = 0;}/*---- bind the socket to a particular address and port number ------------*/void NSSocket::_bind(NodeAddr_t addr, Port_t port) { addr_ = addr; port_ = port;}/*---- connect to the peer TCP entity -------------------------------------*/void NSSocket::connect() { if(agent_==NULL) { fprintf(stderr, "agent_ is null for this socket\n"); fflush(NULL); exit(-1); } ((SocketTcp *)agent_)->connect();}/*---- connect to a particular address and port number --------------------*/void NSSocket::connect(NodeAddr_t peer, Port_t port) { Tcl &tcl = Tcl::instance(); ns_addr_t laddr; Node *lnode=NULL; peer_.addr_ = peer; peer_.port_ = port;#ifdef PDNS if((lnode=(Node *)GetLocalIP(peer))!=NULL) { laddr.addr_ = lnode->address(); laddr.port_ = port; ((Agent *)agent_)->connect(laddr); }else { fflush(NULL); Tcl &tcl = Tcl::instance(); tcl.evalf("[Simulator instance] rconnect %s %d %d", agent_->name(), peer, port); }#else laddr.addr_ = peer; laddr.port_ = port; ((Agent *)agent_)->connect(laddr);#endif ((SocketTcp *)agent_)->connect();}/*---- send user data of certain length -----------------------------------*/int NSSocket::send(int len, PacketData *data) { int res; if(state_ == CONNECTED) { res = ((SocketTcp *)agent_)->sendmsg(data, len); if(res==-1||res==0) state_ = BLOCKED; return res; } switch(state_) { case CONNECTING: case UNCONNECTED: errno_ = ENOTCONN; break; case BLOCKED: errno_ = EWOULDBLOCK; break; default: break; } if(data!=NULL) { delete data; dcnt++; if(dcnt%10000==0) printf("nssocket drop cnt %d\n", dcnt); } return -1;}/*---- close the socket --------------------------------------------------*/void NSSocket::close() { state_ = CLOSING; agent_->close(); } /*---- read all the available data from the socket ----------------------*/void NSSocket::recv() { ((SocketTcp *)agent_)->tcp_command_block_receive(0);}/*- listen() for at most "max" number of incoming connection requests -*/void NSSocket::listen(int max) { ((SocketTcp *)agent_)->listen(max);}//upcalls are called by SocketTcp/*---- TCP is ready for sending -----------------------------------------*/void NSSocket::upcall_send() { if(state_==CLOSING) return; state_ = CONNECTED; if(app_) app_->upcall_send(this);}/*---- TCP receives a connection request --------------------------------*/void NSSocket::upcall_passconn() { if(app_) app_->upcall_passconn(this);}/*---- an (active open) TCP connection is established -------------------*/void NSSocket::upcall_connected(Packet *pkt) {#ifdef PDNS hdr_rti *rtih = hdr_rti::access(pkt); peer_.addr_ = rtih->ipsrc(); peer_.port_ = rtih->ipsrcport();#else hdr_ip *iph = hdr_ip::access(pkt); peer_.addr_ = iph->saddr(); peer_.port_ = iph->sport();#endif state_ = CONNECTED; if(app_) app_->upcall_connected(this);}/*---- TCP is ready for reading -----------------------------------------*/int NSSocket::upcall_recv(PacketData *data) { if (rate_limit_) { long cur = (long)Scheduler::instance().clock(); if(sec_!=cur) { sec_ = cur; secRcv_ = 0; } secRcv_ ++; if(secRcv_ > rate_limit_) return 0; } if(app_) { return app_->upcall_recv(this, data, NULL); }}/*--- Connection Request received -*/void NSSocket::upcall_accept(Packet *synpkt) { Tcl &tcl = Tcl::instance(); tcl.evalf("[Simulator instance] create-sock %d %s -1 0 %d %d", addr_, app_->name(), isPrio_, rate_limit_); NSSocket *sock = (NSSocket *)tcl.lookup(tcl.result()); if(sock==NULL) { fprintf(stderr, "unable to create new socket\n"); return; } hdr_ip *iph = hdr_ip::access(synpkt);#ifdef PDNS ns_addr_t dconn = iph->src(); hdr_rti *rtih = hdr_rti::access(synpkt); peer_.addr_ = rtih->ipsrc(); peer_.port_ = rtih->ipsrcport(); if(!GetLocalIP(peer_.addr_)) { tcl.evalf("[Simulator instance] rconnect %s %d %d\n", sock->agent_->name(), peer_.addr_, peer_.port_); } else sock->agent_->connect(dconn); sock->peer_ = peer_;#else peer_.addr_ = iph->saddr(); peer_.port_ = iph->sport(); sock->peer_ = peer_; sock->agent_->connect(iph->src());#endif ((SocketTcp *)sock->agent_)->ack_syn(synpkt);}void NSSocket::upcall_closing() { state_ = CLOSING; if(app_) app_->upcall_closing(this);}int NSSocket::blocked(int op) { if(op==SOCK_WRITE) { if(state_==CONNECTED) return FALSE; else return TRUE; } if(op==SOCK_READ) { if(((SocketTcp *)agent_)->num_bytes_avail_>0) return FALSE; else return TRUE; }}int NSSocket::command(int argc, const char*const* argv) { Tcl &tcl = Tcl::instance(); if(argc==3) { if(strcmp(argv[1], "set-app")==0) { SocketApp *app = (SocketApp *)tcl.lookup(argv[2]); if(app) { app_ = app; return TCL_OK; } return TCL_ERROR; } if(strcmp(argv[1], "listen")==0) { int max = atoi(argv[2]); listen(max); return TCL_OK; } if(strcmp(argv[1], "rate-limit")==0) { rate_limit_ = atoi(argv[2]); return TCL_OK; } } if(argc==4) { if(strcmp(argv[1], "sbind")==0) { ns_addr_t addr; addr.addr_ = atoi(argv[2]); addr.port_ = atoi(argv[3]); _bind(addr.addr_, addr.port_); return TCL_OK; } } return AdvwTcpApplication::command(argc, argv);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -