Ejemplo n.º 1
0
static int create_control_socket_event(struct event_base * base, control_thread_context_t * context, struct bufferevent ** control_event)
{
    struct bufferevent * new_event = NULL;
    int sock_fd = -1;
    struct timeval read_timeout = { 0 };

    /* Get the connection's socket */
    if (IDEVICE_E_SUCCESS != idevice_connection_get_fd(context->control_connection, &sock_fd)) {
        error("ERROR: Failed to get the socket for the reverse proxy's control connection\n");
        goto cleanup;
    }

    /* libevent needs sockets to be non-blocking */
    if (0 != evutil_make_socket_nonblocking(sock_fd)) {
        error("ERROR: Failed to make the reverse proxy's control socket non-blocking\n");
        goto cleanup;
    }

    /* Create a new bufferevent for the control socket */
    new_event = bufferevent_socket_new(base, sock_fd, 0);
    if (NULL == new_event) {
        error("ERROR: Failed to initialize the reverse proxy's control socket\n");
        goto cleanup;
    }

    /* Init the new bufferevent */
    bufferevent_setcb(new_event, rproxy_control_read_cb, NULL, rproxy_control_event_cb, (void*)context);
    read_timeout.tv_sec = CONTROL_RECV_TIMEOUT;
    read_timeout.tv_usec = 0;
    bufferevent_set_timeouts(new_event, &read_timeout, NULL);

    /* Each control message is a 32bit unsigned int, so tell libevent to call
     * our read callback only when there is enough data */
    bufferevent_setwatermark(new_event, EV_READ, sizeof(uint32_t), 0);

    /* Enable both read & write events */
    if (0 != bufferevent_enable(new_event, EV_READ | EV_WRITE)) {
        error("ERROR: Failed to enable the proxy's control socket\n");
        goto cleanup;
    }

    *control_event = new_event;
    return 0;

cleanup:
    if (new_event) {
        bufferevent_free(new_event);
    }

    return -1;
}
int wi_connect(const char *device_id, char **to_device_id,
    char **to_device_name, int recv_timeout) {
  int ret = -1;

  idevice_t phone = NULL;
  plist_t node = NULL;
  lockdownd_service_descriptor_t service = NULL;
  lockdownd_client_t client = NULL;
  idevice_connection_t connection = NULL;
  int fd = -1;

  // get phone
  if (idevice_new(&phone, device_id)) {
    perror("No iPhone found, is it plugged in?");
    goto leave_cleanup;
  }

  // connect to lockdownd
  if (lockdownd_client_new_with_handshake(
        phone, &client, "ios_webkit_debug_proxy")) {
    perror("Could not connect to lockdownd. Exiting.");
    goto leave_cleanup;
  }

  // get device info
  if (to_device_id &&
      !lockdownd_get_value(client, NULL, "UniqueDeviceID", &node)) {
    plist_get_string_val(node, to_device_id);
    plist_free(node);
    node = NULL;
  }
  if (to_device_name &&
      !lockdownd_get_value(client, NULL, "DeviceName", &node)) {
    plist_get_string_val(node, to_device_name);
  }

  // start webinspector, get port
  if (lockdownd_start_service(client, "com.apple.webinspector", &service) ||
      !service->port) {
    perror("Could not start com.apple.webinspector!");
    goto leave_cleanup;
  }

  // connect to webinspector
  if (idevice_connect(phone, service->port, &connection)) {
    perror("idevice_connect failed!");
    goto leave_cleanup;
  }

  if (client) {
    // not needed anymore
    lockdownd_client_free(client);
    client = NULL;
  }

  // extract the connection fd
  if (idevice_connection_get_fd(connection, &fd)) {
    perror("Unable to get connection file descriptor.");
    goto leave_cleanup;
  }

  if (recv_timeout < 0) {
    int opts = fcntl(fd, F_GETFL);
    if (!opts || fcntl(fd, F_SETFL, (opts | O_NONBLOCK)) < 0) {
      perror("Could not set socket to non-blocking");
      goto leave_cleanup;
    }
  } else {
    long millis = (recv_timeout > 0 ? recv_timeout : 5000);
    struct timeval tv;
    tv.tv_sec = (time_t) (millis / 1000);
    tv.tv_usec = (time_t) ((millis - (tv.tv_sec * 1000)) * 1000);
    if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
          sizeof(tv))) {
      perror("Could not set socket receive timeout");
      goto leave_cleanup;
    }
  }

  // success
  ret = fd;

leave_cleanup:
  if (ret < 0 && fd > 0) {
    close(fd);
  }
  // don't call usbmuxd_disconnect(fd)!
  //idevice_disconnect(connection);
  free(connection);
  lockdownd_client_free(client);
  plist_free(node);
  idevice_free(phone);
  return ret;
}