static void
remove_remote(struct remote_info *ri)
{
  unlink_remote(ri);

  free_remote(ri);
}
Beispiel #2
0
void close_and_free_remote(EV_P_ struct remote *remote) {
    if (remote != NULL) {
        ev_timer_stop(EV_A_ &remote->send_ctx->watcher);
        ev_io_stop(EV_A_ &remote->send_ctx->io);
        ev_io_stop(EV_A_ &remote->recv_ctx->io);
        close(remote->fd);
        free_remote(remote);
    }
}
static void
do_pairing(struct remote_info *ri)
{
  char req_uri[128];
  char *pairing_hash;
  int ret;

  pairing_hash = itunes_pairing_hash(ri->paircode, ri->pin);
  if (!pairing_hash)
    {
      DPRINTF(E_LOG, L_REMOTE, "Could not compute pairing hash!\n");

      goto hash_fail;
    }

  DPRINTF(E_DBG, L_REMOTE, "Pairing hash for %s/%s: %s\n", ri->pi.remote_id, ri->pi.name, pairing_hash);

  /* Prepare request URI */
  /* The servicename variable is the mDNS service group name; currently it's
   * a hash of the library name, but in iTunes the service name and the library
   * ID (DbId) are different (see comment in main.c).
   * Remote uses the service name to perform mDNS lookups.
   */
  ret = snprintf(req_uri, sizeof(req_uri), "/pair?pairingcode=%s&servicename=%016" PRIX64, pairing_hash, libhash);
  free(pairing_hash);
  if ((ret < 0) || (ret >= sizeof(req_uri)))
    {
      DPRINTF(E_WARN, L_REMOTE, "Request URI for pairing exceeds buffer size\n");

      goto req_uri_fail;
    }

  /* Fire up the request */
  if (ri->v6_address)
    {
      ret = send_pairing_request(ri, req_uri, AF_INET6);
      if (ret == 0)
	return;

      DPRINTF(E_WARN, L_REMOTE, "Could not send pairing request on IPv6\n");
    }

  ret = send_pairing_request(ri, req_uri, AF_INET);
  if (ret < 0)
    {
      DPRINTF(E_WARN, L_REMOTE, "Could not send pairing request on IPv4\n");

      goto pairing_fail;
    }

  return;

 pairing_fail:
 req_uri_fail:
 hash_fail:
  free_remote(ri);
}
static void
pairing_free_cb(void *arg)
{
  struct remote_info *ri;

  ri = (struct remote_info *)arg;

  free_remote(ri);
}
Beispiel #5
0
void close_and_free_remote(EV_P_ struct remote *remote) {
    if (remote != NULL) {
        ev_io_stop(EV_A_ &remote->send_ctx->io);
        ev_io_stop(EV_A_ &remote->recv_ctx->io);
        close(remote->fd);
        free_remote(remote);
    }
    if (verbose) {
        LOGD("current remote connection: %d", remote_conn);
    }
}
Beispiel #6
0
/* Thread: main */
void
remote_pairing_deinit(void)
{
  struct remote_info *ri;

  for (ri = remote_list; remote_list; ri = remote_list)
    {
      remote_list = ri->next;

      free_remote(ri);
    }

#ifdef USE_EVENTFD
  close(pairing_efd);
#else
  close(pairing_pipe[0]);
  close(pairing_pipe[1]);
#endif
}
Beispiel #7
0
static void
remote_close_cb(uv_handle_t *handle) {
    struct remote_context *remote = handle->data;
    free_remote(remote);
}
Beispiel #8
0
/* Thread: main (pairing) */
static void
pairing_request_cb(struct evhttp_request *req, void *arg)
{
  struct remote_info *ri;
  uint8_t *response;
  char guid[17];
  int len;
  int i;
  int ret;

  ri = (struct remote_info *)arg;

  if (!req)
    goto cleanup;

  if (req->response_code != HTTP_OK)
    {
      DPRINTF(E_LOG, L_REMOTE, "Pairing failed with Remote %s/%s, HTTP response code %d\n", ri->pi.remote_id, ri->pi.name, req->response_code);

      goto cleanup;
    }

  if (EVBUFFER_LENGTH(req->input_buffer) < 8)
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response too short\n", ri->pi.remote_id, ri->pi.name);

      goto cleanup;
    }

  response = EVBUFFER_DATA(req->input_buffer);

  if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'a'))
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: unknown pairing response, expected cmpa\n", ri->pi.remote_id, ri->pi.name);

      goto cleanup;
    }

  len = (response[4] << 24) | (response[5] << 16) | (response[6] << 8) | (response[7]);
  if (EVBUFFER_LENGTH(req->input_buffer) < 8 + len)
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response truncated (got %d expected %d)\n",
	      ri->pi.remote_id, ri->pi.name, (int)EVBUFFER_LENGTH(req->input_buffer), len + 8);

      goto cleanup;
    }

  response += 8;

  for (; len > 0; len--, response++)
    {
      if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'g'))
	continue;
      else
	{
	  len -= 8;
	  response += 8;

	  break;
	}
    }

  if (len < 8)
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: cmpg truncated in pairing response\n", ri->pi.remote_id, ri->pi.name);

      goto cleanup;
    }

  for (i = 0; i < 8; i++)
    sprintf(guid + (2 * i), "%02X", response[i]);

  ri->pi.guid = strdup(guid);

  DPRINTF(E_INFO, L_REMOTE, "Pairing succeeded with Remote '%s' (id %s), GUID: %s\n", ri->pi.name, ri->pi.remote_id, guid);

  ret = db_pairing_add(&ri->pi);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_REMOTE, "Failed to register pairing!\n");

      goto cleanup;
    }

 cleanup:
  evhttp_connection_free(ri->evcon);
  free_remote(ri);
}