static void
sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_ATS_Information ats[1];
  send_task = GNUNET_SCHEDULER_NO_TASK;

  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
    return;
  char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id));

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n",
              p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s);
  GNUNET_free (receiver_s);


  if (0 == messages_recv)
  {
  	start_normal = GNUNET_TIME_absolute_get();
  }
  if (1 == messages_recv)
  {
		ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY);
		ats[0].value = htonl (1000);
		GNUNET_TRANSPORT_set_traffic_metric (p2->th, &p1->id, TM_SEND, ats, 1);
		ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
		ats[0].value = htonl (10);
		GNUNET_TRANSPORT_set_traffic_metric (p1->th, &p2->id, TM_BOTH, ats, 1);

		start_delayed = GNUNET_TIME_absolute_get();
  }

  s_sending = GNUNET_YES;
  th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, 0,
                                               TIMEOUT_TRANSMIT, &notify_ready,
                                               p1);
}
static void
notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_MessageHeader *message)
{
  struct PeerContext *p = cls;
  struct PeerContext *t = NULL;

  if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity)))
    t = p1;
  if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity)))
    t = p2;
  GNUNET_assert (t != NULL);

  char *ps = GNUNET_strdup (GNUNET_i2s (&p->id));

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n",
              p->no, ps, ntohs (message->type), ntohs (message->size), t->no,
              GNUNET_i2s (&t->id));
  GNUNET_free (ps);

  if ((TEST_MESSAGE_TYPE == ntohs (message->type)) &&
      (TEST_MESSAGE_SIZE == ntohs (message->size)))
  {
    ok = 0;

  }
  else
  {
    GNUNET_break (0);
    ok = 1;
    end ();
    return;
  }

  if (messages_recv <= 1)
  {
    /* Received non-delayed message */
    dur_normal = GNUNET_TIME_absolute_get_duration(start_normal);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received non-delayed message %u after %s\n",
                messages_recv,
                GNUNET_STRINGS_relative_time_to_string (dur_normal,
							GNUNET_YES));

    struct GNUNET_ATS_Properties prop;
    struct GNUNET_TIME_Relative delay;

    delay.rel_value_us = 1000 * 1000LL;
    memset (&prop, 0, sizeof (prop));
    prop.distance = 10;
    GNUNET_TRANSPORT_set_traffic_metric (p1->th,
                                         &p2->id,
                                         &prop,
                                         delay,
                                         GNUNET_TIME_UNIT_ZERO);
    send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL);
  }
  if (2 == messages_recv)
  {
  	/* Received manipulated message */
    	dur_delayed = GNUNET_TIME_absolute_get_duration(start_delayed);
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Received delayed message %u after %s\n",
                  messages_recv,
		  GNUNET_STRINGS_relative_time_to_string (dur_delayed,
							  GNUNET_YES));
      if (dur_delayed.rel_value_us < 1000 * 1000LL)
      {
	GNUNET_break (0);
	ok += 1;
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                    "Delayed message was not delayed correctly: took only %s\n",
		    GNUNET_STRINGS_relative_time_to_string (dur_delayed,
							    GNUNET_YES));
      }
      /* shutdown */
      end ();
  }

  messages_recv ++;
}
/**
 * Main function that will be run.
 *
 * @param cls closure
 * @param args remaining command-line arguments
 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
 * @param c configuration
 */
static void
run (void *cls, char *const *args, const char *cfgfile,
     const struct GNUNET_CONFIGURATION_Handle *c)
{
    char *dbfile;
    struct WhiteListRow *wl_head;
    struct WhiteListRow *wl_entry;
    struct GNUNET_PeerIdentity identity;
    struct GNUNET_ATS_Properties prop;
    struct GNUNET_TIME_Relative delay;
    unsigned long long pid;
    unsigned int nrows;
    int ret;

    if (GNUNET_OK !=
            GNUNET_CONFIGURATION_get_value_number (c, "TESTBED",
                    "PEERID", &pid))
    {
        GNUNET_break (0);
        return;
    }
    if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "TESTBED-UNDERLAY",
            "DBFILE",
            &dbfile))
    {
        GNUNET_break (0);
        return;
    }
    if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, NULL)))
    {
        if (NULL != db)
        {
            LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2");
            GNUNET_break (SQLITE_OK == sqlite3_close (db));
        }
        else
            LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile);
        GNUNET_free (dbfile);
        return;
    }
    DEBUG ("Opened database %s\n", dbfile);
    GNUNET_free (dbfile);
    dbfile = NULL;
    wl_head = NULL;
    if (GNUNET_OK != load_keys (c))
        goto close_db;

    transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL);
    if (NULL == transport)
    {
        GNUNET_break (0);
        return;
    }
    /* read and process whitelist */
    nrows = 0;
    wl_head = NULL;
    nrows = db_read_whitelist (db, pid, &wl_head);
    if ((GNUNET_SYSERR == nrows) || (0 == nrows))
    {
        GNUNET_TRANSPORT_disconnect (transport);
        goto close_db;
    }
    map = GNUNET_CONTAINER_multipeermap_create (nrows, GNUNET_NO);
    while (NULL != (wl_entry = wl_head))
    {
        wl_head = wl_entry->next;
        delay.rel_value_us = wl_entry->latency;
        memset (&prop, 0, sizeof (prop));
        GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity));
        GNUNET_break (GNUNET_OK ==
                      GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity,
                              GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
        DEBUG ("Setting %u ms latency to peer `%s'\n",
               wl_entry->latency,
               GNUNET_i2s (&identity));
        GNUNET_TRANSPORT_set_traffic_metric (transport,
                                             &identity,
                                             &prop,
                                             delay,
                                             delay);
        GNUNET_free (wl_entry);
    }
    bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL);
    shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                    &do_shutdown, NULL);

close_db:
    GNUNET_break (SQLITE_OK == sqlite3_close (db));
    return;
}