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); }
/*************************************************************************** * 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() */