(file) Return to slp.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / slp

   1 mday  1.1 //%/////////////////////////////////////////////////////////////////////////////
   2           //
   3           // Copyright (c) 2001 The Open Group, BMC Software, IBM
   4           //
   5           // Permission is hereby granted, free of charge, to any person obtaining a
   6           // copy of this software and associated documentation files (the "Software"),
   7           // to deal in the Software without restriction, including without limitation
   8           // the rights to use, copy, modify, merge, publish, distribute, sublicense,
   9           // and/or sell copies of the Software, and to permit persons to whom the
  10           // Software is furnished to do so, subject to the following conditions:
  11           //
  12           // The above copyright notice and this permission notice shall be included in 
  13           // all copies or substantial portions of the Software.
  14           //
  15           //
  16           // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17           // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18           // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19           // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20           // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21           // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22 mday  1.1 // DEALINGS IN THE SOFTWARE.
  23           //
  24           //==============================================================================
  25           //
  26           // Author: Mike Day (mdday@us.ibm.com)
  27           //
  28           //%/////////////////////////////////////////////////////////////////////////////
  29           
  30           
  31           #include "slp.h"
  32           
  33           PEGASUS_USING_STD;
  34           
  35           PEGASUS_NAMESPACE_BEGIN
  36           
  37 mday  1.2 PEGASUS_EXPORT String slp_get_host_name(void)
  38 mday  1.1 {
  39 mday  1.2 
  40             String s = String();
  41             Sint8 *buf = new Sint8[255];
  42             if( 0 == gethostname(buf, 254) ) 
  43               s += buf;
  44             delete buf;
  45             return(s);
  46 mday  1.1 }
  47           
  48           
  49           #ifdef _WIN32
  50           PEGASUS_EXPORT int gethostbyname_r(const char *name, 
  51           		    struct hostent *resultbuf, 
  52           		    char *buf, 
  53           		    size_t bufsize, 
  54           		    struct hostent **result, 
  55           		    int *errnop) 
  56           {
  57             name = name;
  58             resultbuf = resultbuf;
  59             buf = buf;
  60             bufsize = bufsize;
  61             
  62             if(NULL == (*result = gethostbyname(name))) {
  63               *errnop = WSAGetLastError();
  64               return(-1);
  65             } 
  66             return(0);
  67 mday  1.1 }
  68           
  69           #endif
  70           
  71 karl  1.3 #ifdef PEGASUS_OS_HPUX
  72           
  73           PEGASUS_EXPORT int gethostbyname_r(const char *name, 
  74           		    struct hostent *resultbuf, 
  75           		    char *buf, 
  76           		    size_t bufsize, 
  77           		    struct hostent **result, 
  78           		    int *errnop) 
  79           {
  80             name = name;
  81             resultbuf = resultbuf;
  82             buf = buf;
  83             bufsize = bufsize;
  84             
  85             if(NULL == (*result = gethostbyname(name))) {
  86               *errnop = h_errno;
  87               return(-1);
  88             } 
  89             return(0);
  90           }
  91           #endif
  92 karl  1.3 
  93 mday  1.2 PEGASUS_EXPORT String slp_get_addr_string_from_url(const String & url) 
  94 mday  1.1 {
  95 mday  1.2   String s = String();
  96 mday  1.1   struct sockaddr_in addr;
  97             if( get_addr_from_url( url, &addr) ) {
  98 mday  1.2     Sint8 *name = new Sint8[255];
  99 mday  1.1 #ifdef _WIN32
 100 mday  1.2     _snprintf(name, 254, "%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port) );
 101 mday  1.1 #else
 102 mday  1.2     snprintf(name, 254, "%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port) );
 103 mday  1.1 #endif
 104 mday  1.2     s += name;
 105               delete [] name;
 106 mday  1.1   }
 107 mday  1.2   return(s);
 108 mday  1.1 }
 109           
 110 mday  1.2 PEGASUS_EXPORT Boolean get_addr_from_url(const String & url, struct sockaddr_in *addr )
 111 mday  1.1 {
 112             Sint8 *bptr, *url_dup;
 113             Boolean ccode = false;
 114           
 115             // isolate the host field 
 116 mday  1.2   bptr = (url_dup = url.allocateCString());
 117 mday  1.1   if(bptr == NULL)
 118               return(false );
 119           
 120             while( (*bptr != '/') && (*bptr != 0x00) )
 121               bptr++;
 122           
 123             if(*bptr == '/' && *(bptr + 1) == '/') {
 124               Sint8 *endptr, *portptr;
 125               endptr = bptr + 2;
 126               while (*endptr != 0x00 && *endptr != '/' && *endptr != ';')
 127                 endptr++;
 128               *endptr = 0x00;
 129               portptr = (endptr - 1) ;
 130           
 131               while( ( portptr > ( bptr + 2 ) ) && ( *portptr != ':' ) )
 132                 portptr--;
 133           
 134               if( *portptr == ':') {
 135                 *portptr = 0x00;
 136                 portptr++;
 137               } else { portptr = NULL; }
 138 mday  1.1     
 139               // bptr points to the host name or address
 140               // portptr points to the port or is null
 141           
 142               if (portptr != NULL)
 143                 addr->sin_port = htons( (Sint16)strtoul(portptr, NULL, 0) );
 144               else
 145                 addr->sin_port = 0x0000;
 146               addr->sin_family = AF_INET;
 147               
 148               bptr += 2;
 149               addr->sin_addr.s_addr = inet_addr(bptr);
 150               if(addr->sin_addr.s_addr == INADDR_NONE) {
 151                 struct hostent *host;
 152                 struct hostent hostbuf;
 153                 Uint8 *temp ;
 154                 Uint32 result, err;
 155                 size_t hostbuflen = 256;
 156                 
 157                 // hopefully a hostname because dotted decimal notation was invalid
 158                 // look for the user@hostname production
 159 mday  1.1       Sint8 *userptr;
 160                 userptr = bptr;
 161                 while( (*userptr != 0x00 ) && (*userptr != '@' ) )
 162           	userptr++;
 163                 if( *userptr == '@' )
 164           	bptr = userptr + 1;
 165                 
 166                 temp = (Uint8 *)malloc(hostbuflen); 
 167                 if(temp != NULL) {
 168           	host = NULL;
 169           	while(temp != NULL && (result = gethostbyname_r(bptr, &hostbuf, (char *)temp, hostbuflen, 
 170           							&host, (int *)&err)) == ERANGE){
 171           	  hostbuflen *= 2;
 172           	  temp = (Uint8 *)realloc(temp, hostbuflen);
 173           	}
 174           	if(host != NULL) {
 175           	  struct in_addr *ptr;
 176           	  if (((ptr = (struct in_addr *)*(host->h_addr_list)) != NULL ) ) {
 177           	    addr->sin_addr.s_addr = ptr->s_addr;
 178           	    ccode = true;
 179           	  }
 180 mday  1.1 	}
 181           	free(temp);
 182                 } /* we allocated the temp buffer for gethostbyname */
 183               } else { ccode = true; } /* host field is not in a valid dotted decimal form */
 184             } /* isolated the host field in the url  */
 185             return(ccode);
 186           }
 187            
 188           
 189 mday  1.2 static Boolean  slp_join_multicast(SOCKET sock, struct in_addr *addr) 
 190           {
 191             
 192             // don't join on the loopback interface
 193             if (addr->s_addr == inet_addr("127.0.0.1") )
 194               return(false);
 195           
 196             struct ip_mreq mreq;
 197             mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.253");
 198             mreq.imr_interface.s_addr = addr->s_addr;
 199             
 200             if(SOCKET_ERROR == setsockopt(sock,IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq))) 
 201               return(false);
 202             return(true);
 203           }
 204           
 205           
 206           
 207           static int slp_join_multicast_all(SOCKET sock)
 208           {
 209           
 210 mday  1.2 
 211             int num_interfaces = 0;
 212           
 213             String host_name = slp_get_host_name();
 214           
 215             if( 0 < host_name.size() ) {
 216               struct hostent hostbuf;
 217               struct hostent *host ;
 218               
 219               int result = 0, err;
 220               size_t hostbuf_len = 512;
 221               Sint8 *hn = host_name.allocateCString( );
 222               Sint8 *buf = (Sint8 *)malloc(hostbuf_len) ;
 223               while( buf != NULL && ( result = gethostbyname_r( hn, 
 224           						      &hostbuf, 
 225           						      buf, 
 226           						      hostbuf_len, 
 227           						      &host, 
 228           						      &err) )  == ERANGE ) {
 229                 hostbuf_len *= 2;
 230                 buf = (Sint8 *)realloc(buf, hostbuf_len);
 231 mday  1.2     } // realloc buffer loop
 232           
 233               if((host != NULL) && (result == 0)) {
 234                 struct in_addr *ptr;
 235                 while ( ( ptr = (struct in_addr *) *(host->h_addr_list)++ ) != NULL ) { 
 236           	if(true == slp_join_multicast(sock, ptr) )
 237           	  num_interfaces++ ;
 238                 } // traversing address list 
 239                 if(buf != NULL)
 240           	free(buf);
 241               } // gethostnume succeeded
 242               delete[] hn;
 243             } // if allocated host buffer
 244             return(num_interfaces);
 245           }
 246           
 247           
 248           static SOCKET  slp_open_listen_sock( void )
 249           {
 250           
 251             SOCKET sock  = socket(AF_INET, SOCK_DGRAM, 0) ;
 252 mday  1.2   int err = 1;
 253             setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err));
 254             struct sockaddr_in local;
 255             local.sin_family = AF_INET;
 256             local.sin_port = htons(427);
 257             local.sin_addr.s_addr  = INADDR_ANY;
 258             bind(sock, (struct sockaddr *)&local, sizeof(local));
 259             slp_join_multicast_all(sock);
 260             return(sock);
 261           }
 262           
 263 mday  1.1 
 264           // static class members (windows only )
 265           #ifdef _WIN32
 266            int slp_client::_winsock_count = 0;
 267            WSADATA slp_client::_wsa_data ;
 268           #endif 
 269           
 270 mday  1.2 
 271           // insert new node at the back of the list 
 272           template<class L> void slp2_list<L>::insert(L *element)
 273 mday  1.1 {
 274             slp2_list *ins = new slp2_list(false);
 275             ins->_rep = element;
 276 mday  1.2   ins->_next = this;
 277             ins->_prev = this->_prev;
 278             this->_prev->_next = ins;
 279             this->_prev = ins;
 280 mday  1.1   _count++;
 281             return;
 282           }
 283           
 284           
 285           template<class L> inline L *slp2_list<L>::next(L * init) 
 286           {
 287             if( init == NULL )
 288               _cur = _next;
 289             else {
 290               assert( init = _cur->_rep );
 291               _cur = _cur->_next;
 292             }
 293             return(_cur->_rep);
 294           }
 295           
 296           template<class L> inline L *slp2_list<L>::prev( L * init  )
 297           {
 298             if( init == NULL ) 
 299               _cur = _next;
 300             else {
 301 mday  1.1     assert( init = _cur->rep ) ;
 302               _cur = _cur->_prev;
 303             }
 304             return(_cur->_rep);
 305           }
 306           
 307           template<class L> inline int slp2_list<L>::count(void) { return(_count) ; }
 308           
 309           template<class L> void slp2_list<L>::empty_list(void) 
 310           {
 311             while( _count > 0 ) {
 312               slp2_list *temp = _next;
 313               temp->unlink();
 314               if(temp->_rep != NULL)
 315                 delete temp->_rep;
 316               delete temp;
 317               _count--;
 318             }
 319             assert(_count == 0);
 320             return;
 321           }
 322 mday  1.1 
 323           
 324           template<class L> L *slp2_list<L>::remove( void )
 325           {
 326             L *ret = NULL;
 327             if( _count > 0 ) {
 328               slp2_list *temp = _next;
 329               temp->unlink();
 330               ret = temp->_rep;
 331               // unhinge ret from temp so it doesn't get destroyed 
 332               temp->_rep = NULL ;
 333               delete temp;
 334               _count--;
 335             }
 336             return(ret);
 337           }
 338           
 339 mday  1.2 
 340           template<class L> L *slp2_list<L>::remove(Sint8 *key)
 341           {
 342             L *ret = NULL;
 343             if( _count > 0 ) {
 344               slp2_list *temp = _next;
 345               while ( temp->_isHead == false ) {
 346                 if( temp->_rep->operator==( key )) {
 347           	temp->unlink();
 348           	ret = temp->_rep;
 349           	temp->_rep = NULL;
 350           	delete temp;
 351           	_count--;
 352           	break;
 353                 }
 354                 temp = temp->_next;
 355               }
 356             }
 357             return(ret);
 358           }
 359           
 360 mday  1.2 
 361           template<class L> Boolean slp2_list<L>::exists(Sint8 *key)
 362           {
 363             if( _count > 0) {
 364               slp2_list *temp = _next;
 365               while(temp->_isHead == false ) {
 366                 if( temp->_rep->operator==( key ))
 367           	return(true);
 368                 temp = temp->_next;
 369               }
 370             }
 371             return(false);
 372           }
 373           
 374           
 375 mday  1.1 da_list::~da_list()
 376           {
 377             //  unlink();
 378 mday  1.2   delete[] url;
 379             delete[] scope;
 380             delete[] attr;
 381             delete[] spi;
 382             delete[] auth;
 383 mday  1.1 }
 384           
 385           
 386 mday  1.2 Boolean da_list::operator ==(const Sint8 *key) const
 387           {
 388             if( ! strcasecmp(url, key) ) 
 389               return(true);
 390             return(false);
 391           }
 392 mday  1.1 
 393           rply_list::~rply_list()
 394           {
 395             //  unlink();
 396 mday  1.2   delete[] url;
 397             delete[] auth;
 398           }
 399           
 400           
 401           Boolean rply_list::operator ==(const Sint8 *key ) const 
 402           {
 403             if (! strcasecmp(url, key) )
 404               return(true);
 405             return(false);
 406           }
 407           
 408           
 409           reg_list::~reg_list()
 410           {
 411             delete[] url;
 412             delete[] attributes;
 413             delete[] service_type;
 414             delete[] scopes;
 415           }
 416           
 417 mday  1.2 
 418           Boolean reg_list::operator ==(const Sint8 *key ) const
 419           {
 420             if( ! strcasecmp(url, key) )
 421               return(true);
 422             return(false);
 423 mday  1.1 }
 424           
 425           
 426           void slp_client::set_target_addr(const Sint8 *addr)
 427           {
 428             if(addr == NULL)
 429               _target_addr = inet_addr("239.255.255.253") ;
 430             else 
 431               _target_addr = inet_addr(addr);
 432           }
 433           
 434           void slp_client::set_local_interface(const Sint8 *iface)
 435           {
 436           
 437             if(iface == NULL)
 438               _local_addr = INADDR_ANY;
 439             else
 440               _local_addr = inet_addr(iface);
 441           }
 442           
 443           void slp_client::set_spi(const Sint8 *spi) 
 444 mday  1.1 {
 445             if(_spi != NULL) 
 446               free(_spi);
 447             if(spi != NULL)
 448               _spi = strdup(spi);
 449             else 
 450               _spi = NULL;
 451             return ;
 452           }
 453           
 454           slp_client::slp_client(const Sint8 *target_addr, 
 455           		       const Sint8 *local_addr, 
 456           		       Uint16 target_port, 
 457           		       const Sint8 *spi )
 458           
 459 mday  1.2   : _pr_buf_len(0), _buf_len (LSLP_MTU), _version((Uint8)1), 
 460               _xid(1),  _target_port(target_port), _spi(NULL), _use_das(false),
 461               _last_da_cycle(0), _retries(3), _ttl(255),  _convergence(1), 
 462               _crypto_context(NULL), das( ), replies( ), regs( )
 463 mday  1.1 
 464           {
 465             set_target_addr(target_addr);
 466             set_local_interface(local_addr);
 467             set_spi(spi);
 468 mday  1.2   _pr_buf = new Sint8[LSLP_MTU];
 469             _msg_buf = new Sint8[LSLP_MTU] ; 
 470             _rcv_buf = new Sint8[LSLP_MTU] ;
 471 mday  1.1   _tv.tv_sec = 1;
 472             _tv.tv_usec = 0;
 473           #ifdef _WIN32
 474             if(_winsock_count == 0)
 475               WSAStartup(0x0002, &_wsa_data);
 476             _winsock_count++;
 477           #endif 
 478 mday  1.2 
 479             // initialize the recieve socket 
 480             _rcv_sock = slp_open_listen_sock( );
 481 mday  1.1 }
 482           
 483           
 484           slp_client::~slp_client()
 485           {
 486 mday  1.2   // close the receive socket 
 487           
 488           
 489           #ifdef _WIN32
 490             _winsock_count--;
 491             if(_winsock_count == 0)
 492               WSACleanup();
 493           #endif 
 494           
 495             delete _pr_buf;;
 496             delete _msg_buf;
 497             delete _rcv_buf;
 498 mday  1.1   if(_spi != NULL)
 499               free(_spi);
 500             if(_crypto_context != NULL)
 501               free(_crypto_context);
 502             das.empty_list();
 503             replies.empty_list();
 504 mday  1.2 
 505 mday  1.1 }
 506           
 507           
 508           void slp_client::prepare_pr_buf(const Sint8 *a)
 509           {
 510             if(a == NULL)
 511               return;;
 512             if(_pr_buf_len > 0) 
 513               *(_pr_buf + _pr_buf_len - 1) = ',' ;
 514             do {
 515               *(_pr_buf + _pr_buf_len) = *a;
 516               a++;
 517               _pr_buf_len++;
 518             }while((*a != 0x00) && (_pr_buf_len < LSLP_MTU - 1)); 
 519             _pr_buf_len++;
 520           }
 521           
 522           Boolean slp_client::prepare_query( Uint16 xid,
 523           				const Sint8 *service_type,
 524           				const Sint8 *scopes, 
 525           				const Sint8 *predicate  ) 
 526 mday  1.1 {
 527             Sint16 len, total_len;
 528             Sint8 *bptr;
 529             if(_msg_buf == NULL || _pr_buf == NULL)
 530               return(false);
 531             if(xid != _xid) {
 532               /* this is a new request */
 533               memset(_pr_buf, 0x00, LSLP_MTU);
 534               _pr_buf_len = 0;
 535               _xid = xid;
 536             }
 537             memset(_msg_buf, 0x00, LSLP_MTU);
 538             bptr = _msg_buf;
 539             _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
 540             _LSLP_SETFUNCTION(bptr, LSLP_SRVRQST);
 541             /* we don't know the length yet */
 542             _LSLP_SETFLAGS(bptr, LSLP_FLAGS_MCAST);
 543             _LSLP_SETXID(bptr, xid);
 544             _LSLP_SETLAN(bptr, LSLP_EN_US);
 545             bptr += ( total_len = _LSLP_HDRLEN(bptr) ) ;
 546               
 547 mday  1.1   if(_pr_buf_len + total_len < LSLP_MTU) {
 548               /* set the pr list length */
 549               _LSLP_SETSHORT(bptr, (len = _pr_buf_len), 0);
 550               if(len)
 551                 memcpy(bptr + 2, _pr_buf, len);
 552               total_len += ( 2 + len );
 553               bptr += (2 + len);
 554           		
 555               if(service_type == NULL)
 556                 len = DA_SRVTYPELEN;
 557               else
 558                 len = strlen(service_type) + 1;
 559               if(total_len + 2 + len < LSLP_MTU) {
 560                 /* set the service type string length */
 561                 _LSLP_SETSHORT(bptr, len, 0);
 562                 if(service_type != NULL)
 563           	memcpy(bptr + 2, service_type, len);
 564                 else
 565           	memcpy(bptr + 2, DA_SRVTYPE, len);
 566           	  	  
 567                 total_len += (2 + len);
 568 mday  1.1       bptr += (2 + len);
 569           
 570                 /* set the scope len and scope type, advance the buffer */
 571           	  
 572                 if(scopes == NULL)
 573           	len = DA_SCOPELEN;
 574                 else
 575           	len = strlen(scopes) + 1;
 576                 if( total_len + 2 + len < LSLP_MTU) {
 577           	_LSLP_SETSHORT(bptr, len, 0);
 578           	if(scopes != NULL) 
 579           	  memcpy(bptr + 2, scopes, len);
 580           	else
 581           	  memcpy(bptr + 2, DA_SCOPE, DA_SCOPELEN);
 582           
 583           	total_len += ( 2 + len);
 584           	bptr += (2 + len);
 585           
 586           	/* stuff the predicate if there is one  */
 587           	if(predicate == NULL)
 588           	  len = 0;
 589 mday  1.1 	else
 590           	  len = strlen(predicate) + 1;
 591           	if( total_len + 2 + len < LSLP_MTU) {
 592           	  _LSLP_SETSHORT(bptr, len, 0);
 593           	  if(predicate != NULL)
 594           	    memcpy(bptr + 2, predicate, len);
 595           	      
 596           	  total_len += (2 + len);
 597           	  bptr += (2 + len);
 598           	      
 599           	  /* stuff the spi */
 600           	      
 601           	  /* set the spi len and spi string */
 602           	  if(_spi == NULL)
 603           	    len = 0;
 604           	  else
 605           	    len = strlen(_spi) + 1;
 606           	      
 607           	  if(total_len + 2 + len < LSLP_MTU) {
 608           	    _LSLP_SETSHORT(bptr, len, 0);
 609           		
 610 mday  1.1 	    if(_spi != NULL)
 611           	      memcpy(bptr + 2, _spi, len);
 612           		
 613           	    total_len += ( 2 + len);
 614           	    bptr += (2 + len);
 615           	    assert(total_len == bptr - _msg_buf);
 616           	    /* now go back and set the length for the entire message */
 617           	    _LSLP_SETLENGTH(_msg_buf, total_len );
 618           	    return(true);
 619           	  } /* room for the spi  */
 620           	} /*  room for predicate  */
 621                 } /* room for the scope  */
 622               } /* room for the service type  */
 623             } /* room for the pr list  */
 624             return(false);
 625           }
 626           
 627           
 628           rply_list *slp_client::get_response( void  )
 629           {
 630             
 631 mday  1.1   rply_list *ret = replies.remove();
 632             return(ret);
 633           }
 634           
 635           
 636           int slp_client::find_das(const Sint8 *predicate, 
 637           			 const Sint8 *scopes)
 638           {
 639             converge_srv_req(NULL, predicate, scopes);
 640 mday  1.2   time(&_last_da_cycle);
 641             if(0 < das.count() )
 642               _use_das = true;
 643             else
 644               _use_das = false;
 645 mday  1.1   return( das.count( ) );
 646           }
 647           
 648           int slp_client::converge_srv_req( const Sint8 *type, 
 649           				  const Sint8 *predicate, 
 650           				  const Sint8 *scopes)
 651           {
 652           
 653             Uint32 old_addr = _target_addr;
 654             set_target_addr( "239.255.255.253" ) ;
 655             srv_req( type, predicate, scopes ) ;
 656             _target_addr = old_addr;
 657             
 658             return( replies.count( ) );
 659           }
 660           
 661           
 662           void slp_client::srv_req( const Sint8 *type, 
 663           			  const Sint8 *predicate, 
 664           			  const Sint8 *scopes)
 665           {
 666 mday  1.1   if ((true == prepare_query( _xid + 1, type, scopes, predicate ))) {
 667               replies.empty_list();
 668               Uint16 convergence = _convergence;
 669               if(convergence-- > 0) { _LSLP_SETFLAGS( _msg_buf, LSLP_FLAGS_MCAST) ; }
 670               send_rcv_udp(  ) ;
 671               while(convergence-- > 0) {
 672                 _LSLP_SLEEP( _tv.tv_usec / 1000 ) ;
 673                 if(prepare_query( _xid, type, scopes, predicate)) {
 674           	_LSLP_SETFLAGS(_msg_buf, LSLP_FLAGS_MCAST) ;
 675           	send_rcv_udp( );
 676                 }
 677               }
 678               /* if this was a multicast request try it on the local machine too  */
 679               if(_convergence) {
 680                 /* save current settings  */
 681                 Sint8 convergence_save = _convergence;
 682                 Uint32 target_save = _target_addr;
 683                 _convergence = 0;
 684                 _target_addr = inet_addr("127.0.0.1" ) ;
 685                 if ((true == prepare_query( _xid + 1, type, scopes, predicate ))) {
 686           	_LSLP_SETFLAGS( _msg_buf, 0 );
 687 mday  1.1 	send_rcv_udp(  );
 688                 }
 689                 /* restore current settings  */
 690                 _convergence = convergence_save;
 691                 _target_addr = target_save;
 692               } /* if we need to do the query on the local machine  */
 693             } /* prepared query  */
 694             memset( _msg_buf, 0x00, LSLP_MTU);
 695             return ;
 696           }
 697           
 698           void slp_client::decode_reply( struct sockaddr_in *remote )
 699           {
 700             
 701 mday  1.2   if( _xid == _LSLP_GETXID( _rcv_buf ))
 702               prepare_pr_buf( inet_ntoa(remote->sin_addr) );
 703           
 704             Sint8 function = _LSLP_GETFUNCTION( _rcv_buf );
 705             switch(function) {
 706             case LSLP_DAADVERT:
 707               decode_daadvert( remote );
 708               return;		
 709             case LSLP_SRVRPLY:
 710               decode_srvrply( remote );
 711               return;
 712             case LSLP_SRVACK:
 713             default:
 714               break;
 715             }
 716 mday  1.1   return;
 717           }
 718           
 719           
 720           void slp_client::decode_srvrply( struct sockaddr_in *remote )
 721           {
 722             Sint8 *bptr;
 723             Sint16 str_len, err, count;
 724             Sint32 total_len, purported_len;
 725           
 726 mday  1.2   bptr = _rcv_buf;
 727 mday  1.1   purported_len = _LSLP_GETLENGTH(bptr);
 728             bptr += (total_len = _LSLP_HDRLEN(bptr));
 729             if(total_len < purported_len) {
 730               rply_list *reply = new rply_list();
 731               if(reply == NULL) abort();
 732               err = _LSLP_GETSHORT(bptr, 0);
 733               count = _LSLP_GETSHORT(bptr, 2);
 734               bptr += 4;
 735               total_len += 4;
 736               /* loop on the url entries  */
 737               while( ( total_len <= purported_len ) && ( count > 0 ) && reply != NULL ) {
 738                 reply->function = LSLP_SRVRPLY;
 739                 reply->err = err;
 740                 reply->lifetime = _LSLP_GETSHORT(bptr, 1);
 741                 total_len += (5 + (str_len = _LSLP_GETSHORT(bptr, 3)));
 742                 if(total_len <= purported_len) {
 743           	Sint8 num_auths;
 744           	if(str_len > 0) {
 745 mday  1.2 	  reply->url = new Sint8[str_len + 1];
 746           	  memcpy(reply->url, bptr + 5, str_len);
 747           	  *((reply->url) + str_len) = 0x00;
 748 mday  1.1 	  bptr += (5 + str_len);
 749           	  reply->auth_blocks = (num_auths = _LSLP_GETBYTE(bptr, 0));
 750           	  total_len += 1;
 751           	  bptr += 1;
 752           	  while(num_auths && (total_len <= purported_len )) {
 753           	    /* iterate past the authenticators for now  */
 754           	    /* need extra code here to authenticate url entries  */
 755           	    total_len += (str_len = _LSLP_GETSHORT(bptr, 2));
 756           	    bptr += str_len;
 757           	    num_auths--;
 758           	  }
 759 mday  1.2 	  // handling duplicate responses is really inefficient, and we're 
 760           	  // not helping things out by checking for dupes this late in the game
 761           	  // however, in order to get to any further urls that may be in the
 762           	  // reply buffer we need to unstuff it anyway. So we are optimizing
 763           	  // for the case where there are no dupes. 
 764           	  if( false == replies.exists(reply->url) ) {
 765           	    strcpy(&(reply->remote[0]), inet_ntoa( remote->sin_addr )) ;
 766           	    replies.insert(reply);
 767           	  } else { delete reply ; }
 768 mday  1.1 	  count--;
 769           	  if((total_len <= purported_len) && (count > 0) )
 770           	    reply = new rply_list( ); 
 771           	  else 
 772           	    reply = NULL;
 773           	} else { delete reply;  reply = NULL ; } /* bad packet */
 774                 } else { delete reply;  reply = NULL ; }  /*  bad packet */
 775               } // while unwrapping multi-response message  
 776             } /* if the hdr length field is consistent with reality */
 777             return;
 778           }
 779           
 780             
 781           void slp_client::decode_daadvert(struct sockaddr_in *remote)
 782           {
 783             Sint8 *bptr;
 784             Sint16 str_len;
 785             Sint32 total_len, purported_len;
 786           
 787 mday  1.2   bptr = _rcv_buf;
 788 mday  1.1   purported_len = _LSLP_GETLENGTH(bptr);
 789             bptr += (total_len = _LSLP_HDRLEN(bptr));
 790             if(total_len < purported_len) {
 791               da_list *adv = new da_list( );
 792               if(adv == NULL) abort();
 793           
 794               adv->function = LSLP_DAADVERT;
 795               adv->err = _LSLP_GETSHORT(bptr, 0);
 796               adv->stateless_boot = _LSLP_GETLONG(bptr, 2);
 797               total_len += (8 + (str_len = _LSLP_GETSHORT(bptr, 6)));
 798               if(total_len < purported_len) {
 799                 /* decode and capture the url  - note: this is a string, not a url-entry structure */
 800 mday  1.2       adv->url = new Sint8[str_len + 1] ;
 801                 memcpy(adv->url, bptr + 8, str_len);
 802                 *((adv->url) + str_len) = 0x00;
 803                 /* advance the pointer past the url string */
 804                 bptr += (str_len + 8);
 805                 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
 806                 if(total_len < purported_len) {
 807           	if(str_len > 0) {
 808           	  adv->scope = new Sint8[str_len + 1] ;
 809           	  memcpy(adv->scope, bptr + 2, str_len);
 810           	  *((adv->scope) + str_len) = 0x00;
 811           	}
 812           	/* advance the pointer past the scope string  */
 813           	bptr += (str_len + 2);
 814 mday  1.1 	total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
 815           	if(total_len < purported_len) {
 816           	  if(str_len > 0) {
 817 mday  1.2 	    adv->attr = new Sint8[str_len + 1] ;
 818           	    memcpy(adv->attr, bptr + 2, str_len);
 819           	    *((adv->attr) + str_len) = 0x00;
 820 mday  1.1 	  }
 821 mday  1.2 	  /* advance the pointer past the attr string */
 822 mday  1.1 	  bptr += (str_len + 2);
 823           	  total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
 824           	  if(total_len < purported_len) {
 825 mday  1.2 	    if(str_len > 0 ) {
 826           	      adv->spi = new Sint8[str_len + 1];
 827           	      memcpy(adv->spi, bptr + 2, str_len);
 828           	      *((adv->spi) + str_len) = 0x00;
 829           	    } /*  if there is an spi  */
 830           		
 831           	    /* advance the pointer past the spi string  */
 832 mday  1.1 	    bptr += (str_len + 2);
 833 mday  1.2 	    adv->auth_blocks = _LSLP_GETBYTE(bptr, 0);
 834           	    
 835           	    // if we already know about this da, remove the existing
 836           	    // entry from our cache and insert this new entry
 837           	    // maybe the stateless boot field changed or the da
 838           	    // supports new scopes, etc. 
 839           	    da_list * exists = das.remove(adv->url);
 840           	    delete exists;
 841           	      
 842           	    /* need code here to handle authenticated urls */
 843           	    strcpy(&(adv->remote[0]), inet_ntoa(remote->sin_addr)) ;
 844           	    das.insert(adv); 
 845           	    return;
 846           	  } /*  spi length field is consistent with hdr */
 847           	} /* attr length field is consistent with hdr */
 848                 } /*  scope length field is consistent with hdr */
 849 mday  1.1     } 
 850             }
 851             return;
 852           }
 853           
 854           
 855           Boolean slp_client::srv_reg(Sint8 *url,
 856           			 Sint8 *attributes,
 857           			 Sint8 *service_type,
 858           			 Sint8 *scopes,
 859           			 Sint16 lifetime) 
 860           {
 861             Sint32 len;
 862             Sint16 str_len;
 863             Sint8 *bptr;
 864           
 865           
 866             /* this is always a new request */
 867             memset( _pr_buf, 0x00, LSLP_MTU);
 868             _pr_buf_len = 0;
 869             _xid++ ;
 870 mday  1.1 
 871             memset(_msg_buf, 0x00, LSLP_MTU);
 872             bptr = _msg_buf;
 873             _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
 874             _LSLP_SETFUNCTION(bptr, LSLP_SRVREG);
 875             /* we don't know the length yet */
 876             _LSLP_SETXID(bptr, _xid);
 877             _LSLP_SETLAN(bptr, LSLP_EN_US);
 878             bptr += (len =  _LSLP_HDRLEN(bptr) ) ;
 879           	
 880             /* construct a url-entry  */
 881           
 882             _LSLP_SETSHORT(bptr, lifetime, 1);
 883             _LSLP_SETSHORT(bptr, (str_len = (strlen(url) + 1)), 3);
 884             len += (5 + str_len );
 885             if(len + 1 < LSLP_MTU ) {
 886               memcpy(bptr + 5, url, str_len);
 887               bptr += (5 + str_len);
 888               /* no auth blocks for now  */
 889               _LSLP_SETBYTE(bptr, 0x00, 0);
 890               bptr++;
 891 mday  1.1     len++;
 892               /* stuff the service type  */
 893               str_len = strlen(service_type) + 1;
 894               if(len + 2 + str_len < LSLP_MTU) {
 895                 _LSLP_SETSHORT(bptr, str_len, 0);
 896                 memcpy(bptr + 2, service_type, str_len);
 897                 bptr += (2 + str_len);
 898                 len += (2 + str_len);
 899                 /* stuff the scope list if there is one */
 900                 if(scopes == NULL)
 901           	str_len = 0;
 902                 else 
 903           	str_len = strlen(scopes) + 1;	  
 904                 if(str_len == 1)
 905           	str_len = 0;
 906                 if(len + 2 + str_len < LSLP_MTU) {
 907           	_LSLP_SETSHORT(bptr, str_len, 0);
 908           	if(str_len) 
 909           	  memcpy(bptr + 2, scopes, str_len);
 910           	      
 911           	len += (2 + str_len);
 912 mday  1.1 	bptr += (2 + str_len);
 913           	/* stuff the attribute string if there is one */
 914           	if(attributes == NULL)
 915           	  str_len = 0;
 916           	else
 917           	  str_len = strlen(attributes) + 1;
 918           	if(str_len == 1)
 919           	  str_len = 0;
 920           	if(len + 2 + str_len < LSLP_MTU) {
 921           	  _LSLP_SETSHORT(bptr, str_len, 0);
 922           	  if(str_len)
 923           	    memcpy(bptr + 2, attributes, str_len);
 924           		  
 925           	  len += ( 2 + str_len);
 926           	  bptr += (2 + str_len);
 927           
 928           	  /* no attribute auths for now */
 929           	  if(len + 1 < LSLP_MTU) {
 930           	    _LSLP_SETBYTE(bptr, 0x00, 0);
 931           	  }
 932           	  len += 1;
 933 mday  1.1 	  /* set the length field in the header */
 934           	  _LSLP_SETLENGTH( _msg_buf, len );
 935           	  if(true == send_rcv_udp(  )) {
 936 mday  1.2 	    if(LSLP_SRVACK == _LSLP_GETFUNCTION( _rcv_buf )) {
 937           	      if(0x0000 == _LSLP_GETSHORT( _rcv_buf, (_LSLP_HDRLEN( _rcv_buf )))) {
 938 mday  1.1 		memset(_msg_buf, 0x00, LSLP_MTU);
 939           		return(true); 
 940           	      }
 941           	    }
 942           	  }
 943           	} /* attribute string fits into buffer */
 944                 } /* scope string fits into buffer  */
 945               } /* service type fits into buffer  */
 946             } /* url fits into buffer  */
 947             memset( _msg_buf, 0x00, LSLP_MTU);
 948             return(false);
 949           }
 950           
 951           
 952           
 953           Boolean slp_client::send_rcv_udp( void )
 954           {
 955             SOCKET sock;
 956             struct sockaddr_in target, local;
 957             Boolean ccode = false;
 958             if(INVALID_SOCKET != (sock = socket(AF_INET, SOCK_DGRAM, 0))) {
 959 mday  1.1     int err = 1;
 960               setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err) );
 961           
 962               local.sin_family = AF_INET;
 963               local.sin_port = 0;
 964               local.sin_addr.s_addr = _local_addr;
 965               if(SOCKET_ERROR != bind(sock, (struct sockaddr *)&local, sizeof(local))) {
 966                 int bcast = ( (_LSLP_GETFLAGS(_msg_buf)) & LSLP_FLAGS_MCAST) ? 1 : 0 ;
 967                 if(bcast) {
 968           	if( (SOCKET_ERROR ==  _LSLP_SET_TTL(sock, _ttl) )  ||  
 969           	    (SOCKET_ERROR == setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const Sint8 *)&bcast, sizeof(bcast)))) {
 970           	  _LSLP_CLOSESOCKET(sock);
 971           	  return(false);
 972           	}
 973           	if(_local_addr != INADDR_ANY ) {
 974           	  struct sockaddr_in ma;
 975           	  memset(&ma, 0x00, sizeof(ma));
 976           	  ma.sin_addr.s_addr = _local_addr;
 977           	  if( (SOCKET_ERROR == setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&ma, sizeof(struct sockaddr_in))) ) {
 978           	    _LSLP_CLOSESOCKET(sock);
 979           	    return(false);
 980 mday  1.1 	  }
 981           	}
 982                 }
 983                 target.sin_family = AF_INET;
 984                 target.sin_port = htons(_target_port);
 985                 target.sin_addr.s_addr = _target_addr;
 986                 if(SOCKET_ERROR == (err = sendto(sock, 
 987           				       _msg_buf, 
 988           				       _LSLP_GETLENGTH(_msg_buf), 
 989           				       0, 
 990           				       (struct sockaddr *)&target, sizeof(target) ))) {
 991           	_LSLP_CLOSESOCKET(sock);
 992           	return(false);
 993                 } /* oops - error sending data */
 994 mday  1.2       if(bcast)
 995           	service_listener_wait(_convergence, sock, false) ;
 996                 else
 997           	service_listener_wait(_convergence, sock, true);
 998               } // bound the socket 
 999 mday  1.1     _LSLP_CLOSESOCKET(sock);
1000             } /*  got the socket */
1001             return(ccode);
1002           }
1003                
1004 mday  1.2 // must be called regularly to process responses 
1005           
1006           Sint32 slp_client::service_listener(void)
1007           {
1008             return service_listener((SOCKET) 0);
1009           }
1010           
1011           
1012           Sint32 slp_client::service_listener_wait(time_t wait, SOCKET extra_sock, Boolean one_only)
1013           {
1014             Sint32 rcv = 0;
1015             time_t now;
1016             time_t start = time(NULL);
1017           
1018             while( time(&now) && ((now - wait ) <= start )  ) {
1019               rcv += service_listener(extra_sock);
1020               if(rcv > 0)
1021                 if(one_only == true)
1022           	return(rcv);
1023               _LSLP_SLEEP(10);
1024             }
1025 mday  1.2   rcv += service_listener(extra_sock);
1026             return(rcv);
1027           }
1028           
1029           Sint32 slp_client::service_listener(SOCKET extra_sock )
1030           {
1031           
1032             fd_set fds;
1033             struct timeval tv = {0, 10}; 
1034             FD_ZERO(&fds);
1035             FD_SET(_rcv_sock, &fds);
1036             if(extra_sock)
1037               FD_SET( extra_sock, &fds);
1038             Sint32 err;
1039             do { 
1040               err = select(_rcv_sock > extra_sock ? _rcv_sock + 1: extra_sock + 1, &fds, NULL, NULL, &tv); 
1041             } while ( (err < 0 )&& (errno == EINTR)) ;
1042             if( 0 < err ) {
1043               struct sockaddr_in remote;
1044               int size = sizeof(remote);
1045               if(extra_sock && FD_ISSET(extra_sock, &fds) ) {
1046 karl  1.3 #ifdef PEGASUS_OS_HPUX
1047                 err = recvfrom(extra_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
1048           #else
1049 mday  1.2       err = recvfrom(extra_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, (socklen_t *)&size);
1050 karl  1.3 #endif
1051 mday  1.2       if(err && err != SOCKET_ERROR)
1052           	decode_reply( &remote );
1053               }
1054               if(FD_ISSET(_rcv_sock, &fds)) {
1055 karl  1.3 #ifdef PEGASUS_OS_HPUX
1056                 err = recvfrom(_rcv_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
1057           #else
1058 mday  1.2       err = recvfrom(_rcv_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, (socklen_t *)&size);
1059 karl  1.3 #endif
1060 mday  1.2       if(err && err != SOCKET_ERROR)
1061           	decode_reply( &remote );
1062               }
1063             }
1064             return(err);
1065           }
1066           
1067 mday  1.1 int slp_client::srv_reg_all( Sint8 *url,
1068           			     Sint8 *attributes,
1069           			     Sint8 *service_type,
1070           			     Sint8 *scopes,
1071           			     Sint16 lifetime)
1072           {
1073           
1074             assert(url != NULL && attributes != NULL && service_type != NULL && scopes != NULL);
1075             if(url == NULL || attributes == NULL || service_type == NULL || scopes == NULL )
1076               return(0);
1077               
1078             // see if we have built a cache of directory agents 
1079             if(  0 == das.count() ) {
1080               // we don't know of any directory agents - see if we can find some 
1081               if( 0 == find_das(NULL, scopes) )
1082                 return(0);
1083             }
1084           
1085             // unicast a srvreg to each da
1086             int registrations = 0;
1087             Uint32 target_addr_save = _target_addr;
1088 mday  1.1   int convergence_save = _convergence;
1089             _convergence = 0;
1090           
1091             da_list *da = das.next(NULL);
1092             while( da != NULL ) {
1093               set_target_addr(da->remote);
1094               if( true == srv_reg( url, attributes, service_type, scopes, lifetime) )
1095                 registrations++;
1096               da = das.next(da);;
1097             }
1098           
1099             /* now try to register with the local host  */
1100             set_target_addr("127.0.0.1");
1101             if(true == srv_reg( url, attributes, service_type, scopes, lifetime) )
1102               registrations++;
1103           
1104             _convergence = convergence_save;
1105             _target_addr = target_addr_save;
1106             
1107             return(registrations);
1108           }
1109 mday  1.1 
1110           
1111           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2