+
+/**
+ * Find an existing session by address.
+ *
+ * @param plugin the plugin
+ * @param sender for which peer should the session be?
+ * @param addr address to look for
+ * @return NULL if session was not found
+ */
+static struct Session *
+lookup_session (struct Plugin *plugin,
+ const struct GNUNET_PeerIdentity *sender,
+ const struct sockaddr_un *addr)
+{
+ struct LookupCtx lctx;
+
+ GNUNET_assert (NULL != plugin);
+ GNUNET_assert (NULL != sender);
+ GNUNET_assert (NULL != addr);
+ lctx.s = NULL;
+ lctx.addr = addr;
+ GNUNET_CONTAINER_multihashmap_get_multiple (plugin->session_map,
+ &sender->hashPubKey,
+ &lookup_session_it, &lctx);
+ return lctx.s;
+}
+
+
+/**
+ * Functions with this signature are called whenever we need
+ * to close a session due to a disconnect or failure to
+ * establish a connection.
+ *
+ * @param s session to close down
+ */
+static void
+disconnect_session (struct Session *s)
+{
+ struct Plugin *plugin = s->plugin;
+ struct UNIXMessageWrapper *msgw;
+ struct UNIXMessageWrapper *next;
+ int removed;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Disconnecting session for peer `%s' `%s'\n",
+ GNUNET_i2s (&s->target),
+ s->addr);
+ plugin->env->session_end (plugin->env->cls, &s->target, s);
+ removed = GNUNET_NO;
+ next = plugin->msg_head;
+ while (NULL != next)
+ {
+ msgw = next;
+ next = msgw->next;
+ if (msgw->session != s)
+ continue;
+ GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw);
+ if (NULL != msgw->cont)
+ msgw->cont (msgw->cont_cls, &msgw->session->target, GNUNET_SYSERR,
+ msgw->payload, 0);
+ GNUNET_free (msgw->msg);
+ GNUNET_free (msgw);
+ removed = GNUNET_YES;
+ }
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (plugin->session_map,
+ &s->target.hashPubKey,
+ s));
+ GNUNET_STATISTICS_set (plugin->env->stats,
+ "# UNIX sessions active",
+ GNUNET_CONTAINER_multihashmap_size (plugin->session_map),
+ GNUNET_NO);
+ if ((GNUNET_YES == removed) && (NULL == plugin->msg_head))
+ reschedule_select (plugin);
+ if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_free (s);