From bef655966045af34e1f20a7211f0cab2e7e79001 Mon Sep 17 00:00:00 2001 From: Zach C Date: Wed, 6 Aug 2008 21:04:09 -0700 Subject: Adds locking and fixes a minor bug in mux_recv Signed-off-by: Matt Colyer --- src/AFC.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- src/AFC.h | 1 + src/ifuse.c | 2 +- src/iphone.c | 2 +- src/usbmux.c | 9 ++++++++- 5 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/AFC.c b/src/AFC.c index 5c9f68c..d7a4dda 100644 --- a/src/AFC.c +++ b/src/AFC.c @@ -26,6 +26,21 @@ const int MAXIMUM_PACKET_SIZE = (2 << 15) - 32; extern int debug; + +/* Locking, for thread-safety (well... kind of, hehe) */ +void afc_lock(AFClient *client) { + while (client->lock) { + sleep(200); + } + client->lock = 1; +} + +void afc_unlock(AFClient *client) { // just to be pretty + client->lock = 0; +} + +/* main AFC functions */ + AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { if (!phone) return NULL; AFClient *client = (AFClient*)malloc(sizeof(AFClient)); @@ -39,6 +54,7 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { client->afc_packet->header1 = 0x36414643; client->afc_packet->header2 = 0x4141504C; client->file_handle = 0; + client->lock = 0; return client; } else { mux_close_connection(client->connection); @@ -184,6 +200,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) { final_buffer = (char*)malloc(sizeof(char) * recv_len); while(current_count < recv_len){ bytes = mux_recv(client->connection, buffer, recv_len-current_count); + if (debug) printf("receive_AFC_data: still collecting packets\n"); if (bytes < 0) { if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes); @@ -194,6 +211,12 @@ int receive_AFC_data(AFClient *client, char **dump_here) { if(debug) printf("receive_AFC_data: mux_recv delivered too much data\n"); break; } + if (strstr(buffer, "CFA6LPAA")) { + if (debug) printf("receive_AFC_data: WARNING: there is AFC data in this packet at %i\n", strstr(buffer, "CFA6LPAA") - buffer); + if (debug) printf("receive_AFC_data: the total packet length is %i\n", bytes); + //continue; // but we do need to continue because packets/headers != data + } + memcpy(final_buffer+current_count, buffer, bytes); current_count += bytes; } @@ -211,18 +234,20 @@ int receive_AFC_data(AFClient *client, char **dump_here) { } char **afc_get_dir_list(AFClient *client, const char *dir) { + afc_lock(client); client->afc_packet->operation = AFC_LIST_DIR; int bytes = 0; char *blah = NULL, **list = NULL; client->afc_packet->entire_length = client->afc_packet->this_length = 0; bytes = dispatch_AFC_packet(client, dir, strlen(dir)); - if (!bytes) return NULL; + if (!bytes) { afc_unlock(client); return NULL; } bytes = receive_AFC_data(client, &blah); - if (!bytes && !blah) return NULL; + if (!bytes && !blah) { afc_unlock(client); return NULL; } list = make_strings_list(blah, bytes); free(blah); + afc_unlock(client); return list; } @@ -243,23 +268,24 @@ char **make_strings_list(char *tokens, int true_length) { int afc_delete_file(AFClient *client, const char *path) { if (!client || !path || !client->afc_packet || !client->connection) return 0; - + afc_lock(client); char *receive = NULL; client->afc_packet->this_length = client->afc_packet->entire_length = 0; client->afc_packet->operation = AFC_DELETE; int bytes; bytes = dispatch_AFC_packet(client, path, strlen(path)); - if (bytes <= 0) return 0; + if (bytes <= 0) { afc_unlock(client); return 0; } bytes = receive_AFC_data(client, &receive); free(receive); - if (bytes <= 0) return 0; + afc_unlock(client); + if (bytes <= 0) { return 0; } else return 1; } int afc_rename_file(AFClient *client, const char *from, const char *to) { if (!client || !from || !to || !client->afc_packet || !client->connection) return 0; - + afc_lock(client); char *receive = NULL; char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); int bytes = 0; @@ -271,10 +297,11 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) { client->afc_packet->entire_length = client->afc_packet->this_length = 0; client->afc_packet->operation = AFC_RENAME; bytes = dispatch_AFC_packet(client, send, strlen(to) + strlen(from) + 2); - if (bytes <= 0) return 0; + if (bytes <= 0) { afc_unlock(client); return 0; } bytes = receive_AFC_data(client, &receive); free(receive); + afc_unlock(client); if (bytes <= 0) return 0; else return 1; } @@ -284,6 +311,7 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) { AFCFile *afc_get_file_info(AFClient *client, const char *path) { client->afc_packet->operation = AFC_GET_INFO; client->afc_packet->entire_length = client->afc_packet->this_length = 0; + afc_lock(client); dispatch_AFC_packet(client, path, strlen(path)); char *received, **list; @@ -293,6 +321,7 @@ AFCFile *afc_get_file_info(AFClient *client, const char *path) { length = receive_AFC_data(client, &received); list = make_strings_list(received, length); free(received); + afc_unlock(client); // the rest is just interpretation anyway if (list) { my_file = (AFCFile *)malloc(sizeof(AFCFile)); for (i = 0; strcmp(list[i], ""); i++) { @@ -323,6 +352,7 @@ AFCFile *afc_get_file_info(AFClient *client, const char *path) { AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) { if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL; if (!client ||!client->connection || !client->afc_packet) return NULL; + afc_lock(client); char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1)); AFCFile *file_infos = NULL; memcpy(further_data, &file_mode, 4); @@ -338,10 +368,12 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) free(further_data); if (bytes <= 0) { if (debug) printf("didn't read enough\n"); + afc_unlock(client); return NULL; } else { length_thing = receive_AFC_data(client, &further_data); if (length_thing && further_data) { + afc_unlock(client); // don't want to hang on the next call... and besides, it'll re-lock, do its thing, and unlock again anyway. file_infos = afc_get_file_info(client, filename); memcpy(&file_infos->filehandle, further_data, 4); return file_infos; @@ -357,6 +389,8 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { if (!client || !client->afc_packet || !client->connection || !file) return -1; AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket)); + if (debug) printf("afc_read_file called for length %i\n"); + afc_lock(client); char *input = NULL; packet->unknown1 = packet->unknown2 = 0; packet->filehandle = file->filehandle; @@ -369,6 +403,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { if (bytes > 0) { bytes = receive_AFC_data(client, &input); + afc_unlock(client); if (bytes < 0) { if (input) free(input); return -1; @@ -382,6 +417,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { return (bytes > length) ? length : bytes; } } else { + afc_unlock(client); return -1; } return 0; @@ -390,6 +426,7 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length) { char *acknowledgement = NULL; if (!client ||!client->afc_packet || !client->connection || !file) return -1; + afc_lock(client); client->afc_packet->this_length = sizeof(AFCPacket) + 8; client->afc_packet->entire_length = client->afc_packet->this_length + length; client->afc_packet->operation = AFC_WRITE; @@ -407,6 +444,7 @@ int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length zero = bytes; bytes = receive_AFC_data(client, &acknowledgement); + afc_unlock(client); if (bytes <= 0) { if (debug) printf("afc_write_file: uh oh?\n"); } @@ -418,6 +456,7 @@ void afc_close_file(AFClient *client, AFCFile *file) { char *buffer = malloc(sizeof(char) * 8); uint32 zero = 0; if (debug) printf("File handle %i\n", file->filehandle); + afc_lock(client); memcpy(buffer, &file->filehandle, sizeof(uint32)); memcpy(buffer+sizeof(uint32), &zero, sizeof(zero)); client->afc_packet->operation = AFC_FILE_CLOSE; @@ -430,6 +469,7 @@ void afc_close_file(AFClient *client, AFCFile *file) { if (!bytes) return; bytes = receive_AFC_data(client, &buffer); + afc_unlock(client); return; if (buffer) free(buffer); // we're *SUPPOSED* to get an "error" here. } diff --git a/src/AFC.h b/src/AFC.h index 2827030..32defbe 100644 --- a/src/AFC.h +++ b/src/AFC.h @@ -38,6 +38,7 @@ typedef struct { usbmux_connection *connection; AFCPacket *afc_packet; int file_handle; + int lock; } AFClient; typedef struct { diff --git a/src/ifuse.c b/src/ifuse.c index f33eaaa..7d6f72a 100644 --- a/src/ifuse.c +++ b/src/ifuse.c @@ -41,7 +41,7 @@ GHashTable *file_handles; int fh_index = 0; -int debug = 0; +int debug = 1; static int ifuse_getattr(const char *path, struct stat *stbuf) { int res = 0; diff --git a/src/iphone.c b/src/iphone.c index 6000a19..426b629 100644 --- a/src/iphone.c +++ b/src/iphone.c @@ -163,7 +163,7 @@ int send_to_phone(iPhone *phone, char *data, int datalen) { * @param data Where to put data read * @param datalen How much data to read in * - * @returns How many bytes were read in, or -1 on error. + * @return How many bytes were read in, or -1 on error. */ int recv_from_phone(iPhone *phone, char *data, int datalen) { if (!phone) return -1; diff --git a/src/usbmux.c b/src/usbmux.c index 235a1f2..d79ee47 100644 --- a/src/usbmux.c +++ b/src/usbmux.c @@ -301,8 +301,15 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { for (i = 0; i < connections; i++) { if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) { // we have a winner. + char *nfb = (char*)malloc(sizeof(char) * (connlist[i]->r_len + (bytes - 28))); + if (connlist[i]->recv_buffer && connlist[i]->r_len) { + memcpy(nfb, connlist[i]->recv_buffer, connlist[i]->r_len); + free(connlist[i]->recv_buffer); + } connlist[i]->r_len += bytes - 28; - connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer + //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer + connlist[i]->recv_buffer = nfb; + nfb = NULL; // A cookie for you if you can guess what "nfb" means. complex = connlist[i]->r_len - (bytes - 28); memcpy(connlist[i]->recv_buffer+complex, buffer+28, bytes-28); // paste into their buffer connlist[i]->header->ocnt += bytes-28; -- cgit v1.1-32-gdbae