コード例 #1
0
ファイル: dev_audio.c プロジェクト: swem/player-git-svn
/** @brief Request to retrieve an audio sample
Data is stored in wav_data */
int playerc_audio_sample_retrieve(playerc_audio_t *device, int index)
{
    int result = 0;
    player_audio_sample_t req;
    player_audio_sample_t * resp;
    req.sample.data_count = 0;
    req.index = index;
    if((result = playerc_client_request(device->info.client, &device->info,
                                        PLAYER_AUDIO_REQ_SAMPLE_RETRIEVE,
                                        &req, (void**)&resp)) < 0)
        return result;

    device->wav_data.data_count = resp->sample.data_count;
    if (device->wav_data.data != NULL)
        free (device->wav_data.data);
    if ((device->wav_data.data = (uint8_t*) malloc (resp->sample.data_count)) == NULL)
    {
        player_audio_sample_t_free(resp);
        PLAYERC_ERR("Failed to allocate space to store wave data locally");
        return -1;
    }
    memcpy(device->wav_data.data, resp->sample.data, resp->sample.data_count * sizeof(device->wav_data.data[0]));
    device->wav_data.format = resp->sample.format;
    player_audio_sample_t_free(resp);

    return 0;
}
コード例 #2
0
ファイル: dev_planner.c プロジェクト: bonsa/mrrocpp
// Get the list of waypoints.  The writes the result into the proxy
// rather than returning it to the caller.
int playerc_planner_get_waypoints(playerc_planner_t *device)
{
  int i;
  int len;
  player_planner_waypoints_req_t config;

  memset(&config, 0, sizeof(config));
  config.subtype = PLAYER_PLANNER_GET_WAYPOINTS_REQ;

  len = playerc_client_request(device->info.client, &device->info,
                               &config, sizeof(config), &config, 
                               sizeof(config));
  if (len < 0)
    return -1;
  if (len == 0)
  {
    PLAYERC_ERR("got unexpected zero-length reply");
    return -1;
  }
  
  device->waypoint_count = (int)ntohs(config.count);
  for(i=0;i<device->waypoint_count;i++)
  {
    device->waypoints[i][0] = ((int)ntohl(config.waypoints[i].x)) / 1e3;
    device->waypoints[i][1] = ((int)ntohl(config.waypoints[i].y)) / 1e3;
    device->waypoints[i][2] = ((int)ntohl(config.waypoints[i].a)) * M_PI / 180;
  }
  return 0;
}
コード例 #3
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Push a packet onto the incoming queue.
void playerc_client_push(playerc_client_t *client,
                         player_msghdr_t *header, void *data)
{
  playerc_client_item_t *item;

  // Check for queue overflow; this will leak mem.
  if (client->qlen == client->qsize)
  {
    PLAYERC_ERR("queue overflow; discarding packets");
    client->qfirst = (client->qfirst + 1) % client->qsize;
    client->qlen -=1;
  }

  item = client->qitems + (client->qfirst + client->qlen) % client->qsize;
  item->header = *header;
  if (header->size && data)
  {
    item->data = malloc(header->size);
    memcpy(item->data, data, header->size);
  }
  else
  {
    item->data = NULL;
  }

  client->qlen +=1;

  return;
}
コード例 #4
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// this method performs a select before the read so we can have a timeout
// this stops the client hanging forever if the target disappears from the network
int timed_recv(int s, void *buf, size_t len, int flags, int timeout)
{
  struct pollfd ufd;
  int ret;

  ufd.fd = s;
  ufd.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;

  ret = poll (&ufd, 1, timeout);
  if (ret <= 0)
  {
    if(errno == EINTR)
      return(0);
    else if (ret == 0)
    {
      PLAYERC_ERR("poll call timed out with no data to recieve");
      return ret;
    }
    else
    {
      PLAYERC_ERR2("poll call failed with error [%d:%s]", errno, strerror(errno));
      return ret;
    }
  }

  return recv(s,buf,len,flags);
}
コード例 #5
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Subscribe to a device
int playerc_client_subscribe(playerc_client_t *client, int code, int index,
                             int access, char *drivername, size_t len)
{
  player_device_req_t req, *resp;
  resp=NULL;

  req.addr.host = 0;
  req.addr.robot = 0;
  req.addr.interf = code;
  req.addr.index = index;
  req.access = access;
  req.driver_name_count = 0;

  if (playerc_client_request(client, NULL, PLAYER_PLAYER_REQ_DEV,
                             (void*)&req, (void**)&resp) < 0)
  {
    PLAYERC_ERR("failed to get response");
    return -1;
  }

  if (req.access != access)
  {
    PLAYERC_ERR2("requested [%d] access, but got [%d] access", access, req.access);
    return -1;
  }

  // Copy the driver name
  strncpy(drivername, resp->driver_name, len);
  player_device_req_t_free(resp);

  return 0;
}
コード例 #6
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Get the driver info for all devices.  The data is written into the
// proxy structure rather than returned to the caller.
int playerc_client_get_driverinfo(playerc_client_t *client)
{
  int i;
  player_device_driverinfo_t req, *resp;

  for (i = 0; i < client->devinfo_count; i++)
  {
    memset(&req,0,sizeof(req));
    req.addr = client->devinfos[i].addr;

    if(playerc_client_request(client, NULL, PLAYER_PLAYER_REQ_DRIVERINFO,
                              &req, (void**)&resp) < 0)
    {
      PLAYERC_ERR("failed to get response");
      return(-1);
    }

    strncpy(client->devinfos[i].drivername, resp->driver_name,
      resp->driver_name_count);
    client->devinfos[i].drivername[resp->driver_name_count] = '\0';

    player_device_driverinfo_t_free(resp);
  }

  return 0;
}
コード例 #7
0
ファイル: dev_log.c プロジェクト: bonsa/mrrocpp
// Change filename
int playerc_log_set_filename(playerc_log_t* device, const char* fname)
{
  player_log_set_filename_t req;

  req.subtype = PLAYER_LOG_SET_FILENAME;
  if(strlen(fname) > (sizeof(req.filename)-1))
  {
    PLAYERC_ERR("filename too long");
    return(-1);
  }
  strcpy((char *) req.filename,fname);

  if(playerc_client_request(device->info.client, &device->info,
                            &req, sizeof(req), NULL, 0) < 0)
  {
    PLAYERC_ERR("failed to set logfile name");
    return(-1);
  }
  return(0);
}
コード例 #8
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Add a device proxy
int playerc_client_adddevice(playerc_client_t *client, playerc_device_t *device)
{
  if (client->device_count >= sizeof(client->device) / sizeof(client->device[0]))
  {
    PLAYERC_ERR("too many devices");
    return -1;
  }
  device->fresh = 0;
  client->device[client->device_count++] = device;
  return 0;
}
コード例 #9
0
ファイル: mclient.c プロジェクト: bonsa/mrrocpp
// Add a client to this multi-client
int playerc_mclient_addclient(playerc_mclient_t *mclient, playerc_client_t *client)
{
  if (mclient->client_count >= sizeof(mclient->client) / sizeof(mclient->client[0]))
  {
    PLAYERC_ERR("too many clients in multi-client; ignoring new client");
    return -1;
  }

  mclient->client[mclient->client_count] = client;
  mclient->client_count++;

  return 0;
}
コード例 #10
0
ファイル: dev_ranger.c プロジェクト: Arkapravo/Player-3.0.2
// Copy geometry to the device
void playerc_ranger_copy_geom(playerc_ranger_t *device, player_ranger_geom_t *geom)
{
  device->device_pose = geom->pose;
  device->device_size = geom->size;

  if(device->element_poses != NULL)
  {
    free(device->element_poses);
    device->element_poses = NULL;
  }
  if(device->element_sizes != NULL)
  {
    free(device->element_sizes);
    device->element_sizes = NULL;
  }
  device->element_count = 0;

  if(geom->element_poses_count > 0)
  {
    if((device->element_poses = (player_pose3d_t *) malloc(geom->element_poses_count * sizeof(player_pose3d_t))) == NULL)
    {
      PLAYERC_ERR("Failed to allocate space to store sensor poses");
      return;
    }
    memcpy(device->element_poses, geom->element_poses, geom->element_poses_count * sizeof(player_pose3d_t));
  }

  if (geom->element_sizes_count > 0)
  {
    if((device->element_sizes = (player_bbox3d_t *) malloc(geom->element_sizes_count * sizeof(player_bbox3d_t))) == NULL)
    {
      PLAYERC_ERR("Failed to allocate space to store sensor sizes");
      return;
    }
    memcpy(device->element_sizes, geom->element_sizes, geom->element_sizes_count * sizeof(player_bbox3d_t));
  }

  device->element_count = geom->element_poses_count;
}
コード例 #11
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Register a callback.  Will be called when after data has been read
// by the indicated device.
int playerc_client_addcallback(playerc_client_t *client, playerc_device_t *device,
                               playerc_callback_fn_t callback, void *data)
{
  if (device->callback_count >= sizeof(device->callback) / sizeof(device->callback[0]))
  {
    PLAYERC_ERR("too many registered callbacks; ignoring new callback");
    return -1;
  }
  device->callback[device->callback_count] = callback;
  device->callback_data[device->callback_count] = data;
  device->callback_count++;

  return 0;
}
コード例 #12
0
ファイル: dev_log.c プロジェクト: bonsa/mrrocpp
// Rewind playback
int playerc_log_set_read_rewind(playerc_log_t* device)
{
  player_log_set_read_rewind_t req;

  req.subtype = PLAYER_LOG_SET_READ_REWIND_REQ;

  if(playerc_client_request(device->info.client, &device->info,
                            &req, sizeof(req),
                            &req, sizeof(req)) < 0)
  {
    PLAYERC_ERR("failed to rewind data playback");
    return(-1);
  }
  return(0);
}
コード例 #13
0
ファイル: dev_ranger.c プロジェクト: Arkapravo/Player-3.0.2
// Calculate scan points
void playerc_ranger_calculate_points(playerc_ranger_t *device)
{
  double b, r, s;
  uint32_t ii;

  device->points_count = device->ranges_count;
  if (device->points_count == 0 && device->points != NULL)
  {
    free(device->points);
    device->points = NULL;
  }
  else
  {
    if((device->points = (player_point_3d_t *) realloc(device->points, device->points_count * sizeof(player_point_3d_t))) == NULL)
    {
      device->points_count = 0;
      PLAYERC_ERR("Failed to allocate space to store points");
      return;
    }

    if (device->points_count >= device->element_count)
    {
      if (device->element_count == 1)
      {
        b = device->min_angle;
        for (ii = 0; ii < device->points_count; ii++)
        {
          r = device->ranges[ii];
          device->points[ii].px = r * cos(b);
          device->points[ii].py = r * sin(b);
          device->points[ii].pz = 0.0;
          b += device->angular_res;
        }
      }
      else
      {
        for (ii = 0; ii < device->element_count; ii++)
        {
          r = device->ranges[ii];
          s = r * cos(device->element_poses[ii].ppitch);
          device->points[ii].px = s * cos(device->element_poses[ii].pyaw) + device->element_poses[ii].px;
          device->points[ii].py = s * sin(device->element_poses[ii].pyaw) + device->element_poses[ii].py;
          device->points[ii].pz = r * sin(device->element_poses[ii].ppitch) + device->element_poses[ii].pz;
        }
      }
    }
  }
}
コード例 #14
0
ファイル: dev_log.c プロジェクト: bonsa/mrrocpp
// Start/stop playback
int playerc_log_set_read_state(playerc_log_t* device, int state)
{
  player_log_set_read_state_t req;

  req.subtype = PLAYER_LOG_SET_READ_STATE_REQ;
  req.state = (uint8_t)state;

  if(playerc_client_request(device->info.client, &device->info,
                            &req, sizeof(req),
                            &req, sizeof(req)) < 0)
  {
    PLAYERC_ERR("failed to start/stop data playback");
    return(-1);
  }
  return(0);
}
コード例 #15
0
ファイル: dev_ranger.c プロジェクト: Arkapravo/Player-3.0.2
// Copy intensity data to the device
void playerc_ranger_copy_intns_data(playerc_ranger_t *device, player_ranger_data_intns_t *data)
{
  if (device->intensities_count != data->intensities_count || device->intensities == NULL)
  {
    // Allocate memory for the new data
    if((device->intensities = (double *) realloc(device->intensities, data->intensities_count * sizeof(double))) == NULL)
    {
      device->intensities_count = 0;
      PLAYERC_ERR("Failed to allocate space to store intensity data");
      return;
    }
  }
  // Copy the range data
  if (data->intensities_count > 0) memcpy(device->intensities, data->intensities, data->intensities_count * sizeof(data->intensities[0]));
  device->intensities_count = data->intensities_count;
}
コード例 #16
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Remove a device proxy
int playerc_client_deldevice(playerc_client_t *client, playerc_device_t *device)
{
  int i;

  for (i = 0; i < client->device_count; i++)
  {
    if (client->device[i] == device)
    {
      memmove(client->device + i, client->device + i + 1,
              (client->device_count - i - 1) * sizeof(client->device[0]));
      client->device_count--;
      return 0;
    }
  }
  PLAYERC_ERR("unknown device");
  return -1;
}
コード例 #17
0
ファイル: dev_log.c プロジェクト: bonsa/mrrocpp
// Get logging/playback state; the result is written into the proxy
int playerc_log_get_state(playerc_log_t* device)
{
  player_log_get_state_t req;

  req.subtype = PLAYER_LOG_GET_STATE_REQ;

  if(playerc_client_request(device->info.client, &device->info,
                            &req, sizeof(req),
                            &req, sizeof(req)) < 0)
  {
    PLAYERC_ERR("failed to get logging/playback state");
    return(-1);
  }
  device->type = req.type;
  device->state = req.state;

  return(0);
}
コード例 #18
0
ファイル: dev_audio.c プロジェクト: swem/player-git-svn
void playerc_audio_putmsg(playerc_audio_t *device,
                          player_msghdr_t *header,
                          uint8_t *data, size_t len)
{
    if((header->type == PLAYER_MSGTYPE_DATA) && (header->subtype == PLAYER_AUDIO_DATA_WAV_REC))
    {
        player_audio_wav_t * wdata = (player_audio_wav_t *) data;
        assert(header->size > 0);
        device->wav_data.data_count = wdata->data_count;
        if (device->wav_data.data != NULL)
            free (device->wav_data.data);
        if ((device->wav_data.data = (uint8_t*) malloc (wdata->data_count)) == NULL)
            PLAYERC_ERR("Failed to allocate space to store wave data locally");
        else
        {
            memcpy(device->wav_data.data, wdata->data, wdata->data_count * sizeof(device->wav_data.data[0]));
            device->wav_data.format = wdata->format;
        }
    }
    else if((header->type == PLAYER_MSGTYPE_DATA) && (header->subtype == PLAYER_AUDIO_DATA_SEQ))
    {
        player_audio_seq_t * sdata = (player_audio_seq_t *) data;
        assert(header->size > 0);
        device->seq_data.tones_count = sdata->tones_count;
        memcpy(device->seq_data.tones, sdata->tones, sdata->tones_count * sizeof(device->seq_data.tones[0]));
    }
    else if((header->type == PLAYER_MSGTYPE_DATA) && (header->subtype == PLAYER_AUDIO_DATA_MIXER_CHANNEL))
    {
        player_audio_mixer_channel_list_t * wdata = (player_audio_mixer_channel_list_t *) data;
        assert(header->size > 0);
        device->mixer_data.channels_count = wdata->channels_count;
        memcpy(device->mixer_data.channels, wdata->channels, wdata->channels_count * sizeof(device->mixer_data.channels[0]));
    }
    else if((header->type == PLAYER_MSGTYPE_DATA) && (header->subtype == PLAYER_AUDIO_DATA_STATE))
    {
        player_audio_state_t *sdata = (player_audio_state_t *) data;
        assert(header->size > 0);
        device->state = sdata->state;
    }
    else
        PLAYERC_WARN2("skipping audio message with unknown type/subtype: %s/%d\n",
                      msgtype_to_str(header->type), header->subtype);
}
コード例 #19
0
ファイル: dev_ranger.c プロジェクト: Arkapravo/Player-3.0.2
// Calculate bearings
void playerc_ranger_calculate_bearings(playerc_ranger_t *device)
{
  double b;
  uint32_t ii;

  device->bearings_count = device->ranges_count;
  if (device->bearings_count == 0 && device->bearings != NULL)
  {
    free(device->bearings);
    device->bearings = NULL;
  }
  else
  {
    if((device->bearings = (double *) realloc(device->bearings, device->bearings_count * sizeof(double))) == NULL)
    {
      device->bearings_count = 0;
      PLAYERC_ERR("Failed to allocate space to store bearings");
      return;
    }

    if (device->bearings_count >= device->element_count)
    {
      if (device->element_count == 1)
      {
        b = device->min_angle;
        for (ii = 0; ii < device->bearings_count; ii++)
        {
          device->bearings[ii] = b + device->device_pose.pyaw;
          b += device->angular_res;
        }
      }
      else
      {
        for (ii = 0; ii < device->element_count; ii++)
        {
          device->bearings[ii] = device->element_poses[ii].pyaw;
        }
      }
    }
  }
}
コード例 #20
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Get the list of available device ids.  The data is written into the
// proxy structure rather than returned to the caller.
int playerc_client_get_devlist(playerc_client_t *client)
{
  uint32_t i;
  player_device_devlist_t *rep_config;

  if(playerc_client_request(client, NULL, PLAYER_PLAYER_REQ_DEVLIST,
                            NULL, (void**)&rep_config) < 0)
  {
    PLAYERC_ERR("failed to get response");
    return(-1);
  }

  for (i = 0; i < rep_config->devices_count; i++)
    client->devinfos[i].addr = rep_config->devices[i];
  client->devinfo_count = rep_config->devices_count;

  player_device_devlist_t_free(rep_config);

  // Now get the driver info
  return playerc_client_get_driverinfo(client);
}
コード例 #21
0
ファイル: device.c プロジェクト: Arkapravo/Player-3.0.2
int playerc_device_get_strprop(playerc_device_t *device, char *property, char **value)
{
  int result = 0;

  player_strprop_req_t req, *resp;
  req.key = property;
  req.key_count = strlen (property) + 1;
  req.value = NULL;
  req.value_count = 0;

  if((result = playerc_client_request(device->client, device,
                            PLAYER_GET_STRPROP_REQ, &req, (void**)&resp)) < 0)
    return result;

  if (((*value) = strdup (resp->value)) == NULL)
  {
    player_strprop_req_t_free(resp);
    PLAYERC_ERR ("Failed to allocate memory to store property value");
    return -1;
  }
  player_strprop_req_t_free(resp);
  return 0;
}
コード例 #22
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;
}
コード例 #23
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;
}
コード例 #24
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Read a raw packet
int playerc_client_readpacket(playerc_client_t *client,
                              player_msghdr_t *header,
                              char *data)
{
  int nbytes;
  player_pack_fn_t packfunc;
  int decode_msglen;

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

  while(client->read_xdrdata_len < PLAYERXDR_MSGHDR_SIZE)
  {
    nbytes = timed_recv(client->sock,
                        client->read_xdrdata + client->read_xdrdata_len,
                        PLAYERXDR_MSGHDR_SIZE - client->read_xdrdata_len,
                        0, (int) client->request_timeout * 1000);
    if (nbytes <= 0)
    {
      if(nbytes == 0)
        return -1;
      if(errno == EINTR)
        continue;
      else
      {
        STRERROR (PLAYERC_ERR2, "recv failed with error [%d: %s]");
        //playerc_client_disconnect(client);
        if(playerc_client_disconnect_retry(client) < 0)
          return(-1);
        else
          continue;
      }
    }
    client->read_xdrdata_len += nbytes;
  }

  // Unpack the header
  if(player_msghdr_pack(client->read_xdrdata,
                        PLAYERXDR_MSGHDR_SIZE,
                        header, PLAYERXDR_DECODE) < 0)
  {
    PLAYERC_ERR("failed to unpack header");
    return -1;
  }
  if (header->size > PLAYERXDR_MAX_MESSAGE_SIZE - PLAYERXDR_MSGHDR_SIZE)
  {
    PLAYERC_WARN1("packet is too large, %d bytes", header->size);
  }

  // Slide over the header
  memmove(client->read_xdrdata,
          client->read_xdrdata + PLAYERXDR_MSGHDR_SIZE,
          client->read_xdrdata_len - PLAYERXDR_MSGHDR_SIZE);
  client->read_xdrdata_len -= PLAYERXDR_MSGHDR_SIZE;

  while(client->read_xdrdata_len < header->size)
  {
    nbytes = timed_recv(client->sock,
                        client->read_xdrdata + client->read_xdrdata_len,
                        header->size - client->read_xdrdata_len,
                        0, (int) client->request_timeout*1000);
    if (nbytes <= 0)
    {
      if(errno == EINTR)
        continue;
      {
        STRERROR (PLAYERC_ERR2, "recv failed with error [%d: %s]");
        //playerc_client_disconnect(client);
        if(playerc_client_disconnect_retry(client) < 0)
          return(-1);
        else
        {
          /* Need to start over; the easiest way is to recursively call
           * myself.  Might be problematic... */
          return(playerc_client_readpacket(client,header,data));
        }
      }
    }
    client->read_xdrdata_len += nbytes;
  }

  if (header->size)
  {
  // Locate the appropriate unpacking function for the message body
    if(!(packfunc = playerxdr_get_packfunc(header->addr.interf, header->type,
                                         header->subtype)))
    {
      // TODO: Allow the user to register a callback to handle unsupported
      // messages
      PLAYERC_ERR4("skipping message from %s:%u with unsupported type %s:%u",
                 interf_to_str(header->addr.interf), header->addr.index, msgtype_to_str(header->type), header->subtype);

      // Slide over the body
      memmove(client->read_xdrdata,
            client->read_xdrdata + header->size,
            client->read_xdrdata_len - header->size);
      client->read_xdrdata_len -= header->size;

      return(-1);
    }

    // Unpack the body
    if((decode_msglen = (*packfunc)(client->read_xdrdata,
                                  header->size, data, PLAYERXDR_DECODE)) < 0)
    {
      PLAYERC_ERR4("decoding failed on message from %s:%u with type %s:%u",
                 interf_to_str(header->addr.interf), header->addr.index, msgtype_to_str(header->type), header->subtype);
      return(-1);
    }
  }
  else
  {
    decode_msglen = 0;
  }
  // Slide over the body
  memmove(client->read_xdrdata,
          client->read_xdrdata + header->size,
          client->read_xdrdata_len - header->size);
  client->read_xdrdata_len -= header->size;

  // Rewrite the header with the decoded message length
  header->size = decode_msglen;

  return 0;
}
コード例 #25
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Write a raw packet
int playerc_client_writepacket(playerc_client_t *client,
                               player_msghdr_t *header, const char *data)
{
  int bytes, ret, length;
  player_pack_fn_t packfunc;
  int encode_msglen;
  struct timeval curr;

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

  // Encode the body first, if it's non-NULL
  if(data)
  {
    // Locate the appropriate packing function for the message body
    if(!(packfunc = playerxdr_get_packfunc(header->addr.interf,
                                       header->type,
                                       header->subtype)))
    {
      // TODO: Allow the user to register a callback to handle unsupported
      // messages
      PLAYERC_ERR4("skipping message to %s:%u with unsupported type %s:%u",
                   interf_to_str(header->addr.interf), header->addr.index, msgtype_to_str(header->type), header->subtype);
      return(-1);
    }

    if((encode_msglen =
        (*packfunc)(client->write_xdrdata + PLAYERXDR_MSGHDR_SIZE,
                    PLAYER_MAX_MESSAGE_SIZE - PLAYERXDR_MSGHDR_SIZE,
                    (void*) data, PLAYERXDR_ENCODE)) < 0)
    {
      PLAYERC_ERR4("encoding failed on message from %s:%u with type %s:%u",
                   interf_to_str(header->addr.interf), header->addr.index, msgtype_to_str(header->type), header->subtype);
      return(-1);
    }
  }
  else
    encode_msglen = 0;

  // Write in the encoded size and current time
  header->size = encode_msglen;
  gettimeofday(&curr,NULL);
  header->timestamp = curr.tv_sec + curr.tv_usec / 1e6;
  // Pack the header
  if(player_msghdr_pack(client->write_xdrdata, PLAYERXDR_MSGHDR_SIZE,
                        header, PLAYERXDR_ENCODE) < 0)
  {
    PLAYERC_ERR("failed to pack header");
    return -1;
  }

  // Send the message
  length = PLAYERXDR_MSGHDR_SIZE + encode_msglen;
  bytes = PLAYERXDR_MSGHDR_SIZE + encode_msglen;
  do
  {
    ret = send(client->sock, &client->write_xdrdata[length-bytes],
               bytes, 0);
    if (ret > 0)
    {
      bytes -= ret;
    }
#if defined (WIN32)
    else if (ret < 0 && (errno != ERRNO_EAGAIN && errno != WSAEINPROGRESS))
#else
    else if (ret < 0 && (errno != ERRNO_EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK))
#endif
    {
      STRERROR (PLAYERC_ERR2, "send on body failed with error [%d: %s]");
      //playerc_client_disconnect(client);
      return(playerc_client_disconnect_retry(client));
    }
  } while (bytes);

  return 0;
}
コード例 #26
0
ファイル: client.c プロジェクト: brunoellll/player-git-svn
// Issue request and await reply (blocking).
int playerc_client_request(playerc_client_t *client,
                           playerc_device_t *deviceinfo,
                           uint8_t subtype,
                           const void *req_data, void **rep_data)
{
  int peek;
  struct timeval start;
  struct timeval curr;
  player_msghdr_t req_header, rep_header;
  memset(&req_header, 0, sizeof(req_header));


  if(deviceinfo == NULL)
  {
    req_header.addr.interf = PLAYER_PLAYER_CODE;
    req_header.type = PLAYER_MSGTYPE_REQ;
  }
  else
  {
    req_header.addr = deviceinfo->addr;
    req_header.type = PLAYER_MSGTYPE_REQ;
  }
  req_header.subtype = subtype;


  if (playerc_client_writepacket(client, &req_header, req_data) < 0)
    return -1;

  // Read packets until we get a reply.  Data packets get queued up
  // for later processing.
  gettimeofday(&start,NULL);
  for(curr = start; tdiff(start,curr)< client->request_timeout; gettimeofday(&curr,NULL))
  {
    // Peek at the socket
    if((peek = playerc_client_internal_peek(client,10)) < 0)
      return -1;
    else if(peek == 0)
      continue;

    // There's data on the socket, so read a packet (blocking).
    if(playerc_client_readpacket(client, &rep_header, client->data) < 0)
      return -1;

    if (rep_header.type == PLAYER_MSGTYPE_DATA || rep_header.type == PLAYER_MSGTYPE_SYNCH)
    {
      // Queue up any incoming data and sync packets for later processing
      playerc_client_push(client, &rep_header, client->data);
    }
    else if(rep_header.type == PLAYER_MSGTYPE_RESP_ACK)
    {
      // Using TCP, we only need to check the interface and index
      if (rep_header.addr.interf != req_header.addr.interf ||
          rep_header.addr.index != req_header.addr.index ||
          rep_header.subtype != req_header.subtype)
      {
        PLAYERC_ERR6("got the wrong kind of reply (%d %d %d != %d %d %d).",rep_header.addr.interf,
                rep_header.addr.index, rep_header.subtype, req_header.addr.interf, req_header.addr.index,
                req_header.subtype);
        return -1;
      }
      if (rep_header.size > 0)
      {
        if (rep_data)
        {
          *rep_data = playerxdr_clone_message(client->data,rep_header.addr.interf, rep_header.type, rep_header.subtype);
        }
        playerxdr_cleanup_message(client->data,rep_header.addr.interf, rep_header.type, rep_header.subtype);
      }
      return(0);
    }
    else if (rep_header.type == PLAYER_MSGTYPE_RESP_NACK)
    {
      // Using TCP, we only need to check the interface and index
      if (rep_header.addr.interf != req_header.addr.interf ||
          rep_header.addr.index != req_header.addr.index ||
          rep_header.subtype != req_header.subtype)
      {
        PLAYERC_ERR("got the wrong kind of reply (not good).");
        return -1;
      }
      PLAYERC_ERR("got NACK from request");
      return -2;
    }
  }

  PLAYERC_ERR4("timed out waiting for server reply to request %s:%d:%s:%d", interf_to_str(req_header.addr.interf), req_header.addr.index, msgtype_to_str(req_header.type), req_header.subtype);
  return -1;
}