/**
 * Function that will be called whenever the plugin internally
 * cleans up a session pointer and hence the service needs to
 * discard all of those sessions as well.  Plugins that do not
 * use sessions can simply omit calling this function and always
 * use NULL wherever a session pointer is needed.  This function
 * should be called BEFORE a potential "TransmitContinuation"
 * from the "TransmitFunction".
 *
 * @param cls closure
 * @param address which address was the session for
 * @param session which session is being destoyed
 */
static void
plugin_env_session_end (void *cls,
                        const struct GNUNET_HELLO_Address *address,
                        struct GNUNET_ATS_Session *session)
{
  struct GNUNET_ATS_SessionKiller *sk;

  if (NULL == address)
  {
    GNUNET_break (0);
    return;
  }
  if (NULL == session)
  {
    GNUNET_break (0);
    return;
  }
  GNUNET_assert (strlen (address->transport_name) > 0);

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Notification from plugin about terminated session %p from peer `%s' address `%s'\n",
              session,
              GNUNET_i2s (&address->peer),
              GST_plugins_a2s (address));

  GST_neighbours_session_terminated (&address->peer, session);
  GST_ats_del_session (address,
                       session);
  GST_blacklist_abort_matching (address, session);

  for (sk = sk_head; NULL != sk; sk = sk->next)
  {
    if (sk->session == session)
    {
      GNUNET_CONTAINER_DLL_remove (sk_head, sk_tail, sk);
      GNUNET_SCHEDULER_cancel (sk->task);
      GNUNET_free(sk);
      break;
    }
  }
}
/**
 * Function that will be called whenever the plugin internally
 * cleans up a session pointer and hence the service needs to
 * discard all of those sessions as well.  Plugins that do not
 * use sessions can simply omit calling this function and always
 * use NULL wherever a session pointer is needed.  This function
 * should be called BEFORE a potential "TransmitContinuation"
 * from the "TransmitFunction".
 *
 * @param cls closure
 * @param peer which peer was the session for
 * @param session which session is being destoyed
 */
static void
plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
                        struct Session *session)
{
  const char *transport_name = cls;
  struct GNUNET_HELLO_Address address;

  GNUNET_assert (strlen (transport_name) > 0);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %X to peer `%s' ended \n",
              session, GNUNET_i2s (peer));
  if (NULL != session)
    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
                     "transport-ats",
                     "Telling ATS to destroy session %p from peer %s\n",
                     session, GNUNET_i2s (peer));
  address.peer = *peer;
  address.address = NULL;
  address.address_length = 0;
  address.transport_name = transport_name;
  GST_neighbours_session_terminated (peer, session);
  GNUNET_ATS_address_destroyed (GST_ats, &address, session);
}