diff options
Diffstat (limited to 'src/client.c')
-rw-r--r-- | src/client.c | 172 |
1 files changed, 113 insertions, 59 deletions
diff --git a/src/client.c b/src/client.c index 85d0c8b..dbbdd5f 100644 --- a/src/client.c +++ b/src/client.c @@ -31,13 +31,15 @@ #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> +#include <netinet/in.h> #include <netinet/tcp.h> #include <sys/un.h> #include <arpa/inet.h> -#include <pthread.h> #include <fcntl.h> #include <plist/plist.h> +#include <libimobiledevice-glue/collection.h> +#include <libimobiledevice-glue/thread.h> #include "log.h" #include "usb.h" @@ -75,9 +77,30 @@ struct mux_client { }; static struct collection client_list; -pthread_mutex_t client_list_mutex; +mutex_t client_list_mutex; static uint32_t client_number = 0; +#ifdef SO_PEERCRED +static char* _get_process_name_by_pid(const int pid) +{ + char* name = (char*)calloc(1024, sizeof(char)); + if(name) { + sprintf(name, "/proc/%d/cmdline", pid); + FILE* f = fopen(name, "r"); + if(f) { + size_t size; + size = fread(name, sizeof(char), 1024, f); + if(size > 0) { + if('\n' == name[size-1]) + name[size-1]='\0'; + } + fclose(f); + } + } + return name; +} +#endif + /** * Receive raw data from the client socket. * @@ -203,32 +226,64 @@ int client_accept(int listenfd) client->events = POLLIN; client->info = NULL; - pthread_mutex_lock(&client_list_mutex); + mutex_lock(&client_list_mutex); client->number = client_number++; collection_add(&client_list, client); - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); #ifdef SO_PEERCRED if (log_level >= LL_INFO) { struct ucred cr; len = sizeof(struct ucred); - getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &cr, &len); + getsockopt(client->fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); if (getpid() == cr.pid) { - usbmuxd_log(LL_INFO, "New client on fd %d (self)", client->fd); + usbmuxd_log(LL_INFO, "Client %d accepted: %s[%d]", client->fd, PACKAGE_NAME, cr.pid); } else { - usbmuxd_log(LL_INFO, "New client on fd %d (pid %d)", client->fd, cr.pid); + char* process_name = _get_process_name_by_pid(cr.pid); + usbmuxd_log(LL_INFO, "Client %d accepted: %s[%d]", client->fd, process_name, cr.pid); + free(process_name); } } #else - usbmuxd_log(LL_INFO, "New client on fd %d", client->fd); + usbmuxd_log(LL_INFO, "Client %d accepted", client->fd); #endif return client->fd; } void client_close(struct mux_client *client) { - usbmuxd_log(LL_INFO, "Disconnecting client fd %d", client->fd); + int found = 0; + mutex_lock(&client_list_mutex); + FOREACH(struct mux_client *lc, &client_list) { + if (client == lc) { + found = 1; + break; + } + } ENDFOREACH + if (!found) { + // in case we get called again but client was already freed + usbmuxd_log(LL_DEBUG, "%s: ignoring for non-existing client %p", __func__, client); + mutex_unlock(&client_list_mutex); + return; + } +#ifdef SO_PEERCRED + if (log_level >= LL_INFO) { + struct ucred cr; + socklen_t len = sizeof(struct ucred); + getsockopt(client->fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); + + if (getpid() == cr.pid) { + usbmuxd_log(LL_INFO, "Client %d is going to be disconnected: %s[%d]", client->fd, PACKAGE_NAME, cr.pid); + } else { + char* process_name = _get_process_name_by_pid(cr.pid); + usbmuxd_log(LL_INFO, "Client %d is going to be disconnected: %s[%d]", client->fd, process_name, cr.pid); + free(process_name); + } + } +#else + usbmuxd_log(LL_INFO, "Client %d is going to be disconnected", client->fd); +#endif if(client->state == CLIENT_CONNECTING1 || client->state == CLIENT_CONNECTING2) { usbmuxd_log(LL_INFO, "Client died mid-connect, aborting device %d connection", client->connect_device); client->state = CLIENT_DEAD; @@ -239,29 +294,28 @@ void client_close(struct mux_client *client) free(client->ib_buf); plist_free(client->info); - pthread_mutex_lock(&client_list_mutex); collection_remove(&client_list, client); - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); free(client); } void client_get_fds(struct fdlist *list) { - pthread_mutex_lock(&client_list_mutex); + mutex_lock(&client_list_mutex); FOREACH(struct mux_client *client, &client_list) { fdlist_add(list, FD_CLIENT, client->fd, client->events); } ENDFOREACH - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); } -static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length) +static int output_buffer_add_message(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtype msg, void *payload, int payload_length) { struct usbmuxd_header hdr; hdr.version = client->proto_version; hdr.length = sizeof(hdr) + payload_length; hdr.message = msg; hdr.tag = tag; - usbmuxd_log(LL_DEBUG, "send_pkt fd %d tag %d msg %d payload_length %d", client->fd, tag, msg, payload_length); + usbmuxd_log(LL_DEBUG, "Client %d output buffer got tag %d msg %d payload_length %d", client->fd, tag, msg, payload_length); uint32_t available = client->ob_capacity - client->ob_size; /* the output buffer _should_ be large enough, but just in case */ @@ -285,14 +339,14 @@ static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtyp return hdr.length; } -static int send_plist_pkt(struct mux_client *client, uint32_t tag, plist_t plist) +static int send_plist(struct mux_client *client, uint32_t tag, plist_t plist) { int res = -1; char *xml = NULL; uint32_t xmlsize = 0; plist_to_xml(plist, &xml, &xmlsize); if (xml) { - res = send_pkt(client, tag, MESSAGE_PLIST, xml, xmlsize); + res = output_buffer_add_message(client, tag, MESSAGE_PLIST, xml, xmlsize); free(xml); } else { usbmuxd_log(LL_ERROR, "%s: Could not convert plist to xml", __func__); @@ -308,11 +362,11 @@ static int send_result(struct mux_client *client, uint32_t tag, uint32_t result) plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "MessageType", plist_new_string("Result")); plist_dict_set_item(dict, "Number", plist_new_uint(result)); - res = send_plist_pkt(client, tag, dict); + res = send_plist(client, tag, dict); plist_free(dict); } else { /* binary packet */ - res = send_pkt(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t)); + res = output_buffer_add_message(client, tag, MESSAGE_RESULT, &result, sizeof(uint32_t)); } return res; } @@ -378,7 +432,7 @@ static int send_device_list(struct mux_client *client, uint32_t tag) free(devs); plist_dict_set_item(dict, "DeviceList", devices); - res = send_plist_pkt(client, tag, dict); + res = send_plist(client, tag, dict); plist_free(dict); return res; } @@ -390,7 +444,7 @@ static int send_listener_list(struct mux_client *client, uint32_t tag) plist_t dict = plist_new_dict(); plist_t listeners = plist_new_array(); - pthread_mutex_lock(&client_list_mutex); + mutex_lock(&client_list_mutex); FOREACH(struct mux_client *lc, &client_list) { if (lc->state == CLIENT_LISTEN) { plist_t n = NULL; @@ -437,10 +491,10 @@ static int send_listener_list(struct mux_client *client, uint32_t tag) plist_array_append_item(listeners, l); } } ENDFOREACH - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); plist_dict_set_item(dict, "ListenerList", listeners); - res = send_plist_pkt(client, tag, dict); + res = send_plist(client, tag, dict); plist_free(dict); return res; @@ -456,7 +510,7 @@ static int send_system_buid(struct mux_client *client, uint32_t tag) plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "BUID", plist_new_string(buid)); free(buid); - res = send_plist_pkt(client, tag, dict); + res = send_plist(client, tag, dict); plist_free(dict); return res; } @@ -472,12 +526,12 @@ static int send_pair_record(struct mux_client *client, uint32_t tag, const char* } config_get_device_record(record_id, &record_data, &record_size); - + if (record_data) { plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "PairRecordData", plist_new_data(record_data, record_size)); free(record_data); - res = send_plist_pkt(client, tag, dict); + res = send_plist(client, tag, dict); plist_free(dict); } else { res = send_result(client, tag, ENOENT); @@ -485,13 +539,13 @@ static int send_pair_record(struct mux_client *client, uint32_t tag, const char* return res; } -static int notify_device_add(struct mux_client *client, struct device_info *dev) +static int send_device_add(struct mux_client *client, struct device_info *dev) { int res = -1; if (client->proto_version == 1) { /* XML plist packet */ plist_t dict = create_device_attached_plist(dev); - res = send_plist_pkt(client, 0, dict); + res = send_plist(client, 0, dict); plist_free(dict); } else { /* binary packet */ @@ -502,12 +556,12 @@ static int notify_device_add(struct mux_client *client, struct device_info *dev) 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)); + res = output_buffer_add_message(client, 0, MESSAGE_DEVICE_ADD, &dmsg, sizeof(dmsg)); } return res; } -static int notify_device_remove(struct mux_client *client, uint32_t device_id) +static int send_device_remove(struct mux_client *client, uint32_t device_id) { int res = -1; if (client->proto_version == 1) { @@ -515,16 +569,16 @@ static int notify_device_remove(struct mux_client *client, uint32_t device_id) plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "MessageType", plist_new_string("Detached")); plist_dict_set_item(dict, "DeviceID", plist_new_uint(device_id)); - res = send_plist_pkt(client, 0, dict); + res = send_plist(client, 0, dict); plist_free(dict); } else { /* binary packet */ - res = send_pkt(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t)); + res = output_buffer_add_message(client, 0, MESSAGE_DEVICE_REMOVE, &device_id, sizeof(uint32_t)); } return res; } -static int notify_device_paired(struct mux_client *client, uint32_t device_id) +static int send_device_paired(struct mux_client *client, uint32_t device_id) { int res = -1; if (client->proto_version == 1) { @@ -532,12 +586,12 @@ static int notify_device_paired(struct mux_client *client, uint32_t device_id) plist_t dict = plist_new_dict(); plist_dict_set_item(dict, "MessageType", plist_new_string("Paired")); plist_dict_set_item(dict, "DeviceID", plist_new_uint(device_id)); - res = send_plist_pkt(client, 0, dict); + res = send_plist(client, 0, dict); plist_free(dict); } else { /* binary packet */ - res = send_pkt(client, 0, MESSAGE_DEVICE_PAIRED, &device_id, sizeof(uint32_t)); + res = output_buffer_add_message(client, 0, MESSAGE_DEVICE_PAIRED, &device_id, sizeof(uint32_t)); } return res; } @@ -553,7 +607,7 @@ static int start_listen(struct mux_client *client) count = device_get_list(0, &devs); dev = devs; for(i=0; devs && i < count; i++) { - if(notify_device_add(client, dev++) < 0) { + if(send_device_add(client, dev++) < 0) { free(devs); return -1; } @@ -604,13 +658,13 @@ static void update_client_info(struct mux_client *client, plist_t dict) client->info = info; } -static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) +static int handle_command(struct mux_client *client, struct usbmuxd_header *hdr) { int res; - usbmuxd_log(LL_DEBUG, "Client command in fd %d len %d ver %d msg %d tag %d", client->fd, hdr->length, hdr->version, hdr->message, hdr->tag); + usbmuxd_log(LL_DEBUG, "Client %d command len %d ver %d msg %d tag %d", client->fd, hdr->length, hdr->version, hdr->message, hdr->tag); if(client->state != CLIENT_COMMAND) { - usbmuxd_log(LL_ERROR, "Client %d command received in the wrong state", client->fd); + usbmuxd_log(LL_ERROR, "Client %d command received in the wrong state, got %d but want %d", client->fd, client->state, CLIENT_COMMAND); if(send_result(client, hdr->tag, RESULT_BADCOMMAND) < 0) return -1; client_close(client); @@ -691,7 +745,7 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) portnum = (uint16_t)val; plist_free(dict); - usbmuxd_log(LL_DEBUG, "Client %d connection request to device %d port %d", client->fd, device_id, ntohs(portnum)); + usbmuxd_log(LL_DEBUG, "Client %d requesting connection 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) @@ -839,7 +893,7 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) return -1; } -static void process_send(struct mux_client *client) +static void output_buffer_process(struct mux_client *client) { int res; if(!client->ob_size) { @@ -849,7 +903,7 @@ static void process_send(struct mux_client *client) } res = send(client->fd, client->ob_buf, client->ob_size, 0); if(res <= 0) { - usbmuxd_log(LL_ERROR, "Send to client fd %d failed: %d %s", client->fd, res, strerror(errno)); + usbmuxd_log(LL_ERROR, "Sending to client fd %d failed: %d %s", client->fd, res, strerror(errno)); client_close(client); return; } @@ -869,7 +923,7 @@ static void process_send(struct mux_client *client) memmove(client->ob_buf, client->ob_buf + res, client->ob_size); } } -static void process_recv(struct mux_client *client) +static void input_buffer_process(struct mux_client *client) { int res; int did_read = 0; @@ -916,21 +970,21 @@ static void process_recv(struct mux_client *client) if(client->ib_size < hdr->length) return; } - client_command(client, hdr); + handle_command(client, hdr); client->ib_size = 0; } void client_process(int fd, short events) { struct mux_client *client = NULL; - pthread_mutex_lock(&client_list_mutex); + mutex_lock(&client_list_mutex); FOREACH(struct mux_client *lc, &client_list) { if(lc->fd == fd) { client = lc; break; } } ENDFOREACH - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); if(!client) { usbmuxd_log(LL_INFO, "client_process: fd %d not found in client list", fd); @@ -942,9 +996,9 @@ void client_process(int fd, short events) device_client_process(client->connect_device, client, events); } else { if(events & POLLIN) { - process_recv(client); + input_buffer_process(client); } else if(events & POLLOUT) { //not both in case client died as part of process_recv - process_send(client); + output_buffer_process(client); } } @@ -952,45 +1006,45 @@ void client_process(int fd, short events) void client_device_add(struct device_info *dev) { - pthread_mutex_lock(&client_list_mutex); + mutex_lock(&client_list_mutex); usbmuxd_log(LL_DEBUG, "client_device_add: id %d, location 0x%x, serial %s", dev->id, dev->location, dev->serial); device_set_visible(dev->id); FOREACH(struct mux_client *client, &client_list) { if(client->state == CLIENT_LISTEN) - notify_device_add(client, dev); + send_device_add(client, dev); } ENDFOREACH - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); } void client_device_remove(int device_id) { - pthread_mutex_lock(&client_list_mutex); + mutex_lock(&client_list_mutex); uint32_t id = device_id; usbmuxd_log(LL_DEBUG, "client_device_remove: id %d", device_id); FOREACH(struct mux_client *client, &client_list) { if(client->state == CLIENT_LISTEN) - notify_device_remove(client, id); + send_device_remove(client, id); } ENDFOREACH - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); } void client_device_paired(int device_id) { - pthread_mutex_lock(&client_list_mutex); + mutex_lock(&client_list_mutex); uint32_t id = device_id; usbmuxd_log(LL_DEBUG, "client_device_paired: id %d", device_id); FOREACH(struct mux_client *client, &client_list) { if (client->state == CLIENT_LISTEN) - notify_device_paired(client, id); + send_device_paired(client, id); } ENDFOREACH - pthread_mutex_unlock(&client_list_mutex); + mutex_unlock(&client_list_mutex); } void client_init(void) { usbmuxd_log(LL_DEBUG, "client_init"); collection_init(&client_list); - pthread_mutex_init(&client_list_mutex, NULL); + mutex_init(&client_list_mutex); } void client_shutdown(void) @@ -999,6 +1053,6 @@ void client_shutdown(void) FOREACH(struct mux_client *client, &client_list) { client_close(client); } ENDFOREACH - pthread_mutex_destroy(&client_list_mutex); + mutex_destroy(&client_list_mutex); collection_free(&client_list); } |