commit 9a8104302de5e95a8e74a79ce3df48fbd98e7167
Author: Hector Martin <[email protected]>
Date:   Tue Oct 20 19:16:07 2009 +0200

    Fix sync notifications
    
    Correctly handles sync locking, quits iPod app at sync start, and has
    saner error handling.
    
    Note: the repeated sync retries are required. The iPod app will fade-out
    and take over 4 seconds if sync starts while music is playing. The
    current timeout is 50*200ms = 10 seconds, which should be reasonable.

 src/itdb_iphone.c |  212 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 118 insertions(+), 94 deletions(-)
---
diff --git a/src/itdb_iphone.c b/src/itdb_iphone.c
index 4f2cea2..fc8aebe 100644
--- a/src/itdb_iphone.c
+++ b/src/itdb_iphone.c
@@ -21,6 +21,7 @@
 #include <itdb_private.h>
 #include <errno.h>
 #include <stdio.h>
+#include <unistd.h>
 #ifdef HAVE_LIBIPHONE
 #include <libiphone/libiphone.h>
 #include <libiphone/lockdown.h>
@@ -34,17 +35,50 @@ struct itdbprep_int {
 };
 typedef struct itdbprep_int *itdbprep_t;
 
+#define LOCK_ATTEMPTS  50
+#define LOCK_WAIT      200000
+
+
+/* libiphone should probably be reworked so we don't have to reopen a 
connection
+   to notification_proxy for every notification... */
+static int itdb_iphone_post_notification(iphone_device_t device,
+                                        lockdownd_client_t client,
+                                        const char *notification)
+{
+    np_client_t np = NULL;
+    int nport = 0;
+
+    lockdownd_start_service(client, "com.apple.mobile.notification_proxy", 
&nport);
+    if (!nport) {
+       fprintf(stderr, "notification_proxy could not be started!\n");
+       return -1;
+    }
+
+    np_client_new(device, nport, &np);
+    if(!np) {
+       fprintf(stderr, "connection to notification_proxy failed!\n");
+       return -1;
+    }
+
+    if(np_post_notification(np, notification)) {
+       fprintf(stderr, "failed to post notification!\n");
+       np_client_free(np);
+       return -1;
+    }
+
+    np_client_free(np);
+    return 0;
+}
+
 int itdb_iphone_start_sync(Itdb_Device *device, void **prepdata)
 {
     int res = 0;
-    int sync_started = 0;
+    int sync_starting = 0;
     itdbprep_t pdata_loc = NULL;
     const char *uuid;
     lockdownd_client_t client = NULL;
     int afcport = 0;
-    np_client_t np = NULL;
-    int nport = 0;
-
+    int i;
 
     uuid = itdb_device_get_uuid (device);
 
@@ -83,49 +117,15 @@ int itdb_iphone_start_sync(Itdb_Device *device, void 
**prepdata)
        goto leave_with_err;
     }
 
-    /* before we try to launch the 'sync in progress...' screen, we'll try
-     * if the lockfile is lockable. If not, abort.
-     */
-    afc_file_open(pdata_loc->afc, "/com.apple.itunes.lock_sync", AFC_FOPEN_RW, 
&pdata_loc->lockfile);
-
-    if (!pdata_loc->lockfile) {
-       fprintf(stderr, "could not open lockfile in first place\n");
+    if (itdb_iphone_post_notification(pdata_loc->device, client, 
NP_SYNC_WILL_START)) {
+       fprintf(stderr, "could not post syncWillStart notification!\n");
        res = -1;
        goto leave_with_err;
     }
+    printf("%s: posted syncWillStart\n", __func__);
+    sync_starting = 1;
 
-    if (afc_file_lock(pdata_loc->afc, pdata_loc->lockfile, AFC_LOCK_EX) != 
IPHONE_E_SUCCESS) {
-       fprintf(stderr, "ERROR: could not lock file in first place!\n");
-       afc_file_close(pdata_loc->afc, pdata_loc->lockfile);
-       pdata_loc->lockfile = 0;
-       goto leave_with_err;
-    }
-
-    if (afc_file_lock(pdata_loc->afc, pdata_loc->lockfile, AFC_LOCK_UN) != 
IPHONE_E_SUCCESS) {
-       fprintf(stderr, "ERROR: could not unlock file in first place!\n");
-    }
-    afc_file_close(pdata_loc->afc, pdata_loc->lockfile);
-    pdata_loc->lockfile = 0;
-
-    lockdownd_start_service(client, "com.apple.mobile.notification_proxy", 
&nport);
-    if (nport) {
-       np_client_new(pdata_loc->device, nport, &np);
-       if (np) {
-           np_post_notification(np, NP_SYNC_WILL_START);
-           sync_started = 1;
-       }
-    }
-    if (!nport || !np) {
-       fprintf(stderr, "notification_proxy could not be started!\n");
-       res = -1;
-       goto leave_with_err;
-    }
-    np_client_free(np);
-
-    nport = 0;
-    np = NULL;
-
-    /* OPEN AND LOCK /com.apple.itunes.lock_sync */ 
+    /* OPEN AND LOCK /com.apple.itunes.lock_sync */
     afc_file_open(pdata_loc->afc, "/com.apple.itunes.lock_sync", AFC_FOPEN_RW, 
&pdata_loc->lockfile);
 
     if (!pdata_loc->lockfile) {
@@ -134,29 +134,39 @@ int itdb_iphone_start_sync(Itdb_Device *device, void 
**prepdata)
        goto leave_with_err;
     }
 
-    if (afc_file_lock(pdata_loc->afc, pdata_loc->lockfile, AFC_LOCK_EX) != 
IPHONE_E_SUCCESS) {
-       fprintf(stderr, "ERROR: could not lock file!\n");
-       afc_file_close(pdata_loc->afc, pdata_loc->lockfile);
-       pdata_loc->lockfile = 0;
+    if (itdb_iphone_post_notification(pdata_loc->device, client, 
"com.apple.itunes-mobdev.syncLockRequest")) {
+       fprintf(stderr, "could not post syncLockRequest\n");
+       res = -1;
        goto leave_with_err;
     }
-
-    lockdownd_start_service(client, "com.apple.mobile.notification_proxy", 
&nport);
-    if (nport) {
-       np_client_new(pdata_loc->device, nport, &np);
-       if (np) {
-           np_post_notification(np, NP_SYNC_DID_START);
+    printf("%s: posted syncLockRequest\n", __func__);
+
+    for (i=0; i<LOCK_ATTEMPTS; i++) {
+       fprintf(stderr, "Locking for sync, attempt %d...\n", i);
+       res = afc_file_lock(pdata_loc->afc, pdata_loc->lockfile, AFC_LOCK_EX);
+       if (res == AFC_E_SUCCESS) {
+           break;
+       } else if (res == AFC_E_OP_WOULD_BLOCK) {
+           usleep(LOCK_WAIT);
+           continue;
+       } else {
+           fprintf(stderr, "ERROR: could not lock file! error code: %d\n", 
res);
+           res = -1;
+           goto leave_with_err;
        }
     }
-    if (!nport || !np) {
-       fprintf(stderr, "notification_proxy could not be started!\n");
+    if (i == LOCK_ATTEMPTS) {
+       fprintf(stderr, "ERROR: timeout while locking for sync\n");
        res = -1;
-       afc_file_lock(pdata_loc->afc, pdata_loc->lockfile, AFC_LOCK_UN);
-       afc_file_close(pdata_loc->afc, pdata_loc->lockfile);
-       pdata_loc->lockfile = 0;
        goto leave_with_err;
     }
-    np_client_free(np);
+
+    if (itdb_iphone_post_notification(pdata_loc->device, client, 
NP_SYNC_DID_START)) {
+       fprintf(stderr, "could not post syncDidStart\n");
+       res = -1;
+       goto leave_with_err;
+    }
+    printf("%s: posted syncDidStart\n", __func__);
 
     lockdownd_client_free(client);
     client = NULL;
@@ -166,41 +176,44 @@ int itdb_iphone_start_sync(Itdb_Device *device, void 
**prepdata)
     return 0;
 
 leave_with_err:
-    if (client && sync_started) {
-       nport = 0;
-       np = NULL;
-       lockdownd_start_service(client, "com.apple.mobile.notification_proxy", 
&nport);
-       if (nport) {
-           np_client_new(pdata_loc->device, nport, &np);
-           if (np) {
-               np_post_notification(np, NP_SYNC_DID_FINISH);
-           }
-       }
-       if (!nport || !np) {
-           fprintf(stderr, "notification_proxy could not be started!\n");
-           res = -1;
-       }
-       np_client_free(np);
-
-       lockdownd_client_free(client);
+    if (client && sync_starting) {
+       itdb_iphone_post_notification(pdata_loc->device, client, 
"com.apple.itunes-mobdev.syncFailedToStart");
+       printf("%s: posted syncFailedToStart\n", __func__);
     }
+
     if (pdata_loc) {
        if (pdata_loc->afc) {
+           if (pdata_loc->lockfile) {
+               afc_file_lock(pdata_loc->afc, pdata_loc->lockfile, AFC_LOCK_UN);
+               afc_file_close(pdata_loc->afc, pdata_loc->lockfile);
+               pdata_loc->lockfile = 0;
+           }
            afc_client_free(pdata_loc->afc);
+           pdata_loc->afc = NULL;
        }
        if (pdata_loc->device) {
            iphone_device_free(pdata_loc->device);
+           pdata_loc->device = NULL;
        }
        g_free(pdata_loc);
+       pdata_loc = NULL;
+    }
+
+    if (client) {
+       lockdownd_client_free(client);
+       client = NULL;
     }
 
+    *prepdata = NULL;
+
     return res;
 }
 
 int itdb_iphone_stop_sync(void *sync_ctx)
 {
-
+    lockdownd_client_t client = NULL;
     itdbprep_t prepdata = sync_ctx;
+
     printf("libitdbprep: %s called\n", __func__);
 
     if (!prepdata) {
@@ -210,33 +223,44 @@ int itdb_iphone_stop_sync(void *sync_ctx)
 
     if (!prepdata->afc) {
        printf("%s called but prepdata->afc is NULL!\n", __func__);
+    } else {
+       /* remove .status-com.apple.itdbprep.command.runPostProcess */
+       if (afc_remove_path(prepdata->afc, "/iTunes_Control/iTunes/iTunes 
Library.itlp/DBTemp/.status-com.apple.itdprep.command.runPostProcess") != 
IPHONE_E_SUCCESS) {
+           fprintf(stderr, "Could not delete 
'.status-com.apple.itdprep.command.runPostProcess'\n");
+       }
+       /* remove ddd.itdbm */
+       if (afc_remove_path(prepdata->afc, "/iTunes_Control/iTunes/iTunes 
Library.itlp/DBTemp/ddd.itdbm") != IPHONE_E_SUCCESS) {
+           fprintf(stderr, "Could not delete 'ddd.itdbm'\n");
+       }
+       if (prepdata->lockfile) {
+           afc_file_lock(prepdata->afc, prepdata->lockfile, AFC_LOCK_UN);
+           afc_file_close(prepdata->afc, prepdata->lockfile);
+           prepdata->lockfile = 0;
+       } else {
+           printf("%s called but lockfile is 0\n", __func__);
+       }
+       afc_client_free(prepdata->afc);
+       prepdata->afc = NULL;
     }
 
-    /* remove .status-com.apple.itdbprep.command.runPostProcess */
-    if (afc_remove_path(prepdata->afc, "/iTunes_Control/iTunes/iTunes 
Library.itlp/DBTemp/.status-com.apple.itdprep.command.runPostProcess") != 
IPHONE_E_SUCCESS) {
-       fprintf(stderr, "Could not delete 
'.status-com.apple.itdprep.command.runPostProcess'\n");
-    }
-    /* remove ddd.itdbm */
-    if (afc_remove_path(prepdata->afc, "/iTunes_Control/iTunes/iTunes 
Library.itlp/DBTemp/ddd.itdbm") != IPHONE_E_SUCCESS) {
-       fprintf(stderr, "Could not delete 'ddd.itdbm'\n");
+    if (LOCKDOWN_E_SUCCESS != lockdownd_client_new(prepdata->device, &client)) 
{
+       fprintf(stderr, "Error: Could not establish lockdownd connection!\n");
+       goto leave;
     }
 
-    if (prepdata->lockfile) {
-       afc_file_lock(prepdata->afc, prepdata->lockfile, AFC_LOCK_UN);
-       afc_file_close(prepdata->afc, prepdata->lockfile);
-       prepdata->lockfile = 0;
-    } else {
-       printf("%s called but lockfile is 0\n", __func__);
-    }
-    if (prepdata->afc) {
-       afc_client_free(prepdata->afc);
-       prepdata->afc = NULL;
+    if(itdb_iphone_post_notification(prepdata->device, client, 
NP_SYNC_DID_FINISH)) {
+       fprintf(stderr, "failed to post syncDidFinish\n");
     }
+    printf("%s: posted syncDidFinish\n", __func__);
 
+    lockdownd_client_free(client);
+
+leave:
     iphone_device_free(prepdata->device);
 
     g_free(prepdata);
 
     return 0;
+
 }
 #endif

------------------------------------------------------------------------------
Return on Information:
Google Enterprise Search pays you back
Get the facts.
http://p.sf.net/sfu/google-dev2dev
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to