(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 mike  1.5 #include "slp.h"
  31           
  32           #ifdef PEGASUS_OS_TRU64
  33           # include <unistd.h>
  34           extern "C" void usleep(unsigned int);
  35           #endif
  36 mday  1.1 
  37           
  38           PEGASUS_USING_STD;
  39           
  40           PEGASUS_NAMESPACE_BEGIN
  41           
  42 mday  1.2 PEGASUS_EXPORT String slp_get_host_name(void)
  43 mday  1.1 {
  44 mday  1.2 
  45             String s = String();
  46             Sint8 *buf = new Sint8[255];
  47             if( 0 == gethostname(buf, 254) ) 
  48               s += buf;
  49             delete buf;
  50             return(s);
  51 mday  1.1 }
  52           
  53           
  54           #ifdef _WIN32
  55           PEGASUS_EXPORT int gethostbyname_r(const char *name, 
  56           		    struct hostent *resultbuf, 
  57           		    char *buf, 
  58           		    size_t bufsize, 
  59           		    struct hostent **result, 
  60           		    int *errnop) 
  61           {
  62             name = name;
  63             resultbuf = resultbuf;
  64             buf = buf;
  65             bufsize = bufsize;
  66             
  67             if(NULL == (*result = gethostbyname(name))) {
  68               *errnop = WSAGetLastError();
  69               return(-1);
  70             } 
  71             return(0);
  72 mday  1.1 }
  73           
  74           #endif
  75           
  76 mike  1.5 #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_TRU64)
  77 karl  1.3 
  78           PEGASUS_EXPORT int gethostbyname_r(const char *name, 
  79           		    struct hostent *resultbuf, 
  80           		    char *buf, 
  81           		    size_t bufsize, 
  82           		    struct hostent **result, 
  83           		    int *errnop) 
  84           {
  85             name = name;
  86             resultbuf = resultbuf;
  87             buf = buf;
  88             bufsize = bufsize;
  89             
  90             if(NULL == (*result = gethostbyname(name))) {
  91               *errnop = h_errno;
  92               return(-1);
  93             } 
  94             return(0);
  95           }
  96 mike  1.5 
  97 karl  1.3 #endif
  98           
  99 mday  1.4 PEGASUS_EXPORT void slp_get_addr_string_from_url(const Sint8 *url, String &addr) 
 100 mday  1.1 {
 101 mday  1.4   Sint8 *name = NULL;
 102             struct sockaddr_in a;
 103             if( get_addr_from_url( url, &a, NULL) ) {
 104               name = new Sint8 [ 255 ] ;
 105 mday  1.1 #ifdef _WIN32
 106 mday  1.4     _snprintf(name, 254, "%s:%d", inet_ntoa(a.sin_addr), ntohs(a.sin_port) );
 107 mday  1.1 #else
 108 mike  1.5 
 109           // ATTN: Mike Brasher: Hack to get built of TRU64:
 110           #ifdef PEGASUS_OS_TRU64
 111               sprintf(name, "%s:%d", inet_ntoa(a.sin_addr), ntohs(a.sin_port) );
 112           #else
 113 mday  1.4     snprintf(name, 254, "%s:%d", inet_ntoa(a.sin_addr), ntohs(a.sin_port) );
 114 mday  1.1 #endif
 115 mike  1.5 
 116           #endif
 117 mday  1.4     addr.clear();
 118               addr = name;
 119 mday  1.2     delete [] name;
 120 mday  1.1   }
 121 mday  1.4   return ;
 122           }
 123           
 124           PEGASUS_EXPORT void slp_get_host_string_from_url(const Sint8 *url, String &host) 
 125           {
 126             Sint8 *s;
 127             struct sockaddr_in addr;
 128             get_addr_from_url(url, &addr, &s );
 129             host.clear();
 130             host = s; 
 131             delete [] s;
 132             return ;
 133 mday  1.1 }
 134           
 135 mday  1.4 PEGASUS_EXPORT Boolean get_addr_from_url(const Sint8 *url, struct sockaddr_in *addr, Sint8 **host)
 136 mday  1.1 {
 137             Sint8 *bptr, *url_dup;
 138             Boolean ccode = false;
 139           
 140             // isolate the host field 
 141 mday  1.4   bptr = (url_dup = strdup(url));
 142 mday  1.1   if(bptr == NULL)
 143               return(false );
 144           
 145             while( (*bptr != '/') && (*bptr != 0x00) )
 146               bptr++;
 147           
 148             if(*bptr == '/' && *(bptr + 1) == '/') {
 149               Sint8 *endptr, *portptr;
 150               endptr = bptr + 2;
 151               while (*endptr != 0x00 && *endptr != '/' && *endptr != ';')
 152                 endptr++;
 153               *endptr = 0x00;
 154               portptr = (endptr - 1) ;
 155           
 156               while( ( portptr > ( bptr + 2 ) ) && ( *portptr != ':' ) )
 157                 portptr--;
 158           
 159               if( *portptr == ':') {
 160                 *portptr = 0x00;
 161                 portptr++;
 162               } else { portptr = NULL; }
 163 mday  1.1     
 164               // bptr points to the host name or address
 165               // portptr points to the port or is null
 166           
 167 mday  1.4     bptr += 2;
 168           
 169               if(host != NULL) {
 170                 *host = new Sint8[ strlen(bptr) + strlen(portptr) + 3] ;
 171                 strcpy(*host, bptr);
 172                 strcat(*host, ":");
 173                 strcat(*host, portptr);
 174               }
 175 mday  1.1     if (portptr != NULL)
 176                 addr->sin_port = htons( (Sint16)strtoul(portptr, NULL, 0) );
 177               else
 178                 addr->sin_port = 0x0000;
 179               addr->sin_family = AF_INET;
 180               
 181 mday  1.4 
 182 mday  1.1     addr->sin_addr.s_addr = inet_addr(bptr);
 183               if(addr->sin_addr.s_addr == INADDR_NONE) {
 184                 struct hostent *host;
 185                 struct hostent hostbuf;
 186                 Uint8 *temp ;
 187                 Uint32 result, err;
 188                 size_t hostbuflen = 256;
 189                 
 190                 // hopefully a hostname because dotted decimal notation was invalid
 191                 // look for the user@hostname production
 192                 Sint8 *userptr;
 193                 userptr = bptr;
 194                 while( (*userptr != 0x00 ) && (*userptr != '@' ) )
 195           	userptr++;
 196                 if( *userptr == '@' )
 197           	bptr = userptr + 1;
 198                 
 199                 temp = (Uint8 *)malloc(hostbuflen); 
 200                 if(temp != NULL) {
 201           	host = NULL;
 202 mike  1.5 	while(temp != NULL && (result = gethostbyname_r(bptr, &hostbuf, 
 203           	    (char *)temp, 
 204           	    hostbuflen, 
 205           	    &host, (int *)&err)) == ERANGE){
 206 mday  1.1 	  hostbuflen *= 2;
 207           	  temp = (Uint8 *)realloc(temp, hostbuflen);
 208           	}
 209           	if(host != NULL) {
 210           	  struct in_addr *ptr;
 211           	  if (((ptr = (struct in_addr *)*(host->h_addr_list)) != NULL ) ) {
 212           	    addr->sin_addr.s_addr = ptr->s_addr;
 213           	    ccode = true;
 214           	  }
 215           	}
 216           	free(temp);
 217                 } /* we allocated the temp buffer for gethostbyname */
 218               } else { ccode = true; } /* host field is not in a valid dotted decimal form */
 219             } /* isolated the host field in the url  */
 220             return(ccode);
 221           }
 222            
 223           
 224 mday  1.4 
 225           static int slp_get_local_interfaces(Uint32 **list)
 226           {
 227             SOCKET sock;
 228             int interfaces = 0;
 229           
 230             delete [] *list;
 231           
 232           #ifdef PEGASUS_OS_TYPE_WINDOWS
 233           
 234             if ( INVALID_SOCKET != ( sock  = WSASocket(AF_INET,
 235           					   SOCK_RAW, 0, NULL, 0, 0) ) ) {
 236               char *output_buf = new char[1024];
 237               DWORD buf_size = 1024, bytes_returned = 0;
 238           
 239               if ( 0 == WSAIoctl( sock, SIO_ADDRESS_LIST_QUERY, NULL, 0, 
 240           			output_buf, buf_size, &bytes_returned, NULL, NULL) ) {
 241                 socket_addr_list *addr_list = (socket_addr_list *)output_buf;
 242                 *list = new Uint32 [ addr_list->count + 1 ] ;
 243                 socket_addr *addr = addr_list->list;
 244                 Uint32 *intp;
 245 mday  1.4       sockaddr_in *sin;
 246                 for( interfaces = 0, intp = *list, sin = (sockaddr_in *)addr ; 
 247           	   interfaces < addr_list->count; 
 248           	   interfaces++ , intp++  ) {
 249           	*intp = sin->sin_addr.s_addr;
 250           	addr++;
 251           	sin = (sockaddr_in *)addr;
 252                 }
 253                 *intp = INADDR_ANY;
 254               }
 255               delete [] output_buf;
 256               _LSLP_CLOSESOCKET(sock);
 257             }
 258             
 259           #else
 260             if( -1 < (sock = socket(AF_INET, SOCK_DGRAM, 0) ) ) {
 261               struct ifconf conf;
 262           
 263               conf.ifc_buf = new char [ 128 * sizeof(struct ifreq )  ];
 264               conf.ifc_len = 128 * sizeof( struct ifreq ) ;
 265               if( -1 < ioctl(sock, SIOCGIFCONF, &conf ) ) {
 266 mday  1.4       
 267                 // count the interfaces 
 268           
 269           
 270                 struct ifreq *r = conf.ifc_req;
 271                 struct sockaddr_in *addr ;
 272                 addr = (struct sockaddr_in *)&r->ifr_addr;
 273                 while(  addr->sin_addr.s_addr != 0 ) {
 274           	interfaces++;
 275           	r++;
 276           	addr = (struct sockaddr_in *)&r->ifr_addr;
 277                 }
 278           
 279                 // now store the addresses
 280           
 281                 *list  = new Uint32 [interfaces + 1 ];
 282                 Uint32 *this_addr = *list;
 283                 r = conf.ifc_req;
 284                 addr = (struct sockaddr_in *)&r->ifr_addr;
 285                 while(  addr->sin_addr.s_addr != 0 ) {
 286           	*this_addr = addr->sin_addr.s_addr;
 287 mday  1.4 	r++;
 288           	this_addr++;
 289           	addr = (struct sockaddr_in *)&r->ifr_addr;
 290                 }
 291                 *this_addr = INADDR_ANY;
 292               } // did the ioctl 
 293               delete [] conf.ifc_buf;
 294               _LSLP_CLOSESOCKET(sock);
 295             } // opened the socket 
 296           
 297           #endif 
 298             // failsafe if the ioctl doesn't work
 299             if( interfaces == 0 ) {
 300               *list = new Uint32 [1] ;
 301               *list[0] = INADDR_ANY; 
 302             }
 303           
 304             return(interfaces);
 305           }
 306           
 307           
 308 mday  1.4 static Boolean  slp_join_multicast(SOCKET sock, Uint32 addr) 
 309 mday  1.2 {
 310             
 311             // don't join on the loopback interface
 312 mday  1.4   if (addr == inet_addr("127.0.0.1") )
 313 mday  1.2     return(false);
 314           
 315             struct ip_mreq mreq;
 316             mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.253");
 317 mday  1.4   mreq.imr_interface.s_addr = addr;
 318 mday  1.2   
 319             if(SOCKET_ERROR == setsockopt(sock,IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq))) 
 320               return(false);
 321             return(true);
 322           }
 323           
 324           
 325           
 326           static int slp_join_multicast_all(SOCKET sock)
 327           {
 328           
 329 mday  1.4   Uint32 *list = NULL , *lptr = NULL;
 330             int num_interfaces = slp_get_local_interfaces(&list);
 331             lptr = list;
 332             while ( *lptr != INADDR_ANY ) {
 333               slp_join_multicast(sock, *lptr) ;
 334               lptr++;
 335             }
 336             delete [] list;
 337 mday  1.2   return(num_interfaces);
 338           }
 339           
 340           
 341 mday  1.4 static SOCKET slp_open_listen_sock( void )
 342 mday  1.2 {
 343           
 344             SOCKET sock  = socket(AF_INET, SOCK_DGRAM, 0) ;
 345             int err = 1;
 346             setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err));
 347             struct sockaddr_in local;
 348             local.sin_family = AF_INET;
 349             local.sin_port = htons(427);
 350             local.sin_addr.s_addr  = INADDR_ANY;
 351 mday  1.4   if( 0 == bind(sock, (struct sockaddr *)&local, sizeof(local)) )
 352               slp_join_multicast_all(sock);
 353 mday  1.2   return(sock);
 354           }
 355           
 356 mday  1.1 
 357 mday  1.4 static Boolean slp_scope_intersection(const Sint8 *our_scopes, Sint8 *his_scopes)
 358           {
 359             const Sint8 delimiters [] = " ," ;
 360             Sint8 *saveptr = NULL, *bptr;
 361           
 362             if(our_scopes == NULL || his_scopes == NULL)
 363               return(true);
 364             bptr = _LSLP_STRTOK(his_scopes, delimiters, &saveptr);
 365             while (NULL != bptr) {
 366           
 367               // convert hist scope string  upper case
 368               for( Sint8 *cp = bptr; *cp; ++cp) {
 369                 if( 'a' <= *cp && *cp <= 'z' )
 370           	*cp += 'A' - 'a' ;
 371               }
 372           
 373               if( NULL != strstr( bptr , our_scopes) )
 374                 return(true);
 375               bptr = _LSLP_STRTOK(NULL, delimiters, &saveptr);
 376             }
 377             return(false);
 378 mday  1.4 }
 379           
 380           
 381 mday  1.1 // static class members (windows only )
 382           #ifdef _WIN32
 383            int slp_client::_winsock_count = 0;
 384            WSADATA slp_client::_wsa_data ;
 385           #endif 
 386           
 387 mday  1.2 
 388           // insert new node at the back of the list 
 389           template<class L> void slp2_list<L>::insert(L *element)
 390 mday  1.1 {
 391             slp2_list *ins = new slp2_list(false);
 392             ins->_rep = element;
 393 mday  1.2   ins->_next = this;
 394             ins->_prev = this->_prev;
 395             this->_prev->_next = ins;
 396             this->_prev = ins;
 397 mday  1.1   _count++;
 398             return;
 399           }
 400           
 401           
 402           template<class L> inline L *slp2_list<L>::next(L * init) 
 403           {
 404             if( init == NULL )
 405               _cur = _next;
 406             else {
 407 mike  1.5     assert( (init = _cur->_rep) != 0 );
 408 mday  1.1     _cur = _cur->_next;
 409             }
 410             return(_cur->_rep);
 411           }
 412           
 413           template<class L> inline L *slp2_list<L>::prev( L * init  )
 414           {
 415             if( init == NULL ) 
 416               _cur = _next;
 417             else {
 418               assert( init = _cur->rep ) ;
 419               _cur = _cur->_prev;
 420             }
 421             return(_cur->_rep);
 422           }
 423           
 424           template<class L> inline int slp2_list<L>::count(void) { return(_count) ; }
 425           
 426           template<class L> void slp2_list<L>::empty_list(void) 
 427           {
 428             while( _count > 0 ) {
 429 mday  1.1     slp2_list *temp = _next;
 430               temp->unlink();
 431               if(temp->_rep != NULL)
 432                 delete temp->_rep;
 433               delete temp;
 434               _count--;
 435             }
 436             assert(_count == 0);
 437             return;
 438           }
 439           
 440           
 441           template<class L> L *slp2_list<L>::remove( void )
 442           {
 443             L *ret = NULL;
 444             if( _count > 0 ) {
 445               slp2_list *temp = _next;
 446               temp->unlink();
 447               ret = temp->_rep;
 448               // unhinge ret from temp so it doesn't get destroyed 
 449               temp->_rep = NULL ;
 450 mday  1.1     delete temp;
 451               _count--;
 452             }
 453             return(ret);
 454           }
 455           
 456 mday  1.2 
 457           template<class L> L *slp2_list<L>::remove(Sint8 *key)
 458           {
 459             L *ret = NULL;
 460             if( _count > 0 ) {
 461               slp2_list *temp = _next;
 462               while ( temp->_isHead == false ) {
 463                 if( temp->_rep->operator==( key )) {
 464           	temp->unlink();
 465           	ret = temp->_rep;
 466           	temp->_rep = NULL;
 467           	delete temp;
 468           	_count--;
 469           	break;
 470                 }
 471                 temp = temp->_next;
 472               }
 473             }
 474             return(ret);
 475           }
 476           
 477 mday  1.2 
 478 mday  1.4 template<class L> L *slp2_list<L>::reference(Sint8 *key)
 479           {
 480             if( _count > 0 ) {
 481               slp2_list *temp = _next;
 482               while(temp->_isHead == false ) {
 483                 if( temp->_rep->operator==(key))
 484           	return(temp->_rep);
 485                 temp = temp->_next;
 486               }
 487             }
 488             return(NULL);
 489           }
 490           
 491 mday  1.2 template<class L> Boolean slp2_list<L>::exists(Sint8 *key)
 492           {
 493             if( _count > 0) {
 494               slp2_list *temp = _next;
 495               while(temp->_isHead == false ) {
 496                 if( temp->_rep->operator==( key ))
 497           	return(true);
 498                 temp = temp->_next;
 499               }
 500             }
 501             return(false);
 502           }
 503           
 504           
 505 mday  1.1 da_list::~da_list()
 506           {
 507             //  unlink();
 508 mday  1.2   delete[] url;
 509             delete[] scope;
 510             delete[] attr;
 511             delete[] spi;
 512             delete[] auth;
 513 mday  1.1 }
 514           
 515           
 516 mday  1.2 Boolean da_list::operator ==(const Sint8 *key) const
 517           {
 518             if( ! strcasecmp(url, key) ) 
 519               return(true);
 520             return(false);
 521           }
 522 mday  1.1 
 523           rply_list::~rply_list()
 524           {
 525             //  unlink();
 526 mday  1.2   delete[] url;
 527             delete[] auth;
 528           }
 529           
 530           
 531           Boolean rply_list::operator ==(const Sint8 *key ) const 
 532           {
 533             if (! strcasecmp(url, key) )
 534               return(true);
 535             return(false);
 536           }
 537           
 538           
 539 mday  1.4 reg_list::reg_list(Sint8 *r_url, 
 540           		   Sint8 *r_attributes, 
 541           		   Sint8 *r_service_type, 
 542           		   Sint8 *r_scopes, 
 543           		   time_t r_lifetime)
 544           {
 545             if( r_url != NULL ) {
 546               url = new Sint8[ strlen(r_url + 1 ) ];
 547               strcpy(url, r_url);
 548             }
 549           
 550             if( r_attributes != NULL ) {
 551               attributes = new Sint8[ strlen(r_attributes) + 1 ];
 552               strcpy(attributes, r_attributes);
 553             }
 554           
 555             if(r_service_type != NULL ) {
 556               service_type = new Sint8[ strlen(r_service_type) + 1 ]; 
 557               strcpy(service_type, r_service_type);
 558             }
 559           
 560 mday  1.4   if(r_scopes != NULL) {
 561               scopes = new Sint8[ strlen(r_scopes ) + 1 ];
 562               strcpy(scopes, r_scopes);
 563             }
 564             lifetime = r_lifetime;
 565           
 566           }
 567           
 568 mday  1.2 reg_list::~reg_list()
 569           {
 570             delete[] url;
 571             delete[] attributes;
 572             delete[] service_type;
 573             delete[] scopes;
 574           }
 575           
 576           
 577           Boolean reg_list::operator ==(const Sint8 *key ) const
 578           {
 579             if( ! strcasecmp(url, key) )
 580               return(true);
 581             return(false);
 582 mday  1.1 }
 583           
 584 mday  1.4 url_entry::url_entry( Uint16 u_lifetime,
 585           		      Sint8 *u_url, 
 586           		      Uint8 u_num_auths,
 587           		      Uint8 *u_auth_blocks)
 588           {
 589           
 590             lifetime = u_lifetime;
 591             if(u_url != NULL && (len = strlen(u_url) )) {
 592               len++;
 593               url = new Sint8[len];
 594               strcpy(url, u_url);
 595             } else { len = 0 ; }
 596           
 597             num_auths = 0;
 598             auth_blocks = NULL;
 599           }
 600           
 601           url_entry::~url_entry() 
 602           {
 603             delete [] url;
 604             delete [] auth_blocks;
 605 mday  1.4 }
 606           
 607           
 608           Boolean url_entry::operator ==(const Sint8 *key) const
 609           {
 610             if( ! strcasecmp(url, key) )
 611               return(true);
 612             return(false);
 613           }
 614           
 615 mday  1.1 
 616           void slp_client::set_target_addr(const Sint8 *addr)
 617           {
 618             if(addr == NULL)
 619               _target_addr = inet_addr("239.255.255.253") ;
 620             else 
 621               _target_addr = inet_addr(addr);
 622           }
 623           
 624           void slp_client::set_local_interface(const Sint8 *iface)
 625           {
 626           
 627             if(iface == NULL)
 628               _local_addr = INADDR_ANY;
 629             else
 630               _local_addr = inet_addr(iface);
 631           }
 632           
 633           void slp_client::set_spi(const Sint8 *spi) 
 634           {
 635 mday  1.4   delete [] _spi;
 636             if(spi != NULL && strlen(spi) ) {
 637               _spi = new Sint8[strlen(spi) + 1 ];
 638               strcpy(_spi, spi);
 639             }
 640 mday  1.1   return ;
 641           }
 642           
 643 mday  1.4 void slp_client::set_scopes(const Sint8 *scopes)
 644           {
 645             delete [] _scopes;
 646             if( scopes != NULL && strlen(scopes) ) {
 647               _scopes = new Sint8[ strlen(scopes) + 1 ];
 648               strcpy(_scopes, scopes);
 649             }
 650             return;
 651           }
 652           
 653 mday  1.1 slp_client::slp_client(const Sint8 *target_addr, 
 654           		       const Sint8 *local_addr, 
 655           		       Uint16 target_port, 
 656 mday  1.4 		       const Sint8 *spi, 
 657           		       const Sint8 *scopes )
 658 mday  1.1 
 659 mday  1.2   : _pr_buf_len(0), _buf_len (LSLP_MTU), _version((Uint8)1), 
 660 mday  1.4     _xid(1),  _target_port(htons(target_port)), _local_addr_list(NULL), 
 661               _spi(NULL), _scopes(NULL),  _use_das(false), _last_da_cycle(0), _retries(3), 
 662               _ttl(255),  _convergence(5), _crypto_context(NULL), das( ), 
 663               replies( ), regs( )
 664 mday  1.1 
 665           {
 666             set_target_addr(target_addr);
 667             set_local_interface(local_addr);
 668             set_spi(spi);
 669 mday  1.4   set_scopes(scopes);
 670 mday  1.2   _pr_buf = new Sint8[LSLP_MTU];
 671             _msg_buf = new Sint8[LSLP_MTU] ; 
 672             _rcv_buf = new Sint8[LSLP_MTU] ;
 673 mday  1.4   _tv.tv_sec = 0;
 674             _tv.tv_usec = 200000;
 675 mday  1.1 #ifdef _WIN32
 676             if(_winsock_count == 0)
 677               WSAStartup(0x0002, &_wsa_data);
 678             _winsock_count++;
 679           #endif 
 680 mday  1.2 
 681 mday  1.4   // build our local address list
 682             slp_get_local_interfaces( &_local_addr_list ) ;
 683           
 684             // before opening the listen socket we need to see if the local machine is a da
 685             // if it is, don't open the listen socket
 686             _rcv_sock = INVALID_SOCKET;
 687             local_srv_req(NULL, NULL, "DEFAULT");
 688             if(0 < das.count() )
 689               _rcv_sock = INVALID_SOCKET;
 690             else
 691               _rcv_sock = slp_open_listen_sock( );
 692 mday  1.1 }
 693           
 694           
 695           slp_client::~slp_client()
 696           {
 697 mday  1.2   // close the receive socket 
 698 mday  1.4   _LSLP_CLOSESOCKET( _rcv_sock ) ;
 699 mday  1.2 #ifdef _WIN32
 700             _winsock_count--;
 701             if(_winsock_count == 0)
 702               WSACleanup();
 703           #endif 
 704           
 705 mday  1.4   delete [] _pr_buf;
 706             delete [] _msg_buf;
 707             delete [] _rcv_buf;
 708             delete [] _local_addr_list;
 709             delete [] _spi;
 710             delete [] _scopes;
 711           
 712 mday  1.1   if(_crypto_context != NULL)
 713               free(_crypto_context);
 714             das.empty_list();
 715             replies.empty_list();
 716           }
 717           
 718           
 719           void slp_client::prepare_pr_buf(const Sint8 *a)
 720           {
 721             if(a == NULL)
 722               return;;
 723             if(_pr_buf_len > 0) 
 724               *(_pr_buf + _pr_buf_len - 1) = ',' ;
 725             do {
 726               *(_pr_buf + _pr_buf_len) = *a;
 727               a++;
 728               _pr_buf_len++;
 729             }while((*a != 0x00) && (_pr_buf_len < LSLP_MTU - 1)); 
 730             _pr_buf_len++;
 731           }
 732           
 733 mday  1.1 Boolean slp_client::prepare_query( Uint16 xid,
 734           				const Sint8 *service_type,
 735           				const Sint8 *scopes, 
 736           				const Sint8 *predicate  ) 
 737           {
 738             Sint16 len, total_len;
 739             Sint8 *bptr;
 740             if(_msg_buf == NULL || _pr_buf == NULL)
 741               return(false);
 742             if(xid != _xid) {
 743               /* this is a new request */
 744               memset(_pr_buf, 0x00, LSLP_MTU);
 745               _pr_buf_len = 0;
 746               _xid = xid;
 747             }
 748             memset(_msg_buf, 0x00, LSLP_MTU);
 749             bptr = _msg_buf;
 750             _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
 751             _LSLP_SETFUNCTION(bptr, LSLP_SRVRQST);
 752             /* we don't know the length yet */
 753 mday  1.4   _LSLP_SETFLAGS(bptr, 0);
 754 mday  1.1   _LSLP_SETXID(bptr, xid);
 755             _LSLP_SETLAN(bptr, LSLP_EN_US);
 756             bptr += ( total_len = _LSLP_HDRLEN(bptr) ) ;
 757               
 758             if(_pr_buf_len + total_len < LSLP_MTU) {
 759               /* set the pr list length */
 760               _LSLP_SETSHORT(bptr, (len = _pr_buf_len), 0);
 761               if(len)
 762                 memcpy(bptr + 2, _pr_buf, len);
 763               total_len += ( 2 + len );
 764               bptr += (2 + len);
 765           		
 766               if(service_type == NULL)
 767                 len = DA_SRVTYPELEN;
 768               else
 769                 len = strlen(service_type) + 1;
 770               if(total_len + 2 + len < LSLP_MTU) {
 771                 /* set the service type string length */
 772                 _LSLP_SETSHORT(bptr, len, 0);
 773                 if(service_type != NULL)
 774           	memcpy(bptr + 2, service_type, len);
 775 mday  1.1       else
 776           	memcpy(bptr + 2, DA_SRVTYPE, len);
 777           	  	  
 778                 total_len += (2 + len);
 779                 bptr += (2 + len);
 780           
 781                 /* set the scope len and scope type, advance the buffer */
 782           	  
 783                 if(scopes == NULL)
 784           	len = DA_SCOPELEN;
 785                 else
 786           	len = strlen(scopes) + 1;
 787                 if( total_len + 2 + len < LSLP_MTU) {
 788           	_LSLP_SETSHORT(bptr, len, 0);
 789           	if(scopes != NULL) 
 790           	  memcpy(bptr + 2, scopes, len);
 791           	else
 792           	  memcpy(bptr + 2, DA_SCOPE, DA_SCOPELEN);
 793           
 794           	total_len += ( 2 + len);
 795           	bptr += (2 + len);
 796 mday  1.1 
 797           	/* stuff the predicate if there is one  */
 798           	if(predicate == NULL)
 799           	  len = 0;
 800           	else
 801           	  len = strlen(predicate) + 1;
 802           	if( total_len + 2 + len < LSLP_MTU) {
 803           	  _LSLP_SETSHORT(bptr, len, 0);
 804           	  if(predicate != NULL)
 805           	    memcpy(bptr + 2, predicate, len);
 806           	      
 807           	  total_len += (2 + len);
 808           	  bptr += (2 + len);
 809           	      
 810           	  /* stuff the spi */
 811           	      
 812           	  /* set the spi len and spi string */
 813           	  if(_spi == NULL)
 814           	    len = 0;
 815           	  else
 816           	    len = strlen(_spi) + 1;
 817 mday  1.1 	      
 818           	  if(total_len + 2 + len < LSLP_MTU) {
 819           	    _LSLP_SETSHORT(bptr, len, 0);
 820           		
 821           	    if(_spi != NULL)
 822           	      memcpy(bptr + 2, _spi, len);
 823           		
 824           	    total_len += ( 2 + len);
 825           	    bptr += (2 + len);
 826           	    assert(total_len == bptr - _msg_buf);
 827           	    /* now go back and set the length for the entire message */
 828           	    _LSLP_SETLENGTH(_msg_buf, total_len );
 829           	    return(true);
 830           	  } /* room for the spi  */
 831           	} /*  room for predicate  */
 832                 } /* room for the scope  */
 833               } /* room for the service type  */
 834             } /* room for the pr list  */
 835             return(false);
 836           }
 837           
 838 mday  1.1 
 839           rply_list *slp_client::get_response( void  )
 840           {
 841             
 842 mday  1.4   return(replies.remove());
 843 mday  1.1 }
 844           
 845           
 846           int slp_client::find_das(const Sint8 *predicate, 
 847           			 const Sint8 *scopes)
 848           {
 849             converge_srv_req(NULL, predicate, scopes);
 850 mday  1.2   time(&_last_da_cycle);
 851             if(0 < das.count() )
 852               _use_das = true;
 853             else
 854               _use_das = false;
 855 mday  1.1   return( das.count( ) );
 856           }
 857           
 858 mday  1.4 
 859           // smart interface to slp discovery. uses das if they are present, 
 860           // convergence otherwise.
 861           // periodically forces an active da discovery cycle 
 862           
 863           void slp_client::discovery_cycle ( const Sint8 *type, 
 864           				   const Sint8 *predicate, 
 865           				   const Sint8 *scopes) 
 866           
 867           {
 868             // see if we have built a cache of directory agents 
 869             if(  0 == das.count() ) {
 870               // we don't know of any directory agents - see if we need to do active da discovery
 871               if( ((time(NULL)) - _last_da_cycle ) > (60 * 5) )
 872                 find_das(NULL, scopes) ;
 873             }
 874           
 875             // if there are das, unicast a srvreq to each da
 876           
 877             if( 0 < das.count() ) {
 878           
 879 mday  1.4     da_list *da = das.next(NULL);
 880               struct sockaddr_in addr;
 881               while( da != NULL ) {
 882                 addr.sin_port = htons(427);
 883                 addr.sin_family = AF_INET;
 884                 addr.sin_addr.s_addr = inet_addr(da->remote);
 885                 unicast_srv_req(type, predicate, scopes, &addr);
 886                 da = das.next(da);
 887               }
 888             } else {
 889               // do a convergence request because we don't have any das to use 
 890           
 891               converge_srv_req(type, predicate, scopes );
 892             }
 893             return; 
 894           }
 895           
 896           // this request MUST be retried <_convergence> times on EACH interface 
 897           // regardless of how many responses we have received 
 898           // it can be VERY time consuming but is the most thorough 
 899           // discovery method 
 900 mday  1.4 void slp_client::converge_srv_req( const Sint8 *type, 
 901           				   const Sint8 *predicate, 
 902           				   const Sint8 *scopes)
 903           {
 904           
 905             Uint32 old_target_addr = _target_addr;
 906             Uint32 old_local_addr = _local_addr;
 907             set_target_addr( "239.255.255.253" ) ;
 908             
 909             Uint32 *p_addr = _local_addr_list;
 910             Uint16 convergence; 
 911             Uint32 loopback = inet_addr("127.0.0.1");
 912           
 913             do {
 914               if( *p_addr == loopback ) {
 915                 p_addr++;
 916                 continue; 
 917               }
 918               _local_addr = *p_addr;
 919               convergence = _convergence;
 920           
 921 mday  1.4     if(prepare_query( _xid + 1, type, scopes, predicate)) {
 922           	_LSLP_SETFLAGS(_msg_buf, LSLP_FLAGS_MCAST) ;
 923           	send_rcv_udp( );
 924                 }
 925           
 926               while(--convergence > 0) {
 927                 if(prepare_query( _xid, type, scopes, predicate)) {
 928           	_LSLP_SETFLAGS(_msg_buf, LSLP_FLAGS_MCAST) ;
 929           	send_rcv_udp( );
 930                 }
 931               }
 932               p_addr++;
 933             }   while( *p_addr != INADDR_ANY ) ;
 934           
 935           
 936             // always try a local request
 937             local_srv_req(type, predicate, scopes);
 938           
 939             _target_addr = old_target_addr;
 940             _local_addr = old_local_addr;
 941             return ;
 942 mday  1.4 }
 943           
 944           
 945           
 946           // this request will be retried MAX <_retries> times 
 947           // but will always end when the first response is received
 948           // This request is best when using a directory agent
 949           void slp_client::unicast_srv_req( const Sint8 *type, 
 950 mday  1.1 				  const Sint8 *predicate, 
 951 mday  1.4 				  const Sint8 *scopes, 
 952           				  struct sockaddr_in *addr )
 953           {
 954           
 955             Uint32 target_addr_save, local_addr_save;
 956             Uint16 target_port_save;
 957             struct timeval tv_save;
 958             
 959             target_addr_save = _target_addr;
 960             local_addr_save = _local_addr;
 961             target_port_save = _target_port;
 962           
 963             tv_save.tv_sec = _tv.tv_sec;
 964             _tv.tv_sec = 1;
 965             
 966             // let the host decide which interface to use 
 967             _local_addr = INADDR_ANY; 
 968             _target_addr = addr->sin_addr.s_addr;
 969             _target_port = addr->sin_port;
 970           
 971             
 972 mday  1.4   int retries = _retries ;
 973             int old_count = replies.count() ;
 974             srv_req(type, predicate, scopes, false) ;
 975             while( --retries > 0 && replies.count() == old_count ) {
 976               srv_req(type, predicate, scopes, true );
 977             }
 978             _target_addr = target_addr_save;
 979             _local_addr = local_addr_save;
 980             _target_port = target_port_save;
 981             _tv.tv_sec = tv_save.tv_sec;
 982             return;
 983           }
 984           
 985           // this request is targeted to the loopback interface, 
 986           // and has a tiny wait timer. It should be resolved quickly. 
 987           // It will never be retried.
 988           void slp_client::local_srv_req( const Sint8 *type, 
 989           				const Sint8 *predicate, 
 990           				const Sint8 *scopes )
 991           
 992           
 993 mday  1.1 {
 994           
 995 mday  1.4   Uint32 target_addr_save;
 996             struct timeval tv_save;
 997             
 998             target_addr_save = _target_addr;
 999           
1000             tv_save.tv_sec = _tv.tv_sec;
1001             tv_save.tv_usec = _tv.tv_usec;
1002             _tv.tv_sec = 0;
1003             _tv.tv_usec = 1000000;
1004             
1005             // let the host decide which interface to use 
1006             _local_addr = INADDR_ANY; 
1007             _target_addr = inet_addr("127.0.0.1");
1008             _target_port = htons(427);
1009           
1010 mday  1.1   
1011 mday  1.4   srv_req(type, predicate, scopes, false) ;
1012           
1013             _target_addr = target_addr_save;
1014           
1015             _tv.tv_sec = tv_save.tv_sec;
1016             _tv.tv_usec = tv_save.tv_usec;
1017             return;
1018           
1019 mday  1.1 }
1020           
1021           
1022 mday  1.4 // workhorse request function
1023 mday  1.1 void slp_client::srv_req( const Sint8 *type, 
1024           			  const Sint8 *predicate, 
1025 mday  1.4 			  const Sint8 *scopes, 
1026           			  Boolean retry )
1027 mday  1.1 {
1028 mday  1.4   if ((true == prepare_query( (retry == true) ? _xid : _xid + 1, 
1029           			      type, 
1030           			      scopes, 
1031           			      predicate ))) {
1032 mday  1.1     send_rcv_udp(  ) ;
1033             } /* prepared query  */
1034             return ;
1035           }
1036           
1037 mday  1.4 void slp_client::decode_msg( struct sockaddr_in *remote )
1038 mday  1.1 {
1039             
1040 mday  1.2   if( _xid == _LSLP_GETXID( _rcv_buf ))
1041               prepare_pr_buf( inet_ntoa(remote->sin_addr) );
1042           
1043             Sint8 function = _LSLP_GETFUNCTION( _rcv_buf );
1044             switch(function) {
1045             case LSLP_DAADVERT:
1046               decode_daadvert( remote );
1047               return;		
1048 mday  1.4   case LSLP_SRVRQST:
1049               decode_srvreq( remote );
1050               return;
1051 mday  1.2   case LSLP_SRVRPLY:
1052               decode_srvrply( remote );
1053               return;
1054             case LSLP_SRVACK:
1055             default:
1056               break;
1057             }
1058 mday  1.1   return;
1059           }
1060           
1061           
1062           void slp_client::decode_srvrply( struct sockaddr_in *remote )
1063           {
1064             Sint8 *bptr;
1065             Sint16 str_len, err, count;
1066             Sint32 total_len, purported_len;
1067           
1068 mday  1.2   bptr = _rcv_buf;
1069 mday  1.1   purported_len = _LSLP_GETLENGTH(bptr);
1070             bptr += (total_len = _LSLP_HDRLEN(bptr));
1071             if(total_len < purported_len) {
1072               rply_list *reply = new rply_list();
1073               if(reply == NULL) abort();
1074               err = _LSLP_GETSHORT(bptr, 0);
1075               count = _LSLP_GETSHORT(bptr, 2);
1076               bptr += 4;
1077               total_len += 4;
1078               /* loop on the url entries  */
1079               while( ( total_len <= purported_len ) && ( count > 0 ) && reply != NULL ) {
1080                 reply->function = LSLP_SRVRPLY;
1081                 reply->err = err;
1082                 reply->lifetime = _LSLP_GETSHORT(bptr, 1);
1083                 total_len += (5 + (str_len = _LSLP_GETSHORT(bptr, 3)));
1084                 if(total_len <= purported_len) {
1085           	Sint8 num_auths;
1086           	if(str_len > 0) {
1087 mday  1.2 	  reply->url = new Sint8[str_len + 1];
1088           	  memcpy(reply->url, bptr + 5, str_len);
1089           	  *((reply->url) + str_len) = 0x00;
1090 mday  1.1 	  bptr += (5 + str_len);
1091           	  reply->auth_blocks = (num_auths = _LSLP_GETBYTE(bptr, 0));
1092           	  total_len += 1;
1093           	  bptr += 1;
1094           	  while(num_auths && (total_len <= purported_len )) {
1095           	    /* iterate past the authenticators for now  */
1096           	    /* need extra code here to authenticate url entries  */
1097           	    total_len += (str_len = _LSLP_GETSHORT(bptr, 2));
1098           	    bptr += str_len;
1099           	    num_auths--;
1100           	  }
1101 mday  1.2 	  // handling duplicate responses is really inefficient, and we're 
1102           	  // not helping things out by checking for dupes this late in the game
1103           	  // however, in order to get to any further urls that may be in the
1104           	  // reply buffer we need to unstuff it anyway. So we are optimizing
1105           	  // for the case where there are no dupes. 
1106           	  if( false == replies.exists(reply->url) ) {
1107           	    strcpy(&(reply->remote[0]), inet_ntoa( remote->sin_addr )) ;
1108           	    replies.insert(reply);
1109           	  } else { delete reply ; }
1110 mday  1.1 	  count--;
1111           	  if((total_len <= purported_len) && (count > 0) )
1112           	    reply = new rply_list( ); 
1113           	  else 
1114           	    reply = NULL;
1115           	} else { delete reply;  reply = NULL ; } /* bad packet */
1116                 } else { delete reply;  reply = NULL ; }  /*  bad packet */
1117               } // while unwrapping multi-response message  
1118             } /* if the hdr length field is consistent with reality */
1119             return;
1120           }
1121           
1122             
1123           void slp_client::decode_daadvert(struct sockaddr_in *remote)
1124           {
1125             Sint8 *bptr;
1126             Sint16 str_len;
1127             Sint32 total_len, purported_len;
1128           
1129 mday  1.2   bptr = _rcv_buf;
1130 mday  1.1   purported_len = _LSLP_GETLENGTH(bptr);
1131             bptr += (total_len = _LSLP_HDRLEN(bptr));
1132             if(total_len < purported_len) {
1133               da_list *adv = new da_list( );
1134               if(adv == NULL) abort();
1135           
1136               adv->function = LSLP_DAADVERT;
1137               adv->err = _LSLP_GETSHORT(bptr, 0);
1138               adv->stateless_boot = _LSLP_GETLONG(bptr, 2);
1139               total_len += (8 + (str_len = _LSLP_GETSHORT(bptr, 6)));
1140               if(total_len < purported_len) {
1141                 /* decode and capture the url  - note: this is a string, not a url-entry structure */
1142 mday  1.2       adv->url = new Sint8[str_len + 1] ;
1143                 memcpy(adv->url, bptr + 8, str_len);
1144                 *((adv->url) + str_len) = 0x00;
1145                 /* advance the pointer past the url string */
1146                 bptr += (str_len + 8);
1147                 total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
1148                 if(total_len < purported_len) {
1149           	if(str_len > 0) {
1150           	  adv->scope = new Sint8[str_len + 1] ;
1151           	  memcpy(adv->scope, bptr + 2, str_len);
1152           	  *((adv->scope) + str_len) = 0x00;
1153           	}
1154           	/* advance the pointer past the scope string  */
1155           	bptr += (str_len + 2);
1156 mday  1.1 	total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
1157           	if(total_len < purported_len) {
1158           	  if(str_len > 0) {
1159 mday  1.2 	    adv->attr = new Sint8[str_len + 1] ;
1160           	    memcpy(adv->attr, bptr + 2, str_len);
1161           	    *((adv->attr) + str_len) = 0x00;
1162 mday  1.1 	  }
1163 mday  1.2 	  /* advance the pointer past the attr string */
1164 mday  1.1 	  bptr += (str_len + 2);
1165           	  total_len += (2 + (str_len = _LSLP_GETSHORT(bptr, 0)));
1166           	  if(total_len < purported_len) {
1167 mday  1.2 	    if(str_len > 0 ) {
1168           	      adv->spi = new Sint8[str_len + 1];
1169           	      memcpy(adv->spi, bptr + 2, str_len);
1170           	      *((adv->spi) + str_len) = 0x00;
1171           	    } /*  if there is an spi  */
1172           		
1173           	    /* advance the pointer past the spi string  */
1174 mday  1.1 	    bptr += (str_len + 2);
1175 mday  1.2 	    adv->auth_blocks = _LSLP_GETBYTE(bptr, 0);
1176           	    
1177           	    // if we already know about this da, remove the existing
1178           	    // entry from our cache and insert this new entry
1179           	    // maybe the stateless boot field changed or the da
1180           	    // supports new scopes, etc. 
1181           	    da_list * exists = das.remove(adv->url);
1182           	    delete exists;
1183           	      
1184           	    /* need code here to handle authenticated urls */
1185           	    strcpy(&(adv->remote[0]), inet_ntoa(remote->sin_addr)) ;
1186           	    das.insert(adv); 
1187           	    return;
1188           	  } /*  spi length field is consistent with hdr */
1189           	} /* attr length field is consistent with hdr */
1190                 } /*  scope length field is consistent with hdr */
1191 mday  1.1     } 
1192             }
1193             return;
1194           }
1195           
1196           
1197 mday  1.4 void slp_client::decode_srvreq(struct sockaddr_in *remote )
1198           {
1199             
1200             Sint8 *bptr;
1201             Sint16 str_len, err = LSLP_PARSE_ERROR ;
1202             Sint32 total_len, purported_len;
1203           		    time_t current;
1204             
1205             bptr = _rcv_buf;
1206             purported_len = _LSLP_GETLENGTH(bptr);
1207             bptr += (total_len = _LSLP_HDRLEN(bptr));
1208             if(total_len < purported_len) {
1209               if( 0 < regs.count() ) {
1210                 // advance past the slp v2 header
1211                 // get the previous responder list 
1212                 str_len = _LSLP_GETSHORT(bptr, 0);
1213                 if ( (str_len + total_len + 2 < purported_len )) {
1214           	if( false == slp_previous_responder( (str_len ? bptr + 2 : NULL ) )) {
1215           	  Sint8 *service_type = NULL;
1216           	  Sint8 *scopes = NULL;
1217           	  Sint8 *spi = NULL;
1218 mday  1.4 	  slp2_list<url_entry> url_list ;
1219           
1220           	  bptr += 2 + str_len;
1221           	  total_len += 2 + str_len;
1222           	  // extract the service type string 
1223           	  str_len = _LSLP_GETSHORT(bptr, 0);
1224           	  if(str_len && (str_len + total_len + 2 < purported_len )) {
1225           	    service_type = new Sint8[str_len + 1]; // one extra byte 
1226           	    strcpy(service_type, bptr + 2);
1227           
1228           	    // set the error code to zero 
1229           	    err = 0; 
1230           	    bptr += 2 + str_len;
1231           	    total_len += 2 + str_len;
1232           
1233           	    // extract the scope list
1234           
1235           	    str_len = _LSLP_GETSHORT(bptr, 0);
1236           	    if( str_len + total_len + 2 < purported_len) {
1237           	      if(str_len > 0 ) {
1238           		scopes = new Sint8[str_len + 1] ; // one extra byte
1239 mday  1.4 		strcpy(scopes, bptr + 2);
1240           	      }
1241           
1242           	      // see if the requested scopes intersect with our scopes 
1243           
1244           	      if (true == slp_scope_intersection(_scopes, scopes) ) {
1245           
1246           		bptr += 2 + str_len;
1247           		total_len += 2 + str_len;
1248           
1249           		// this is a very lightweight client and currently 
1250           		// doesn't support predicate evaluation. 
1251           		// we will answer srvreq messages with no predicate
1252           		// however, if there is a predicate, we can't evaluate it
1253           		// so we won't answer it. 
1254           
1255           		// extract the predicate
1256           		str_len = _LSLP_GETSHORT(bptr, 0) ;
1257           		if(str_len == 0 ) {
1258           		  // ignore the spi for now. 
1259           		  // look for a srvtype match 
1260 mday  1.4 
1261           		  reg_list *reg = regs.next(NULL);
1262           		  while( reg != 0 ) {
1263           		    // check the lifetime 
1264           
1265           		    if( (current = time(NULL)) > reg->lifetime ) {
1266           		      // this guy is stale, unlink him and start over 
1267           		      regs.remove(reg->url);
1268           		      delete reg;
1269           		      reg = regs.next(NULL);
1270           		      continue;
1271           		    }
1272           		    if( ! strcasecmp( reg->service_type, service_type ) ) {
1273           		      // found a match
1274           		      
1275           
1276           
1277           
1278           		      url_entry *entry = new url_entry((reg->lifetime - time(NULL) ), 
1279           						       reg->url ) ;
1280           		      url_list.insert(entry);
1281 mday  1.4 		    }
1282           		    reg = regs.next(reg);
1283           		  } // traversing list
1284           
1285           		} // if there is no predicate 
1286           	      } // scopes intersect 
1287           	    } // scope string fits
1288           	  } // svc type string fits
1289           	  
1290           	  Boolean mcast = ( ((_LSLP_GETFLAGS( _rcv_buf )) & (LSLP_FLAGS_MCAST) ) ? true : false   ) ;
1291           	  if(mcast == false || url_list.count() ) {
1292           
1293           	    // we need to respond to this message
1294           	    
1295           	    _LSLP_SETVERSION(_msg_buf, LSLP_PROTO_VER);
1296           	    _LSLP_SETFUNCTION(_msg_buf, LSLP_SRVRPLY);
1297           	    // skip the length for now
1298           	    _LSLP_SETFLAGS(_msg_buf, 0);
1299           	    _LSLP_SETNEXTEXT(_msg_buf, 0, LSLP_NEXT_EX);
1300           	    _LSLP_SETXID( _msg_buf, ( _LSLP_GETXID(_rcv_buf)  )  );
1301           	    _LSLP_SETLAN(_msg_buf, LSLP_EN_US );
1302 mday  1.4 	    Sint32 msg_len = _LSLP_HDRLEN(_msg_buf);
1303           	    Sint8 *bptr = _msg_buf + msg_len;
1304           	    _LSLP_SETSHORT(bptr, err, 0);
1305           	    _LSLP_SETSHORT( bptr, url_list.count() , 2 );
1306           	    
1307           	    bptr += 4;
1308           	    msg_len += 4;
1309           	    while ( 0 < url_list.count() ) {
1310           	      url_entry *entry = url_list.remove() ;
1311           	      assert(entry != NULL);
1312           
1313           	      // check the length 
1314           	      if ( (msg_len + 6 + entry->len ) <= LSLP_MTU ) {
1315           		_LSLP_SETSHORT(bptr, entry->lifetime, 1);
1316           		_LSLP_SETSHORT(bptr, entry->len, 3);
1317           		memcpy(bptr + 5, entry->url, entry->len);
1318           
1319           		bptr += (5 + entry->len );
1320           		msg_len += (5 + entry->len); 
1321           
1322           		// for now don't support authentication
1323 mday  1.4 		_LSLP_SETBYTE(bptr, 0, 0);
1324           		bptr++;
1325           		msg_len++;
1326           	      
1327           	      } else  {   
1328           		// set the overvlow flag because we ran out of room 
1329           		// also decrement the count of urls
1330           		// possibly a subsequent url will fit so kee going 
1331           		_LSLP_SETFLAGS(_msg_buf,  LSLP_FLAGS_OVERFLOW);
1332           		Sint8 *save = bptr;
1333           		bptr = _msg_buf + _LSLP_HDRLEN(_msg_buf) ;
1334           		_LSLP_SETSHORT(bptr, ( _LSLP_GETSHORT(bptr, 2) - 1 ) , 2 );
1335           		bptr = save;
1336           	      }
1337           	      delete entry;
1338           	    }
1339           
1340           	    // ok, now we can set the length
1341           	    _LSLP_SETLENGTH(_msg_buf, msg_len );
1342           
1343           	    // _msg_buf is stuffed with the service reply. now we need 
1344 mday  1.4 	    // to allocate a socket and send it back to the requesting node 
1345           	    SOCKET sock;
1346           	    if(INVALID_SOCKET != (sock = socket(AF_INET, SOCK_DGRAM, 0))) {
1347           	      int err = 1;
1348           	      setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err) );
1349           	      struct sockaddr_in local;
1350           	      local.sin_family = AF_INET;
1351           	      local.sin_port = _target_port ; 
1352           	      local.sin_addr.s_addr = _local_addr;
1353           	      if(SOCKET_ERROR != bind(sock, (struct sockaddr *)&local, sizeof(local))) {
1354           		sendto(sock, _msg_buf, msg_len , 0, 
1355           		      (struct sockaddr *)remote, sizeof(struct sockaddr_in )) ;
1356           	      } // successfully bound this socket 
1357           	      _LSLP_CLOSESOCKET(sock);
1358           	    } // successfully opened this socket
1359           	  } // we must respond to this request 
1360           	  delete [] spi; 
1361           	  delete [] scopes;
1362           	  delete [] service_type; 
1363           	} // not on the pr list 
1364                 } // pr list length is consistent 
1365 mday  1.4     } // if there are local registrations
1366             } // if length is consistent
1367           }
1368           
1369           
1370 mday  1.1 Boolean slp_client::srv_reg(Sint8 *url,
1371           			 Sint8 *attributes,
1372           			 Sint8 *service_type,
1373           			 Sint8 *scopes,
1374           			 Sint16 lifetime) 
1375           {
1376             Sint32 len;
1377             Sint16 str_len;
1378             Sint8 *bptr;
1379           
1380           
1381             /* this is always a new request */
1382             memset( _pr_buf, 0x00, LSLP_MTU);
1383             _pr_buf_len = 0;
1384             _xid++ ;
1385           
1386             memset(_msg_buf, 0x00, LSLP_MTU);
1387             bptr = _msg_buf;
1388             _LSLP_SETVERSION(bptr, LSLP_PROTO_VER);
1389             _LSLP_SETFUNCTION(bptr, LSLP_SRVREG);
1390             /* we don't know the length yet */
1391 mday  1.1   _LSLP_SETXID(bptr, _xid);
1392             _LSLP_SETLAN(bptr, LSLP_EN_US);
1393             bptr += (len =  _LSLP_HDRLEN(bptr) ) ;
1394           	
1395             /* construct a url-entry  */
1396           
1397             _LSLP_SETSHORT(bptr, lifetime, 1);
1398             _LSLP_SETSHORT(bptr, (str_len = (strlen(url) + 1)), 3);
1399             len += (5 + str_len );
1400             if(len + 1 < LSLP_MTU ) {
1401               memcpy(bptr + 5, url, str_len);
1402               bptr += (5 + str_len);
1403               /* no auth blocks for now  */
1404               _LSLP_SETBYTE(bptr, 0x00, 0);
1405               bptr++;
1406               len++;
1407               /* stuff the service type  */
1408               str_len = strlen(service_type) + 1;
1409               if(len + 2 + str_len < LSLP_MTU) {
1410                 _LSLP_SETSHORT(bptr, str_len, 0);
1411                 memcpy(bptr + 2, service_type, str_len);
1412 mday  1.1       bptr += (2 + str_len);
1413                 len += (2 + str_len);
1414                 /* stuff the scope list if there is one */
1415                 if(scopes == NULL)
1416           	str_len = 0;
1417                 else 
1418           	str_len = strlen(scopes) + 1;	  
1419                 if(str_len == 1)
1420           	str_len = 0;
1421                 if(len + 2 + str_len < LSLP_MTU) {
1422           	_LSLP_SETSHORT(bptr, str_len, 0);
1423           	if(str_len) 
1424           	  memcpy(bptr + 2, scopes, str_len);
1425           	      
1426           	len += (2 + str_len);
1427           	bptr += (2 + str_len);
1428           	/* stuff the attribute string if there is one */
1429           	if(attributes == NULL)
1430           	  str_len = 0;
1431           	else
1432           	  str_len = strlen(attributes) + 1;
1433 mday  1.1 	if(str_len == 1)
1434           	  str_len = 0;
1435           	if(len + 2 + str_len < LSLP_MTU) {
1436           	  _LSLP_SETSHORT(bptr, str_len, 0);
1437           	  if(str_len)
1438           	    memcpy(bptr + 2, attributes, str_len);
1439           		  
1440           	  len += ( 2 + str_len);
1441           	  bptr += (2 + str_len);
1442           
1443           	  /* no attribute auths for now */
1444           	  if(len + 1 < LSLP_MTU) {
1445           	    _LSLP_SETBYTE(bptr, 0x00, 0);
1446           	  }
1447           	  len += 1;
1448           	  /* set the length field in the header */
1449           	  _LSLP_SETLENGTH( _msg_buf, len );
1450 mday  1.4 	  int retries = _retries;
1451           	  while( --retries ) {
1452           	    if(true == send_rcv_udp(  )) {
1453           	      if(LSLP_SRVACK == _LSLP_GETFUNCTION( _rcv_buf )) {
1454           		if(0x0000 == _LSLP_GETSHORT( _rcv_buf, (_LSLP_HDRLEN( _rcv_buf )))) {
1455           		  memset(_msg_buf, 0x00, LSLP_MTU);
1456           		  return(true); 
1457           		}
1458 mday  1.1 	      }
1459 mday  1.4 	    } // received a response 
1460           	  } // retrying the unicast 
1461 mday  1.1 	} /* attribute string fits into buffer */
1462                 } /* scope string fits into buffer  */
1463               } /* service type fits into buffer  */
1464             } /* url fits into buffer  */
1465             memset( _msg_buf, 0x00, LSLP_MTU);
1466             return(false);
1467           }
1468           
1469           
1470           
1471           Boolean slp_client::send_rcv_udp( void )
1472           {
1473             SOCKET sock;
1474             struct sockaddr_in target, local;
1475             Boolean ccode = false;
1476             if(INVALID_SOCKET != (sock = socket(AF_INET, SOCK_DGRAM, 0))) {
1477               int err = 1;
1478               setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&err, sizeof(err) );
1479           
1480               local.sin_family = AF_INET;
1481               local.sin_port = 0;
1482 mday  1.1     local.sin_addr.s_addr = _local_addr;
1483               if(SOCKET_ERROR != bind(sock, (struct sockaddr *)&local, sizeof(local))) {
1484                 int bcast = ( (_LSLP_GETFLAGS(_msg_buf)) & LSLP_FLAGS_MCAST) ? 1 : 0 ;
1485                 if(bcast) {
1486           	if( (SOCKET_ERROR ==  _LSLP_SET_TTL(sock, _ttl) )  ||  
1487           	    (SOCKET_ERROR == setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const Sint8 *)&bcast, sizeof(bcast)))) {
1488           	  _LSLP_CLOSESOCKET(sock);
1489           	  return(false);
1490           	}
1491           	if(_local_addr != INADDR_ANY ) {
1492           	  struct sockaddr_in ma;
1493           	  memset(&ma, 0x00, sizeof(ma));
1494           	  ma.sin_addr.s_addr = _local_addr;
1495           	  if( (SOCKET_ERROR == setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&ma, sizeof(struct sockaddr_in))) ) {
1496           	    _LSLP_CLOSESOCKET(sock);
1497           	    return(false);
1498           	  }
1499           	}
1500                 }
1501                 target.sin_family = AF_INET;
1502 mday  1.4       target.sin_port = _target_port;
1503 mday  1.1       target.sin_addr.s_addr = _target_addr;
1504                 if(SOCKET_ERROR == (err = sendto(sock, 
1505           				       _msg_buf, 
1506           				       _LSLP_GETLENGTH(_msg_buf), 
1507           				       0, 
1508           				       (struct sockaddr *)&target, sizeof(target) ))) {
1509           	_LSLP_CLOSESOCKET(sock);
1510           	return(false);
1511                 } /* oops - error sending data */
1512 mday  1.4 
1513           
1514                 while ( 0 < service_listener( sock ) ) { ccode = true; }
1515           
1516 mday  1.2     } // bound the socket 
1517 mday  1.1     _LSLP_CLOSESOCKET(sock);
1518             } /*  got the socket */
1519             return(ccode);
1520           }
1521                
1522 mday  1.2 // must be called regularly to process responses 
1523           
1524           Sint32 slp_client::service_listener(void)
1525           {
1526             return service_listener((SOCKET) 0);
1527           }
1528           
1529           
1530           Sint32 slp_client::service_listener_wait(time_t wait, SOCKET extra_sock, Boolean one_only)
1531           {
1532             Sint32 rcv = 0;
1533             time_t now;
1534             time_t start = time(NULL);
1535           
1536             while( time(&now) && ((now - wait ) <= start )  ) {
1537               rcv += service_listener(extra_sock);
1538               if(rcv > 0)
1539                 if(one_only == true)
1540           	return(rcv);
1541 mike  1.5 
1542           #ifdef PEGASUS_OS_TRU64
1543               usleep(10 * 1000);
1544           #else
1545 mday  1.2     _LSLP_SLEEP(10);
1546 mike  1.5 #endif
1547 mday  1.2   }
1548             rcv += service_listener(extra_sock);
1549             return(rcv);
1550           }
1551           
1552           Sint32 slp_client::service_listener(SOCKET extra_sock )
1553           {
1554           
1555 mday  1.4   struct timeval tv; 
1556 mday  1.2   fd_set fds;
1557             FD_ZERO(&fds);
1558 mday  1.4   if(_rcv_sock != INVALID_SOCKET) {
1559               FD_SET(_rcv_sock, &fds);
1560             }
1561 mday  1.2   if(extra_sock)
1562               FD_SET( extra_sock, &fds);
1563             Sint32 err;
1564             do { 
1565 mday  1.4     tv.tv_sec = _tv.tv_sec;
1566               tv.tv_usec = _tv.tv_usec;
1567 mday  1.2     err = select(_rcv_sock > extra_sock ? _rcv_sock + 1: extra_sock + 1, &fds, NULL, NULL, &tv); 
1568             } while ( (err < 0 )&& (errno == EINTR)) ;
1569             if( 0 < err ) {
1570               struct sockaddr_in remote;
1571 mday  1.4 
1572 mike  1.5 #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_TRU64)
1573 mday  1.2     int size = sizeof(remote);
1574 karl  1.3 #else
1575 mday  1.4     socklen_t size = sizeof(remote);
1576 karl  1.3 #endif
1577 mday  1.4 
1578               if(extra_sock && FD_ISSET(extra_sock, &fds) )
1579                 err = recvfrom(extra_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
1580               if(_rcv_sock != INVALID_SOCKET) {
1581                 if(FD_ISSET(_rcv_sock, &fds)) 
1582           	err = recvfrom(_rcv_sock, _rcv_buf, LSLP_MTU, 0, (struct sockaddr *)&remote, &size);
1583 mday  1.2     }
1584 mday  1.4 
1585               if(err && err != SOCKET_ERROR)
1586                 decode_msg( &remote );
1587             } 
1588             if (err == SOCKET_ERROR) {
1589               // our interfaces could be disconnected or we could be a laptop that 
1590               // just got pulled from the network, etc. 
1591               _LSLP_CLOSESOCKET(_rcv_sock );
1592               if( 0 < slp_get_local_interfaces( & _local_addr_list ) ) {
1593                 if(_rcv_sock != INVALID_SOCKET)
1594                 	_rcv_sock = slp_open_listen_sock( );
1595 mday  1.2     }
1596 mday  1.4   } 
1597 mday  1.2   return(err);
1598           }
1599           
1600 mday  1.1 int slp_client::srv_reg_all( Sint8 *url,
1601           			     Sint8 *attributes,
1602           			     Sint8 *service_type,
1603           			     Sint8 *scopes,
1604           			     Sint16 lifetime)
1605           {
1606           
1607             assert(url != NULL && attributes != NULL && service_type != NULL && scopes != NULL);
1608             if(url == NULL || attributes == NULL || service_type == NULL || scopes == NULL )
1609               return(0);
1610               
1611             // see if we have built a cache of directory agents 
1612             if(  0 == das.count() ) {
1613 mday  1.4     // we don't know of any directory agents - see if we need to do active da discovery
1614               if( ((time(NULL)) - _last_da_cycle ) > (60 * 5) )
1615                 find_das(NULL, scopes) ;
1616 mday  1.1   }
1617           
1618 mday  1.4   // keep track of how many times we register
1619 mday  1.1   int registrations = 0;
1620 mday  1.4 
1621             // save target and convergence parameters 
1622 mday  1.1   Uint32 target_addr_save = _target_addr;
1623             int convergence_save = _convergence;
1624             _convergence = 0;
1625           
1626 mday  1.4   // if there are das, unicast a srvreg to each da
1627           
1628             if( 0 < das.count() ) {
1629           
1630               da_list *da = das.next(NULL);
1631               while( da != NULL ) {
1632                 set_target_addr(da->remote);
1633                 if( true == srv_reg( url, attributes, service_type, scopes, lifetime) )
1634           	registrations++;
1635                 da = das.next(da);;
1636               }
1637 mday  1.1   }
1638           
1639 mday  1.4   // restore parameters 
1640 mday  1.1   _convergence = convergence_save;
1641             _target_addr = target_addr_save;
1642             
1643 mday  1.4 
1644             // if we have registered with any das, act like a service agent and cache our
1645             // own registration. This provides a failsafe in case the DA is not available 
1646             srv_reg_local(url, attributes, service_type, scopes, lifetime);
1647             registrations++;
1648             
1649 mday  1.1   return(registrations);
1650           }
1651           
1652 mday  1.4 
1653           void  slp_client::srv_reg_local ( Sint8 *url,
1654           				  Sint8 *attributes, 
1655           				  Sint8 *service_type, 
1656           				  Sint8 *scopes, 
1657           				  Sint16 lifetime) 
1658           {
1659             reg_list *reg = NULL;
1660             // first see if the reg already exists. if it does, just update the lifetime
1661             if ( NULL != (reg = regs.reference(url))) {
1662               reg->lifetime = lifetime + time(NULL);
1663             } else {  // new reg 
1664               reg = new reg_list(url, attributes, service_type, scopes, (lifetime + time(NULL)));
1665               regs.insert(reg);
1666             }
1667             return;
1668           }
1669           
1670           Boolean slp_client::slp_previous_responder(Sint8 *pr_list)
1671           {
1672           
1673 mday  1.4   Sint8 *a, *s = NULL;
1674             Uint32 addr, *list_addr;
1675             if(pr_list == NULL || 0 == strlen(pr_list))
1676               return(false);
1677           
1678             a = _LSLP_STRTOK(pr_list, ",", &s);
1679             while(NULL != a ) {
1680               if(INADDR_NONE != (addr = inet_addr(a))) {
1681                 list_addr = _local_addr_list;
1682                 while( INADDR_ANY != *list_addr ) {
1683           	if(*list_addr == addr)
1684           	  return(true);
1685           	list_addr++;
1686                 }
1687               }
1688               a = _LSLP_STRTOK(NULL, ",", &s);
1689             }
1690             return(false);
1691           }
1692 mday  1.1 
1693           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2