unsigned short SLPGetRefreshInterval() {
	slp_handle_impl_t *hp;	/* SLP handle for this request */
	SLPError err;		/* any SLPError */
	char *reply = NULL;	/* reply from slpd */
	void *collator = NULL;	/* attr collation handle */
	int mr = 0;		/* max results placeholder */
	unsigned short max = 0;	/* max interval result cookie */
	char *msg = NULL;	/* attrrqst msg */
	char hostname[MAXHOSTNAMELEN];	/* name of this host */

	if ((err = SLPOpen("en", SLP_FALSE, (void **)&hp)) != SLP_OK) {
	    slp_err(LOG_INFO, 0, "SLPGetRefreshInterval",
		    "Could not get SLPHandle: %s", slp_strerror(err));
	    return (0);
	}

	/* tag this as an internal call */
	hp->internal_call = SLP_TRUE;

	/* scope is name of this host */
	(void) gethostname(hostname, MAXHOSTNAMELEN);

	if (slp_packAttrRqst_single(SLP_SUN_DA_TYPE,
				    hostname,
				    "min-refresh-interval",
				    &msg, "en") != SLP_OK) {
	    goto done;
	}

	if (slp_send2slpd(msg, &reply) != SLP_OK) {
	    goto done;
	}

	(void) slp_UnpackAttrReply(hp, reply, refresh_interval_cb,
				    &max, &collator, &mr);

	/* clean up by invoking last call */
	(void) slp_UnpackAttrReply(hp, NULL, refresh_interval_cb,
				    &max, &collator, &mr);

done:
	if (msg) free(msg);
	if (reply) free(reply);

	SLPClose(hp);

	return (max);
}
Example #2
0
/***************************************************************************
 * sl_collect:
 *
 * Routine to manage a connection to a SeedLink server based on the values
 * given in the slconn struct and collect data.
 *
 * Designed to run in a tight loop at the heart of a client program, this
 * function will return every time a packet is received.
 *
 * Returns SLPACKET when something is received and sets the slpack
 * pointer to the received packet.  When the connection was closed by
 * the server or the termination sequence completed SLTERMINATE is
 * returned and the slpack pointer is set to NULL.
 ***************************************************************************/
int
sl_collect (SLCD * slconn, SLpacket ** slpack)
{
  int    bytesread;
  double current_time;
  char   retpacket;

  /* For select()ing during the read loop */
  struct timeval select_tv;
  fd_set         select_fd;
  int            select_ret;

  *slpack = NULL;

  /* Check if the info was set */
  if ( slconn->info != NULL )
    {
      slconn->stat->query_mode = InfoQuery;
    }
  
  /* If the connection is not up check the SLCD and reset the timing variables */
  if ( slconn->link == -1 )
    {
      if ( sl_checkslcd(slconn) )
	{
	  sl_log_r (slconn, 2, 0, "problems with the connection description\n");
	  return SLTERMINATE;
	}

      slconn->stat->netto_trig     = -1;	   /* Init net timeout trigger to reset state */
      slconn->stat->keepalive_trig = -1;	   /* Init keepalive trigger to reset state */
    }

  /* Start the primary loop  */
  while (1)
    {
      if ( ! slconn->terminate )
	{
	  if (slconn->link == -1)
	    {
	      slconn->stat->sl_state = SL_DOWN;
	    }
	  
	  /* Check for network timeout */
	  if (slconn->stat->sl_state == SL_DATA && slconn->netto && slconn->stat->netto_trig > 0)
	    {
	      sl_log_r (slconn, 1, 0, "network timeout (%ds), reconnecting in %ds\n",
			slconn->netto, slconn->netdly);
	      slconn->link = sl_disconnect (slconn);
	      slconn->stat->sl_state = SL_DOWN;
	      slconn->stat->netto_trig = -1;
	      slconn->stat->netdly_trig = -1;
	    }
	  
	  /* Check if a keepalive packet needs to be sent */
	  if (slconn->stat->sl_state == SL_DATA && !slconn->stat->expect_info &&
	      slconn->keepalive && slconn->stat->keepalive_trig > 0)
	    {
	      sl_log_r (slconn, 1, 2, "sending keepalive request\n");
	      
	      if ( sl_send_info (slconn, "ID", 3) != -1 )
		{
		  slconn->stat->query_mode = KeepAliveQuery;
		  slconn->stat->expect_info = 1;
		  slconn->stat->keepalive_trig = -1;
		}
	    }
	  
	  /* Check if an in-stream INFO request needs to be sent */
	  if (slconn->stat->sl_state == SL_DATA && !slconn->stat->expect_info && slconn->info)
	    {
	      if ( sl_send_info (slconn, slconn->info, 1) != -1 )
		{
		  slconn->stat->query_mode = InfoQuery;
		  slconn->stat->expect_info = 1;
		}
	      else
		{
		  slconn->stat->query_mode = NoQuery;
		}
	      
	      slconn->info = NULL;
	    }
	  
	  /* Throttle the loop while delaying */
	  if (slconn->stat->sl_state == SL_DOWN && slconn->stat->netdly_trig > 0)
	    {
	      slp_usleep (500000);
	    }
	  
	  /* Connect to remote SeedLink */
	  if (slconn->stat->sl_state == SL_DOWN && slconn->stat->netdly_trig == 0)
	    {
	      if (sl_connect (slconn, 1) != -1)
		{
		  slconn->stat->sl_state = SL_UP;
		}
	      slconn->stat->netto_trig = -1;
	      slconn->stat->netdly_trig = -1;
	      slconn->stat->keepalive_trig = -1;
	    }
	  
	  /* Negotiate/configure the connection */
	  if (slconn->stat->sl_state == SL_UP)
	    {
	      int slconfret = 0;
	      
	      /* Only send query if a query is set and no streams are defined,
	       * if streams are defined we'll send the query after configuration.
	       */
	      if (slconn->info && slconn->streams == NULL)
		{
		  if ( sl_send_info (slconn, slconn->info, 1) != -1 )
		    {
		      slconn->stat->query_mode = InfoQuery;
		      slconn->stat->expect_info = 1;
		    }
		  else
		    {
		      slconn->stat->query_mode = NoQuery;
		      slconn->stat->expect_info = 0;
		    }
		  
		  slconn->info = NULL;
		}
	      else
		{
		  slconfret = sl_configlink (slconn);
		  slconn->stat->expect_info = 0;
		}
	      
	      if (slconfret != -1)
		{
		  slconn->stat->recptr = 0;    /* initialize the data buffer pointers */
		  slconn->stat->sendptr = 0;
		  slconn->stat->sl_state = SL_DATA;
		}
	      else
		{
		  sl_log_r (slconn, 2, 0, "negotiation with remote SeedLink failed\n");
		  slconn->link = sl_disconnect (slconn);
		  slconn->stat->netdly_trig = -1;
		}
	    }
	}
      else /* We are terminating */
	{
	  if (slconn->link != -1)
	    {
	      slconn->link = sl_disconnect (slconn);
	    }

	  slconn->stat->sl_state = SL_DOWN;
	}

      /* DEBUG
      sl_log_r (slconn, 1, 0, "link: %d, sendptr: %d, recptr: %d, diff: %d\n",
                slconn->link, slconn->stat->sendptr, slconn->stat->recptr,
		(slconn->stat->recptr - slconn->stat->sendptr) );
      */
	  
      /* Process data in buffer */
      while (slconn->stat->recptr - slconn->stat->sendptr >= SLHEADSIZE + SLRECSIZE)
	{
	  retpacket = 1;
	  
	  /* Check for an INFO packet */
	  if (!strncmp (&slconn->stat->databuf[slconn->stat->sendptr], INFOSIGNATURE, 6))
	    {
	      char terminator;
	      
	      terminator = (slconn->stat->databuf[slconn->stat->sendptr + SLHEADSIZE - 1] != '*');
	      
	      if ( !slconn->stat->expect_info )
		{
		  sl_log_r (slconn, 2, 0, "unexpected INFO packet received, skipping\n");
		}
	      else
		{
		  if ( terminator )
		    {
		      slconn->stat->expect_info = 0;
		    }
		  
		  /* Keep alive packets are not returned */
		  if ( slconn->stat->query_mode == KeepAliveQuery )
		    {
		      retpacket = 0;
		      
		      if ( !terminator )
			{
			  sl_log_r (slconn, 2, 0, "non-terminated keep-alive packet received!?!\n");
			}
		      else
			{
			  sl_log_r (slconn, 1, 2, "keepalive packet received\n");
			}
		    }
		}
	      
	      if ( slconn->stat->query_mode != NoQuery )
		{
		  slconn->stat->query_mode = NoQuery;
		}
	    }
	  else    /* Update the stream chain entry if not an INFO packet */
	    {
	      if ( (update_stream (slconn, (SLpacket *) &slconn->stat->databuf[slconn->stat->sendptr])) == -1 )
		{
		  /* If updating didn't work the packet is broken */
		  retpacket = 0;
		}
	    }
	  
	  /* Increment the send pointer */
	  slconn->stat->sendptr += (SLHEADSIZE + SLRECSIZE);
	  
	  /* Return packet */
	  if ( retpacket )
	    {
	      *slpack = (SLpacket *) &slconn->stat->databuf[slconn->stat->sendptr - (SLHEADSIZE + SLRECSIZE)];
	      return SLPACKET;
	    }
	}
      
      /* A trap door for terminating, all complete data packets from the buffer
	 have been sent to the caller */
      if ( slconn->terminate ) {
	return SLTERMINATE;
      }
      
      /* After processing the packet buffer shift the data */
      if ( slconn->stat->sendptr )
	    {
	      memmove (slconn->stat->databuf,
		       &slconn->stat->databuf[slconn->stat->sendptr],
		       slconn->stat->recptr - slconn->stat->sendptr);
	      
	      slconn->stat->recptr -= slconn->stat->sendptr;
	      slconn->stat->sendptr = 0;
	    }
      
      /* Catch cases where the data stream stopped */
      if ((slconn->stat->recptr - slconn->stat->sendptr) == 7 &&
	  !strncmp (&slconn->stat->databuf[slconn->stat->sendptr], "ERROR\r\n", 7))
	{
	  sl_log_r (slconn, 2, 0, "SeedLink server reported an error with the last command\n");
	  slconn->link = sl_disconnect (slconn);
	  return SLTERMINATE;
	}
      
      if ((slconn->stat->recptr - slconn->stat->sendptr) == 3 &&
	  !strncmp (&slconn->stat->databuf[slconn->stat->sendptr], "END", 3))
	{
	  sl_log_r (slconn, 1, 1, "End of buffer or selected time window\n");
	  slconn->link = sl_disconnect (slconn);
	  return SLTERMINATE;
	}
      
      /* Read incoming data if connection is up */
      if (slconn->stat->sl_state == SL_DATA)
	{
	  /* Check for more available data from the socket */
	  bytesread = 0;

	  /* Poll the server */
	  FD_ZERO (&select_fd);
	  FD_SET ((unsigned int)slconn->link, &select_fd);
	  select_tv.tv_sec = 0;
	  select_tv.tv_usec = 500000;  /* Block up to 0.5 seconds */

	  select_ret = select ((slconn->link + 1), &select_fd, NULL, NULL, &select_tv);

	  /* Check the return from select(), an interrupted system call error
	     will be reported if a signal handler was used.  If the terminate
	     flag is set this is not an error. */
	  if (select_ret > 0)
	    {
	      if (!FD_ISSET (slconn->link, &select_fd))
		{
		  sl_log_r (slconn, 2, 0, "select() reported data but socket not in set!\n");
		}
	      else
		{
		  bytesread = sl_recvdata (slconn, (void *) &slconn->stat->databuf[slconn->stat->recptr],
					   BUFSIZE - slconn->stat->recptr, slconn->sladdr);
		}
	    }
	  else if (select_ret < 0 && ! slconn->terminate)
	    {
	      sl_log_r (slconn, 2, 0, "select() error: %s\n", slp_strerror ());
	      slconn->link = sl_disconnect (slconn);
	      slconn->stat->netdly_trig = -1;
	    }

	  if (bytesread < 0)            /* read() failed */
	    {
	      slconn->link = sl_disconnect (slconn);
	      slconn->stat->netdly_trig = -1;
	    }
	  else if (bytesread > 0)	/* Data is here, process it */
	    {
	      slconn->stat->recptr += bytesread;

	      /* Reset the timeout and keepalive timers */
	      slconn->stat->netto_trig     = -1;
	      slconn->stat->keepalive_trig = -1;
	    }
	}

      /* Update timing variables */
      current_time = sl_dtime ();

      /* Network timeout timing logic */
      if (slconn->netto)
	{
	  if (slconn->stat->netto_trig == -1)	/* reset timer */
	    {
	      slconn->stat->netto_time = current_time;
	      slconn->stat->netto_trig = 0;
	    }
	  else if (slconn->stat->netto_trig == 0 &&
		   (current_time - slconn->stat->netto_time) > slconn->netto)
	    {
	      slconn->stat->netto_trig = 1;
	    }
	}
      
      /* Keepalive/heartbeat interval timing logic */
      if (slconn->keepalive)
	{
	  if (slconn->stat->keepalive_trig == -1)	/* reset timer */
	    {
	      slconn->stat->keepalive_time = current_time;
	      slconn->stat->keepalive_trig = 0;
	    }
	  else if (slconn->stat->keepalive_trig == 0 &&
		   (current_time - slconn->stat->keepalive_time) > slconn->keepalive)
	    {
	      slconn->stat->keepalive_trig = 1;
	    }
	}
      
      /* Network delay timing logic */
      if (slconn->netdly)
	{
	  if (slconn->stat->netdly_trig == -1)	/* reset timer */
	    {
	      slconn->stat->netdly_time = current_time;
	      slconn->stat->netdly_trig = 1;
	    }
	  else if (slconn->stat->netdly_trig == 1 &&
		   (current_time - slconn->stat->netdly_time) > slconn->netdly)
	    {
	      slconn->stat->netdly_trig = 0;
	    }
	}
    }				/* End of primary loop */
}  /* End of sl_collect() */