⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slp-ua.cc

📁 the User Agent and Service Agent functionality of the Service Location Protocol, based on RFC 2608:
💻 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 + -