Sync is back: Backed out changeset 6ff593da2c91
authorDirk Zimmermann <dirk@pep-project.org>
Fri, 03 Nov 2017 17:37:54 +0100
changeset 331c9377de4a7ba
parent 322 6ff593da2c91
child 332 b78c428a9f1e
child 358 62c4a8f277bf
Sync is back: Backed out changeset 6ff593da2c91
pEpObjCAdapter/PEPInternalSession.m
pEpObjCAdapter/PEPObjCAdapter+Internal.h
pEpObjCAdapter/PEPObjCAdapter.h
pEpObjCAdapter/PEPObjCAdapter.m
pEpObjCTests/iOSTests.m
     1.1 --- a/pEpObjCAdapter/PEPInternalSession.m	Fri Nov 03 08:53:57 2017 +0100
     1.2 +++ b/pEpObjCAdapter/PEPInternalSession.m	Fri Nov 03 17:37:54 2017 +0100
     1.3 @@ -38,12 +38,16 @@
     1.4          if (status != PEP_STATUS_OK) {
     1.5              return nil;
     1.6          }
     1.7 +
     1.8 +        [PEPObjCAdapter bindSession:self];
     1.9      }
    1.10      return self;
    1.11  }
    1.12  
    1.13  - (void)dealloc
    1.14  {
    1.15 +    [PEPObjCAdapter unbindSession:self];
    1.16 +
    1.17      [[PEPObjCAdapter initLock] lock];
    1.18      release(_session);
    1.19      [[PEPObjCAdapter initLock] unlock];
     2.1 --- a/pEpObjCAdapter/PEPObjCAdapter+Internal.h	Fri Nov 03 08:53:57 2017 +0100
     2.2 +++ b/pEpObjCAdapter/PEPObjCAdapter+Internal.h	Fri Nov 03 17:37:54 2017 +0100
     2.3 @@ -9,6 +9,8 @@
     2.4  #ifndef PEPIOSAdapter_Internal_h
     2.5  #define PEPIOSAdapter_Internal_h
     2.6  
     2.7 +#import "sync.h"
     2.8 +
     2.9  #import "PEPQueue.h"
    2.10  #import "PEPInternalSession.h"
    2.11  
    2.12 @@ -24,6 +26,11 @@
    2.13  + (void)registerExamineFunction:(PEP_SESSION)session;
    2.14  + (PEPQueue*)getLookupQueue;
    2.15  
    2.16 ++ (PEPQueue*)getSyncQueue;
    2.17 ++ (id <PEPSyncDelegate>)getSyncDelegate;
    2.18 ++ (void)bindSession:(PEPInternalSession*)session;
    2.19 ++ (void)unbindSession:(PEPInternalSession*)session;
    2.20 +
    2.21  @end
    2.22  
    2.23  #endif /* PEPIOSAdapter_Internal_h */
     3.1 --- a/pEpObjCAdapter/PEPObjCAdapter.h	Fri Nov 03 08:53:57 2017 +0100
     3.2 +++ b/pEpObjCAdapter/PEPObjCAdapter.h	Fri Nov 03 17:37:54 2017 +0100
     3.3 @@ -9,9 +9,20 @@
     3.4  #import <Foundation/Foundation.h>
     3.5  
     3.6  #import "PEPSession.h"
     3.7 +#include "sync_app.h"
     3.8  
     3.9  @class PEPLanguage;
    3.10  
    3.11 +@protocol PEPKeyManagementDelegate <NSObject>
    3.12 +- (void)identityUpdated:(_Nonnull id)identity;
    3.13 +@end
    3.14 +
    3.15 +@protocol PEPSyncDelegate <NSObject>
    3.16 +- (PEP_STATUS)notifyHandshakeWithSignal:(sync_handshake_signal)signal me:(_Nonnull id)me partner:(_Nonnull id)partner;
    3.17 +- (PEP_STATUS)sendMessage:(_Nonnull id)msg;
    3.18 +- (PEP_STATUS)fastPolling:(bool)isfast;
    3.19 +@end
    3.20 +
    3.21  @interface PEPObjCAdapter : NSObject
    3.22  
    3.23  /**
    3.24 @@ -33,4 +44,15 @@
    3.25  + (void)setupTrustWordsDB;
    3.26  + (void)setupTrustWordsDB:(NSBundle * _Nonnull)rootBundle;
    3.27  
    3.28 +/**
    3.29 + Start Sync.
    3.30 + - Note: There is only one Sync session and thread
    3.31 + */
    3.32 ++ (void)startSync:(_Nonnull id <PEPSyncDelegate>)delegate;
    3.33 +
    3.34 +/**
    3.35 + Stop Sync.
    3.36 + */
    3.37 ++ (void)stopSync;
    3.38 +
    3.39  @end
     4.1 --- a/pEpObjCAdapter/PEPObjCAdapter.m	Fri Nov 03 08:53:57 2017 +0100
     4.2 +++ b/pEpObjCAdapter/PEPObjCAdapter.m	Fri Nov 03 17:37:54 2017 +0100
     4.3 @@ -44,6 +44,61 @@
     4.4  }
     4.5  
     4.6  ///////////////////////////////////////////////////////////////////////////////
     4.7 +// Sync - C part
     4.8 +
     4.9 +// Called by sync thread only
    4.10 +PEP_STATUS notify_handshake(void *unused_object, pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal)
    4.11 +{
    4.12 +    id <PEPSyncDelegate> syncDelegate = [PEPObjCAdapter getSyncDelegate];
    4.13 +    if ( syncDelegate )
    4.14 +        return [syncDelegate
    4.15 +                notifyHandshakeWithSignal:signal
    4.16 +                me:PEP_identityDictFromStruct(me)
    4.17 +                partner:PEP_identityDictFromStruct(partner)];
    4.18 +    else
    4.19 +        return PEP_SYNC_NO_NOTIFY_CALLBACK;
    4.20 +}
    4.21 +
    4.22 +// Called by sync thread only
    4.23 +PEP_STATUS message_to_send(void *unused_object, message *msg)
    4.24 +{
    4.25 +    id <PEPSyncDelegate> syncDelegate = [PEPObjCAdapter getSyncDelegate];
    4.26 +    if ( syncDelegate )
    4.27 +        return [syncDelegate sendMessage:PEP_messageDictFromStruct(msg)];
    4.28 +    else
    4.29 +        return PEP_SEND_FUNCTION_NOT_REGISTERED;
    4.30 +}
    4.31 +
    4.32 +// called indirectly by decrypt message - any thread/session
    4.33 +int inject_sync_msg(void *msg, void *unused_management)
    4.34 +{
    4.35 +    PEPQueue *q = [PEPObjCAdapter getSyncQueue];
    4.36 +    [q enqueue:[NSValue valueWithPointer:msg]];
    4.37 +    
    4.38 +    return 0;
    4.39 +}
    4.40 +
    4.41 +// Called by sync thread only
    4.42 +void *retrieve_next_sync_msg(void *unused_mamagement, time_t *timeout)
    4.43 +{
    4.44 +    bool needs_fastpoll = (*timeout != 0);
    4.45 +    
    4.46 +    id <PEPSyncDelegate> syncDelegate = [PEPObjCAdapter getSyncDelegate];
    4.47 +    if ( syncDelegate && needs_fastpoll )
    4.48 +        [syncDelegate fastPolling:true];
    4.49 +    
    4.50 +    PEPQueue *q = [PEPObjCAdapter getSyncQueue];
    4.51 +    
    4.52 +    void* result = (void*)[[q timedDequeue:timeout] pointerValue];
    4.53 +    
    4.54 +    if ( syncDelegate && needs_fastpoll )
    4.55 +        [syncDelegate fastPolling:false];
    4.56 +    
    4.57 +    return result;
    4.58 +    
    4.59 +}
    4.60 +
    4.61 +///////////////////////////////////////////////////////////////////////////////
    4.62  // DB and paths
    4.63  
    4.64  const char* _Nullable SystemDB = NULL;
    4.65 @@ -241,4 +296,151 @@
    4.66      return lookupQueue;
    4.67  }
    4.68  
    4.69 +///////////////////////////////////////////////////////////////////////////////
    4.70 +// Sync - ObjC part
    4.71 +
    4.72 +static PEPQueue *syncQueue = nil;
    4.73 +static NSThread *syncThread = nil;
    4.74 +static NSConditionLock *syncThreadJoinCond = nil;
    4.75 +static PEP_SESSION sync_session = NULL;
    4.76 +static id <PEPSyncDelegate> syncDelegate = nil;
    4.77 +
    4.78 +
    4.79 ++ (void)syncThreadRoutine:(id)object
    4.80 +{
    4.81 +    [syncThreadJoinCond lock];
    4.82 +    
    4.83 +    
    4.84 +    PEP_STATUS status;
    4.85 +    
    4.86 +    status = do_sync_protocol(sync_session,
    4.87 +                              /* "object" : notifying, sending (unused) */
    4.88 +                              "NOTNULL");
    4.89 +    
    4.90 +    // TODO : log something if status not as expected
    4.91 +
    4.92 +    [syncThreadJoinCond unlockWithCondition:YES];
    4.93 +}
    4.94 +
    4.95 ++ (void)attachSyncSession:(PEP_SESSION)session
    4.96 +{
    4.97 +    if(sync_session)
    4.98 +        attach_sync_session(session, sync_session);
    4.99 +}
   4.100 +
   4.101 ++ (void)detachSyncSession:(PEP_SESSION)session
   4.102 +{
   4.103 +    detach_sync_session(session);
   4.104 +}
   4.105 +
   4.106 ++ (void)startSync:(id <PEPSyncDelegate>)delegate;
   4.107 +{
   4.108 +    syncDelegate = delegate;
   4.109 +    
   4.110 +    if (!syncQueue)
   4.111 +    {
   4.112 +        syncQueue = [[PEPQueue alloc]init];
   4.113 +        
   4.114 +        syncThreadJoinCond = [[NSConditionLock alloc] initWithCondition:NO];
   4.115 +        
   4.116 +        [[PEPObjCAdapter initLock] lock];
   4.117 +        PEP_STATUS status = init(&sync_session);
   4.118 +        [[PEPObjCAdapter initLock] unlock];
   4.119 +        if (status != PEP_STATUS_OK) {
   4.120 +            return;
   4.121 +        }
   4.122 +        
   4.123 +        register_sync_callbacks(sync_session,
   4.124 +                                /* "management" : queuing (unused) */
   4.125 +                                "NOTNULL",
   4.126 +                                message_to_send,
   4.127 +                                notify_handshake,
   4.128 +                                inject_sync_msg,
   4.129 +                                retrieve_next_sync_msg);
   4.130 +        
   4.131 +        syncThread = [[NSThread alloc]
   4.132 +                      initWithTarget:self
   4.133 +                      selector:@selector(syncThreadRoutine:)
   4.134 +                      object:nil];
   4.135 +        
   4.136 +        [syncThread start];
   4.137 +    }
   4.138 +    
   4.139 +    NSMutableArray* sessionList = [PEPObjCAdapter boundSessions];
   4.140 +    NSValue* v;
   4.141 +    PEPInternalSession* session;
   4.142 +    @synchronized (sessionList) {
   4.143 +        for (v in sessionList) {
   4.144 +            session = [v nonretainedObjectValue];
   4.145 +            [PEPObjCAdapter attachSyncSession:[session session]];
   4.146 +        }
   4.147 +    }
   4.148 +}
   4.149 +
   4.150 ++ (void)stopSync
   4.151 +{
   4.152 +    NSMutableArray* sessionList = [PEPObjCAdapter boundSessions];
   4.153 +    NSValue* v;
   4.154 +    PEPInternalSession* session;
   4.155 +    @synchronized (sessionList) {
   4.156 +        for (v in sessionList) {
   4.157 +            session = [v nonretainedObjectValue];
   4.158 +            [PEPObjCAdapter detachSyncSession:[session session]];
   4.159 +        }
   4.160 +    }
   4.161 +    
   4.162 +    syncDelegate = nil;
   4.163 +    
   4.164 +    if (syncQueue)
   4.165 +    {
   4.166 +        [syncQueue purge:^(id item){
   4.167 +            sync_msg_t *msg = [item pointerValue];
   4.168 +            free_sync_msg(msg);
   4.169 +        }];
   4.170 +        
   4.171 +        [syncThreadJoinCond lockWhenCondition:YES];
   4.172 +        [syncThreadJoinCond unlock];
   4.173 +        
   4.174 +        [[PEPObjCAdapter initLock] lock];
   4.175 +        release(sync_session);
   4.176 +        [[PEPObjCAdapter initLock] unlock];
   4.177 +        
   4.178 +        sync_session = NULL;
   4.179 +        syncThread = nil;
   4.180 +        syncQueue = nil;
   4.181 +        syncThreadJoinCond = nil;
   4.182 +    }
   4.183 +}
   4.184 +
   4.185 ++ (PEPQueue*)getSyncQueue
   4.186 +{
   4.187 +    return syncQueue;
   4.188 +}
   4.189 +
   4.190 ++ (id <PEPSyncDelegate>)getSyncDelegate
   4.191 +{
   4.192 +    return syncDelegate;
   4.193 +}
   4.194 +
   4.195 ++ (void)bindSession:(PEPInternalSession*)session
   4.196 +{
   4.197 +    NSMutableArray* sessionList = [PEPObjCAdapter boundSessions];
   4.198 +    @synchronized (sessionList) {
   4.199 +        [sessionList addObject:[NSValue valueWithNonretainedObject:session]];
   4.200 +    }
   4.201 +    
   4.202 +    [PEPObjCAdapter registerExamineFunction:[session session]];
   4.203 +    [PEPObjCAdapter attachSyncSession:[session session]];
   4.204 +}
   4.205 +
   4.206 ++ (void)unbindSession:(PEPInternalSession*)session
   4.207 +{
   4.208 +    [PEPObjCAdapter detachSyncSession:[session session]];
   4.209 +    
   4.210 +    NSMutableArray* sessionList = [PEPObjCAdapter boundSessions];
   4.211 +    @synchronized (sessionList) {
   4.212 +        [sessionList removeObject:[NSValue valueWithNonretainedObject:session]];
   4.213 +    }
   4.214 +}
   4.215 +
   4.216  @end
     5.1 --- a/pEpObjCTests/iOSTests.m	Fri Nov 03 08:53:57 2017 +0100
     5.2 +++ b/pEpObjCTests/iOSTests.m	Fri Nov 03 17:37:54 2017 +0100
     5.3 @@ -34,6 +34,62 @@
     5.4      return [NSDictionary dictionaryWithDictionary:dict];
     5.5  }
     5.6  
     5.7 +// MARK: - PEPSyncDelegate
     5.8 +
     5.9 +@interface SomeSyncDelegate : NSObject<PEPSyncDelegate>
    5.10 +
    5.11 +- (BOOL)waitUntilSent:(time_t)maxSec;
    5.12 +
    5.13 +@property (nonatomic) bool sendWasCalled;
    5.14 +@property (nonatomic, strong) NSCondition *cond;
    5.15 +
    5.16 +@end
    5.17 +
    5.18 +@implementation SomeSyncDelegate
    5.19 +
    5.20 +- (id)init
    5.21 +{
    5.22 +    if (self = [super init])  {
    5.23 +        self.sendWasCalled = false;
    5.24 +        self.cond = [[NSCondition alloc] init];
    5.25 +    }
    5.26 +    return self;
    5.27 +}
    5.28 +
    5.29 +- (PEP_STATUS)notifyHandshakeWithSignal:(sync_handshake_signal)signal me:(id)me
    5.30 +                                partner:(id)partner
    5.31 +{
    5.32 +    return PEP_STATUS_OK;
    5.33 +}
    5.34 +
    5.35 +- (PEP_STATUS)sendMessage:(id)msg
    5.36 +{
    5.37 +    [_cond lock];
    5.38 +
    5.39 +    _sendWasCalled = true;
    5.40 +    [_cond signal];
    5.41 +    [_cond unlock];
    5.42 +
    5.43 +    return PEP_STATUS_OK;
    5.44 +}
    5.45 +
    5.46 +- (PEP_STATUS)fastPolling:(bool)isfast
    5.47 +{
    5.48 +    return PEP_STATUS_OK;
    5.49 +}
    5.50 +
    5.51 +- (BOOL)waitUntilSent:(time_t)maxSec
    5.52 +{
    5.53 +    bool res;
    5.54 +    [_cond lock];
    5.55 +    [_cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow: 2]];
    5.56 +    res = _sendWasCalled;
    5.57 +    [_cond unlock];
    5.58 +    return res;
    5.59 +}
    5.60 +
    5.61 +@end
    5.62 +
    5.63  // MARK: - iOSTests
    5.64  
    5.65  @interface iOSTests : XCTestCase
    5.66 @@ -229,6 +285,32 @@
    5.67      [self pEpCleanUp];
    5.68  }
    5.69  
    5.70 +- (void)testSyncSession
    5.71 +{
    5.72 +    SomeSyncDelegate *syncDelegate = [[SomeSyncDelegate alloc] init];
    5.73 +    [self pEpSetUp];
    5.74 +    
    5.75 +    // This should attach session just created
    5.76 +    [PEPObjCAdapter startSync:syncDelegate];
    5.77 +
    5.78 +    NSMutableDictionary *identMe = [NSMutableDictionary dictionaryWithObjectsAndKeys:
    5.79 +                                    @"pEp Test iOS GenKey", kPepUsername,
    5.80 +                                    @"pep.test.iosgenkey@pep-project.org", kPepAddress,
    5.81 +                                    @"Me", kPepAddress,
    5.82 +                                    nil];
    5.83 +    
    5.84 +    [session mySelf:identMe];
    5.85 +    
    5.86 +    bool res = [syncDelegate waitUntilSent:2];
    5.87 +    
    5.88 +    XCTAssert(res);
    5.89 +    
    5.90 +    // This should detach session just created
    5.91 +    [PEPObjCAdapter stopSync];
    5.92 +    
    5.93 +    [self pEpCleanUp];
    5.94 +}
    5.95 +
    5.96  - (void)testTrustWords
    5.97  {
    5.98      [self pEpSetUp];