summaryrefslogtreecommitdiffstats
path: root/daemon/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/client.c')
-rw-r--r--daemon/client.c198
1 files changed, 187 insertions, 11 deletions
diff --git a/daemon/client.c b/daemon/client.c
index 194632d..80bc0c7 100644
--- a/daemon/client.c
+++ b/daemon/client.c
@@ -32,12 +32,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <sys/un.h>
#include <arpa/inet.h>
+#ifdef HAVE_PLIST
+#include <plist/plist.h>
+#endif
+
#include "log.h"
#include "usb.h"
#include "client.h"
#include "device.h"
+#ifdef HAVE_PLIST
+#define CMD_BUF_SIZE 1024
+#else
#define CMD_BUF_SIZE 256
+#endif
#define REPLY_BUF_SIZE 1024
enum client_state {
@@ -61,6 +69,7 @@ struct mux_client {
uint32_t connect_tag;
int connect_device;
enum client_state state;
+ uint32_t proto_version;
};
static struct collection client_list;
@@ -155,7 +164,7 @@ void client_get_fds(struct fdlist *list)
static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length)
{
struct usbmuxd_header hdr;
- hdr.version = USBMUXD_PROTOCOL_VERSION;
+ hdr.version = client->proto_version;
hdr.length = sizeof(hdr) + payload_length;
hdr.message = msg;
hdr.tag = tag;
@@ -175,7 +184,30 @@ static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtyp
static int send_result(struct mux_client *client, uint32_t tag, uint32_t result)
{
- return send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t));
+ int res = -1;
+#ifdef HAVE_PLIST
+ if (client->proto_version == 1) {
+ /* XML plist packet */
+ char *xml = NULL;
+ uint32_t xmlsize = 0;
+ plist_t dict = plist_new_dict();
+ plist_dict_insert_item(dict, "MessageType", plist_new_string("Result"));
+ plist_dict_insert_item(dict, "Number", plist_new_uint(result));
+ plist_to_xml(dict, &xml, &xmlsize);
+ plist_free(dict);
+ if (xml) {
+ res = send_pkt(client, tag, MESSAGE_PLIST, xml, xmlsize);
+ free(xml);
+ } else {
+ usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__);
+ }
+ } else
+#endif
+ {
+ /* binary packet */
+ res = send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t));
+ }
+ return res;
}
int client_notify_connect(struct mux_client *client, enum usbmuxd_result result)
@@ -203,19 +235,73 @@ int client_notify_connect(struct mux_client *client, enum usbmuxd_result result)
static int notify_device_add(struct mux_client *client, struct device_info *dev)
{
- struct usbmuxd_device_record dmsg;
- memset(&dmsg, 0, sizeof(dmsg));
- dmsg.device_id = dev->id;
- strncpy(dmsg.serial_number, dev->serial, 256);
- dmsg.serial_number[255] = 0;
- dmsg.location = dev->location;
- dmsg.product_id = dev->pid;
- return send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg));
+ int res = -1;
+#ifdef HAVE_PLIST
+ if (client->proto_version == 1) {
+ /* XML plist packet */
+ char *xml = NULL;
+ uint32_t xmlsize = 0;
+ plist_t dict = plist_new_dict();
+ plist_dict_insert_item(dict, "MessageType", plist_new_string("Attached"));
+ plist_t props = plist_new_dict();
+ // TODO: get current usb speed
+ plist_dict_insert_item(props, "ConnectionSpeed", plist_new_uint(480000000));
+ plist_dict_insert_item(props, "ConnectionType", plist_new_string("USB"));
+ plist_dict_insert_item(props, "DeviceID", plist_new_uint(dev->id));
+ plist_dict_insert_item(props, "LocationID", plist_new_uint(dev->location));
+ plist_dict_insert_item(props, "ProductID", plist_new_uint(dev->pid));
+ plist_dict_insert_item(props, "SerialNumber", plist_new_string(dev->serial));
+ plist_dict_insert_item(dict, "Properties", props);
+ plist_to_xml(dict, &xml, &xmlsize);
+ plist_free(dict);
+ if (xml) {
+ res = send_pkt(client, 0, MESSAGE_PLIST, xml, xmlsize);
+ free(xml);
+ } else {
+ usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__);
+ }
+ } else
+#endif
+ {
+ /* binary packet */
+ struct usbmuxd_device_record dmsg;
+ memset(&dmsg, 0, sizeof(dmsg));
+ dmsg.device_id = dev->id;
+ strncpy(dmsg.serial_number, dev->serial, 256);
+ dmsg.serial_number[255] = 0;
+ dmsg.location = dev->location;
+ dmsg.product_id = dev->pid;
+ res = send_pkt(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg));
+ }
+ return res;
}
static int notify_device_remove(struct mux_client *client, uint32_t device_id)
{
- return send_pkt(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t));
+ int res = -1;
+#ifdef HAVE_PLIST
+ if (client->proto_version == 1) {
+ /* XML plist packet */
+ char *xml = NULL;
+ uint32_t xmlsize = 0;
+ plist_t dict = plist_new_dict();
+ plist_dict_insert_item(dict, "MessageType", plist_new_string("Detached"));
+ plist_dict_insert_item(dict, "DeviceID", plist_new_uint(device_id));
+ plist_to_xml(dict, &xml, &xmlsize);
+ plist_free(dict);
+ if (xml) {
+ res = send_pkt(client, 0, MESSAGE_PLIST, xml, xmlsize);
+ free(xml);
+ } else {
+ usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__);
+ }
+ } else
+#endif
+ {
+ /* binary packet */
+ res = send_pkt(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t));
+ }
+ return res;
}
static int start_listen(struct mux_client *client)
@@ -263,7 +349,92 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr)
}
struct usbmuxd_connect_request *ch;
+#ifdef HAVE_PLIST
+ char *payload;
+ uint32_t payload_size;
+#endif
+
switch(hdr->message) {
+#ifdef HAVE_PLIST
+ case MESSAGE_PLIST:
+ client->proto_version = 1;
+ payload = (char*)(hdr) + sizeof(struct usbmuxd_header);
+ payload_size = hdr->length - sizeof(struct usbmuxd_header);
+ plist_t dict = NULL;
+ plist_from_xml(payload, payload_size, &dict);
+ if (!dict) {
+ usbmuxd_log(LL_ERROR, "Could not parse plist from payload!");
+ return -1;
+ } else {
+ char *message = NULL;
+ plist_t node = plist_dict_get_item(dict, "MessageType");
+ plist_get_string_val(node, &message);
+ if (!message) {
+ usbmuxd_log(LL_ERROR, "Could not extract MessageType from plist!");
+ plist_free(dict);
+ return -1;
+ }
+ if (!strcmp(message, "Listen")) {
+ free(message);
+ plist_free(dict);
+ if (send_result(client, hdr->tag, 0) < 0)
+ return -1;
+ usbmuxd_log(LL_DEBUG, "Client %d now LISTENING", client->fd);
+ return start_listen(client);
+ } else if (!strcmp(message, "Connect")) {
+ uint64_t val;
+ uint16_t portnum = 0;
+ uint32_t device_id = 0;
+ free(message);
+ // get device id
+ node = plist_dict_get_item(dict, "DeviceID");
+ if (!node) {
+ usbmuxd_log(LL_ERROR, "Received connect request without device_id!");
+ plist_free(dict);
+ if (send_result(client, hdr->tag, RESULT_BADDEV) < 0)
+ return -1;
+ return 0;
+ }
+ val = 0;
+ plist_get_uint_val(node, &val);
+ device_id = (uint32_t)val;
+
+ // get port number
+ node = plist_dict_get_item(dict, "PortNumber");
+ if (!node) {
+ usbmuxd_log(LL_ERROR, "Received connect request without port number!");
+ plist_free(dict);
+ if (send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0)
+ return -1;
+ return 0;
+ }
+ val = 0;
+ plist_get_uint_val(node, &val);
+ portnum = (uint16_t)val;
+
+ usbmuxd_log(LL_DEBUG, "Client %d connection request to device %d port %d", client->fd, device_id, ntohs(portnum));
+ res = device_start_connect(device_id, ntohs(portnum), client);
+ if(res < 0) {
+ if (send_result(client, hdr->tag, -res) < 0)
+ return -1;
+ } else {
+ client->connect_tag = hdr->tag;
+ client->connect_device = device_id;
+ client->state = CLIENT_CONNECTING1;
+ }
+ return 0;
+ } else {
+ usbmuxd_log(LL_ERROR, "Unexpected command '%s' received!", message);
+ free(message);
+ plist_free(dict);
+ if (send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0)
+ return -1;
+ return 0;
+ }
+ }
+ // should not be reached?!
+ return -1;
+#endif
case MESSAGE_LISTEN:
if(send_result(client, hdr->tag, 0) < 0)
return -1;
@@ -341,8 +512,13 @@ static void process_recv(struct mux_client *client)
did_read = 1;
}
struct usbmuxd_header *hdr = (void*)client->ib_buf;
+#ifdef HAVE_PLIST
+ if((hdr->version != 0) && (hdr->version != 1)) {
+ usbmuxd_log(LL_INFO, "Client %d version mismatch: expected 0 or 1, got %d", client->fd, hdr->version);
+#else
if(hdr->version != USBMUXD_PROTOCOL_VERSION) {
usbmuxd_log(LL_INFO, "Client %d version mismatch: expected %d, got %d", client->fd, USBMUXD_PROTOCOL_VERSION, hdr->version);
+#endif
client_close(client);
}
if(hdr->length > client->ib_capacity) {