summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac28
-rw-r--r--dev/Makefile.am3
-rw-r--r--dev/main.c59
-rw-r--r--fdi/31-apple-mobile-device.fdi5
-rw-r--r--include/libiphone/libiphone.h5
-rw-r--r--src/AFC.c106
-rw-r--r--src/AFC.h40
-rw-r--r--src/Makefile.am4
-rw-r--r--src/NotificationProxy.c263
-rw-r--r--src/NotificationProxy.h31
-rw-r--r--src/usbmux.c7
11 files changed, 529 insertions, 22 deletions
diff --git a/configure.ac b/configure.ac
index ec7e11a..a91d9f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,4 +68,32 @@ fi
AS_COMPILER_FLAGS(GLOBAL_CFLAGS, "-Wall -Wextra -Wmissing-declarations -Wredundant-decls -Wshadow -Wpointer-arith -Wwrite-strings -Wswitch-default -Wno-unused-parameter")
AC_SUBST(GLOBAL_CFLAGS)
+# check for large file support
+AC_SYS_LARGEFILE
+LFS_CFLAGS=''
+if test "$enable_largefile" != no; then
+ if test "$ac_cv_sys_file_offset_bits" != 'no'; then
+ LFS_CFLAGS="$LFS_CFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
+ else
+ AC_MSG_CHECKING(for native large file support)
+ AC_RUN_IFELSE([#include <unistd.h>
+ int main (int argc, char **argv)
+ {
+ exit(!(sizeof(off_t) == 8));
+ }],
+ [ac_cv_sys_file_offset_bits=64; AC_DEFINE(_FILE_OFFSET_BITS,64)
+ AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)])
+ fi
+ if test "$ac_cv_sys_large_files" != 'no'; then
+ LFS_CFLAGS="$LFS_CFLAGS -D_LARGE_FILES=1"
+ fi
+ AC_FUNC_FSEEKO
+ if test "$ac_cv_sys_largefile_source" != 'no'; then
+ LFS_CFLAGS="$LFS_CFLAGS -D_LARGEFILE_SOURCE=1"
+ fi
+fi
+AC_SUBST(LFS_CFLAGS)
+
AC_OUTPUT(Makefile src/Makefile include/Makefile fdi/Makefile dev/Makefile swig/Makefile libiphone-1.0.pc)
+
diff --git a/dev/Makefile.am b/dev/Makefile.am
index f976ccc..f7d1109 100644
--- a/dev/Makefile.am
+++ b/dev/Makefile.am
@@ -1,6 +1,6 @@
INCLUDES = -I$(top_srcdir)/include
-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g
+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(LFS_CFLAGS)
AM_LDFLAGS = $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS)
bin_PROGRAMS = iphoneclient lckd-client afccheck msyncclient
@@ -22,3 +22,4 @@ msyncclient_SOURCES = msyncclient.c
msyncclient_CFLAGS = $(AM_CFLAGS)
msyncclient_LDFLAGS = $(AM_LDFLAGS)
msyncclient_LDADD = ../src/libiphone.la
+
diff --git a/dev/main.c b/dev/main.c
index 6514bf8..babcf67 100644
--- a/dev/main.c
+++ b/dev/main.c
@@ -27,12 +27,51 @@
#include <libiphone/libiphone.h>
#include "../src/utils.h"
+void perform_syncWillStart(iphone_device_t phone, iphone_lckd_client_t control)
+{
+ int nport = 0;
+ iphone_np_client_t np;
+
+ iphone_lckd_start_service(control, "com.apple.mobile.notification_proxy", &nport);
+ if (nport) {
+ printf("::::::::::::::: np was started ::::::::::::\n");
+ iphone_np_new_client(phone, 3555, nport, &np);
+ if (np) {
+ printf("::::::::: PostNotification com.apple.itunes-mobdev.syncWillStart\n");
+ iphone_np_post_notification(np, "com.apple.itunes-mobdev.syncWillStart");
+ iphone_np_free_client(np);
+ }
+ } else {
+ printf("::::::::::::::: np was NOT started ::::::::::::\n");
+ }
+}
+
+void perform_syncDidStart(iphone_device_t phone, iphone_lckd_client_t control)
+{
+ int nport = 0;
+ iphone_np_client_t np;
+
+ iphone_lckd_start_service(control, "com.apple.mobile.notification_proxy", &nport);
+ if (nport) {
+ printf("::::::::::::::: np was started ::::::::::::\n");
+ sleep(1);
+ iphone_np_new_client(phone, 3555, nport, &np);
+ if (np) {
+ printf("::::::::: PostNotification com.apple.itunes-mobdev.syncDidStart\n");
+ iphone_np_post_notification(np, "com.apple.itunes-mobdev.syncDidStart");
+ iphone_np_free_client(np);
+ }
+ } else {
+ printf("::::::::::::::: np was NOT started ::::::::::::\n");
+ }
+}
int main(int argc, char *argv[])
{
int bytes = 0, port = 0, i = 0;
iphone_lckd_client_t control = NULL;
iphone_device_t phone = NULL;
+ iphone_afc_file_t lockfile = NULL;
if (argc > 1 && !strcasecmp(argv[1], "--debug")) {
iphone_set_debug(1);
@@ -64,6 +103,16 @@ int main(int argc, char *argv[])
iphone_afc_client_t afc = NULL;
iphone_afc_new_client(phone, 3432, port, &afc);
if (afc) {
+ perform_syncWillStart(phone, control);
+
+ iphone_afc_open_file(afc, "/com.apple.itunes.lock_sync", IPHONE_AFC_FILE_WRITE, &lockfile);
+ if (lockfile) {
+ printf("locking file\n");
+ iphone_afc_lock_file(afc, lockfile, 2 | 4);
+
+ perform_syncDidStart(phone, control);
+ }
+
char **dirs = NULL;
iphone_afc_get_dir_list(afc, "/eafaedf", &dirs);
if (!dirs)
@@ -138,7 +187,17 @@ int main(int argc, char *argv[])
printf("Couldn't read!\n");
free(threeletterword);
iphone_afc_close_file(afc, my_file);
+ }
+
+ if (lockfile) {
+ printf("XXX sleeping 2 seconds\n");
+ sleep(2);
+
+ printf("XXX unlocking file\n");
+ iphone_afc_lock_file(afc, lockfile, 8 | 4);
+ printf("XXX closing file\n");
+ iphone_afc_close_file(afc, lockfile);
}
iphone_afc_free_client(afc);
} else {
diff --git a/fdi/31-apple-mobile-device.fdi b/fdi/31-apple-mobile-device.fdi
index 3e9ccc9..d598409 100644
--- a/fdi/31-apple-mobile-device.fdi
+++ b/fdi/31-apple-mobile-device.fdi
@@ -5,11 +5,12 @@
<match key="usb.vendor_id" int="0x05ac">
<match key="usb.product_id" compare_ge="0x1290">
<match key="usb.product_id" compare_le="0x1293">
- <append key="info.capabilities" type="strlist">afc</append>
+ <match key="usb.interface.number" int="0x1">
+ <append key="info.capabilities" type="strlist">afc</append>
+ </match>
</match>
</match>
</match>
</match>
</device>
</deviceinfo>
-
diff --git a/include/libiphone/libiphone.h b/include/libiphone/libiphone.h
index 9823bed..0035e2f 100644
--- a/include/libiphone/libiphone.h
+++ b/include/libiphone/libiphone.h
@@ -81,6 +81,9 @@ typedef struct iphone_afc_file_int *iphone_afc_file_t;
struct iphone_msync_client_int;
typedef struct iphone_msync_client_int *iphone_msync_client_t;
+struct iphone_np_client_int;
+typedef struct iphone_np_client_int *iphone_np_client_t;
+
//debug related functions
#define DBGMASK_ALL 0xFFFF
#define DBGMASK_NONE 0x0000
@@ -124,6 +127,7 @@ iphone_error_t iphone_afc_get_dir_list ( iphone_afc_client_t client, const char
iphone_error_t iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf );
iphone_error_t iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, iphone_afc_file_mode_t file_mode, iphone_afc_file_t *file );
iphone_error_t iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file);
+iphone_error_t iphone_afc_lock_file ( iphone_afc_client_t client, iphone_afc_file_t file, int operation);
iphone_error_t iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length, uint32_t *bytes);
iphone_error_t iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length, uint32_t *bytes);
iphone_error_t iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos);
@@ -131,6 +135,7 @@ iphone_error_t iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc
iphone_error_t iphone_afc_delete_file ( iphone_afc_client_t client, const char *path);
iphone_error_t iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to);
iphone_error_t iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir);
+iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path, off_t newsize);
diff --git a/src/AFC.c b/src/AFC.c
index 67d37f3..dfe8af7 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -178,7 +178,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int
log_debug_msg("dispatch_AFC_packet: sent the first now go with the second\n");
log_debug_msg("Length: %i\n", length - offset);
log_debug_msg("Buffer: \n");
- log_debug_msg(data + offset);
+ log_debug_buffer(data + offset, length - offset);
iphone_mux_send(client->connection, data + offset, length - offset, &bytes);
return bytes;
@@ -916,6 +916,63 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
return IPHONE_E_SUCCESS;
}
+/** Locks or unlocks a file on the phone.
+ *
+ * makes use of flock, see
+ * http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/flock.2.html
+ *
+ * operation (same as in sys/file.h on linux):
+ *
+ * LOCK_SH 1 // shared lock
+ * LOCK_EX 2 // exclusive lock
+ * LOCK_NB 4 // don't block when locking
+ * LOCK_UN 8 // unlock
+ *
+ * @param client The client to close the file with.
+ * @param file A pointer to an AFCFile struct containing the file handle of the
+ * file to close.
+ * @operation the lock or unlock operation to perform.
+ */
+iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, iphone_afc_file_t file, int operation)
+{
+ if (!client || !file)
+ return IPHONE_E_INVALID_ARG;
+ char *buffer = malloc(16);
+ uint32_t zero = 0;
+ int bytes = 0;
+ uint64_t op = operation;
+
+ afc_lock(client);
+
+ log_debug_msg("afc_lock_file: File handle %i\n", file->filehandle);
+
+ // Send command
+ memcpy(buffer, &file->filehandle, sizeof(uint32_t));
+ memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero));
+ memcpy(buffer + 8, &op, 8);
+
+ client->afc_packet->operation = AFC_FILE_LOCK;
+ client->afc_packet->entire_length = client->afc_packet->this_length = 0;
+ bytes = dispatch_AFC_packet(client, buffer, 15);
+ free(buffer);
+ buffer = NULL;
+
+ if (bytes <= 0) {
+ afc_unlock(client);
+ log_debug_msg("fuck\n");
+ return IPHONE_E_UNKNOWN_ERROR;
+ }
+ // Receive the response
+ bytes = receive_AFC_data(client, &buffer);
+ log_debug_msg("%s: receiving response (%d bytes)\n", __func__, bytes);
+ if (buffer) {
+ log_debug_buffer(buffer, bytes);
+ free(buffer);
+ }
+ afc_unlock(client);
+ return IPHONE_E_SUCCESS;
+}
+
/** Seeks to a given position of a pre-opened file on the phone.
*
* @param client The client to use to seek to the position.
@@ -1016,6 +1073,53 @@ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_f
}
}
+/** Sets the size of a file on the phone without prior opening it.
+ *
+ * @param client The client to use to set the file size.
+ * @param path The path of the file to be truncated.
+ * @param newsize The size to set the file to.
+ *
+ * @return IPHONE_E_SUCCESS if everything went well, IPHONE_E_INVALID_ARG
+ * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
+ */
+iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path, off_t newsize)
+{
+ char *response = NULL;
+ char *send = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8));
+ int bytes = 0;
+ uint64_t size_requested = newsize;
+
+ if (!client || !path || !client->afc_packet || !client->connection)
+ return IPHONE_E_INVALID_ARG;
+
+ afc_lock(client);
+
+ // Send command
+ memcpy(send, &size_requested, 8);
+ memcpy(send + 8, path, strlen(path) + 1);
+ client->afc_packet->entire_length = client->afc_packet->this_length = 0;
+ client->afc_packet->operation = AFC_TRUNCATE;
+ bytes = dispatch_AFC_packet(client, send, 8 + strlen(path));
+ free(send);
+ if (bytes <= 0) {
+ afc_unlock(client);
+ return IPHONE_E_NOT_ENOUGH_DATA;
+ }
+ // Receive response
+ bytes = receive_AFC_data(client, &response);
+ if (response)
+ free(response);
+
+ afc_unlock(client);
+
+ if (bytes < 0) {
+ return IPHONE_E_NOT_ENOUGH_DATA;
+ } else {
+ return IPHONE_E_SUCCESS;
+ }
+}
+
+
uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file)
{
return file->filehandle;
diff --git a/src/AFC.h b/src/AFC.h
index 5e4d17c..90b406a 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -58,20 +58,34 @@ struct iphone_afc_file_int {
enum {
AFC_ERROR = 0x00000001,
- AFC_GET_INFO = 0x0000000a,
- AFC_GET_DEVINFO = 0x0000000b,
- AFC_LIST_DIR = 0x00000003,
- AFC_MAKE_DIR = 0x00000009,
- AFC_DELETE = 0x00000008,
- AFC_RENAME = 0x00000018,
AFC_SUCCESS_RESPONSE = 0x00000002,
- AFC_FILE_OPEN = 0x0000000d,
- AFC_FILE_CLOSE = 0x00000014,
- AFC_FILE_SEEK = 0x00000011,
- AFC_FILE_TRUNCATE = 0x00000015,
- AFC_FILE_HANDLE = 0x0000000e,
- AFC_READ = 0x0000000f,
- AFC_WRITE = 0x00000010
+ AFC_LIST_DIR = 0x00000003, // ReadDir
+ // 0x00000004 // ReadFile
+ // 0x00000005 // WriteFile
+ // 0x00000006 // WritePart
+ AFC_TRUNCATE = 0x00000007, // Truncate
+ AFC_DELETE = 0x00000008, // RemovePath
+ AFC_MAKE_DIR = 0x00000009, // MakeDir
+ AFC_GET_INFO = 0x0000000a, // GetFileInfo
+ AFC_GET_DEVINFO = 0x0000000b, // GetDeviceInfo
+ // 0x0000000c // same as 5, but writes to temp file, then renames it.
+ AFC_FILE_OPEN = 0x0000000d, // FileRefOpen
+ AFC_FILE_HANDLE = 0x0000000e, // _unknownPacket
+ AFC_READ = 0x0000000f, // FileRefRead
+ AFC_WRITE = 0x00000010, // FileRefWrite
+ AFC_FILE_SEEK = 0x00000011, // FileRefSeek
+ AFC_FILE_TELL = 0x00000012, // FileRefTell
+ // 0x00000013 // _unknownPacket
+ AFC_FILE_CLOSE = 0x00000014, // FileRefClose
+ AFC_FILE_TRUNCATE = 0x00000015, // FileRefSetFileSize (ftruncate)
+ // 0x00000016 // SetFatalError
+ // 0x00000017 // SetConnectionOptions
+ AFC_RENAME = 0x00000018, // RenamePath
+ // 0x00000019 // SetFSBlockSize (0x800000)
+ // 0x0000001A // SetBlockSize (0x800000)
+ AFC_FILE_LOCK = 0x0000001B, // FileRefLock
+ AFC_MAKE_LINK = 0x0000001C // MakeLink
};
+
uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file);
diff --git a/src/Makefile.am b/src/Makefile.am
index 039632f..71667ae 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
INCLUDES = -I$(top_srcdir)/include
-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) -g
+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS)
AM_LDFLAGS = $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS)
bin_PROGRAMS = libiphone-initconf
@@ -12,4 +12,4 @@ libiphone_initconf_LDFLAGS = $(libgthread2_LIBS) $(AM_LDFLAGS)
lib_LTLIBRARIES = libiphone.la
-libiphone_la_SOURCES = usbmux.c iphone.c lockdown.c AFC.c userpref.c utils.c MobileSync.c
+libiphone_la_SOURCES = usbmux.c iphone.c lockdown.c AFC.c NotificationProxy.c userpref.c utils.c MobileSync.c
diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c
new file mode 100644
index 0000000..eec7857
--- /dev/null
+++ b/src/NotificationProxy.c
@@ -0,0 +1,263 @@
+/*
+ * NotificationProxy.c
+ * Notification Proxy implementation.
+ *
+ * Copyright (c) 2009 Nikias Bassen, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <plist/plist.h>
+#include "NotificationProxy.h"
+#include "utils.h"
+
+/** Locks an NP client, done for thread safety stuff.
+ *
+ * @param client The NP
+ */
+static void np_lock(iphone_np_client_t client)
+{
+ log_debug_msg("NP: Locked\n");
+ g_mutex_lock(client->mutex);
+}
+
+/** Unlocks an NP client, done for thread safety stuff.
+ *
+ * @param client The NP
+ */
+static void np_unlock(iphone_np_client_t client)
+{
+ log_debug_msg("NP: Unlocked\n");
+ g_mutex_unlock(client->mutex);
+}
+
+/** Makes a connection to the NP service on the phone.
+ *
+ * @param phone The iPhone to connect on.
+ * @param s_port The source port.
+ * @param d_port The destination port.
+ *
+ * @return A handle to the newly-connected client or NULL upon error.
+ */
+iphone_error_t iphone_np_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_np_client_t *client )
+{
+ int ret = IPHONE_E_SUCCESS;
+
+ //makes sure thread environment is available
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+ iphone_np_client_t client_loc = (iphone_np_client_t) malloc(sizeof(struct iphone_np_client_int));
+
+ if (!device)
+ return IPHONE_E_INVALID_ARG;
+
+ // Attempt connection
+ client_loc->connection = NULL;
+ ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection);
+ if (IPHONE_E_SUCCESS != ret || !client_loc->connection) {
+ free(client_loc);
+ return ret;
+ }
+
+ client_loc->mutex = g_mutex_new();
+
+ *client = client_loc;
+ return IPHONE_E_SUCCESS;
+}
+
+/** Disconnects an NP client from the phone.
+ *
+ * @param client The client to disconnect.
+ */
+iphone_error_t iphone_np_free_client ( iphone_np_client_t client )
+{
+ if (!client || !client->connection )
+ return IPHONE_E_INVALID_ARG;
+
+ iphone_mux_free_client(client->connection);
+ free(client);
+ return IPHONE_E_SUCCESS;
+}
+
+/** Sends a notification to the NP client.
+ *
+ * notification messages seen so far:
+ * com.apple.itunes-mobdev.syncWillStart
+ * com.apple.itunes-mobdev.syncDidStart
+ *
+ * @param client The client to send to
+ * @param notification The notification Message
+ */
+iphone_error_t iphone_np_post_notification( iphone_np_client_t client, const char *notification )
+{
+ char *XML_content = NULL;
+ uint32_t length = 0;
+ int bytes = 0;
+ iphone_error_t ret;
+ unsigned char sndbuf[4096];
+ int sndlen = 0;
+ int nlen = 0;
+ plist_t dict = NULL;
+
+ if (!client || !notification) {
+ return IPHONE_E_INVALID_ARG;
+ }
+ np_lock(client);
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "PostNotification");
+ plist_add_sub_key_el(dict, "Name");
+ plist_add_sub_string_el(dict, notification);
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen += 4;
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen += length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "Shutdown");
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen+=4;
+
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen+=length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+
+ log_debug_buffer(sndbuf, sndlen);
+
+ iphone_mux_send(client->connection, sndbuf, sndlen, &bytes);
+ if (bytes <= 0) {
+ np_unlock(client);
+ return bytes;
+ }
+
+ np_unlock(client);
+ return bytes;
+}
+
+/** Notifies the iphone to send a notification on certain events.
+ *
+ * observation messages seen so far:
+ * com.apple.itunes-client.syncCancelRequest
+ * com.apple.itunes-client.syncSuspendRequest
+ * com.apple.itunes-client.syncResumeRequest
+ * com.apple.mobile.lockdown.phone_number_changed
+ * com.apple.mobile.lockdown.device_name_changed
+ * com.apple.springboard.attemptactivation
+ * com.apple.mobile.data_sync.domain_changed
+ * com.apple.mobile.application_installed
+ * com.apple.mobile.application_uninstalled
+ *
+ * @param client The client to send to
+ */
+iphone_error_t iphone_np_observe_notification( iphone_np_client_t client )
+{
+ plist_t dict = NULL;
+ char *XML_content = NULL;
+ uint32_t length = 0;
+ int bytes = 0;
+ iphone_error_t ret;
+ unsigned char sndbuf[4096];
+ int sndlen = 0;
+ int nlen = 0;
+ int i=0;
+ const char *notifications[10] = {
+ "com.apple.itunes-client.syncCancelRequest",
+ "com.apple.itunes-client.syncSuspendRequest",
+ "com.apple.itunes-client.syncResumeRequest",
+ "com.apple.mobile.lockdown.phone_number_changed",
+ "com.apple.mobile.lockdown.device_name_changed",
+ "com.apple.springboard.attemptactivation",
+ "com.apple.mobile.data_sync.domain_changed",
+ "com.apple.mobile.application_installed",
+ "com.apple.mobile.application_uninstalled",
+ NULL};
+
+ sndlen = 0;
+
+ if (!client) {
+ return IPHONE_E_INVALID_ARG;
+ }
+ np_lock(client);
+
+ while (notifications[i]) {
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "ObserveNotification");
+ plist_add_sub_key_el(dict, "Name");
+ plist_add_sub_string_el(dict, notifications[i++]);
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen += 4;
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen += length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+ }
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "Shutdown");
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen+=4;
+
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen+=length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+
+ log_debug_buffer(sndbuf, sndlen);
+
+ iphone_mux_send(client->connection, sndbuf, sndlen, &bytes);
+ if (bytes <= 0) {
+ np_unlock(client);
+ return bytes;
+ }
+
+ np_unlock(client);
+ return bytes;
+}
diff --git a/src/NotificationProxy.h b/src/NotificationProxy.h
new file mode 100644
index 0000000..57ad751
--- /dev/null
+++ b/src/NotificationProxy.h
@@ -0,0 +1,31 @@
+/*
+ * NotificationProxy.h
+ * Notification Proxy header file.
+ *
+ * Copyright (c) 2009 Nikias Bassen, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libiphone/libiphone.h"
+#include "usbmux.h"
+#include "iphone.h"
+
+#include <glib.h>
+
+struct iphone_np_client_int {
+ iphone_umux_client_t connection;
+ GMutex *mutex;
+};
+
diff --git a/src/usbmux.c b/src/usbmux.c
index 5eaa1d1..22ce588 100644
--- a/src/usbmux.c
+++ b/src/usbmux.c
@@ -309,7 +309,8 @@ iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t
}
// Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above.
- return datalen;
+ *recv_bytes = datalen;
+ return IPHONE_E_SUCCESS;
} else {
memcpy(data, client->recv_buffer, client->r_len);
free(client->recv_buffer); // don't need to deal with anymore, but...
@@ -362,10 +363,10 @@ iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t
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 = client->r_len + (bytes - 28) - datalen;
+ complex = client->r_len + ((bytes - 28) - datalen);
client->recv_buffer = (char *) realloc(client->recv_buffer, (sizeof(char) * complex));
client->r_len = complex;
- complex = client->r_len - (bytes - 28) - datalen;
+ complex = client->r_len - ((bytes - 28) - datalen);
memcpy(client->recv_buffer + complex, buffer + 28 + datalen, (bytes - 28) - datalen);
free(buffer);
client->header->ocnt += bytes - 28;