コード例 #1
0
ファイル: mclient.c プロジェクト: bonsa/mrrocpp
// Read from a bunch of clients
int playerc_mclient_read(playerc_mclient_t *mclient, int timeout)
{
  int i, count;

  // Configure poll structure to wait for incoming data 
  for (i = 0; i < mclient->client_count; i++)
  {
    mclient->pollfd[i].fd = mclient->client[i]->sock;
    mclient->pollfd[i].events = POLLIN;
    mclient->pollfd[i].revents = 0;
  }

  // Wait for incoming data 
  count = poll(mclient->pollfd, mclient->client_count, timeout);
  if (count < 0)
  {
    PLAYERC_ERR1("poll returned error [%s]", strerror(errno));
    return -1;
  }

  // Now read from each of the waiting sockets 
  for (i = 0; i < mclient->client_count; i++)
  {
    if ((mclient->pollfd[i].revents & POLLIN) > 0)
    {
      if(playerc_client_read(mclient->client[i]))
      {
        // cache the latest timestamp
        if(mclient->client[i]->datatime > mclient->time)
          mclient->time = mclient->client[i]->datatime;
      }
    }
  }
  return count;
}
コード例 #2
0
// Process incoming data
void playerc_micronsonar_putmsg(playerc_micronsonar_t *device, player_msghdr_t *header,
                player_micronsonar_data_t *data, size_t len)
{
  if((header->type == PLAYER_MSGTYPE_DATA) &&
     (header->subtype == PLAYER_MICRONSONAR_DATA_STATE))
  {
    device->width        = data->width;
    device->height       = data->height;
    device->bpp          = data->bpp;
    device->format       = data->format;
    device->image_count  = data->image_count;
    device->image        = realloc(device->image, sizeof(device->image[0])*device->image_count);
    device->centreX      = data->centreX;
    device->centreY      = data->centreY;
    device->range        = data->range;
    device->numBins      = data->numBins;
    device->startAngle   = data->startAngle;
    device->endAngle     = data->endAngle;
    
    if (device->image)
      memcpy(device->image, data->image, device->image_count);
    else
      PLAYERC_ERR1("failed to allocate memory for image, needed %ld bytes\n", sizeof(device->image[0])*device->image_count);
  }
  else
    PLAYERC_WARN2("skipping micronsonar message with unknown type/subtype: %s/%d\n",
                 msgtype_to_str(header->type), header->subtype);
  return;
}
コード例 #3
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Disconnect from the server
int playerc_client_disconnect(playerc_client_t *client)
{
#if defined (WIN32)
  if (closesocket(client->sock) != 0)
  {
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                   ErrNo, 0, (LPTSTR) &errBuffer, 0, NULL);
    PLAYERC_ERR1("closesocket failed with error [%s]", (LPTSTR) errBuffer);
    LocalFree(errBuffer);
  }
#else
  if (close(client->sock) < 0)
  {
    PLAYERC_ERR1("close failed with error [%s]", strerror(errno));
    client->sock = -1;
    return -1;
  }
#endif
  client->sock = -1;
  client->connected = 0;
  return 0;
}
コード例 #4
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Destroy a player client
void playerc_client_destroy(playerc_client_t *client)
{
  player_msghdr_t header;
  // Pop everything off the queue.
  while (!playerc_client_pop(client, &header, client->data))
  {
	  playerxdr_cleanup_message(client->data,header.addr.interf, header.type, header.subtype);
  }

#if defined (WIN32)
  // Clean up the Windows sockets API (this can safely be done as many times as we like)
  if (WSACleanup () != 0)
    PLAYERC_ERR1 ("Failed to clean up Windows sockets API with error %s", WSAGetLastError ());
#endif

  free(client->data);
  free(client->write_xdrdata);
  free(client->read_xdrdata);
  free(client->host);
  free(client);
  return;
}
コード例 #5
0
ファイル: mclient.c プロジェクト: bonsa/mrrocpp
// Test to see if there is pending data.
// Returns -1 on error, 0 or 1 otherwise.
int playerc_mclient_peek(playerc_mclient_t *mclient, int timeout)
{
  int i, count;

  // Configure poll structure to wait for incoming data 
  for (i = 0; i < mclient->client_count; i++)
  {
    mclient->pollfd[i].fd = mclient->client[i]->sock;
    mclient->pollfd[i].events = POLLIN;
    mclient->pollfd[i].revents = 0;
  }

  // Wait for incoming data 
  count = poll(mclient->pollfd, mclient->client_count, timeout);
  if (count < 0)
  {
    PLAYERC_ERR1("poll returned error [%s]", strerror(errno));
    return -1;
  }

  return (count > 0);
}
コード例 #6
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Test to see if there is pending data. Don't send a data request.
int playerc_client_internal_peek(playerc_client_t *client, int timeout)
{
  int count;
  struct pollfd fd;

  if (client->sock < 0)
  {
    PLAYERC_WARN("no socket to peek at");
    return -1;
  }

  fd.fd = client->sock;
  //fd.events = POLLIN | POLLHUP;
  fd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
  fd.revents = 0;

  // Wait for incoming data
  count = poll(&fd, 1, timeout);
  if (count < 0)
  {
    if(errno == EINTR)
      return(0);
    else
    {
      PLAYERC_ERR1("poll returned error [%s]", strerror(errno));
      //playerc_client_disconnect(client);
      return(playerc_client_disconnect_retry(client));
    }
  }
  if (count > 0 && (fd.revents & POLLHUP))
  {
    PLAYERC_ERR("socket disconnected");
    //playerc_client_disconnect(client);
    return(playerc_client_disconnect_retry(client));
  }
  return count;
}
コード例 #7
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Connect to the server
int playerc_client_connect(playerc_client_t *client)
{
#if defined(HAVE_GETADDRINFO)
  struct addrinfo* addr_ptr = NULL;
#else
  struct hostent* entp = NULL;
#endif
  char banner[PLAYER_IDENT_STRLEN];
  int ret;
  //double t;
  /*
  struct timeval last;
  struct timeval curr;
  */
#if defined (WIN32)
  unsigned long setting = 0;
#else
  int old_flags;
  struct itimerval timer;
  struct sigaction sigact;
#endif
  struct sockaddr_in clientaddr;

  // Construct socket
  if(client->transport == PLAYERC_TRANSPORT_UDP)
  {
#if defined (WIN32)
    if((client->sock = socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
#else
    if((client->sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
#endif
    {
      STRERROR(PLAYERC_ERR2, "socket() failed with error [%d: %s]");
      return -1;
    }
    /*
     * INADDR_ANY indicates that any network interface (IP address)
     * for the local host may be used (presumably the OS will choose the
     * right one).
     *
     * Specifying sin_port = 0 allows the system to choose the port.
     */
    clientaddr.sin_family = AF_INET;
    clientaddr.sin_addr.s_addr = INADDR_ANY;
    clientaddr.sin_port = 0;

    if(bind(client->sock,
            (struct sockaddr*)&clientaddr, sizeof(clientaddr)) < -1)
    {
      STRERROR(PLAYERC_ERR2, "bind() failed with error [%d: %s]");
      return -1;
    }
  }
  else
  {
#if defined (WIN32)
    if((client->sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
#else
    if((client->sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
#endif
    {
      STRERROR(PLAYERC_ERR2, "socket() failed with error [%d: %s]");
      return -1;
    }
  }

#if ENABLE_TCP_NODELAY
  // Disable Nagel's algorithm for lower latency
  {
    int yes = 1;
    if(setsockopt(client->sock, IPPROTO_TCP, TCP_NODELAY, &yes,
                  sizeof(int)) == -1)
    {
      PLAYERC_ERR("failed to enable TCP_NODELAY - setsockopt failed");
      return -1;
    }
  }
#endif

  // Construct server address
  memset(&client->server, 0, sizeof(client->server));
  client->server.sin_family = AF_INET;
  client->server.sin_port = htons(client->port);
#if defined(HAVE_GETADDRINFO)
  if (getaddrinfo(client->host, NULL, NULL, &addr_ptr) != 0)
  {
    playerc_client_disconnect(client);
    PLAYERC_ERR("getaddrinfo() failed with error");
    return -1;
  }
  assert(addr_ptr);
  assert(addr_ptr->ai_addr);
#ifdef AF_INET6
  if (((addr_ptr->ai_addr->sa_family) != AF_INET) &&
      ((addr_ptr->ai_addr->sa_family) != AF_INET6))
#else
  if ((addr_ptr->ai_addr->sa_family) != AF_INET)
#endif
  {
    playerc_client_disconnect(client);
    PLAYERC_ERR("unsupported internet address family");
    return -1;
  }
  client->server.sin_addr.s_addr = ((struct sockaddr_in *)(addr_ptr->ai_addr))->sin_addr.s_addr;
  freeaddrinfo(addr_ptr);
  addr_ptr = NULL;
#else
  entp = gethostbyname(client->host);
  if (entp == NULL)
  {
    playerc_client_disconnect(client);
    STRERROR(PLAYERC_ERR2, "gethostbyname() failed with error [%d: %s]");
    return -1;
  }
  assert(entp->h_length <= sizeof (client->server.sin_addr));
  memcpy(&(client->server.sin_addr), entp->h_addr_list[0], entp->h_length);
#endif
  // Connect the socket
  /*
  t = client->request_timeout;
  do
  {
    if (t <= 0)
    {
      PLAYERC_ERR2("connect call on [%s:%d] timed out",
                   client->host, client->port);
      return -1;
    }
    gettimeofday(&last,NULL);
    puts("calling connect");
    ret = connect(client->sock, (struct sockaddr*)&client->server,
                  sizeof(client->server));
    gettimeofday(&curr,NULL);
    t -= ((curr.tv_sec + curr.tv_usec/1e6) -
          (last.tv_sec + last.tv_usec/1e6));
  } while (ret == -1 && (errno == EALREADY || errno == EAGAIN || errno == EINPROGRESS));
  */

  // In Windows, the connect timeout is (apparently) a registry setting.
#if !defined (WIN32)
  /* Set up a timer to interrupt the connection process */
  timer.it_interval.tv_sec = 0;
  timer.it_interval.tv_usec = 0;
  timer.it_value.tv_sec = (int)floor(client->request_timeout);
  timer.it_value.tv_usec =
          (int)rint(fmod(client->request_timeout,timer.it_value.tv_sec)*1e6);
  if(setitimer(ITIMER_REAL, &timer, NULL) != 0)
    PLAYERC_WARN("failed to set up connection timer; "
                "indefinite hang may result");

  /* Turn off system call restart so that connect() will terminate when the
   * alarm goes off */
  if(sigaction(SIGALRM, NULL, &sigact) != 0)
    PLAYERC_WARN("failed to get SIGALRM action data; "
                "unexpected exit may result");
  else
  {
#ifdef SA_RESTART
    sigact.sa_handler = dummy;
    sigact.sa_flags &= ~SA_RESTART;
    if(sigaction(SIGALRM, &sigact, NULL) != 0)
#endif
      PLAYERC_WARN("failed to set SIGALRM action data; "
                  "unexpected exit may result");
  }
#endif

  ret = connect(client->sock, (struct sockaddr*)&client->server,
                sizeof(client->server));

#if !defined (WIN32)
  /* Turn off timer */
  timer.it_value.tv_sec = 0;
  timer.it_value.tv_usec = 0;
  if(setitimer(ITIMER_REAL, &timer, NULL) != 0)
    PLAYERC_WARN("failed to turn off connection timer; "
                "unexpected exit may result");

  /* Restore normal SIGALRM behavior */
#ifdef SA_RESTART
  sigact.sa_handler = SIG_DFL;
  sigact.sa_flags |= SA_RESTART;
  if(sigaction(SIGALRM, &sigact, NULL) != 0)
#endif
    PLAYERC_WARN("failed to reset SIGALRM action data; "
                "unexpected behavior may result");
#endif

  if (ret < 0)
  {
    playerc_client_disconnect(client);
#if defined (WIN32)
    FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                   ErrNo, 0, (LPTSTR) &errBuffer, 0, NULL);
    PLAYERC_ERR4 ("connect call on [%s:%d] failed with error [%d:%s]",
                 client->host, client->port, ErrNo, (LPTSTR) errBuffer);
    LocalFree (errBuffer);
#else
    PLAYERC_ERR4("connect call on [%s:%d] failed with error [%d:%s]",
                 client->host, client->port, errno, strerror(ErrNo));
#endif
    return -1;
  }

  // For UDP, send an empty msg to get things going
  if(client->transport == PLAYERC_TRANSPORT_UDP)
  {
    if(send(client->sock, NULL, 0, 0) < 0)
    {
      STRERROR(PLAYERC_ERR2, "send() failed with error [%d: %s]");
      return -1;
    }
  }

  // set socket to be blocking
#if defined (WIN32)
  if (ioctlsocket (client->sock, FIONBIO, &setting) == SOCKET_ERROR)
  {
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                   ErrNo, 0, (LPTSTR) &errBuffer, 0, NULL);
    PLAYERC_ERR1("error getting socket flags [%s]", (LPTSTR) errBuffer);
    LocalFree(errBuffer);
  }
#else
  if ((old_flags = fcntl(client->sock, F_GETFL)) < 0)
  {
    PLAYERC_ERR1("error getting socket flags [%s]", strerror(errno));
    return -1;
  }
  if (fcntl(client->sock, F_SETFL, old_flags & ~O_NONBLOCK) < 0)
  {
    PLAYERC_ERR1("error setting socket non-blocking [%s]", strerror(errno));
    return -1;
  }
#endif


  // Get the banner
  if (timed_recv(client->sock, banner, sizeof(banner), 0, 2000) < sizeof(banner))
  {
    playerc_client_disconnect(client);
    PLAYERC_ERR("incomplete initialization string");
    return -1;
  }

  //set the datamode to pull
  playerc_client_datamode(client, PLAYER_DATAMODE_PULL);

  PLAYERC_WARN4("[%s] connected on [%s:%d] with sock %d\n", banner, client->host, client->port, client->sock);

  client->connected = 1;
  return 0;
}
コード例 #8
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Create a player client
playerc_client_t *playerc_client_create(playerc_mclient_t *mclient, const char *host, int port)
{
  playerc_client_t *client;
#if defined (WIN32)
  // Initialise Windows sockets API (this can safely be done as many times as we like)
  // Thus must be called once for every client creation, in order to match the calls on
  // client destruction (winsocks uses an internal reference counter to ensure only the
  // final call to WSACleanup actually does anything).
  WSADATA info;
  int result;
  if ((result = WSAStartup (MAKEWORD (2, 2), &info)) != 0)
  {
    PLAYERC_ERR1 ("Failed to initialise Windows sockets API with error %d", result);
  }
#endif

  // Have we done one-time intialization work yet?
  if(!init_done)
  {
    playerxdr_ftable_init();
    if (itable_init () != 0)
      return NULL;
    init_done = 1;
  }

  client = malloc(sizeof(playerc_client_t));
  memset(client, 0, sizeof(playerc_client_t));

  client->id = client;
  client->host = strdup(host);
  client->port = port;
  client->connected = 0;

  if (mclient)
    playerc_mclient_addclient(mclient, client);

  // TODO: make this memory allocation more conservative
  client->data = (char*)malloc(PLAYER_MAX_MESSAGE_SIZE);
  client->write_xdrdata = (char*)malloc(PLAYERXDR_MAX_MESSAGE_SIZE);
  client->read_xdrdata = (char*)malloc(PLAYERXDR_MAX_MESSAGE_SIZE);
  client->read_xdrdata_len = 0;
  assert(client->data);
  assert(client->write_xdrdata);
  assert(client->read_xdrdata);

  client->qfirst = 0;
  client->qlen = 0;
  client->qsize = sizeof(client->qitems) / sizeof(client->qitems[0]);

  client->datatime = 0;
  client->lasttime = 0;

  /* this is the server's default */
  client->mode = PLAYER_DATAMODE_PUSH;
  client->transport = PLAYERC_TRANSPORT_TCP;
  client->data_requested = 0;
  client->data_received = 0;

  client->request_timeout = 5.0;

  client->retry_limit = 0;
  client->retry_time = 2.0;

  return client;
}