📄 slp-ua.cc
字号:
#include "slp/slp-ua.h"u_int16_t G_Xid = 0;int rx_count = 0;int rx_advertcount = 0;RNG G_arrival;// SLPua OTcl linkage classstatic class SLPuaClass : public TclClass { public: SLPuaClass() : TclClass("Application/SLPua") {} TclObject* create(int, const char*const*) { return (new SLPua); }} class_slp_ua;void reReqTimer::expire(Event *){ s_->send_srvrqst_pkt(r_, a_); if (m_==REG) resched(i_); else resched(G_arrival.exponential(i_));}void urlCacheTimer::expire(Event *){ s_->remove_cached_url(n_);}void retxTimer::expire(Event *){ if (n_->retxok || !n_->gotreply) h_->update_resched_resend(n_); else //no further responses caused by the PR_LIST h_->remove_from_table (n_->xid);}// Constructor (also initialize instances of timers)SLPua::SLPua() : running_(0) , rqstTable_(this){ bind("pktsize_",&pktsize_); bind("dstport_",&dstport_); bind_bool("maxSearch_",&maxSearch_); number_of_scopes_ = 0; url_head = NULL;}// OTcl command interpreterint SLPua::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 3) { if (strcmp(argv[1], "attach-agent") == 0) { agent_ = (Agent*) TclObject::lookup(argv[2]); if (agent_ == 0) { tcl.resultf("no such agent %s", argv[2]); return(TCL_ERROR); } // Make sure the underlying agent support MM if(agent_->supportSLP()) { agent_->enableSLP(); } else { tcl.resultf("agent \"%s\" does not support SLP Application", argv[2]); return(TCL_ERROR); } agent_->attachApp(this); return(TCL_OK); } else if (strcmp(argv[1],"add-scope") == 0) { add_scope(argv[2]); return(TCL_OK); } else if (strcmp(argv[1],"remove-scope") == 0) { remove_scope(argv[2]); return(TCL_OK); } } else if (((argc==4)||(argc==6))&&(strcmp(argv[1],"rqst-service") == 0)) { if (argc==6) { if (strcmp(argv[4],"-reg")==0) reReqTimer *resend=new reReqTimer(this, atof(argv[5]), (nsaddr_t)strtol(argv[3], (char **)NULL, 16), argv[2], REG); if (strcmp(argv[4],"-exp")==0) reReqTimer *resend=new reReqTimer(this, atof(argv[5]), (nsaddr_t)strtol(argv[3], (char **)NULL, 16), argv[2], EXP); } send_srvrqst_pkt(argv[2],(nsaddr_t)strtol(argv[3], (char **)NULL, 16)); return(TCL_OK); } return (Application::command(argc, argv));}void SLPua::init(){ //add_scope("DEFAULT"); xid_seed(); }void SLPua::add_scope(const char* newscope) { char *scope = small_string(newscope); for (int i=0; i<number_of_scopes_; i++) { if (strcmp(local_scopes_[i],scope)==0) { // already in list return; } } if (number_of_scopes_==SLP_MAX_SCOPE) { printf("Can't add anymore scopes, MAX=%d scopes per SA\n",SLP_MAX_SCOPE); return; } local_scopes_[number_of_scopes_]=scope;#ifdef DEBUGUA printf("UA:Added %s, total=%d Scope \n",local_scopes_[number_of_scopes_], number_of_scopes_+1);#endif number_of_scopes_++;}void SLPua::remove_scope(const char *removescope) { int i,j; char *scope = small_string(removescope); for (i=0; i<number_of_scopes_; i++) { if (strcmp(local_scopes_[i],scope)==0) break; } number_of_scopes_--; for (j=i; j<number_of_scopes_; j++) { local_scopes_[j]=strdup(local_scopes_[j+1]); }}void SLPua::cache_url(u_int16_t url_entry_count, const char* url) { urlNode *c; hdr_slp_url *addurl; int index=0; for (int i=0; i<url_entry_count; i++) { addurl=(hdr_slp_url *)(url + index); if (addurl->lifetime != 0) { #ifdef DEBUGUA printf("%f: Expiring after %f\n",CURRENT_TIME(),(double)(addurl->lifetime)-CURRENT_TIME()); #endif c = new urlNode(this, (double)(addurl->lifetime)); (c->data).lifetime=addurl->lifetime; (c->data).url=strdup(addurl->url); (c->data).url_length=addurl->url_length; (c->data).auth_no=0; c->next = url_head; url_head = c; #ifdef DEBUGUA printf("UA:Cached %s %d\n",(url_head->data).url, (url_head->data).auth_no); #endif } index+=sizeof(hdr_slp_url); } }static bool match(const char *url, const char *service){ int position; char *token; char *temp1; char *temp2; temp1=strdup(url); token=strstr(temp1,"://"); position = token -temp1; temp2=strndup(temp1,position); delete temp1; if (strstr(temp2,service) != NULL) { delete temp2; return true; } else { delete temp2; return false; } }bool SLPua::search_cached_urls(const char* service){ bool matched=false; urlNode *c = url_head; int offset; Tcl& tcl = Tcl::instance(); char wrk[5000]; while (c!=NULL) { if (match((c->data).url,service)==true) { matched=true; tcl.evalf("puts $tracefd \"C n%d: %f****Cached service urls matches %s\"",agent_->addr(),CURRENT_TIME(),(c->data).url); return matched; } c=c->next; } return matched;} void SLPua::remove_cached_url(urlNode *removeurl) { urlNode *p=NULL, *c=url_head; while ((c!=NULL) && (c != removeurl)) { p=c; c=c->next; } if (c==NULL) return; if (p==NULL) url_head = c->next; else p->next = c->next; delete c; //we assume that a cached service doesn't timeout before MC_CONFIG_MAX, so we do //not care to remove it from the prlist if the request retransmission are still active}void SLPua::start(){ init(); running_ = 1;}void SLPua::stop(){ running_ = 0;}char * SLPua::get_local_scopes() const{ char buf[21]; char str[SLP_MAX_SCOPE*20]=""; for (int i=0; i<number_of_scopes_; i++) { if (i==0) { sprintf(buf,"%s",local_scopes_[i]); strcat(str,buf); } else { sprintf(buf,",%s",local_scopes_[i]); strcat(str,buf); } } return strdup(str);}// Send application data packetvoid SLPua::send_srvrqst_pkt(const char* service_type, nsaddr_t destaddr){ //first check if request service is cached if (search_cached_urls(service_type)==true) return; #ifdef DEBUG printf("No cached match...sending request\n"); #endif //Otherwise, send a new service request ns_addr_t dest; dest.addr_=destaddr; dest.port_=dstport_; char * scopes = get_local_scopes(); //printf("Dest is %d:%d\n",dest.addr_,dest.port_); hdr_slp_srvrqst srvrqst_buf; if (running_) { // the below info is passed to UDPslp agent, which will write it // to SLP SRVRQST header after packet creation. srvrqst_buf.version = SLP_VERSION; srvrqst_buf.function_id = SLPTYPE_SRVRQST; srvrqst_buf.flags = SLP_REQUEST_MCAST; srvrqst_buf.next_ext_offset=0; srvrqst_buf.xid = xid_generate(); srvrqst_buf.language_tag_length=strlen(SLP_LANGUAGE); srvrqst_buf.language_tag=SLP_LANGUAGE; srvrqst_buf.length_prlist=0; srvrqst_buf.length_service_type=strlen(service_type); srvrqst_buf.string_service_type=strdup(service_type); srvrqst_buf.length_scope_list=strlen(scopes); srvrqst_buf.string_scope_list=scopes; srvrqst_buf.length_predicate=0; srvrqst_buf.length_spi=0; srvrqst_buf.length=srvrqst_buf.size();#ifdef DEBUG printf("n%d: UA Sending Service Request (xid=%d) to %x:%d\n",agent_->addr(), srvrqst_buf.xid,dest.addr_,dest.port_);#endif rqstTable_.add_resched_send(srvrqst_buf.xid, srvrqst_buf.length, (char*) &srvrqst_buf, dest); }}// Receive message from underlying agentvoid SLPua::recv_slpmsg(ns_addr_t src, int nbytes, const char *msg){#ifdef DEBUGUA printf("n%d: UA receiving message from %x:%d\n",agent_->addr(),src.addr_, src.port_);#endif if(msg) { hdr_slp* slp_buf = (hdr_slp*) msg; if (slp_buf->function_id == SLPTYPE_SRVRPLY) { // If received packet is a request packet hdr_slp_srvrply* slp_srvrply_buf = (hdr_slp_srvrply*) msg; //print service reply here #ifdef DEBUG printReply(slp_srvrply_buf); #endif cache_url(slp_srvrply_buf->url_entry_count,slp_srvrply_buf->url); if (maxSearch_) rqstTable_.add_pr(slp_srvrply_buf->xid, src.addr_); else rqstTable_.cancel_retx(slp_srvrply_buf->xid); #ifdef DEBUGUA printf("n%d:String is %s\n",agent_->addr(),rqstTable_.get_pr(slp_srvrply_buf->xid)); #endif } else if (slp_buf->function_id == SLPTYPE_SAADVERT) { hdr_slp_saadvert* slp_saadvert_buf = (hdr_slp_saadvert*) msg; printf("n%d: ****Received a service advert xid=%d scopes=%s url=%s (adv count=%d)\n", agent_->addr(), slp_saadvert_buf->xid, slp_saadvert_buf->string_scope_list,slp_saadvert_buf->url,++rx_advertcount); if (maxSearch_) rqstTable_.add_pr(slp_saadvert_buf->xid, src.addr_); else rqstTable_.cancel_retx(slp_saadvert_buf->xid); //configure SA with scopes from the SAAdvert discover_scopes(slp_saadvert_buf->string_scope_list, slp_saadvert_buf->length_scope_list); } } }void SLPua::discover_scopes(const char* scope_list, u_int16_t length_scope){ if (length_scope==0) return; char *delimiters = ","; char *token; char scope[length_scope]; strcpy(scope,scope_list); token=strtok(scope, delimiters); while (token!=NULL) { add_scope(token); token=strtok(NULL, delimiters); }} void SLPua::printReply (hdr_slp_srvrply* rply){ printf("n%d: ****Received a service reply xid=%d url=%d (count=%d)\n",agent_->addr(), rply->xid, rply->url_entry_count,++rx_count); int index=0; for (int i=0; i<rply->url_entry_count; i++) { printf("%s*",((hdr_slp_url *)((rply->url) + index))->url); index+=sizeof(hdr_slp_url); } printf("\n");}void SLPua::xid_seed(void){ G_Xid=0; //G_Xid = (u_int16_t)Random::uniform(65535);}u_int16_t SLPua::xid_generate(void){ G_Xid++; return G_Xid; //return ((u_int16_t)Random::uniform(65535));}rqstHashTable::rqstHashTable(SLPua *s) { s_ = s; tablesize = SLP_MAX_OUTSTANDING*3; table = new rqstNode* [tablesize]; for (int i=0; i<tablesize; i++) { table[i] = NULL; } }int rqstHashTable::hash (u_int16_t xid) const{ return (xid%tablesize);}void rqstHashTable::add_pr(u_int16_t xid, int newaddress){ rqstNode *c; int key=hash(xid); for (c=table[key]; c!=NULL; c=c->next) { if (c->xid == xid) { add_local_pr(c, newaddress); return; } }}void rqstHashTable::cancel_retx(u_int16_t xid){ rqstNode *c; int key=hash(xid); for (c=table[key]; c!=NULL; c=c->next) { if (c->xid == xid) { //cancel retransmissions c->retx_timer_.cancel(); //remove node from hash table remove_from_table (xid); return; } }}void rqstHashTable::add_local_pr(rqstNode* c, int newaddress){ for (int i=0; i<c->number_of_pr; i++) { if (c->local_pr[i]==newaddress) { // already in list return; } } if (c->number_of_pr==SLP_MAX_PRLIST) { printf("Can't add anymore prev. responders, MAX=%d pr per SA\n",SLP_MAX_PRLIST); return; } c->local_pr[c->number_of_pr]=newaddress; c->number_of_pr++; c->retxok=true; c->gotreply=true;}char * rqstHashTable::get_pr(u_int16_t xid) const{ rqstNode *c; int key = hash(xid); for (c=table[key]; c!=NULL; c=c->next) { if (c->xid == xid) return (get_local_pr(c)); } return ("");}char * rqstHashTable::get_local_pr(const rqstNode* c) const{ char buf[21]; char str[SLP_MAX_PRLIST*21]=""; for (int i=0; i<c->number_of_pr; i++) { if (i==0) { sprintf(buf,"%d",c->local_pr[i]); strcat(str,buf); } else { sprintf(buf,",%d",c->local_pr[i]); strcat(str,buf); } } return strdup(str);}void rqstHashTable::add_resched_send(u_int16_t xid, int size, const char *mssg, ns_addr_t dst){ /* if size exceeds SLP pkt size, then do nothing */ if (size > s_->pktsize_) { #ifdef DEBUGUA printf("Will not send request, size=%d, max=%d\n",size,s_->pktsize_); #endif return; } /*adding new node*/ rqstNode *c; int key=hash(xid); c = new rqstNode(this); c->xid = xid; c->number_of_pr = 0; c->next = table[key]; memcpy(&c->msg,mssg, sizeof(hdr_slp_srvrqst)); c->dest=dst; c->timeout=SLP_INITIAL_TIMEOUT; c->expire=CURRENT_TIME()+SLP_CONFIG_MC_MAX; table[key]=c; /*rescheduling packet*/ c->retx_timer_.resched(c->timeout); c->retxok=false; c->gotreply=false; /*sending packet*/ s_->agent_->sendto(size, c->msg, c->dest); // send to UDP #ifdef DEBUGUA printf("(xid=%d) Current Time=%f, next retx=%f, expire=%f\n",c->xid, CURRENT_TIME(), c->timeout+CURRENT_TIME(), c->expire); #endif }void rqstHashTable::update_resched_resend(rqstNode *n){ //retrasnmit until CONFIG_MC_MAX is reached if (CURRENT_TIME() >= n->expire) { //remove this request history from hashtable remove_from_table (n->xid); return; } hdr_slp_srvrqst* srvrqst_buf = (hdr_slp_srvrqst*) n->msg; //adding the prlist to srvrqst packet before its resent char *pr=get_local_pr(n); srvrqst_buf->length_prlist=strlen(pr); srvrqst_buf->string_prlist=pr; srvrqst_buf->length=srvrqst_buf->size(); n->retxok=false; //retrasnmit until request will no longer fit in a single datagram if (srvrqst_buf->size() > s_->pktsize_) { #ifdef DEBUGUA printf("Will not send request, size=%d, max=%d\n",srvrqst_buf->size(),s_->pktsize_); #endif return; } #ifdef DEBUGUA printf("R(xid=%d) Current Time=%f, next retx=%f\n",n->xid, CURRENT_TIME(), n->timeout+(CURRENT_TIME()*2.0)); #endif /*Rescheduling*/ n->retx_timer_.resched(n->timeout*=2.0); ///*Re-sending*/ s_->agent_->sendto(srvrqst_buf->length, n->msg, n->dest); }void rqstHashTable::remove_from_table (u_int16_t xid){ int key=hash(xid); rqstNode *p=NULL, *c=table[key]; while ((c!=NULL) && (xid!=c->xid)) { p=c; c=c->next; } if (c==NULL) { printf("Error: Didn't find the node to be deleted from hash table\n"); return; } //now adjust pointers if (p==NULL) //Node to be deleted is the first node table[key] = c->next; else p->next = c->next; delete c; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -