diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AFC.c | 66 | ||||
| -rw-r--r-- | src/AFC.h | 11 | ||||
| -rw-r--r-- | src/ifuse.c | 5 | ||||
| -rw-r--r-- | src/iphone.c | 3 | ||||
| -rw-r--r-- | src/lockdown.c | 36 | ||||
| -rw-r--r-- | src/lockdown.h | 3 | ||||
| -rw-r--r-- | src/plist.h | 1 | ||||
| -rw-r--r-- | src/usbmux.c | 251 | ||||
| -rw-r--r-- | src/usbmux.h | 17 | ||||
| -rw-r--r-- | src/userpref.c | 2 | 
10 files changed, 277 insertions, 118 deletions
| @@ -34,7 +34,6 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {  	else {  		client->afc_packet = (AFCPacket*)malloc(sizeof(AFCPacket));  		if (client->afc_packet) { -			client->phone = phone;  			client->afc_packet->packet_num = 0;  			client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = client->afc_packet->entire_length = client->afc_packet->this_length = 0;  			client->afc_packet->header1 = 0x36414643; @@ -42,7 +41,7 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {  			client->file_handle = 0;  			return client;  		} else { -			mux_close_connection(client->phone, client->connection); +			mux_close_connection(client->connection);  			free(client);  			return NULL;  		} @@ -53,8 +52,8 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {  void afc_disconnect(AFClient *client) {  	// client and its members should never be NULL is assumed here. -	if (!client || !client->connection || !client->phone || !client->afc_packet) return; -	mux_close_connection(client->phone, client->connection); +	if (!client || !client->connection || !client->afc_packet) return; +	mux_close_connection(client->connection);  	free(client->afc_packet);  	free(client);  } @@ -67,10 +66,10 @@ int count_nullspaces(char *string, int number) {  	return nulls;  } -int dispatch_AFC_packet(AFClient *client, char *data, int length) { +int dispatch_AFC_packet(AFClient *client, const char *data, int length) {  	char *buffer;  	int bytes = 0, offset = 0; -	if (!client || !client->connection || !client->phone || !client->afc_packet) return 0; +	if (!client || !client->connection || !client->afc_packet) return 0;  	if (!data || !length) length = 0;  	client->afc_packet->packet_num++; @@ -91,7 +90,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) {  		}  		if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n");  		memcpy(buffer+sizeof(AFCPacket), data, offset); -		bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); +		bytes = mux_send(client->connection, buffer, client->afc_packet->this_length);  		free(buffer);  		if (bytes <= 0) { return 0; }  		if (debug) { @@ -102,7 +101,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) {  		} -		bytes = mux_send(client->phone, client->connection, data+offset, length-offset); +		bytes = mux_send(client->connection, data+offset, length-offset);  		if (bytes <= 0) { return 0; }  		else { return bytes; }  	} else { @@ -114,7 +113,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) {  		if (length > 0) { memcpy(buffer+sizeof(AFCPacket), data, length); buffer[sizeof(AFCPacket)+length] = '\0'; }  		if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout);  		if (debug) printf("\n"); -		bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); +		bytes = mux_send(client->connection, buffer, client->afc_packet->this_length);  		if (bytes <= 0) return 0;  		else return bytes;  	} @@ -126,9 +125,9 @@ int receive_AFC_data(AFClient *client, char **dump_here) {  	char *buffer = (char*)malloc(sizeof(AFCPacket) * 4);  	char *final_buffer = NULL;  	int bytes = 0, recv_len = 0, current_count=0; -        int retval = 0; +    int retval = 0; -	bytes = mux_recv(client->phone, client->connection, buffer, sizeof(AFCPacket) * 4); +	bytes = mux_recv(client->connection, buffer, sizeof(AFCPacket) * 4);  	if (bytes <= 0) {  		free(buffer);  		printf("Just didn't get enough.\n"); @@ -151,10 +150,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) {  	uint32 param1 = buffer[sizeof(AFCPacket)];  	free(buffer); -	if (r_packet->operation == 0x01 && !((client->afc_packet->operation == AFC_DELETE && param1 == 7))) { -		if (debug) printf("Oops? Bad operation code received: 0x%0X\n", r_packet->operation); -		if (param1 == 0) { +	if (r_packet->operation == AFC_ERROR +			&& !(client->afc_packet->operation == AFC_DELETE && param1 == 7) +	   ) +	{ +		if (debug) printf("Oops? Bad operation code received: 0x%X, operation=0x%X, param1=%d\n", +				r_packet->operation, client->afc_packet->operation, param1); +		recv_len = r_packet->entire_length - r_packet->this_length; +		if (debug) printf("recv_len=%d\n", recv_len); +		if(param1 == 0) {  			if (debug) printf("... false alarm, but still\n"); +			*dump_here = NULL;  			return 1;  		}  		else { if (debug) printf("Errno %i\n", param1); } @@ -167,13 +173,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) {  	recv_len = r_packet->entire_length - r_packet->this_length;  	free(r_packet); -	if (!recv_len) return bytes; +	if (!recv_len) +	{ +		*dump_here = NULL; +		return 0; +	}  	// Keep collecting packets until we have received the entire file.  	buffer = (char*)malloc(sizeof(char) * (recv_len < MAXIMUM_PACKET_SIZE) ? recv_len : MAXIMUM_PACKET_SIZE);  	final_buffer = (char*)malloc(sizeof(char) * recv_len);  	while(current_count < recv_len){ -		bytes = mux_recv(client->phone, client->connection, buffer, recv_len-current_count); +		bytes = mux_recv(client->connection, buffer, recv_len-current_count);  		if (bytes < 0)  		{  			if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes); @@ -200,7 +210,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) {  	return current_count;  } -char **afc_get_dir_list(AFClient *client, char *dir) { +char **afc_get_dir_list(AFClient *client, const char *dir) {  	client->afc_packet->operation = AFC_LIST_DIR;  	int bytes = 0;  	char *blah = NULL, **list = NULL; @@ -232,7 +242,7 @@ 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->phone ||!client->connection) return 0; +	if (!client || !path || !client->afc_packet || !client->connection) return 0;  	char *receive = NULL;  	client->afc_packet->this_length = client->afc_packet->entire_length = 0; @@ -248,7 +258,7 @@ int afc_delete_file(AFClient *client, const char *path) {  }  int afc_rename_file(AFClient *client, const char *from, const char *to) { -	if (!client || !from || !to || !client->afc_packet || !client->phone || !client->connection) return 0; +	if (!client || !from || !to || !client->afc_packet || !client->connection) return 0;  	char *receive = NULL;  	char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); @@ -271,7 +281,7 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) { -AFCFile *afc_get_file_info(AFClient *client, char *path) { +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;  	dispatch_AFC_packet(client, path, strlen(path)); @@ -312,7 +322,7 @@ AFCFile *afc_get_file_info(AFClient *client, 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->phone ||!client->afc_packet) return NULL; +	if (!client ||!client->connection || !client->afc_packet) return NULL;  	char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1));  	AFCFile *file_infos = NULL;  	memcpy(further_data, &file_mode, 4); @@ -345,7 +355,7 @@ 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->phone || !client->connection || !file) return -1; +	if (!client || !client->afc_packet || !client->connection || !file) return -1;  	AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket));  	char *input = NULL;  	packet->unknown1 = packet->unknown2 = 0; @@ -359,11 +369,15 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {  	if (bytes > 0) {  		bytes = receive_AFC_data(client, &input); -		if (bytes <= 0) { +		if (bytes < 0) {  			if (input) free(input);  			return -1; +		} else if (bytes == 0) { +			if (input) free(input); +			return 0;  		} else { -			memcpy(data, input, (bytes > length) ? length : bytes); +			if (input) +				memcpy(data, input, (bytes > length) ? length : bytes);  			free(input);  			return (bytes > length) ? length : bytes;  		} @@ -373,9 +387,9 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {  	return 0;  } -int afc_write_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->phone || !client->connection || !file) return -1; +	if (!client ||!client->afc_packet || !client->connection || !file) return -1;  	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; @@ -35,8 +35,7 @@ typedef struct {  } AFCPacket;  typedef struct { -	usbmux_tcp_header *connection; -	iPhone *phone; +	usbmux_connection *connection;  	AFCPacket *afc_packet;  	int file_handle;  } AFClient; @@ -79,14 +78,14 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port);  void afc_disconnect(AFClient *client);  int count_nullspaces(char *string, int number);  char **make_strings_list(char *tokens, int true_length); -int dispatch_AFC_packet(AFClient *client, char *data, int length); +int dispatch_AFC_packet(AFClient *client, const char *data, int length);  int receive_AFC_data(AFClient *client, char **dump_here); -char **afc_get_dir_list(AFClient *client, char *dir); -AFCFile *afc_get_file_info(AFClient *client, char *path); +char **afc_get_dir_list(AFClient *client, const char *dir); +AFCFile *afc_get_file_info(AFClient *client, const char *path);  AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode);  void afc_close_file(AFClient *client, AFCFile *file);  int afc_read_file(AFClient *client, AFCFile *file, char *data, int length); -int afc_write_file(AFClient *client, AFCFile *file, char *data, int length); +int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length);  int afc_delete_file(AFClient *client, const char *path);  int afc_rename_file(AFClient *client, const char *from, const char *to); diff --git a/src/ifuse.c b/src/ifuse.c index e4d14e5..900bb17 100644 --- a/src/ifuse.c +++ b/src/ifuse.c @@ -155,9 +155,10 @@ void *ifuse_init(struct fuse_conn_info *conn) {          return afc;  } -void ifuse_cleanup(AFClient *afc) { +void ifuse_cleanup(void *data) { +	AFClient *afc = (AFClient *)data;  	if (afc) { -		iPhone *phone = afc->phone; +		iPhone *phone = afc->connection->phone;  		afc_disconnect(afc);  		free_iPhone(phone);  	} diff --git a/src/iphone.c b/src/iphone.c index e4acea9..aa9687c 100644 --- a/src/iphone.c +++ b/src/iphone.c @@ -171,10 +171,11 @@ int send_to_phone(iPhone *phone, char *data, int datalen) {  int recv_from_phone(iPhone *phone, char *data, int datalen) {  	if (!phone) return -1;  	int bytes = 0; +	if (debug) printf("recv_from_phone(): attempting to receive %i bytes\n", datalen);  	bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, 3500);  	if(bytes < 0)  	{ -		if(debug) printf("recv_from_iphone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes)); +		if(debug) printf("recv_from_phone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes));  		return -1;  	}  	return bytes; diff --git a/src/lockdown.c b/src/lockdown.c index 7fd3aa6..4fd8a66 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -39,7 +39,6 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) {  	control->ssl_session = (gnutls_session_t*)malloc(sizeof(gnutls_session_t));  	control->in_SSL = 0; -	control->iphone = phone;  	control->gtls_buffer_hack_len = 0;  	return control;  } @@ -47,7 +46,7 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) {  void lockdown_close(lockdownd_client *control) {  	if (!control) return;  	if (control->connection) { -		mux_close_connection(control->iphone, control->connection); +		mux_close_connection(control->connection);  	}  	if (control->ssl_session) free(control->ssl_session); @@ -56,21 +55,23 @@ void lockdown_close(lockdownd_client *control) {  int lockdownd_recv(lockdownd_client *control, char **dump_data) { +	if (!control) return 0;  	char *receive;  	uint32 datalen = 0, bytes = 0; -	if (!control->in_SSL) bytes = mux_recv(control->iphone, control->connection, &datalen, sizeof(datalen)); +	if (!control->in_SSL) bytes = mux_recv(control->connection, (char *)&datalen, sizeof(datalen));  	else bytes = gnutls_record_recv(*control->ssl_session, &datalen, sizeof(datalen));  	datalen = ntohl(datalen);  	receive = (char*)malloc(sizeof(char) * datalen); -	if (!control->in_SSL) bytes = mux_recv(control->iphone, control->connection, receive, datalen); +	if (!control->in_SSL) bytes = mux_recv(control->connection, receive, datalen);  	else bytes = gnutls_record_recv(*control->ssl_session, receive, datalen);  	*dump_data = receive;  	return bytes;  }  int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) { +	if (!control) return 0;  	char *real_query;  	int bytes; @@ -78,29 +79,39 @@ int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) {  	length = htonl(length);  	memcpy(real_query, &length, sizeof(length));  	memcpy(real_query+4, raw_data, ntohl(length)); -	if (!control->in_SSL) bytes = mux_send(control->iphone, control->connection, real_query, ntohl(length)+sizeof(length)); +	if (debug) { +		printf("lockdownd_send(): made the query, sending it along\n"); +		FILE *packet = fopen("grpkt", "w"); +		fwrite(real_query, 1, ntohl(length)+4, packet); +		fclose(packet); +		packet = NULL; +	} +	 +	if (!control->in_SSL) bytes = mux_send(control->connection, real_query, ntohl(length)+sizeof(length));  	else gnutls_record_send(*control->ssl_session, real_query, ntohl(length)+sizeof(length)); +	if (debug) printf("lockdownd_send(): sent it!\n"); +	free(real_query);  	return bytes;  }  int lockdownd_hello(lockdownd_client *control) { +	if (!control) return 0;  	xmlDocPtr plist = new_plist();  	xmlNode *dict, *key;  	char **dictionary;  	int bytes = 0, i = 0; +	if (debug) printf("lockdownd_hello() called\n");  	dict = add_child_to_plist(plist, "dict", "\n", NULL, 0);  	key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1);  	char *XML_content;  	uint32 length; -	xmlDocDumpMemory(plist, &XML_content, &length); -	 +	xmlDocDumpMemory(plist, (xmlChar **)&XML_content, &length);  	bytes = lockdownd_send(control, XML_content, length);  	xmlFree(XML_content);  	xmlFreeDoc(plist); plist = NULL; -	  	bytes = lockdownd_recv(control, &XML_content);  	plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); @@ -118,6 +129,7 @@ int lockdownd_hello(lockdownd_client *control) {  	for (i = 0; strcmp(dictionary[i], ""); i+=2) {  		if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i+1], "Success")) {  			free_dictionary(dictionary); +			if (debug) printf("lockdownd_hello(): success\n");  			return 1;  		}  	} @@ -147,7 +159,7 @@ int lockdownd_start_SSL_session(lockdownd_client *control, const char *HostID) {  		return 0;  	} -	xmlDocDumpMemory(plist, &what2send, &len); +	xmlDocDumpMemory(plist, (xmlChar **)&what2send, &len);  	bytes = lockdownd_send(control, what2send, len);  	xmlFree(what2send); @@ -239,7 +251,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size  	control = (lockdownd_client*)transport;  	if (debug) printf("lockdownd_secuwrite() called\n");  	if (debug) printf("pre-send\nlength = %i\n", length); -	bytes = mux_send(control->iphone, control->connection, buffer, length); +	bytes = mux_send(control->connection, buffer, length);  	if (debug) printf("post-send\nsent %i bytes\n", bytes);  	if (debug) {  		FILE *my_ssl_packet = fopen("sslpacketwrite.out", "w+"); @@ -289,7 +301,7 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_  	char *recv_buffer = (char*)malloc(sizeof(char) * (length * 1000)); // ensuring nothing stupid happens  	if (debug) printf("pre-read\nclient wants %i bytes\n", length); -	bytes = mux_recv(control->iphone, control->connection, recv_buffer, (length * 1000)); +	bytes = mux_recv(control->connection, recv_buffer, (length * 1000));  	if (debug) printf("post-read\nwe got %i bytes\n", bytes);  	if (debug && bytes < 0) {  		printf("lockdownd_securead(): uh oh\n"); @@ -339,7 +351,7 @@ int lockdownd_start_service(lockdownd_client *control, const char *service) {  	key = add_key_str_dict_element(plist, dict, "Service", service, 1);  	if (!key) { xmlFreeDoc(plist); return 0; } -	xmlDocDumpMemory(plist, &XML_query, &length); +	xmlDocDumpMemory(plist, (xmlChar **)&XML_query, &length);  	lockdownd_send(control, XML_query, length);  	free(XML_query); diff --git a/src/lockdown.h b/src/lockdown.h index 874afb9..4abfe18 100644 --- a/src/lockdown.h +++ b/src/lockdown.h @@ -28,9 +28,8 @@  #include <string.h>  typedef struct { -	usbmux_tcp_header *connection; +	usbmux_connection *connection;  	gnutls_session_t *ssl_session; -	iPhone *iphone;  	int in_SSL;  	char *gtls_buffer_hack;  	int gtls_buffer_hack_len; diff --git a/src/plist.h b/src/plist.h index 7b72456..3d1edda 100644 --- a/src/plist.h +++ b/src/plist.h @@ -29,5 +29,6 @@ xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *ke  xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth);  void free_plist(xmlDocPtr plist);  xmlDocPtr new_plist(); +char **read_dict_element_strings(xmlNode *dict);  void free_dictionary(char **dictionary);  #endif diff --git a/src/usbmux.c b/src/usbmux.c index bdeea09..043f8af 100644 --- a/src/usbmux.c +++ b/src/usbmux.c @@ -29,6 +29,9 @@  extern int debug; +static usbmux_connection **connlist = NULL; +static int connections = 0; +  usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) {  	usbmux_tcp_header *conn = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));  	conn->type = htonl(6); @@ -54,6 +57,47 @@ usbmux_version_header *version_header() {  	return version;  } + +// Maintenance functions. + +/* delete_connection(connection) + * 	connection: the connection to delete from the tracking list. + * Removes a connection from the list of connections made. + * The list of connections is necessary for buffering. + */ + +void delete_connection(usbmux_connection *connection) { +	usbmux_connection **newlist = (usbmux_connection**)malloc(sizeof(usbmux_connection*) * (connections - 1)); +	int i = 0, j = 0; +	for (i = 0; i < connections; i++) { +		if (connlist[i] == connection) continue; +		else { +			newlist[j] = connlist[i]; +			j++; +		} +	} +	free(connlist); +	connlist = newlist; +	connections--; +	if (connection->recv_buffer) free(connection->recv_buffer); +	if (connection->header) free(connection->header); +	connection->r_len = 0; +	free(connection); +} + +/* add_connection(connection) + * 	connection: the connection to add to the global list of connections. + * Adds a connection to the list of connections made. + * The connection list is necessary for buffering. + */ + +void add_connection(usbmux_connection *connection) { +	usbmux_connection **newlist = (usbmux_connection**)realloc(connlist, sizeof(usbmux_connection*) * (connections+1)); +	newlist[connections] = connection; +	connlist = newlist; +	connections++; +} +  /* mux_connect(phone, s_port, d_port)   * This is a higher-level USBMuxTCP-type function.   * 	phone: the iPhone to initialize a connection on. @@ -64,27 +108,33 @@ usbmux_version_header *version_header() {   * Returns a mux TCP header for the connection which is used for tracking and data transfer.   */  -usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) { +usbmux_connection *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) {  	if (!phone || !s_port || !d_port) return NULL;  	int bytes = 0;  	// Initialize connection stuff -	usbmux_tcp_header *new_connection; -	new_connection = new_mux_packet(s_port, d_port); +	usbmux_connection *new_connection = (usbmux_connection*)malloc(sizeof(usbmux_connection)); +	new_connection->header = new_mux_packet(s_port, d_port);  	usbmux_tcp_header *response;  	response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));  	// blargg -	if (new_connection) { -		new_connection->tcp_flags = 0x02; -		new_connection->length = htonl(new_connection->length); -		new_connection->length16 = htons(new_connection->length16); +	if (new_connection && new_connection->header) { +		new_connection->header->tcp_flags = 0x02; +		new_connection->header->length = htonl(new_connection->header->length); +		new_connection->header->length16 = htons(new_connection->header->length16); -		if (send_to_phone(phone, (char*)new_connection, sizeof(*new_connection)) >= 0) { +		if (send_to_phone(phone, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {  			bytes = recv_from_phone(phone, (char*)response, sizeof(*response));  			if (response->tcp_flags != 0x12) return NULL;  			else { -				new_connection->tcp_flags = 0x10; -				new_connection->scnt = 1; -				new_connection->ocnt = 1; +				if (debug) printf("mux_connect: connection success\n"); +				new_connection->header->tcp_flags = 0x10; +				new_connection->header->scnt = 1; +				new_connection->header->ocnt = 1; +				add_connection(new_connection); +				new_connection->phone = phone; +				new_connection->recv_buffer = NULL; +				new_connection->r_len = 0; +				add_connection(new_connection);  				return new_connection;  			}  		} else { @@ -103,23 +153,24 @@ usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) {   *    * Doesn't return anything; WILL FREE THE CONNECTION'S MEMORY!!!   */ -void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) { -	if (!phone || !connection) return; + +void mux_close_connection(usbmux_connection *connection) { +	if (!connection || !connection->phone) return; -	connection->tcp_flags = 0x04; -	connection->scnt = htonl(connection->scnt); -	connection->ocnt = htonl(connection->ocnt); +	connection->header->tcp_flags = 0x04; +	connection->header->scnt = htonl(connection->header->scnt); +	connection->header->ocnt = htonl(connection->header->ocnt);  	int bytes = 0; -	bytes = usb_bulk_write(phone->device, BULKOUT, (char*)connection, sizeof(*connection), 800); +	bytes = usb_bulk_write(connection->phone->device, BULKOUT, (char*)connection->header, sizeof(usbmux_tcp_header), 800);  	if(debug && bytes < 0)  		printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror()); -	bytes = usb_bulk_read(phone->device, BULKIN, (char*)connection, sizeof(*connection), 800); +	bytes = usb_bulk_read(connection->phone->device, BULKIN, (char*)connection->header, sizeof(usbmux_tcp_header), 800);  	if(debug && bytes < 0)  		printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); -	free(connection); +	delete_connection(connection);  }  /* mux_send(phone, connection, data, datalen) @@ -131,40 +182,46 @@ void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) {   *    * Returns number of bytes sent, minus the header (28), or -1 on error.   */ -int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) { -	if (!phone || !connection || !data || datalen == 0) return -1; +int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) { +	if (!connection->phone || !connection || !data || datalen == 0) return -1;  	// connection->scnt and connection->ocnt should already be in host notation...  	// we don't need to change them juuuust yet.   	int bytes = 0;  	if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen); -	char *buffer = (char*)malloc(sizeof(*connection) + datalen + 2); // allow 2 bytes of safety padding +	char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding  	// Set the length and pre-emptively htonl/htons it -	connection->length = htonl(sizeof(*connection) + datalen); -	connection->length16 = htons(sizeof(*connection) + datalen); +	connection->header->length = htonl(sizeof(usbmux_tcp_header) + datalen); +	connection->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen);  	// Put scnt and ocnt into big-endian notation -	connection->scnt = htonl(connection->scnt); -	connection->ocnt = htonl(connection->ocnt); +	connection->header->scnt = htonl(connection->header->scnt); +	connection->header->ocnt = htonl(connection->header->ocnt);  	// Concatenation of stuff in the buffer. -	memcpy(buffer, connection, sizeof(*connection)); -	memcpy(buffer+sizeof(*connection)/*+sizeof(datalen)*/, data, datalen); +	memcpy(buffer, connection->header, sizeof(usbmux_tcp_header)); +	memcpy(buffer+sizeof(usbmux_tcp_header), data, datalen);  	// We have a buffer full of data, we should now send it to the phone. -	if (debug) printf("actually sending %i bytes of data at %x\n", sizeof(*connection)+datalen, buffer); +	if (debug) printf("actually sending %i bytes of data at %x\n", sizeof(usbmux_tcp_header)+datalen, buffer); -	bytes = send_to_phone(phone, buffer, sizeof(*connection)+datalen); -	 +	bytes = send_to_phone(connection->phone, buffer, sizeof(usbmux_tcp_header)+datalen); +	if (debug) printf("mux_send: sent %i bytes!\n", bytes);  	// Now that we've sent it off, we can clean up after our sloppy selves. -	free(buffer); +	if (debug) { +		FILE *packet = fopen("packet", "a+"); +		fwrite(buffer, 1, bytes, packet); +		fclose(packet); +		printf("\n"); +	} +	if (buffer) free(buffer);  	// Re-calculate scnt and ocnt -	connection->scnt = ntohl(connection->scnt) + datalen; -	connection->ocnt = ntohl(connection->ocnt); +	connection->header->scnt = ntohl(connection->header->scnt) + datalen; +	connection->header->ocnt = ntohl(connection->header->ocnt);  	// Revert lengths -	connection->length = ntohl(connection->length); -	connection->length16 = ntohs(connection->length16); +	connection->header->length = ntohl(connection->header->length); +	connection->header->length16 = ntohs(connection->header->length16);  	// Now return the bytes.  	if (bytes < sizeof(*connection)+datalen) { @@ -186,39 +243,103 @@ int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 da   * Returns: how many bytes were read, or -1 if something bad happens.   */ -int mux_recv(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) { -	char *buffer = (char*)malloc(sizeof(*connection) + sizeof(datalen) + datalen); -	int bytes = 0, my_datalen = 0; +int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { +	/* +	 * Order of operation: +	 * 1.) Check if the connection has a pre-received buffer. +	 * 2.) If so, fill data with the buffer, as much as needed. +	 * 	a.) Return quickly if the buffer has enough +	 * 	b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return) +	 * 3.) If not, receive directly from the phone.  +	 * 	a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation. +	 * 	b.) If not, find the connection the ports belong to and fill that connection's buffer, then return mux_recv with the same args to try again. +	 */  	if (debug) printf("mux_recv: datalen == %i\n", datalen); -	bytes = recv_from_phone(phone, buffer, sizeof(*connection) + datalen); -	if (debug) printf("mux_recv: bytes == %i\n", bytes); -	if (bytes < datalen) { -		if (bytes < 28) { -			// if they didn't do that annoying thing, something else mighta happened. -			if (debug) printf("mux_recv: bytes too low anyway!\n"); -			free(buffer); -			return -1; -		} else if (bytes == 28) { // no data... -			free(buffer); -			return 0; -		} else { // bytes > 28 -			my_datalen = ntohl(buffer[4]) - 28; -			connection->ocnt += my_datalen; -			memcpy(data, buffer+28, bytes - 28); -			free(buffer); -			if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28); -			return bytes - 28; +	int bytes = 0, i = 0, complex = 0, offset = 0; +	char *buffer = NULL; +	usbmux_tcp_header *header = NULL; +		 +	if (connection->recv_buffer) { +		if (connection->r_len >= datalen) { +			memcpy(data, connection->recv_buffer, datalen); +			if (connection->r_len == datalen) { +				// reset everything +				free(connection->recv_buffer); +				connection->r_len = 0; +				connection->recv_buffer = NULL; +			} else { +				buffer = (char*)malloc(sizeof(char) * (connection->r_len - datalen)); +				memcpy(buffer, connection->recv_buffer+datalen, (connection->r_len - datalen)); +				connection->r_len -= datalen; +				free(connection->recv_buffer); +				connection->recv_buffer = buffer; +			} +			 +			// Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above. +			return datalen; +		} else { +			memcpy(data, connection->recv_buffer, connection->r_len); +			free(connection->recv_buffer); // don't need to deal with anymore, but... +			offset = connection->r_len; // see #2b, above +			connection->r_len = 0;  		} -	} else {// all's good, they didn't do anything bonky. -		my_datalen = ntohl(buffer[4]) - 28;  -		connection->ocnt += my_datalen; -		if (bytes == (datalen+28)) memcpy(data, buffer+28, datalen);  -		else if (bytes == datalen) memcpy(data, buffer+28, datalen-28); +	} // End of what to do if we have a pre-buffer. See #1 and #2 above.  +	 +	buffer = (char*)malloc(sizeof(char) * 131072); // make sure we get enough ;) +	 +	// See #3. +	bytes = recv_from_phone(connection->phone, buffer, 131072); +	if (bytes < 28) { +		free(buffer); +		if (debug) printf("mux_recv: Did not even get the header.\n"); +		return -1; +	} +	 +	header = (usbmux_tcp_header*)buffer; +	if (header->sport != connection->header->dport || header->dport != connection->header->sport) { +		// Ooooops -- we got someone else's packet. +		// We gotta stick it in their buffer. (Take that any old way you want ;) ) +		for (i = 0; i < connections; i++) { +			if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) { +				// we have a winner. +				connlist[i]->r_len += bytes - 28; +				connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer +				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; +			} +		} +		// If it wasn't ours, it's been handled by this point... or forgotten. +		// Free our buffer and continue. +		free(buffer); +		buffer = NULL; +		return mux_recv(connection, data, datalen); // recurse back in to try again +	} + +	// The packet was absolutely meant for us if it hits this point. +	// The pre-buffer has been taken care of, so, again, if we're at this point we have to read from the phone. +	 +	if ((bytes-28) > datalen) { +		// Copy what we need into the data, buffer the rest because we can. +		memcpy(data+offset, buffer+28, datalen); // data+offset: see #2b, above +		complex = connection->r_len + (bytes-28) - datalen; +		connection->recv_buffer = (char*)realloc(connection->recv_buffer, (sizeof(char) * complex)); +		connection->r_len = complex; +		complex = connection->r_len - (bytes-28) - datalen; +		memcpy(connection->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen); +		free(buffer); +		connection->header->ocnt += bytes-28; +		return datalen; +	} else { +		// Fill the data with what we have, and just return. +		memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above +		connection->header->ocnt += bytes-28;  		free(buffer); -		if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28); -		return bytes - 28; +		return (bytes-28);  	} -	return bytes; +	// If we get to this point, 'tis probably bad. +	if (debug) printf("mux_recv: Heisenbug: bytes and datalen not matching up\n"); +	return -1;  } diff --git a/src/usbmux.h b/src/usbmux.h index 7c17dd1..332dc8a 100644 --- a/src/usbmux.h +++ b/src/usbmux.h @@ -43,6 +43,13 @@ typedef struct {  	uint16 window, nullnull, length16;  } usbmux_tcp_header; +typedef struct { +	usbmux_tcp_header *header; +	iPhone *phone; +	char *recv_buffer; +	int r_len; +} usbmux_connection; +  usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port);  typedef struct { @@ -51,8 +58,10 @@ typedef struct {  usbmux_version_header *version_header(); -usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port); -void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection); -int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen); -int mux_recv(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen); +usbmux_connection *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port); +void mux_close_connection(usbmux_connection *connection); +int mux_send(usbmux_connection *connection, const char *data, uint32 datalen); +int mux_recv(usbmux_connection *connection, char *data, uint32 datalen); + +  #endif diff --git a/src/userpref.c b/src/userpref.c index 366016c..27aded5 100644 --- a/src/userpref.c +++ b/src/userpref.c @@ -20,6 +20,8 @@   */  #include <glib.h> +#include <stdio.h> +#include <string.h>  #include "userpref.h"  #define LIBIPHONE_CONF_DIR  "libiphone" | 
