ENGINE-135 added *Beaconed states to avoid sending handshake requests twice ENGINE-135
authorEdouard Tisserant <edouard@pep-project.org>
Thu, 05 Jan 2017 13:05:00 +0100
branchENGINE-135
changeset 1523bc4a9401af51
parent 1522 57c2dbcb70dd
child 1524 1994d9dcda63
ENGINE-135 added *Beaconed states to avoid sending handshake requests twice
src/pEpEngine.c
src/sync_actions.c
src/sync_impl.c
sync/devicegroup.fsm
sync/generated/sync_fsm.c
sync/generated/sync_fsm.h
     1.1 --- a/src/pEpEngine.c	Tue Dec 20 22:51:41 2016 +0100
     1.2 +++ b/src/pEpEngine.c	Thu Jan 05 13:05:00 2017 +0100
     1.3 @@ -42,6 +42,8 @@
     1.4      "update person set device_group = ?1 "
     1.5      "where id = '" PEP_OWN_USERID "';";
     1.6  
     1.7 +// TODO leave group
     1.8 +
     1.9  static const char *sql_get_device_group = 
    1.10      "select device_group from person "
    1.11      "where id = '" PEP_OWN_USERID "';";
     2.1 --- a/src/sync_actions.c	Tue Dec 20 22:51:41 2016 +0100
     2.2 +++ b/src/sync_actions.c	Thu Jan 05 13:05:00 2017 +0100
     2.3 @@ -12,9 +12,11 @@
     2.4  
     2.5  // conditions
     2.6  
     2.7 +// TODO : move that SQL statement with other prepared SQL statements in pEpEngine.c
     2.8  static const char *sql_stored_group_keys =
     2.9          "select count(device_group) from person where id = '" PEP_OWN_USERID "';"; 
    2.10  
    2.11 +// TODO  is that necessary ?
    2.12  static int _stored_group_keys(void *_gc, int count, char **text, char **name)
    2.13  {
    2.14      assert(_gc);
    2.15 @@ -100,6 +102,27 @@
    2.16      return result;
    2.17  }
    2.18  
    2.19 +int sameIdentities(PEP_SESSION session, Identity a, Identity b)
    2.20 +{
    2.21 +    assert(session);
    2.22 +    assert(a);
    2.23 +    assert(b);
    2.24 +
    2.25 +    if (!(session && a && b))
    2.26 +        return invalid_condition; // error
    2.27 +
    2.28 +    if ((a->fpr != NULL && b->fpr != NULL) ||
    2.29 +        (!_same_fpr(a->fpr, strlen(a->fpr), b->fpr, strlen(b->fpr))) ||
    2.30 +        (a->address != NULL && b->address != NULL) ||
    2.31 +        strcmp(a->address, b->address) != 0 ||
    2.32 +        (a->user_id != NULL && b->user_id != NULL) ||
    2.33 +        strcmp(a->user_id, b->user_id) != 0)
    2.34 +            return 0;
    2.35 +    return 1;
    2.36 +}
    2.37 +
    2.38 +// actions
    2.39 +
    2.40  PEP_STATUS _notifyHandshake(
    2.41          PEP_SESSION session,
    2.42          Identity partner,
     3.1 --- a/src/sync_impl.c	Tue Dec 20 22:51:41 2016 +0100
     3.2 +++ b/src/sync_impl.c	Thu Jan 05 13:05:00 2017 +0100
     3.3 @@ -355,13 +355,6 @@
     3.4                                  goto free_all;
     3.5                              }
     3.6                              
     3.7 -                            // Ignore and consume handshakes with devices
     3.8 -                            // already using trusted own key to encrypt
     3.9 -                            if (rating >= PEP_rating_trusted){
    3.10 -                                consume = true;
    3.11 -                                goto free_all;
    3.12 -                            }
    3.13 -
    3.14                              break;
    3.15                          // accepting GroupKeys needs encryption and trust of peer device
    3.16                          case DeviceGroup_Protocol__payload_PR_groupKeys:
    3.17 @@ -375,7 +368,7 @@
    3.18                                  goto free_all;
    3.19                              }
    3.20  
    3.21 -                            // check trust of identity using user_id given in payload
    3.22 +                            // check trust of identity using user_id given in msg.header.me
    3.23                              // to exacly match identity of device, the one trusted in
    3.24                              // case of accepted handshake
    3.25                              pEp_identity *_from = new_identity(NULL, 
     4.1 --- a/sync/devicegroup.fsm	Tue Dec 20 22:51:41 2016 +0100
     4.2 +++ b/sync/devicegroup.fsm	Thu Jan 05 13:05:00 2017 +0100
     4.3 @@ -20,6 +20,7 @@
     4.4      fsm DeviceState filename=sync {
     4.5          condition storedGroupKeys();
     4.6          condition keyElectionWon(Identity partner);
     4.7 +        condition sameIdentities(Identity a, Identity b);
     4.8  
     4.9          state InitState {
    4.10              on Init {
    4.11 @@ -30,22 +31,47 @@
    4.12          }
    4.13  
    4.14          state Sole end=1 {
    4.15 -            on KeyGen // injected by generate_keypair()
    4.16 +            on KeyGen
    4.17                  do sendBeacon;
    4.18              on CannotDecrypt
    4.19 -                do sendBeacon;  // cry, baby
    4.20 -            on Beacon(Identity partner) // this event will not happen for already
    4.21 -                                        // rejected partners
    4.22 +                do sendBeacon;
    4.23 +            on Beacon(Identity partner){
    4.24                  do sendHandshakeRequest(partner);
    4.25 +                go SoleBeaconed(partner);
    4.26 +            }
    4.27              on HandshakeRequest(Identity partner) {
    4.28                  do sendHandshakeRequest(partner);
    4.29                  go HandshakingSole(partner);
    4.30              }
    4.31          }
    4.32  
    4.33 +        state SoleBeaconed timeout=600 (Identity expected) {
    4.34 +            on KeyGen{
    4.35 +                do sendBeacon;
    4.36 +                go Sole;
    4.37 +            }
    4.38 +            on CannotDecrypt{
    4.39 +                do sendBeacon;
    4.40 +                go Sole;
    4.41 +            }
    4.42 +            on Beacon(Identity partner) {
    4.43 +                do sendHandshakeRequest(partner);
    4.44 +                go SoleBeaconed(partner);
    4.45 +            }
    4.46 +            on HandshakeRequest(Identity partner) {
    4.47 +                if sameIdentities(partner, expected) {
    4.48 +                    // do nothing, to avoid sending handshake request twice 
    4.49 +                } else {
    4.50 +                    do sendHandshakeRequest(partner);
    4.51 +                }
    4.52 +                go HandshakingSole(partner);
    4.53 +            }
    4.54 +            on Timeout go Sole;
    4.55 +        }
    4.56 +
    4.57          state HandshakingSole timeout=600 (Identity expected) {
    4.58              on Init{
    4.59 -                if keyElectionWon(partner) {    // an already existing group
    4.60 +                if keyElectionWon(partner) {
    4.61                      do notifyInitFormGroup(partner);
    4.62                  } else {
    4.63                      do notifyInitAddOurDevice(partner);
    4.64 @@ -53,13 +79,12 @@
    4.65              }
    4.66  
    4.67              on HandshakeRejected(Identity partner) {
    4.68 -                do rejectHandshake(partner);             // stores rejection of partner
    4.69 +                do rejectHandshake(partner);
    4.70                  go Sole;
    4.71              }
    4.72              on HandshakeAccepted(Identity partner) {
    4.73                  do acceptHandshake(partner); 
    4.74 -                if keyElectionWon(partner) {    // an already existing group
    4.75 -                                                // always wins
    4.76 +                if keyElectionWon(partner) {
    4.77                      do sendGroupKeys(partner);
    4.78                      do notifyAcceptedGroupCreated(partner);
    4.79                      go Grouped;
    4.80 @@ -75,10 +100,11 @@
    4.81      
    4.82          state WaitForGroupKeysSole timeout=600 (Identity expected) {
    4.83              on GroupKeys(Identity partner, Stringlist keys) {
    4.84 -                // TODO ensure partner == expected
    4.85 -                do storeGroupKeys(partner, keys);
    4.86 -                do notifyAcceptedDeviceAdded(partner);
    4.87 -                go Grouped;
    4.88 +                if sameIdentities(partner, expected) {
    4.89 +                    do storeGroupKeys(partner, keys);
    4.90 +                    do notifyAcceptedDeviceAdded(partner);
    4.91 +                    go Grouped;
    4.92 +                }
    4.93              }
    4.94              on Timeout {
    4.95                  do notifyTimeout(expected);
    4.96 @@ -92,11 +118,13 @@
    4.97              on KeyGen
    4.98                  do sendGroupUpdate;
    4.99              on CannotDecrypt
   4.100 -                do sendUpdateRequest; // TODO: narrow request to missing key
   4.101 +                do sendUpdateRequest;
   4.102              on UpdateRequest
   4.103                  do sendGroupUpdate;
   4.104 -            on Beacon(Identity partner)
   4.105 +            on Beacon(Identity partner){
   4.106                  do sendHandshakeRequest(partner);
   4.107 +                go GroupedBeaconed(partner);
   4.108 +            }
   4.109              on HandshakeRequest(Identity partner) {
   4.110                  do sendHandshakeRequest(partner);
   4.111                  go HandshakingGrouped(partner);
   4.112 @@ -105,6 +133,30 @@
   4.113                  do storeGroupKeys(partner, keys);
   4.114          }
   4.115  
   4.116 +        state GroupedBeaconed timeout=600 (Identity expected){
   4.117 +            on KeyGen
   4.118 +                do sendGroupUpdate;
   4.119 +            on CannotDecrypt
   4.120 +                do sendUpdateRequest;
   4.121 +            on UpdateRequest
   4.122 +                do sendGroupUpdate;
   4.123 +            on Beacon(Identity partner){
   4.124 +                do sendHandshakeRequest(partner);
   4.125 +                go GroupedBeaconed(partner);
   4.126 +            }
   4.127 +            on HandshakeRequest(Identity partner) {
   4.128 +                if sameIdentities(partner, expected) {
   4.129 +                    // do nothing, to avoid sending handshake request twice 
   4.130 +                } else {
   4.131 +                    do sendHandshakeRequest(partner);
   4.132 +                }
   4.133 +                go HandshakingGrouped(partner);
   4.134 +            }
   4.135 +            on GroupUpdate(Identity partner, Stringlist keys)
   4.136 +                do storeGroupKeys(partner, keys);
   4.137 +            on Timeout go Grouped;
   4.138 +        }
   4.139 +
   4.140          state HandshakingGrouped timeout=600 (Identity expected) {
   4.141              on Init
   4.142                  do notifyInitAddOurDevice(partner);
     5.1 --- a/sync/generated/sync_fsm.c	Tue Dec 20 22:51:41 2016 +0100
     5.2 +++ b/sync/generated/sync_fsm.c	Thu Jan 05 13:05:00 2017 +0100
     5.3 @@ -81,7 +81,9 @@
     5.4                          return (int) invalid_out_of_memory;
     5.5                      if (status != PEP_STATUS_OK)
     5.6                          return (int) invalid_action;
     5.7 -                    break;
     5.8 +                    session->sync_state_payload = identity_dup(partner);
     5.9 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Sole, event=Beacon", "target=SoleBeaconed")
    5.10 +                    return SoleBeaconed;
    5.11                  }
    5.12                  case HandshakeRequest:
    5.13                  {
    5.14 @@ -101,6 +103,106 @@
    5.15              }
    5.16              break;
    5.17          }
    5.18 +        case SoleBeaconed:
    5.19 +        {
    5.20 +            Identity expected = (Identity)session->sync_state_payload;
    5.21 +            *timeout = 600;
    5.22 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=SoleBeaconed")
    5.23 +            switch (event) {
    5.24 +                case Init: DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=Init") break;
    5.25 +                case KeyGen:
    5.26 +                {
    5.27 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=KeyGen")
    5.28 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=KeyGen", "action=sendBeacon")
    5.29 +                    status = sendBeacon(session, state, NULL, NULL);
    5.30 +                    if (status == PEP_OUT_OF_MEMORY)
    5.31 +                        return (int) invalid_out_of_memory;
    5.32 +                    if (status != PEP_STATUS_OK)
    5.33 +                        return (int) invalid_action;
    5.34 +                    if(session->sync_state_payload){
    5.35 +                        free_identity((Identity)session->sync_state_payload);
    5.36 +                        session->sync_state_payload = NULL;
    5.37 +                    }
    5.38 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=KeyGen", "target=Sole")
    5.39 +                    return Sole;
    5.40 +                }
    5.41 +                case CannotDecrypt:
    5.42 +                {
    5.43 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=CannotDecrypt")
    5.44 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=CannotDecrypt", "action=sendBeacon")
    5.45 +                    status = sendBeacon(session, state, NULL, NULL);
    5.46 +                    if (status == PEP_OUT_OF_MEMORY)
    5.47 +                        return (int) invalid_out_of_memory;
    5.48 +                    if (status != PEP_STATUS_OK)
    5.49 +                        return (int) invalid_action;
    5.50 +                    if(session->sync_state_payload){
    5.51 +                        free_identity((Identity)session->sync_state_payload);
    5.52 +                        session->sync_state_payload = NULL;
    5.53 +                    }
    5.54 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=CannotDecrypt", "target=Sole")
    5.55 +                    return Sole;
    5.56 +                }
    5.57 +                case Beacon:
    5.58 +                {
    5.59 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=Beacon")
    5.60 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=Beacon", "action=sendHandshakeRequest")
    5.61 +                    status = sendHandshakeRequest(session, state, partner, NULL);
    5.62 +                    if (status == PEP_OUT_OF_MEMORY)
    5.63 +                        return (int) invalid_out_of_memory;
    5.64 +                    if (status != PEP_STATUS_OK)
    5.65 +                        return (int) invalid_action;
    5.66 +                    if(session->sync_state_payload){
    5.67 +                        free_identity((Identity)session->sync_state_payload);
    5.68 +                        session->sync_state_payload = NULL;
    5.69 +                    }
    5.70 +                    session->sync_state_payload = identity_dup(partner);
    5.71 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=Beacon", "target=SoleBeaconed")
    5.72 +                    return SoleBeaconed;
    5.73 +                }
    5.74 +                case HandshakeRequest:
    5.75 +                {
    5.76 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=HandshakeRequest")
    5.77 +                    cond_result = sameIdentities(session, partner, expected);
    5.78 +                    #ifndef NDEBUG
    5.79 +                    char resstr[11] = {0,};
    5.80 +                    snprintf(resstr,10,"result=%d",cond_result);
    5.81 +                    #endif
    5.82 +                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=SoleBeaconed, event=HandshakeRequest, condition=sameIdentities", resstr)
    5.83 +                    if (cond_result < 0)
    5.84 +                        return cond_result;
    5.85 +                    if (cond_result) {
    5.86 +                    }
    5.87 +                    else {
    5.88 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=SoleBeaconed, event=HandshakeRequest", "action=sendHandshakeRequest")
    5.89 +                        status = sendHandshakeRequest(session, state, partner, NULL);
    5.90 +                        if (status == PEP_OUT_OF_MEMORY)
    5.91 +                            return (int) invalid_out_of_memory;
    5.92 +                        if (status != PEP_STATUS_OK)
    5.93 +                            return (int) invalid_action;
    5.94 +                    }
    5.95 +                    if(session->sync_state_payload){
    5.96 +                        free_identity((Identity)session->sync_state_payload);
    5.97 +                        session->sync_state_payload = NULL;
    5.98 +                    }
    5.99 +                    session->sync_state_payload = identity_dup(partner);
   5.100 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=HandshakeRequest", "target=HandshakingSole")
   5.101 +                    return HandshakingSole;
   5.102 +                }
   5.103 +                case Timeout:
   5.104 +                {
   5.105 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=SoleBeaconed", "event=Timeout")
   5.106 +                    if(session->sync_state_payload){
   5.107 +                        free_identity((Identity)session->sync_state_payload);
   5.108 +                        session->sync_state_payload = NULL;
   5.109 +                    }
   5.110 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=SoleBeaconed, event=Timeout", "target=Sole")
   5.111 +                    return Sole;
   5.112 +                }
   5.113 +                default:
   5.114 +                    return (DeviceState_state) invalid_event;
   5.115 +            }
   5.116 +            break;
   5.117 +        }
   5.118          case HandshakingSole:
   5.119          {
   5.120              Identity expected = (Identity)session->sync_state_payload;
   5.121 @@ -238,24 +340,35 @@
   5.122                  case GroupKeys:
   5.123                  {
   5.124                      DEBUG_LOG("FSM event", "sync_fsm.c, state=WaitForGroupKeysSole", "event=GroupKeys")
   5.125 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=storeGroupKeys")
   5.126 -                    status = storeGroupKeys(session, state, partner, extra /*keys*/);
   5.127 -                    if (status == PEP_OUT_OF_MEMORY)
   5.128 -                        return (int) invalid_out_of_memory;
   5.129 -                    if (status != PEP_STATUS_OK)
   5.130 -                        return (int) invalid_action;
   5.131 -                    DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=notifyAcceptedDeviceAdded")
   5.132 -                    status = notifyAcceptedDeviceAdded(session, state, partner, NULL);
   5.133 -                    if (status == PEP_OUT_OF_MEMORY)
   5.134 -                        return (int) invalid_out_of_memory;
   5.135 -                    if (status != PEP_STATUS_OK)
   5.136 -                        return (int) invalid_action;
   5.137 -                    if(session->sync_state_payload){
   5.138 -                        free_identity((Identity)session->sync_state_payload);
   5.139 -                        session->sync_state_payload = NULL;
   5.140 +                    cond_result = sameIdentities(session, partner, expected);
   5.141 +                    #ifndef NDEBUG
   5.142 +                    char resstr[11] = {0,};
   5.143 +                    snprintf(resstr,10,"result=%d",cond_result);
   5.144 +                    #endif
   5.145 +                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys, condition=sameIdentities", resstr)
   5.146 +                    if (cond_result < 0)
   5.147 +                        return cond_result;
   5.148 +                    if (cond_result) {
   5.149 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=storeGroupKeys")
   5.150 +                        status = storeGroupKeys(session, state, partner, extra /*keys*/);
   5.151 +                        if (status == PEP_OUT_OF_MEMORY)
   5.152 +                            return (int) invalid_out_of_memory;
   5.153 +                        if (status != PEP_STATUS_OK)
   5.154 +                            return (int) invalid_action;
   5.155 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "action=notifyAcceptedDeviceAdded")
   5.156 +                        status = notifyAcceptedDeviceAdded(session, state, partner, NULL);
   5.157 +                        if (status == PEP_OUT_OF_MEMORY)
   5.158 +                            return (int) invalid_out_of_memory;
   5.159 +                        if (status != PEP_STATUS_OK)
   5.160 +                            return (int) invalid_action;
   5.161 +                        if(session->sync_state_payload){
   5.162 +                            free_identity((Identity)session->sync_state_payload);
   5.163 +                            session->sync_state_payload = NULL;
   5.164 +                        }
   5.165 +                        DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "target=Grouped")
   5.166 +                        return Grouped;
   5.167                      }
   5.168 -                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=WaitForGroupKeysSole, event=GroupKeys", "target=Grouped")
   5.169 -                    return Grouped;
   5.170 +                    break;
   5.171                  }
   5.172                  case Timeout:
   5.173                  {
   5.174 @@ -336,7 +449,9 @@
   5.175                          return (int) invalid_out_of_memory;
   5.176                      if (status != PEP_STATUS_OK)
   5.177                          return (int) invalid_action;
   5.178 -                    break;
   5.179 +                    session->sync_state_payload = identity_dup(partner);
   5.180 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=Grouped, event=Beacon", "target=GroupedBeaconed")
   5.181 +                    return GroupedBeaconed;
   5.182                  }
   5.183                  case HandshakeRequest:
   5.184                  {
   5.185 @@ -367,6 +482,118 @@
   5.186              }
   5.187              break;
   5.188          }
   5.189 +        case GroupedBeaconed:
   5.190 +        {
   5.191 +            Identity expected = (Identity)session->sync_state_payload;
   5.192 +            *timeout = 600;
   5.193 +            DEBUG_LOG("Entering FSM state", "sync_fsm.c", "state=GroupedBeaconed")
   5.194 +            switch (event) {
   5.195 +                case Init: DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=Init") break;
   5.196 +                case KeyGen:
   5.197 +                {
   5.198 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=KeyGen")
   5.199 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=KeyGen", "action=sendGroupUpdate")
   5.200 +                    status = sendGroupUpdate(session, state, NULL, NULL);
   5.201 +                    if (status == PEP_OUT_OF_MEMORY)
   5.202 +                        return (int) invalid_out_of_memory;
   5.203 +                    if (status != PEP_STATUS_OK)
   5.204 +                        return (int) invalid_action;
   5.205 +                    break;
   5.206 +                }
   5.207 +                case CannotDecrypt:
   5.208 +                {
   5.209 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=CannotDecrypt")
   5.210 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=CannotDecrypt", "action=sendUpdateRequest")
   5.211 +                    status = sendUpdateRequest(session, state, NULL, NULL);
   5.212 +                    if (status == PEP_OUT_OF_MEMORY)
   5.213 +                        return (int) invalid_out_of_memory;
   5.214 +                    if (status != PEP_STATUS_OK)
   5.215 +                        return (int) invalid_action;
   5.216 +                    break;
   5.217 +                }
   5.218 +                case UpdateRequest:
   5.219 +                {
   5.220 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=UpdateRequest")
   5.221 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=UpdateRequest", "action=sendGroupUpdate")
   5.222 +                    status = sendGroupUpdate(session, state, NULL, NULL);
   5.223 +                    if (status == PEP_OUT_OF_MEMORY)
   5.224 +                        return (int) invalid_out_of_memory;
   5.225 +                    if (status != PEP_STATUS_OK)
   5.226 +                        return (int) invalid_action;
   5.227 +                    break;
   5.228 +                }
   5.229 +                case Beacon:
   5.230 +                {
   5.231 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=Beacon")
   5.232 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=Beacon", "action=sendHandshakeRequest")
   5.233 +                    status = sendHandshakeRequest(session, state, partner, NULL);
   5.234 +                    if (status == PEP_OUT_OF_MEMORY)
   5.235 +                        return (int) invalid_out_of_memory;
   5.236 +                    if (status != PEP_STATUS_OK)
   5.237 +                        return (int) invalid_action;
   5.238 +                    if(session->sync_state_payload){
   5.239 +                        free_identity((Identity)session->sync_state_payload);
   5.240 +                        session->sync_state_payload = NULL;
   5.241 +                    }
   5.242 +                    session->sync_state_payload = identity_dup(partner);
   5.243 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupedBeaconed, event=Beacon", "target=GroupedBeaconed")
   5.244 +                    return GroupedBeaconed;
   5.245 +                }
   5.246 +                case HandshakeRequest:
   5.247 +                {
   5.248 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=HandshakeRequest")
   5.249 +                    cond_result = sameIdentities(session, partner, expected);
   5.250 +                    #ifndef NDEBUG
   5.251 +                    char resstr[11] = {0,};
   5.252 +                    snprintf(resstr,10,"result=%d",cond_result);
   5.253 +                    #endif
   5.254 +                    DEBUG_LOG("FSM condition", "sync_fsm.c, state=GroupedBeaconed, event=HandshakeRequest, condition=sameIdentities", resstr)
   5.255 +                    if (cond_result < 0)
   5.256 +                        return cond_result;
   5.257 +                    if (cond_result) {
   5.258 +                    }
   5.259 +                    else {
   5.260 +                        DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=HandshakeRequest", "action=sendHandshakeRequest")
   5.261 +                        status = sendHandshakeRequest(session, state, partner, NULL);
   5.262 +                        if (status == PEP_OUT_OF_MEMORY)
   5.263 +                            return (int) invalid_out_of_memory;
   5.264 +                        if (status != PEP_STATUS_OK)
   5.265 +                            return (int) invalid_action;
   5.266 +                    }
   5.267 +                    if(session->sync_state_payload){
   5.268 +                        free_identity((Identity)session->sync_state_payload);
   5.269 +                        session->sync_state_payload = NULL;
   5.270 +                    }
   5.271 +                    session->sync_state_payload = identity_dup(partner);
   5.272 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupedBeaconed, event=HandshakeRequest", "target=HandshakingGrouped")
   5.273 +                    return HandshakingGrouped;
   5.274 +                }
   5.275 +                case GroupUpdate:
   5.276 +                {
   5.277 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=GroupUpdate")
   5.278 +                    DEBUG_LOG("FSM action", "sync_fsm.c, state=GroupedBeaconed, event=GroupUpdate", "action=storeGroupKeys")
   5.279 +                    status = storeGroupKeys(session, state, partner, extra /*keys*/);
   5.280 +                    if (status == PEP_OUT_OF_MEMORY)
   5.281 +                        return (int) invalid_out_of_memory;
   5.282 +                    if (status != PEP_STATUS_OK)
   5.283 +                        return (int) invalid_action;
   5.284 +                    break;
   5.285 +                }
   5.286 +                case Timeout:
   5.287 +                {
   5.288 +                    DEBUG_LOG("FSM event", "sync_fsm.c, state=GroupedBeaconed", "event=Timeout")
   5.289 +                    if(session->sync_state_payload){
   5.290 +                        free_identity((Identity)session->sync_state_payload);
   5.291 +                        session->sync_state_payload = NULL;
   5.292 +                    }
   5.293 +                    DEBUG_LOG("FSM transition", "sync_fsm.c, state=GroupedBeaconed, event=Timeout", "target=Grouped")
   5.294 +                    return Grouped;
   5.295 +                }
   5.296 +                default:
   5.297 +                    return (DeviceState_state) invalid_event;
   5.298 +            }
   5.299 +            break;
   5.300 +        }
   5.301          case HandshakingGrouped:
   5.302          {
   5.303              Identity expected = (Identity)session->sync_state_payload;
     6.1 --- a/sync/generated/sync_fsm.h	Tue Dec 20 22:51:41 2016 +0100
     6.2 +++ b/sync/generated/sync_fsm.h	Thu Jan 05 13:05:00 2017 +0100
     6.3 @@ -32,6 +32,7 @@
     6.4  
     6.5  int storedGroupKeys(PEP_SESSION session);
     6.6  int keyElectionWon(PEP_SESSION session, Identity partner);
     6.7 +int sameIdentities(PEP_SESSION session, Identity a, Identity b);
     6.8  
     6.9  // states
    6.10  
    6.11 @@ -46,9 +47,11 @@
    6.12      DeviceState_state_NONE = 0,
    6.13      InitState, 
    6.14      Sole, 
    6.15 +    SoleBeaconed, 
    6.16      HandshakingSole, 
    6.17      WaitForGroupKeysSole, 
    6.18      Grouped, 
    6.19 +    GroupedBeaconed, 
    6.20      HandshakingGrouped
    6.21  } DeviceState_state;
    6.22  
    6.23 @@ -62,10 +65,10 @@
    6.24      GroupKeys = 4,
    6.25      KeyGen, 
    6.26      CannotDecrypt, 
    6.27 +    Timeout, 
    6.28      HandshakeRejected, 
    6.29      HandshakeAccepted, 
    6.30      Cancel, 
    6.31 -    Timeout, 
    6.32      UpdateRequest, 
    6.33      GroupUpdate
    6.34  } DeviceState_event;