big
[oweals/gnunet.git] / src / social / social_api.c
index 1db8e501ac0b51e4d94b3b73e0fc4e09b70d5818..89843831be02164972b6c04c6877066d88156391 100644 (file)
@@ -183,6 +183,7 @@ struct GNUNET_SOCIAL_Place
    */
   struct GNUNET_PSYC_Slicer *slicer;
 
+  // FIXME: do we need is_disconnecing like on the psyc and multicast APIs?
   /**
    * Function called after disconnected from the service.
    */
@@ -371,6 +372,68 @@ struct ZoneAddNymHandle
 };
 
 
+/*** CLEANUP / DISCONNECT ***/
+
+
+static void
+host_cleanup (struct GNUNET_SOCIAL_Host *hst)
+{
+  if (NULL != hst->slicer)
+  {
+    GNUNET_PSYC_slicer_destroy (hst->slicer);
+    hst->slicer = NULL;
+  }
+  GNUNET_free (hst);
+}
+
+
+static void
+guest_cleanup (struct GNUNET_SOCIAL_Guest *gst)
+{
+  GNUNET_free (gst);
+}
+
+
+static void
+place_cleanup (struct GNUNET_SOCIAL_Place *plc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "cleaning up place %p\n",
+              plc);
+  if (NULL != plc->tmit)
+  {
+    GNUNET_PSYC_transmit_destroy (plc->tmit);
+    plc->tmit = NULL;
+  }
+  if (NULL != plc->connect_env)
+  {
+    GNUNET_MQ_discard (plc->connect_env);
+    plc->connect_env = NULL;
+  }
+  if (NULL != plc->mq)
+  {
+    GNUNET_MQ_destroy (plc->mq);
+    plc->mq = NULL;
+  }
+  if (NULL != plc->disconnect_cb)
+  {
+    plc->disconnect_cb (plc->disconnect_cls);
+    plc->disconnect_cb = NULL;
+  }
+
+  (GNUNET_YES == plc->is_host)
+    ? host_cleanup ((struct GNUNET_SOCIAL_Host *) plc)
+    : guest_cleanup ((struct GNUNET_SOCIAL_Guest *) plc);
+}
+
+
+static void
+place_disconnect (struct GNUNET_SOCIAL_Place *plc)
+{
+  place_cleanup (plc);
+}
+
+
 /*** NYM ***/
 
 static struct GNUNET_SOCIAL_Nym *
@@ -428,7 +491,7 @@ host_recv_notice_place_leave_method (void *cls,
 
   struct GNUNET_SOCIAL_Nym *nym = nym_get_or_create (&msg->slave_pub_key);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Host received method for message ID %" PRIu64 " from nym %s: %s\n",
               message_id, GNUNET_h2s (&nym->pub_key_hash), method_name);
 
@@ -436,7 +499,7 @@ host_recv_notice_place_leave_method (void *cls,
   hst->notice_place_leave_env = GNUNET_PSYC_env_create ();
 
   char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key);
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "_notice_place_leave: got method from nym %s (%s).\n",
               GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str);
   GNUNET_free (str);
@@ -458,7 +521,7 @@ host_recv_notice_place_leave_modifier (void *cls,
   if (NULL == hst->notice_place_leave_env)
     return;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Host received modifier for _notice_place_leave message with ID %" PRIu64 ":\n"
               "%c%s: %.*s\n",
               message_id, oper, name, value_size, (const char *) value);
@@ -485,7 +548,7 @@ host_recv_notice_place_leave_eom (void *cls,
     return;
 
   char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&hst->notice_place_leave_nym->pub_key);
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "_notice_place_leave: got EOM from nym %s (%s).\n",
               GNUNET_h2s (&hst->notice_place_leave_nym->pub_key_hash), str);
   GNUNET_free (str);
@@ -818,9 +881,6 @@ handle_host_enter_request (void *cls,
 {
   struct GNUNET_SOCIAL_Host *hst = cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "handle_host_enter_request\n");
-
   if (NULL == hst->answer_door_cb)
      return;
 
@@ -1018,80 +1078,24 @@ handle_app_place_end (void *cls,
 }
 
 
-/*** CLEANUP / DISCONNECT ***/
-
-
-static void
-host_cleanup (struct GNUNET_SOCIAL_Host *hst)
-{
-  if (NULL != hst->slicer)
-  {
-    GNUNET_PSYC_slicer_destroy (hst->slicer);
-    hst->slicer = NULL;
-  }
-  GNUNET_free (hst);
-}
-
-
-static void
-guest_cleanup (struct GNUNET_SOCIAL_Guest *gst)
-{
-  GNUNET_free (gst);
-}
-
-
-static void
-place_cleanup (struct GNUNET_SOCIAL_Place *plc)
-{
-  struct GNUNET_HashCode place_pub_hash;
-
-  GNUNET_CRYPTO_hash (&plc->pub_key, sizeof (plc->pub_key), &place_pub_hash);
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "%s place cleanup: %s\n",
-              GNUNET_YES == plc->is_host ? "host" : "guest",
-              GNUNET_h2s (&place_pub_hash));
-
-  if (NULL != plc->tmit)
-  {
-    GNUNET_PSYC_transmit_destroy (plc->tmit);
-    plc->tmit = NULL;
-  }
-  if (NULL != plc->connect_env)
-  {
-    GNUNET_MQ_discard (plc->connect_env);
-    plc->connect_env = NULL;
-  }
-  if (NULL != plc->mq)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "destroying MQ (place_cleanup)\n");
-    GNUNET_MQ_destroy (plc->mq);
-    plc->mq = NULL;
-  }
-  if (NULL != plc->disconnect_cb)
-  {
-    plc->disconnect_cb (plc->disconnect_cls);
-    plc->disconnect_cb = NULL;
-  }
-
-  (GNUNET_YES == plc->is_host)
-    ? host_cleanup ((struct GNUNET_SOCIAL_Host *) plc)
-    : guest_cleanup ((struct GNUNET_SOCIAL_Guest *) plc);
-}
-
-
+/**
+ * Handler for a #GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK message received
+ * from the social service.
+ *
+ * @param cls the place of type `struct GNUNET_SOCIAL_Place`
+ * @param msg the message received from the service
+ */
 static void
-place_disconnect (struct GNUNET_SOCIAL_Place *plc)
+handle_place_leave_ack (void *cls,
+                        const struct GNUNET_MessageHeader *msg)
 {
-  struct GNUNET_HashCode place_pub_hash;
+  struct GNUNET_SOCIAL_Place *plc = cls;
 
-  GNUNET_CRYPTO_hash (&plc->pub_key,
-                      sizeof (plc->pub_key),
-                      &place_pub_hash);
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "place_disconnect, plc = %s\n",
-              GNUNET_h2s (&place_pub_hash));
-  place_cleanup (plc);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "%s left place %p\n",
+              plc->is_host ? "host" : "guest", 
+              plc);
+  place_disconnect (plc);  
 }
 
 
@@ -1130,8 +1134,6 @@ host_disconnected (void *cls, enum GNUNET_MQ_Error error)
   }
   if (NULL != plc->mq)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "destroying MQ (host_disconnected)\n");
     GNUNET_MQ_destroy (plc->mq);
     plc->mq = NULL;
   }
@@ -1153,6 +1155,10 @@ host_connect (struct GNUNET_SOCIAL_Host *hst)
                              GNUNET_MESSAGE_TYPE_SOCIAL_HOST_ENTER_ACK,
                              struct HostEnterAck,
                              hst),
+    GNUNET_MQ_hd_fixed_size (place_leave_ack,
+                             GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK,
+                             struct GNUNET_MessageHeader,
+                             plc),
     GNUNET_MQ_hd_var_size (host_enter_request,
                            GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST,
                            struct GNUNET_PSYC_JoinRequestMessage,
@@ -1501,6 +1507,9 @@ GNUNET_SOCIAL_host_announce (struct GNUNET_SOCIAL_Host *hst,
                              void *notify_data_cls,
                              enum GNUNET_SOCIAL_AnnounceFlags flags)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "PSYC_transmit_message for host, method: %s\n",
+              method_name);
   if (GNUNET_OK ==
       GNUNET_PSYC_transmit_message (hst->plc.tmit, method_name, env,
                                     NULL, notify_data, notify_data_cls, flags))
@@ -1573,32 +1582,6 @@ GNUNET_SOCIAL_host_disconnect (struct GNUNET_SOCIAL_Host *hst,
 }
 
 
-/**
- * Closure for #host_leave_cont.
- */
-struct HostLeaveContext
-{
-  struct GNUNET_SOCIAL_Host *hst;
-  GNUNET_ContinuationCallback disconnect_cb;
-  void *disconnect_cb_cls;
-};
-
-
-/**
- * FIXME.
- */
-static void
-host_leave_cont (void *cls)
-{
-  struct HostLeaveContext *hlc = cls;
-
-  GNUNET_SOCIAL_host_disconnect (hlc->hst,
-                                 hlc->disconnect_cb,
-                                 hlc->disconnect_cb_cls);
-  GNUNET_free (hlc);
-}
-
-
 /**
  * Stop hosting the home.
  *
@@ -1622,23 +1605,13 @@ GNUNET_SOCIAL_host_leave (struct GNUNET_SOCIAL_Host *hst,
                           GNUNET_ContinuationCallback disconnect_cb,
                           void *cls)
 {
-  struct GNUNET_MessageHeader *msg;
   struct GNUNET_MQ_Envelope *envelope;
-  struct HostLeaveContext *hlc;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "GNUNET_SOCIAL_host_leave\n");
   GNUNET_SOCIAL_host_announce (hst, "_notice_place_closing", env, NULL, NULL,
                                GNUNET_SOCIAL_ANNOUNCE_NONE);
-  envelope = GNUNET_MQ_msg (msg,
-                            GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
-  hlc = GNUNET_new (struct HostLeaveContext);
-  hlc->hst = hst;
-  hlc->disconnect_cb = disconnect_cb;
-  hlc->disconnect_cb_cls = cls;
-  GNUNET_MQ_notify_sent (envelope,
-                         &host_leave_cont,
-                         hlc);
+  hst->plc.disconnect_cb = disconnect_cb;
+  hst->plc.disconnect_cls = cls;
+  envelope = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
   GNUNET_MQ_send (hst->plc.mq,
                   envelope);
 }
@@ -1679,8 +1652,6 @@ guest_disconnected (void *cls, enum GNUNET_MQ_Error error)
   }
   if (NULL != plc->mq)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "destroying MQ (guest_disconnected)\n");
     GNUNET_MQ_destroy (plc->mq);
     plc->mq = NULL;
   }
@@ -1702,6 +1673,10 @@ guest_connect (struct GNUNET_SOCIAL_Guest *gst)
                              GNUNET_MESSAGE_TYPE_SOCIAL_GUEST_ENTER_ACK,
                              struct GNUNET_PSYC_CountersResultMessage,
                              gst),
+    GNUNET_MQ_hd_fixed_size (place_leave_ack,
+                             GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE_ACK,
+                             struct GNUNET_MessageHeader,
+                             plc),
     GNUNET_MQ_hd_var_size (guest_enter_decision,
                            GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION,
                            struct GNUNET_PSYC_JoinDecisionMessage,
@@ -1928,6 +1903,64 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app,
 }
 
 
+struct ReconnectContext
+{
+  struct GNUNET_SOCIAL_Guest *guest;
+  int *result;
+  int64_t *max_message_id;
+  GNUNET_SOCIAL_GuestEnterCallback enter_cb;
+  void *enter_cls;
+};
+
+
+static void
+guest_enter_reconnect_cb (void *cls,
+                          int result,
+                          const struct GNUNET_CRYPTO_EddsaPublicKey *place_pub_key,
+                          uint64_t max_message_id)
+{
+  struct ReconnectContext *reconnect_ctx = cls;
+
+  GNUNET_assert (NULL != reconnect_ctx);
+  reconnect_ctx->result = GNUNET_new (int);
+  *(reconnect_ctx->result) = result; 
+  reconnect_ctx->max_message_id = GNUNET_new (int64_t);
+  *(reconnect_ctx->max_message_id) = max_message_id;
+}
+
+
+static void
+guest_entry_dcsn_reconnect_cb (void *cls,
+                               int is_admitted,
+                               const struct GNUNET_PSYC_Message *entry_resp)
+{
+  struct ReconnectContext *reconnect_ctx = cls;
+  struct GNUNET_SOCIAL_Guest *gst = reconnect_ctx->guest;
+
+  GNUNET_assert (NULL != reconnect_ctx);
+  GNUNET_assert (NULL != reconnect_ctx->result);
+  GNUNET_assert (NULL != reconnect_ctx->max_message_id);
+  if (GNUNET_YES != is_admitted)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Guest was rejected after calling "
+                "GNUNET_SOCIAL_guest_enter_reconnect ()\n");
+  }
+  else if (NULL != reconnect_ctx->enter_cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "guest reconnected!\n");
+    reconnect_ctx->enter_cb (reconnect_ctx->enter_cls,
+                             *(reconnect_ctx->result),
+                             &gst->plc.pub_key,
+                             *(reconnect_ctx->max_message_id));
+  }
+  GNUNET_free (reconnect_ctx->result);
+  GNUNET_free (reconnect_ctx->max_message_id);
+  GNUNET_free (reconnect_ctx);
+}
+
+
 /**
  * Reconnect to an already entered place as guest.
  *
@@ -1938,8 +1971,8 @@ GNUNET_SOCIAL_guest_enter_by_name (const struct GNUNET_SOCIAL_App *app,
  *        Flags for the entry.
  * @param slicer
  *        Slicer to use for processing incoming requests from guests.
- * @param local_enter_cb
- *        Called upon connection established to the social service.
+ * @param enter_cb
+ *        Called upon re-entering is complete.
  * @param entry_decision_cb
  *        Called upon receiving entry decision.
  *
@@ -1949,11 +1982,12 @@ struct GNUNET_SOCIAL_Guest *
 GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn,
                                      enum GNUNET_PSYC_SlaveJoinFlags flags,
                                      struct GNUNET_PSYC_Slicer *slicer,
-                                     GNUNET_SOCIAL_GuestEnterCallback local_enter_cb,
+                                     GNUNET_SOCIAL_GuestEnterCallback enter_cb,
                                      void *cls)
 {
   struct GNUNET_SOCIAL_Guest *gst = GNUNET_malloc (sizeof (*gst));
   struct GNUNET_SOCIAL_Place *plc = &gst->plc;
+  struct ReconnectContext *reconnect_ctx;
 
   uint16_t app_id_size = strlen (gconn->app->id) + 1;
   struct GuestEnterRequest *greq;
@@ -1972,10 +2006,15 @@ GNUNET_SOCIAL_guest_enter_reconnect (struct GNUNET_SOCIAL_GuestConnection *gconn
   plc->pub_key = gconn->plc_msg.place_pub_key;
   plc->ego_pub_key = gconn->plc_msg.ego_pub_key;
 
-  plc->op = GNUNET_OP_create ();
+  reconnect_ctx = GNUNET_new (struct ReconnectContext);
+  reconnect_ctx->guest = gst;
+  reconnect_ctx->enter_cb = enter_cb;
+  reconnect_ctx->enter_cls = cls;
 
-  gst->enter_cb = local_enter_cb;
-  gst->cb_cls = cls;
+  plc->op = GNUNET_OP_create ();
+  gst->enter_cb = &guest_enter_reconnect_cb;
+  gst->entry_dcsn_cb = &guest_entry_dcsn_reconnect_cb;
+  gst->cb_cls = reconnect_ctx;
 
   guest_connect (gst);
   return gst;
@@ -2062,46 +2101,12 @@ GNUNET_SOCIAL_guest_disconnect (struct GNUNET_SOCIAL_Guest *gst,
 {
   struct GNUNET_SOCIAL_Place *plc = &gst->plc;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "GNUNET_SOCIAL_guest_disconnect, gst = %p\n",
-              gst);
   plc->disconnect_cb = disconnect_cb;
   plc->disconnect_cls = cls;
   place_disconnect (plc);
 }
 
 
-/**
- * Closure for #leave_done_cont.
- */
-struct LeaveContext
-{
-  struct GNUNET_SOCIAL_Guest *gst;
-  GNUNET_ContinuationCallback disconnect_cb;
-  void *disconnect_cb_cls;
-};
-
-
-/**
- * The leave message was transmitted, now complete the
- * disconnection process.
- *
- * @param cls a `struct LeaveContext`
- */
-static void
-leave_done_cont (void *cls)
-{
-  struct LeaveContext *lc = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "social_api: guest's place_leave message sent!\n");
-  GNUNET_SOCIAL_guest_disconnect (lc->gst,
-                                  lc->disconnect_cb,
-                                  lc->disconnect_cb_cls);
-  GNUNET_free (lc);
-}
-
-
 /**
  * Leave a place temporarily or permanently.
  *
@@ -2124,25 +2129,13 @@ GNUNET_SOCIAL_guest_leave (struct GNUNET_SOCIAL_Guest *gst,
                            GNUNET_ContinuationCallback disconnect_cb,
                            void *cls)
 {
-  struct GNUNET_MessageHeader *msg;
   struct GNUNET_MQ_Envelope *envelope;
-  struct LeaveContext *lc;
 
   GNUNET_SOCIAL_guest_talk (gst, "_notice_place_leave", env, NULL, NULL,
                             GNUNET_SOCIAL_TALK_NONE);
-
-
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "social_api: place_leave\n");
-  envelope = GNUNET_MQ_msg (msg,
-                            GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
-  lc = GNUNET_new (struct LeaveContext);
-  lc->gst = gst;
-  lc->disconnect_cb = disconnect_cb;
-  lc->disconnect_cb_cls = cls;
-  GNUNET_MQ_notify_sent (envelope,
-                         &leave_done_cont,
-                         lc);
+  gst->plc.disconnect_cb = disconnect_cb;
+  gst->plc.disconnect_cls = cls;
+  envelope = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SOCIAL_PLACE_LEAVE);
   GNUNET_MQ_send (gst->plc.mq,
                   envelope);
 }
@@ -2780,6 +2773,8 @@ GNUNET_SOCIAL_app_disconnect (struct GNUNET_SOCIAL_App *app,
                               GNUNET_ContinuationCallback disconnect_cb,
                               void *disconnect_cls)
 {
+  if (NULL == app) return;
+
   app->disconnect_cb = disconnect_cb;
   app->disconnect_cls = disconnect_cls;