summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2013-02-26 17:24:23 +0100
committerGravatar Martin Szulecki2013-02-27 16:18:15 +0100
commitf8066bbf5169b7d7e68771bce677355e33a595c1 (patch)
tree8e8ee0a82c3a363c171c7124884af80a68e7cd08 /src
parentca23188eaab07d744e9cf85d9bf69ed323e94186 (diff)
downloadlibimobiledevice-f8066bbf5169b7d7e68771bce677355e33a595c1.tar.gz
libimobiledevice-f8066bbf5169b7d7e68771bce677355e33a595c1.tar.bz2
implement base service that all other services inherit from
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/afc.c71
-rw-r--r--src/afc.h5
-rw-r--r--src/file_relay.c2
-rw-r--r--src/house_arrest.c4
-rw-r--r--src/misagent.c2
-rw-r--r--src/mobilebackup2.c8
-rw-r--r--src/property_list_service.c51
-rw-r--r--src/property_list_service.h3
-rw-r--r--src/service.c276
-rw-r--r--src/service.h59
11 files changed, 404 insertions, 80 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 136baf4..574075e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ libimobiledevice_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBIMOBILEDEVICE_SO_
9libimobiledevice_la_SOURCES = idevice.c idevice.h \ 9libimobiledevice_la_SOURCES = idevice.c idevice.h \
10 debug.c debug.h\ 10 debug.c debug.h\
11 userpref.c userpref.h\ 11 userpref.c userpref.h\
12 service.c service.h\
12 property_list_service.c property_list_service.h\ 13 property_list_service.c property_list_service.h\
13 device_link_service.c device_link_service.h\ 14 device_link_service.c device_link_service.h\
14 lockdown.c lockdown.h\ 15 lockdown.c lockdown.h\
@@ -31,4 +32,4 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \
31 32
32if WIN32 33if WIN32
33libimobiledevice_la_LIBADD += -lole32 34libimobiledevice_la_LIBADD += -lole32
34endif \ No newline at end of file 35endif
diff --git a/src/afc.c b/src/afc.c
index b5228aa..83ee2ca 100644
--- a/src/afc.c
+++ b/src/afc.c
@@ -69,9 +69,7 @@ static void afc_unlock(afc_client_t client)
69 * Makes a connection to the AFC service on the device using the given 69 * Makes a connection to the AFC service on the device using the given
70 * connection. 70 * connection.
71 * 71 *
72 * @param connection An idevice_connection_t that must have been previously 72 * @param serviceclient A connected service client
73 * connected using idevice_connect(). Note that this connection will
74 * not be closed by calling afc_client_free().
75 * @param client Pointer that will be set to a newly allocated afc_client_t 73 * @param client Pointer that will be set to a newly allocated afc_client_t
76 * upon successful return. 74 * upon successful return.
77 * 75 *
@@ -79,14 +77,14 @@ static void afc_unlock(afc_client_t client)
79 * invalid, or AFC_E_NO_MEM if there is a memory allocation problem. 77 * invalid, or AFC_E_NO_MEM if there is a memory allocation problem.
80 */ 78 */
81 79
82afc_error_t afc_client_new_from_connection(idevice_connection_t connection, afc_client_t *client) 80afc_error_t afc_client_new_with_service_client(service_client_t serviceclient, afc_client_t *client)
83{ 81{
84 if (!connection) 82 if (!serviceclient)
85 return AFC_E_INVALID_ARG; 83 return AFC_E_INVALID_ARG;
86 84
87 afc_client_t client_loc = (afc_client_t) malloc(sizeof(struct afc_client_private)); 85 afc_client_t client_loc = (afc_client_t) malloc(sizeof(struct afc_client_private));
88 client_loc->connection = connection; 86 client_loc->parent = serviceclient;
89 client_loc->own_connection = 0; 87 client_loc->free_parent = 0;
90 88
91 /* allocate a packet */ 89 /* allocate a packet */
92 client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket)); 90 client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket));
@@ -113,10 +111,6 @@ afc_error_t afc_client_new_from_connection(idevice_connection_t connection, afc_
113 111
114/** 112/**
115 * Makes a connection to the AFC service on the device. 113 * Makes a connection to the AFC service on the device.
116 * This function calls afc_client_new_from_connection() after creating
117 * a connection to the specified device and port.
118 *
119 * @see afc_client_new_from_connection
120 * 114 *
121 * @param device The device to connect to. 115 * @param device The device to connect to.
122 * @param service The service descriptor returned by lockdownd_start_service. 116 * @param service The service descriptor returned by lockdownd_start_service.
@@ -132,21 +126,16 @@ afc_error_t afc_client_new(idevice_t device, lockdownd_service_descriptor_t serv
132 if (!device || service->port == 0) 126 if (!device || service->port == 0)
133 return AFC_E_INVALID_ARG; 127 return AFC_E_INVALID_ARG;
134 128
135 /* attempt connection */ 129 service_client_t parent = NULL;
136 idevice_connection_t connection = NULL; 130 if (service_client_new(device, service, &parent) != SERVICE_E_SUCCESS) {
137 if (idevice_connect(device, service->port, &connection) != IDEVICE_E_SUCCESS) {
138 return AFC_E_MUX_ERROR; 131 return AFC_E_MUX_ERROR;
139 } 132 }
140 133
141 /* enable SSL if requested */ 134 afc_error_t err = afc_client_new_with_service_client(parent, client);
142 if (service->ssl_enabled)
143 idevice_connection_enable_ssl(connection);
144
145 afc_error_t err = afc_client_new_from_connection(connection, client);
146 if (err != AFC_E_SUCCESS) { 135 if (err != AFC_E_SUCCESS) {
147 idevice_disconnect(connection); 136 service_client_free(parent);
148 } else { 137 } else {
149 (*client)->own_connection = 1; 138 (*client)->free_parent = 1;
150 } 139 }
151 return err; 140 return err;
152} 141}
@@ -162,9 +151,9 @@ afc_error_t afc_client_free(afc_client_t client)
162 if (!client || !client->afc_packet) 151 if (!client || !client->afc_packet)
163 return AFC_E_INVALID_ARG; 152 return AFC_E_INVALID_ARG;
164 153
165 if (client->own_connection && client->connection) { 154 if (client->free_parent && client->parent) {
166 idevice_disconnect(client->connection); 155 service_client_free(client->parent);
167 client->connection = NULL; 156 client->parent = NULL;
168 } 157 }
169 free(client->afc_packet); 158 free(client->afc_packet);
170#ifdef WIN32 159#ifdef WIN32
@@ -196,7 +185,7 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, const char *data, ui
196 uint32_t offset = 0; 185 uint32_t offset = 0;
197 uint32_t sent = 0; 186 uint32_t sent = 0;
198 187
199 if (!client || !client->connection || !client->afc_packet) 188 if (!client || !client->parent || !client->afc_packet)
200 return AFC_E_INVALID_ARG; 189 return AFC_E_INVALID_ARG;
201 190
202 *bytes_sent = 0; 191 *bytes_sent = 0;
@@ -229,7 +218,7 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, const char *data, ui
229 /* send AFC packet header */ 218 /* send AFC packet header */
230 AFCPacket_to_LE(client->afc_packet); 219 AFCPacket_to_LE(client->afc_packet);
231 sent = 0; 220 sent = 0;
232 idevice_connection_send(client->connection, (void*)client->afc_packet, sizeof(AFCPacket), &sent); 221 service_send(client->parent, (void*)client->afc_packet, sizeof(AFCPacket), &sent);
233 AFCPacket_from_LE(client->afc_packet); 222 AFCPacket_from_LE(client->afc_packet);
234 if (sent == 0) { 223 if (sent == 0) {
235 /* FIXME: should this be handled as success?! */ 224 /* FIXME: should this be handled as success?! */
@@ -239,7 +228,7 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, const char *data, ui
239 228
240 /* send AFC packet data */ 229 /* send AFC packet data */
241 sent = 0; 230 sent = 0;
242 idevice_connection_send(client->connection, data, offset, &sent); 231 service_send(client->parent, data, offset, &sent);
243 if (sent == 0) { 232 if (sent == 0) {
244 return AFC_E_SUCCESS; 233 return AFC_E_SUCCESS;
245 } 234 }
@@ -251,7 +240,7 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, const char *data, ui
251 debug_buffer(data + offset, length - offset); 240 debug_buffer(data + offset, length - offset);
252 241
253 sent = 0; 242 sent = 0;
254 idevice_connection_send(client->connection, data + offset, length - offset, &sent); 243 service_send(client->parent, data + offset, length - offset, &sent);
255 244
256 *bytes_sent = sent; 245 *bytes_sent = sent;
257 return AFC_E_SUCCESS; 246 return AFC_E_SUCCESS;
@@ -264,7 +253,7 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, const char *data, ui
264 /* send AFC packet header */ 253 /* send AFC packet header */
265 AFCPacket_to_LE(client->afc_packet); 254 AFCPacket_to_LE(client->afc_packet);
266 sent = 0; 255 sent = 0;
267 idevice_connection_send(client->connection, (void*)client->afc_packet, sizeof(AFCPacket), &sent); 256 service_send(client->parent, (void*)client->afc_packet, sizeof(AFCPacket), &sent);
268 AFCPacket_from_LE(client->afc_packet); 257 AFCPacket_from_LE(client->afc_packet);
269 if (sent == 0) { 258 if (sent == 0) {
270 return AFC_E_SUCCESS; 259 return AFC_E_SUCCESS;
@@ -275,7 +264,7 @@ static afc_error_t afc_dispatch_packet(afc_client_t client, const char *data, ui
275 debug_info("packet data follows"); 264 debug_info("packet data follows");
276 265
277 debug_buffer(data, length); 266 debug_buffer(data, length);
278 idevice_connection_send(client->connection, data, length, &sent); 267 service_send(client->parent, data, length, &sent);
279 *bytes_sent += sent; 268 *bytes_sent += sent;
280 } 269 }
281 return AFC_E_SUCCESS; 270 return AFC_E_SUCCESS;
@@ -303,7 +292,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, uint3
303 *bytes_recv = 0; 292 *bytes_recv = 0;
304 293
305 /* first, read the AFC header */ 294 /* first, read the AFC header */
306 idevice_connection_receive(client->connection, (char*)&header, sizeof(AFCPacket), bytes_recv); 295 service_receive(client->parent, (char*)&header, sizeof(AFCPacket), bytes_recv);
307 AFCPacket_from_LE(&header); 296 AFCPacket_from_LE(&header);
308 if (*bytes_recv == 0) { 297 if (*bytes_recv == 0) {
309 debug_info("Just didn't get enough."); 298 debug_info("Just didn't get enough.");
@@ -357,7 +346,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, uint3
357 346
358 *dump_here = (char*)malloc(entire_len); 347 *dump_here = (char*)malloc(entire_len);
359 if (this_len > 0) { 348 if (this_len > 0) {
360 idevice_connection_receive(client->connection, *dump_here, this_len, bytes_recv); 349 service_receive(client->parent, *dump_here, this_len, bytes_recv);
361 if (*bytes_recv <= 0) { 350 if (*bytes_recv <= 0) {
362 free(*dump_here); 351 free(*dump_here);
363 *dump_here = NULL; 352 *dump_here = NULL;
@@ -375,7 +364,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, uint3
375 364
376 if (entire_len > this_len) { 365 if (entire_len > this_len) {
377 while (current_count < entire_len) { 366 while (current_count < entire_len) {
378 idevice_connection_receive(client->connection, (*dump_here)+current_count, entire_len - current_count, bytes_recv); 367 service_receive(client->parent, (*dump_here)+current_count, entire_len - current_count, bytes_recv);
379 if (*bytes_recv <= 0) { 368 if (*bytes_recv <= 0) {
380 debug_info("Error receiving data (recv returned %d)", *bytes_recv); 369 debug_info("Error receiving data (recv returned %d)", *bytes_recv);
381 break; 370 break;
@@ -625,7 +614,7 @@ afc_error_t afc_remove_path(afc_client_t client, const char *path)
625 uint32_t bytes = 0; 614 uint32_t bytes = 0;
626 afc_error_t ret = AFC_E_UNKNOWN_ERROR; 615 afc_error_t ret = AFC_E_UNKNOWN_ERROR;
627 616
628 if (!client || !path || !client->afc_packet || !client->connection) 617 if (!client || !path || !client->afc_packet || !client->parent)
629 return AFC_E_INVALID_ARG; 618 return AFC_E_INVALID_ARG;
630 619
631 afc_lock(client); 620 afc_lock(client);
@@ -668,7 +657,7 @@ afc_error_t afc_rename_path(afc_client_t client, const char *from, const char *t
668 uint32_t bytes = 0; 657 uint32_t bytes = 0;
669 afc_error_t ret = AFC_E_UNKNOWN_ERROR; 658 afc_error_t ret = AFC_E_UNKNOWN_ERROR;
670 659
671 if (!client || !from || !to || !client->afc_packet || !client->connection) 660 if (!client || !from || !to || !client->afc_packet || !client->parent)
672 return AFC_E_INVALID_ARG; 661 return AFC_E_INVALID_ARG;
673 662
674 afc_lock(client); 663 afc_lock(client);
@@ -800,7 +789,7 @@ afc_file_open(afc_client_t client, const char *filename,
800 /* set handle to 0 so in case an error occurs, the handle is invalid */ 789 /* set handle to 0 so in case an error occurs, the handle is invalid */
801 *handle = 0; 790 *handle = 0;
802 791
803 if (!client || !client->connection || !client->afc_packet) 792 if (!client || !client->parent || !client->afc_packet)
804 return AFC_E_INVALID_ARG; 793 return AFC_E_INVALID_ARG;
805 794
806 afc_lock(client); 795 afc_lock(client);
@@ -856,7 +845,7 @@ afc_file_read(afc_client_t client, uint64_t handle, char *data, uint32_t length,
856 const uint32_t MAXIMUM_READ_SIZE = 1 << 16; 845 const uint32_t MAXIMUM_READ_SIZE = 1 << 16;
857 afc_error_t ret = AFC_E_SUCCESS; 846 afc_error_t ret = AFC_E_SUCCESS;
858 847
859 if (!client || !client->afc_packet || !client->connection || handle == 0) 848 if (!client || !client->afc_packet || !client->parent || handle == 0)
860 return AFC_E_INVALID_ARG; 849 return AFC_E_INVALID_ARG;
861 debug_info("called for length %i", length); 850 debug_info("called for length %i", length);
862 851
@@ -933,7 +922,7 @@ afc_file_write(afc_client_t client, uint64_t handle, const char *data, uint32_t
933 char *out_buffer = NULL; 922 char *out_buffer = NULL;
934 afc_error_t ret = AFC_E_SUCCESS; 923 afc_error_t ret = AFC_E_SUCCESS;
935 924
936 if (!client || !client->afc_packet || !client->connection || !bytes_written || (handle == 0)) 925 if (!client || !client->afc_packet || !client->parent || !bytes_written || (handle == 0))
937 return AFC_E_INVALID_ARG; 926 return AFC_E_INVALID_ARG;
938 927
939 afc_lock(client); 928 afc_lock(client);
@@ -1258,7 +1247,7 @@ afc_error_t afc_truncate(afc_client_t client, const char *path, uint64_t newsize
1258 uint64_t size_requested = htole64(newsize); 1247 uint64_t size_requested = htole64(newsize);
1259 afc_error_t ret = AFC_E_UNKNOWN_ERROR; 1248 afc_error_t ret = AFC_E_UNKNOWN_ERROR;
1260 1249
1261 if (!client || !path || !client->afc_packet || !client->connection) 1250 if (!client || !path || !client->afc_packet || !client->parent)
1262 return AFC_E_INVALID_ARG; 1251 return AFC_E_INVALID_ARG;
1263 1252
1264 afc_lock(client); 1253 afc_lock(client);
@@ -1302,7 +1291,7 @@ afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const c
1302 uint64_t type = htole64(linktype); 1291 uint64_t type = htole64(linktype);
1303 afc_error_t ret = AFC_E_UNKNOWN_ERROR; 1292 afc_error_t ret = AFC_E_UNKNOWN_ERROR;
1304 1293
1305 if (!client || !target || !linkname || !client->afc_packet || !client->connection) 1294 if (!client || !target || !linkname || !client->afc_packet || !client->parent)
1306 return AFC_E_INVALID_ARG; 1295 return AFC_E_INVALID_ARG;
1307 1296
1308 afc_lock(client); 1297 afc_lock(client);
@@ -1350,7 +1339,7 @@ afc_error_t afc_set_file_time(afc_client_t client, const char *path, uint64_t mt
1350 uint64_t mtime_loc = htole64(mtime); 1339 uint64_t mtime_loc = htole64(mtime);
1351 afc_error_t ret = AFC_E_UNKNOWN_ERROR; 1340 afc_error_t ret = AFC_E_UNKNOWN_ERROR;
1352 1341
1353 if (!client || !path || !client->afc_packet || !client->connection) 1342 if (!client || !path || !client->afc_packet || !client->parent)
1354 return AFC_E_INVALID_ARG; 1343 return AFC_E_INVALID_ARG;
1355 1344
1356 afc_lock(client); 1345 afc_lock(client);
diff --git a/src/afc.h b/src/afc.h
index 0c242f5..bdb1f16 100644
--- a/src/afc.h
+++ b/src/afc.h
@@ -30,6 +30,7 @@
30#endif 30#endif
31 31
32#include "libimobiledevice/afc.h" 32#include "libimobiledevice/afc.h"
33#include "service.h"
33#include "endianness.h" 34#include "endianness.h"
34 35
35#define AFC_MAGIC "CFA6LPAA" 36#define AFC_MAGIC "CFA6LPAA"
@@ -57,7 +58,7 @@ typedef struct {
57} AFCFilePacket; 58} AFCFilePacket;
58 59
59struct afc_client_private { 60struct afc_client_private {
60 idevice_connection_t connection; 61 service_client_t parent;
61 AFCPacket *afc_packet; 62 AFCPacket *afc_packet;
62 int file_handle; 63 int file_handle;
63 int lock; 64 int lock;
@@ -66,7 +67,7 @@ struct afc_client_private {
66#else 67#else
67 pthread_mutex_t mutex; 68 pthread_mutex_t mutex;
68#endif 69#endif
69 int own_connection; 70 int free_parent;
70}; 71};
71 72
72/* AFC Operations */ 73/* AFC Operations */
diff --git a/src/file_relay.c b/src/file_relay.c
index e72be66..39382fb 100644
--- a/src/file_relay.c
+++ b/src/file_relay.c
@@ -188,7 +188,7 @@ file_relay_error_t file_relay_request_sources(file_relay_client_t client, const
188 free(ack); 188 free(ack);
189 err = FILE_RELAY_E_SUCCESS; 189 err = FILE_RELAY_E_SUCCESS;
190 190
191 *connection = client->parent->connection; 191 *connection = client->parent->parent->connection;
192 192
193leave: 193leave:
194 if (dict) { 194 if (dict) {
diff --git a/src/house_arrest.c b/src/house_arrest.c
index e0d7771..ec76346 100644
--- a/src/house_arrest.c
+++ b/src/house_arrest.c
@@ -105,7 +105,7 @@ house_arrest_error_t house_arrest_client_free(house_arrest_client_t client)
105 return HOUSE_ARREST_E_INVALID_ARG; 105 return HOUSE_ARREST_E_INVALID_ARG;
106 106
107 house_arrest_error_t err = HOUSE_ARREST_E_SUCCESS; 107 house_arrest_error_t err = HOUSE_ARREST_E_SUCCESS;
108 if (client->parent && client->parent->connection) { 108 if (client->parent && client->parent->parent->connection) {
109 house_arrest_error(property_list_service_client_free(client->parent)); 109 house_arrest_error(property_list_service_client_free(client->parent));
110 } 110 }
111 client->parent = NULL; 111 client->parent = NULL;
@@ -242,7 +242,7 @@ afc_error_t afc_client_new_from_house_arrest_client(house_arrest_client_t client
242 if (!client || !client->parent || (client->mode == HOUSE_ARREST_CLIENT_MODE_AFC)) { 242 if (!client || !client->parent || (client->mode == HOUSE_ARREST_CLIENT_MODE_AFC)) {
243 return AFC_E_INVALID_ARG; 243 return AFC_E_INVALID_ARG;
244 } 244 }
245 afc_error_t err = afc_client_new_from_connection(client->parent->connection, afc_client); 245 afc_error_t err = afc_client_new_with_service_client(client->parent->parent, afc_client);
246 if (err == AFC_E_SUCCESS) { 246 if (err == AFC_E_SUCCESS) {
247 client->mode = HOUSE_ARREST_CLIENT_MODE_AFC; 247 client->mode = HOUSE_ARREST_CLIENT_MODE_AFC;
248 } 248 }
diff --git a/src/misagent.c b/src/misagent.c
index c624603..cb84188 100644
--- a/src/misagent.c
+++ b/src/misagent.c
@@ -132,7 +132,7 @@ misagent_error_t misagent_client_free(misagent_client_t client)
132 return MISAGENT_E_INVALID_ARG; 132 return MISAGENT_E_INVALID_ARG;
133 133
134 misagent_error_t err = MISAGENT_E_SUCCESS; 134 misagent_error_t err = MISAGENT_E_SUCCESS;
135 if (client->parent && client->parent->connection) { 135 if (client->parent && client->parent->parent) {
136 misagent_error(property_list_service_client_free(client->parent)); 136 misagent_error(property_list_service_client_free(client->parent));
137 } 137 }
138 client->parent = NULL; 138 client->parent = NULL;
diff --git a/src/mobilebackup2.c b/src/mobilebackup2.c
index bcf5944..15ba469 100644
--- a/src/mobilebackup2.c
+++ b/src/mobilebackup2.c
@@ -279,13 +279,13 @@ mobilebackup2_error_t mobilebackup2_send_raw(mobilebackup2_client_t client, cons
279 279
280 *bytes = 0; 280 *bytes = 0;
281 281
282 idevice_connection_t conn = client->parent->parent->connection; 282 service_client_t raw = client->parent->parent->parent;
283 283
284 int bytes_loc = 0; 284 int bytes_loc = 0;
285 uint32_t sent = 0; 285 uint32_t sent = 0;
286 do { 286 do {
287 bytes_loc = 0; 287 bytes_loc = 0;
288 idevice_connection_send(conn, data+sent, length-sent, (uint32_t*)&bytes_loc); 288 service_send(raw, data+sent, length-sent, (uint32_t*)&bytes_loc);
289 if (bytes_loc <= 0) 289 if (bytes_loc <= 0)
290 break; 290 break;
291 sent += bytes_loc; 291 sent += bytes_loc;
@@ -321,7 +321,7 @@ mobilebackup2_error_t mobilebackup2_receive_raw(mobilebackup2_client_t client, c
321 if (!client || !client->parent || !data || (length == 0) || !bytes) 321 if (!client || !client->parent || !data || (length == 0) || !bytes)
322 return MOBILEBACKUP2_E_INVALID_ARG; 322 return MOBILEBACKUP2_E_INVALID_ARG;
323 323
324 idevice_connection_t conn = client->parent->parent->connection; 324 service_client_t raw = client->parent->parent->parent;
325 325
326 *bytes = 0; 326 *bytes = 0;
327 327
@@ -329,7 +329,7 @@ mobilebackup2_error_t mobilebackup2_receive_raw(mobilebackup2_client_t client, c
329 uint32_t received = 0; 329 uint32_t received = 0;
330 do { 330 do {
331 bytes_loc = 0; 331 bytes_loc = 0;
332 idevice_connection_receive(conn, data+received, length-received, (uint32_t*)&bytes_loc); 332 service_receive(raw, data+received, length-received, (uint32_t*)&bytes_loc);
333 if (bytes_loc <= 0) break; 333 if (bytes_loc <= 0) break;
334 received += bytes_loc; 334 received += bytes_loc;
335 } while (received < length); 335 } while (received < length);
diff --git a/src/property_list_service.c b/src/property_list_service.c
index 15adbc8..025a9bc 100644
--- a/src/property_list_service.c
+++ b/src/property_list_service.c
@@ -25,27 +25,28 @@
25#include <string.h> 25#include <string.h>
26 26
27#include "property_list_service.h" 27#include "property_list_service.h"
28#include "idevice.h"
29#include "debug.h" 28#include "debug.h"
30#include "endianness.h" 29#include "endianness.h"
31 30
32/** 31/**
33 * Convert an idevice_error_t value to an property_list_service_error_t value. 32 * Convert a service_error_t value to a property_list_service_error_t value.
34 * Used internally to get correct error codes. 33 * Used internally to get correct error codes.
35 * 34 *
36 * @param err An idevice_error_t error code 35 * @param err A service_error_t error code
37 * 36 *
38 * @return A matching property_list_service_error_t error code, 37 * @return A matching property_list_service_error_t error code,
39 * PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR otherwise. 38 * PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR otherwise.
40 */ 39 */
41static property_list_service_error_t idevice_to_property_list_service_error(idevice_error_t err) 40static property_list_service_error_t service_to_property_list_service_error(service_error_t err)
42{ 41{
43 switch (err) { 42 switch (err) {
44 case IDEVICE_E_SUCCESS: 43 case SERVICE_E_SUCCESS:
45 return PROPERTY_LIST_SERVICE_E_SUCCESS; 44 return PROPERTY_LIST_SERVICE_E_SUCCESS;
46 case IDEVICE_E_INVALID_ARG: 45 case SERVICE_E_INVALID_ARG:
47 return PROPERTY_LIST_SERVICE_E_INVALID_ARG; 46 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
48 case IDEVICE_E_SSL_ERROR: 47 case SERVICE_E_MUX_ERROR:
48 return PROPERTY_LIST_SERVICE_E_MUX_ERROR;
49 case SERVICE_E_SSL_ERROR:
49 return PROPERTY_LIST_SERVICE_E_SSL_ERROR; 50 return PROPERTY_LIST_SERVICE_E_SSL_ERROR;
50 default: 51 default:
51 break; 52 break;
@@ -70,19 +71,15 @@ property_list_service_error_t property_list_service_client_new(idevice_t device,
70 if (!device || (service->port == 0) || !client || *client) 71 if (!device || (service->port == 0) || !client || *client)
71 return PROPERTY_LIST_SERVICE_E_INVALID_ARG; 72 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
72 73
73 /* Attempt connection */ 74 service_client_t parent = NULL;
74 idevice_connection_t connection = NULL; 75 service_error_t rerr = service_client_new(device, service, &parent);
75 if (idevice_connect(device, service->port, &connection) != IDEVICE_E_SUCCESS) { 76 if (rerr != SERVICE_E_SUCCESS) {
76 return PROPERTY_LIST_SERVICE_E_MUX_ERROR; 77 return service_to_property_list_service_error(rerr);
77 } 78 }
78 79
79 /* create client object */ 80 /* create client object */
80 property_list_service_client_t client_loc = (property_list_service_client_t)malloc(sizeof(struct property_list_service_client_private)); 81 property_list_service_client_t client_loc = (property_list_service_client_t)malloc(sizeof(struct property_list_service_client_private));
81 client_loc->connection = connection; 82 client_loc->parent = parent;
82
83 /* enable SSL if requested */
84 if (service->ssl_enabled == 1)
85 property_list_service_enable_ssl(client_loc);
86 83
87 /* all done, return success */ 84 /* all done, return success */
88 *client = client_loc; 85 *client = client_loc;
@@ -103,7 +100,7 @@ property_list_service_error_t property_list_service_client_free(property_list_se
103 if (!client) 100 if (!client)
104 return PROPERTY_LIST_SERVICE_E_INVALID_ARG; 101 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
105 102
106 property_list_service_error_t err = idevice_to_property_list_service_error(idevice_disconnect(client->connection)); 103 property_list_service_error_t err = service_to_property_list_service_error(service_client_free(client->parent));
107 free(client); 104 free(client);
108 return err; 105 return err;
109} 106}
@@ -130,7 +127,7 @@ static property_list_service_error_t internal_plist_send(property_list_service_c
130 uint32_t nlen = 0; 127 uint32_t nlen = 0;
131 int bytes = 0; 128 int bytes = 0;
132 129
133 if (!client || (client && !client->connection) || !plist) { 130 if (!client || (client && !client->parent) || !plist) {
134 return PROPERTY_LIST_SERVICE_E_INVALID_ARG; 131 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
135 } 132 }
136 133
@@ -146,9 +143,9 @@ static property_list_service_error_t internal_plist_send(property_list_service_c
146 143
147 nlen = htobe32(length); 144 nlen = htobe32(length);
148 debug_info("sending %d bytes", length); 145 debug_info("sending %d bytes", length);
149 idevice_connection_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); 146 service_send(client->parent, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
150 if (bytes == sizeof(nlen)) { 147 if (bytes == sizeof(nlen)) {
151 idevice_connection_send(client->connection, content, length, (uint32_t*)&bytes); 148 service_send(client->parent, content, length, (uint32_t*)&bytes);
152 if (bytes > 0) { 149 if (bytes > 0) {
153 debug_info("sent %d bytes", bytes); 150 debug_info("sent %d bytes", bytes);
154 debug_plist(plist); 151 debug_plist(plist);
@@ -222,11 +219,11 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis
222 uint32_t pktlen = 0; 219 uint32_t pktlen = 0;
223 uint32_t bytes = 0; 220 uint32_t bytes = 0;
224 221
225 if (!client || (client && !client->connection) || !plist) { 222 if (!client || (client && !client->parent) || !plist) {
226 return PROPERTY_LIST_SERVICE_E_INVALID_ARG; 223 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
227 } 224 }
228 225
229 idevice_connection_receive_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); 226 service_receive_with_timeout(client->parent, (char*)&pktlen, sizeof(pktlen), &bytes, timeout);
230 debug_info("initial read=%i", bytes); 227 debug_info("initial read=%i", bytes);
231 if (bytes < 4) { 228 if (bytes < 4) {
232 debug_info("initial read failed!"); 229 debug_info("initial read failed!");
@@ -240,7 +237,7 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis
240 content = (char*)malloc(pktlen); 237 content = (char*)malloc(pktlen);
241 238
242 while (curlen < pktlen) { 239 while (curlen < pktlen) {
243 idevice_connection_receive(client->connection, content+curlen, pktlen-curlen, &bytes); 240 service_receive(client->parent, content+curlen, pktlen-curlen, &bytes);
244 if (bytes <= 0) { 241 if (bytes <= 0) {
245 res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; 242 res = PROPERTY_LIST_SERVICE_E_MUX_ERROR;
246 break; 243 break;
@@ -332,9 +329,9 @@ property_list_service_error_t property_list_service_receive_plist(property_list_
332 */ 329 */
333property_list_service_error_t property_list_service_enable_ssl(property_list_service_client_t client) 330property_list_service_error_t property_list_service_enable_ssl(property_list_service_client_t client)
334{ 331{
335 if (!client || !client->connection) 332 if (!client || !client->parent)
336 return PROPERTY_LIST_SERVICE_E_INVALID_ARG; 333 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
337 return idevice_to_property_list_service_error(idevice_connection_enable_ssl(client->connection)); 334 return service_to_property_list_service_error(service_enable_ssl(client->parent));
338} 335}
339 336
340/** 337/**
@@ -349,8 +346,8 @@ property_list_service_error_t property_list_service_enable_ssl(property_list_ser
349 */ 346 */
350property_list_service_error_t property_list_service_disable_ssl(property_list_service_client_t client) 347property_list_service_error_t property_list_service_disable_ssl(property_list_service_client_t client)
351{ 348{
352 if (!client || !client->connection) 349 if (!client || !client->parent)
353 return PROPERTY_LIST_SERVICE_E_INVALID_ARG; 350 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
354 return idevice_to_property_list_service_error(idevice_connection_disable_ssl(client->connection)); 351 return service_to_property_list_service_error(service_disable_ssl(client->parent));
355} 352}
356 353
diff --git a/src/property_list_service.h b/src/property_list_service.h
index 8b15c09..c18fd76 100644
--- a/src/property_list_service.h
+++ b/src/property_list_service.h
@@ -23,6 +23,7 @@
23#define __PROPERTY_LIST_SERVICE_H 23#define __PROPERTY_LIST_SERVICE_H
24 24
25#include <libimobiledevice/lockdown.h> 25#include <libimobiledevice/lockdown.h>
26#include "service.h"
26#include "idevice.h" 27#include "idevice.h"
27 28
28/* Error Codes */ 29/* Error Codes */
@@ -35,7 +36,7 @@
35#define PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR -256 36#define PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR -256
36 37
37struct property_list_service_client_private { 38struct property_list_service_client_private {
38 idevice_connection_t connection; 39 service_client_t parent;
39}; 40};
40 41
41typedef struct property_list_service_client_private *property_list_service_client_t; 42typedef struct property_list_service_client_private *property_list_service_client_t;
diff --git a/src/service.c b/src/service.c
new file mode 100644
index 0000000..929beff
--- /dev/null
+++ b/src/service.c
@@ -0,0 +1,276 @@
1/*
2 * service.c
3 * generic service implementation.
4 *
5 * Copyright (c) 2013 Nikias Bassen. All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24#include <stdlib.h>
25#include <string.h>
26
27#include "service.h"
28#include "idevice.h"
29#include "debug.h"
30
31/**
32 * Convert an idevice_error_t value to an service_error_t value.
33 * Used internally to get correct error codes.
34 *
35 * @param err An idevice_error_t error code
36 *
37 * @return A matching service_error_t error code,
38 * SERVICE_E_UNKNOWN_ERROR otherwise.
39 */
40static service_error_t idevice_to_service_error(idevice_error_t err)
41{
42 switch (err) {
43 case IDEVICE_E_SUCCESS:
44 return SERVICE_E_SUCCESS;
45 case IDEVICE_E_INVALID_ARG:
46 return SERVICE_E_INVALID_ARG;
47 case IDEVICE_E_SSL_ERROR:
48 return SERVICE_E_SSL_ERROR;
49 default:
50 break;
51 }
52 return SERVICE_E_UNKNOWN_ERROR;
53}
54
55/**
56 * Creates a new service for the specified service descriptor.
57 *
58 * @param device The device to connect to.
59 * @param service The service descriptor returned by lockdownd_start_service.
60 * @param client Pointer that will be set to a newly allocated
61 * service_client_t upon successful return.
62 *
63 * @return SERVICE_E_SUCCESS on success,
64 * SERVICE_E_INVALID_ARG when one of the arguments is invalid,
65 * or SERVICE_E_MUX_ERROR when connecting to the device failed.
66 */
67service_error_t service_client_new(idevice_t device, lockdownd_service_descriptor_t service, service_client_t *client)
68{
69 if (!device || (service->port == 0) || !client || *client)
70 return SERVICE_E_INVALID_ARG;
71
72 /* Attempt connection */
73 idevice_connection_t connection = NULL;
74 if (idevice_connect(device, service->port, &connection) != IDEVICE_E_SUCCESS) {
75 return SERVICE_E_MUX_ERROR;
76 }
77
78 /* create client object */
79 service_client_t client_loc = (service_client_t)malloc(sizeof(struct service_client_private));
80 client_loc->connection = connection;
81
82 /* enable SSL if requested */
83 if (service->ssl_enabled == 1)
84 service_enable_ssl(client_loc);
85
86 /* all done, return success */
87 *client = client_loc;
88 return SERVICE_E_SUCCESS;
89}
90
91/**
92 * Starts a new service on the specified device with given name and
93 * connects to it.
94 *
95 * @param device The device to connect to.
96 * @param service_name The name of the service to start.
97 * @param client Pointer that will point to a newly allocated service_client_t
98 * upon successful return. Must be freed using service_client_free() after
99 * use.
100 *
101 * @return SERVICE_E_SUCCESS on success, or a SERVICE_E_* error code
102 * otherwise.
103 */
104service_error_t service_start_service(idevice_t device, const char* service_name, service_client_t *client)
105{
106 *client = NULL;
107
108 lockdownd_client_t lckd = NULL;
109 if (LOCKDOWN_E_SUCCESS != lockdownd_client_new_with_handshake(device, &lckd, NULL)) {
110 debug_info("Could not create a lockdown client.");
111 return SERVICE_E_START_SERVICE_ERROR;
112 }
113
114 lockdownd_service_descriptor_t service = NULL;
115 lockdownd_start_service(lckd, service_name, &service);
116 lockdownd_client_free(lckd);
117
118 if (service->port <= 0) {
119 debug_info("Could not start service %s!", service_name);
120 return SERVICE_E_START_SERVICE_ERROR;
121 }
122
123 service_error_t res = service_client_new(device, service, client);
124 if (res != SERVICE_E_SUCCESS) {
125 debug_info("Could not connect to service %s! Port: %i, error: %i", service_name, service->port, res);
126 return res;
127 }
128
129 if (service) {
130 lockdownd_service_descriptor_free(service);
131 service = NULL;
132 }
133
134 return SERVICE_E_SUCCESS;
135}
136
137/**
138 * Frees a service instance.
139 *
140 * @param client The service instance to free.
141 *
142 * @return SERVICE_E_SUCCESS on success,
143 * SERVICE_E_INVALID_ARG when client is invalid, or a
144 * SERVICE_E_UNKNOWN_ERROR when another error occured.
145 */
146service_error_t service_client_free(service_client_t client)
147{
148 if (!client)
149 return SERVICE_E_INVALID_ARG;
150
151 service_error_t err = idevice_to_service_error(idevice_disconnect(client->connection));
152 free(client);
153 return err;
154}
155
156/**
157 * Sends data using the given service client.
158 *
159 * @param client The service client to use for sending.
160 * @param data Data to send
161 * @param size Size of the data to send
162 * @param sent Number of bytes sent (can be NULL to ignore)
163 *
164 * @return SERVICE_E_SUCCESS on success,
165 * SERVICE_E_INVALID_ARG when one or more parameters are
166 * invalid, or SERVICE_E_UNKNOWN_ERROR when an unspecified
167 * error occurs.
168 */
169service_error_t service_send(service_client_t client, const char* data, uint32_t size, uint32_t *sent)
170{
171 service_error_t res = SERVICE_E_UNKNOWN_ERROR;
172 int bytes = 0;
173
174 if (!client || (client && !client->connection) || !data || (size == 0)) {
175 return SERVICE_E_INVALID_ARG;
176 }
177
178 debug_info("sending %d bytes", size);
179 res = idevice_to_service_error(idevice_connection_send(client->connection, data, size, (uint32_t*)&bytes));
180 if (bytes <= 0) {
181 debug_info("ERROR: sending to device failed.");
182 }
183 if (sent) {
184 *sent = (uint32_t)bytes;
185 }
186
187 return res;
188}
189
190/**
191 * Receives data using the given service client with specified timeout.
192 *
193 * @param client The service client to use for receiving
194 * @param data Buffer that will be filled with the data received
195 * @param size Number of bytes to receive
196 * @param received Number of bytes received (can be NULL to ignore)
197 * @param timeout Maximum time in milliseconds to wait for data.
198 *
199 * @return SERVICE_E_SUCCESS on success,
200 * SERVICE_E_INVALID_ARG when one or more parameters are
201 * invalid, SERVICE_E_MUX_ERROR when a communication error
202 * occurs, or SERVICE_E_UNKNOWN_ERROR when an unspecified
203 * error occurs.
204 */
205service_error_t service_receive_with_timeout(service_client_t client, char* data, uint32_t size, uint32_t *received, unsigned int timeout)
206{
207 service_error_t res = SERVICE_E_UNKNOWN_ERROR;
208 int bytes = 0;
209
210 if (!client || (client && !client->connection) || !data || (size == 0)) {
211 return SERVICE_E_INVALID_ARG;
212 }
213
214 res = idevice_to_service_error(idevice_connection_receive_timeout(client->connection, data, size, (uint32_t*)&bytes, timeout));
215 if (bytes <= 0) {
216 debug_info("could not read data");
217 }
218 if (received) {
219 *received = (uint32_t)bytes;
220 }
221
222 return res;
223}
224
225/**
226 * Receives data using the given service client.
227 *
228 * @param client The service client to use for receiving
229 * @param data Buffer that will be filled with the data received
230 * @param size Number of bytes to receive
231 * @param received Number of bytes received (can be NULL to ignore)
232 *
233 * @return SERVICE_E_SUCCESS on success,
234 * SERVICE_E_INVALID_ARG when one or more parameters are
235 * invalid, SERVICE_E_MUX_ERROR when a communication error
236 * occurs, or SERVICE_E_UNKNOWN_ERROR when an unspecified
237 * error occurs.
238 */
239service_error_t service_receive(service_client_t client, char* data, uint32_t size, uint32_t *received)
240{
241 return service_receive_with_timeout(client, data, size, received, 10000);
242}
243
244/**
245 * Enable SSL for the given service client.
246 *
247 * @param client The connected service client for that SSL should be enabled.
248 *
249 * @return SERVICE_E_SUCCESS on success,
250 * SERVICE_E_INVALID_ARG if client or client->connection is
251 * NULL, SERVICE_E_SSL_ERROR when SSL could not be enabled,
252 * or SERVICE_E_UNKNOWN_ERROR otherwise.
253 */
254service_error_t service_enable_ssl(service_client_t client)
255{
256 if (!client || !client->connection)
257 return SERVICE_E_INVALID_ARG;
258 return idevice_to_service_error(idevice_connection_enable_ssl(client->connection));
259}
260
261/**
262 * Disable SSL for the given service client.
263 *
264 * @param client The connected service client for that SSL should be disabled.
265 *
266 * @return SERVICE_E_SUCCESS on success,
267 * SERVICE_E_INVALID_ARG if client or client->connection is
268 * NULL, or SERVICE_E_UNKNOWN_ERROR otherwise.
269 */
270service_error_t service_disable_ssl(service_client_t client)
271{
272 if (!client || !client->connection)
273 return SERVICE_E_INVALID_ARG;
274 return idevice_to_service_error(idevice_connection_disable_ssl(client->connection));
275}
276
diff --git a/src/service.h b/src/service.h
new file mode 100644
index 0000000..e498ed7
--- /dev/null
+++ b/src/service.h
@@ -0,0 +1,59 @@
1/*
2 * service.h
3 * Definitions for the generic service implementation
4 *
5 * Copyright (c) 2013 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifndef SERVICE_H
22#define SERVICE_H
23
24#include "libimobiledevice/lockdown.h"
25#include "idevice.h"
26
27/* Error Codes */
28#define SERVICE_E_SUCCESS 0
29#define SERVICE_E_INVALID_ARG -1
30#define SERVICE_E_MUX_ERROR -3
31#define SERVICE_E_SSL_ERROR -4
32#define SERVICE_E_START_SERVICE_ERROR -5
33#define SERVICE_E_UNKNOWN_ERROR -256
34
35struct service_client_private {
36 idevice_connection_t connection;
37};
38
39typedef struct service_client_private *service_client_t;
40
41typedef int16_t service_error_t;
42
43/* creation and destruction */
44service_error_t service_client_new(idevice_t device, lockdownd_service_descriptor_t service, service_client_t *client);
45service_error_t service_start_service(idevice_t device, const char* service_name, service_client_t *client);
46service_error_t service_client_free(service_client_t client);
47
48/* sending */
49service_error_t service_send(service_client_t client, const char *data, uint32_t size, uint32_t *sent);
50
51/* receiving */
52service_error_t service_receive_with_timeout(service_client_t client, char *data, uint32_t size, uint32_t *received, unsigned int timeout);
53service_error_t service_receive(service_client_t client, char *data, uint32_t size, uint32_t *received);
54
55/* misc */
56service_error_t service_enable_ssl(service_client_t client);
57service_error_t service_disable_ssl(service_client_t client);
58
59#endif