/**
 * Called with any sensor reading messages received from CADET.
 *
 * Each time the function must call #GNUNET_CADET_receive_done on the channel
 * in order to receive the next message. This doesn't need to be immediate:
 * can be delayed if some processing is done on the message.
 *
 * @param cls Closure (set from #GNUNET_CADET_connect).
 * @param channel Connection to the other end.
 * @param channel_ctx Place to store local state associated with the channel.
 * @param message The actual message.
 * @return #GNUNET_OK to keep the channel open,
 *         #GNUNET_SYSERR to close it (signal serious error).
 */
static int
handle_sensor_reading (void *cls, struct GNUNET_CADET_Channel *channel,
                       void **channel_ctx,
                       const struct GNUNET_MessageHeader *message)
{
  struct ClientPeerContext *cp = *channel_ctx;
  struct ClientSensorReading *reading;

  reading = parse_reading_message (message, sensors);
  if (NULL == reading)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "Received an invalid sensor reading from peer `%s'.\n",
                GNUNET_i2s (&cp->peerid));
    return GNUNET_SYSERR;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              "Received a sensor reading from peer `%s':\n"
              "# Sensor name: `%s'\n" "# Timestamp: %" PRIu64 "\n"
              "# Value size: %" PRIu64 ".\n", GNUNET_i2s (&cp->peerid),
              reading->sensor->name, reading->timestamp, reading->value_size);
  GNUNET_PEERSTORE_store (peerstore, values_subsystem, &cp->peerid,
                          reading->sensor->name, reading->value,
                          reading->value_size, GNUNET_TIME_UNIT_FOREVER_ABS,
                          GNUNET_PEERSTORE_STOREOPTION_MULTIPLE, NULL, NULL);
  GNUNET_free (reading->value);
  GNUNET_free (reading);
  GNUNET_CADET_receive_done (channel);
  return GNUNET_OK;
}
/**
 * Function to handle a ring message incoming over cadet
 *
 * @param cls closure, NULL
 * @param channel the channel over which the message arrived
 * @param channel_ctx the channel context, can be NULL
 *                    or point to the `struct Channel`
 * @param message the incoming message
 * @return #GNUNET_OK
 */
static int
handle_cadet_ring_message (void *cls,
                           struct GNUNET_CADET_Channel *channel,
                           void **channel_ctx,
                           const struct GNUNET_MessageHeader *message)
{
  struct Channel *ch = *channel_ctx;
  struct Line *line = ch->line;
  const struct CadetPhoneRingMessage *msg;
  struct GNUNET_MQ_Envelope *env;
  struct ClientPhoneRingMessage *cring;
  struct CadetPhoneRingInfoPS rs;

  msg = (const struct CadetPhoneRingMessage *) message;
  rs.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
  rs.purpose.size = htonl (sizeof (struct CadetPhoneRingInfoPS));
  rs.line_port = line->line_port;
  rs.target_peer = my_identity;
  rs.expiration_time = msg->expiration_time;

  if (GNUNET_OK !=
      GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
                                  &rs.purpose,
                                  &msg->signature,
                                  &msg->caller_id))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (msg->expiration_time)).rel_value_us)
  {
    /* ancient call, replay? */
    GNUNET_break_op (0);
    /* Note that our reliance on time here is awkward; better would be
       to use a more complex challenge-response protocol against
       replay attacks.  Left for future work ;-). */
    return GNUNET_SYSERR;
  }
  if (CS_CALLEE_INIT != ch->status)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  GNUNET_CADET_receive_done (channel);
  ch->status = CS_CALLEE_RINGING;
  env = GNUNET_MQ_msg (cring,
                       GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
  cring->cid = ch->cid;
  cring->caller_id = msg->caller_id;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending RING message to client. CID is %u\n",
              (unsigned int) ch->cid);
  GNUNET_MQ_send (line->mq,
                  env);
  return GNUNET_OK;
}
/**
 * Function to handle a resume message incoming over cadet
 *
 * @param cls closure, NULL
 * @param channel the channel over which the message arrived
 * @param channel_ctx the channel context, can be NULL
 *                    or point to the `struct Channel`
 * @param message the incoming message
 * @return #GNUNET_OK
 */
static int
handle_cadet_resume_message (void *cls,
                             struct GNUNET_CADET_Channel *channel,
                             void **channel_ctx,
                             const struct GNUNET_MessageHeader *message)
{
  struct Channel *ch = *channel_ctx;
  struct Line *line;
  struct GNUNET_MQ_Envelope *env;
  struct ClientPhoneResumeMessage *resume;

  if (NULL == ch)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "RESUME message received for non-existing line, dropping channel.\n");
    return GNUNET_SYSERR;
  }
  line = ch->line;
  GNUNET_CADET_receive_done (channel);
  if (GNUNET_YES != ch->suspended_remote)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "RESUME message received for non-suspended channel, dropping channel.\n");
    return GNUNET_SYSERR;
  }
  switch (ch->status)
  {
  case CS_CALLEE_INIT:
    GNUNET_break (0);
    break;
  case CS_CALLEE_RINGING:
    GNUNET_break (0);
    break;
  case CS_CALLEE_CONNECTED:
    ch->suspended_remote = GNUNET_NO;
    break;
  case CS_CALLEE_SHUTDOWN:
    return GNUNET_OK;
  case CS_CALLER_CALLING:
    GNUNET_break (0);
    break;
  case CS_CALLER_CONNECTED:
    ch->suspended_remote = GNUNET_NO;
    break;
  case CS_CALLER_SHUTDOWN:
    return GNUNET_OK;
  }
  env = GNUNET_MQ_msg (resume,
                       GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
  resume->cid = ch->cid;
  GNUNET_MQ_send (line->mq,
                  env);
  return GNUNET_OK;
}
/**
 * Called with any anomaly report received from a peer.
 *
 * Each time the function must call #GNUNET_CADET_receive_done on the channel
 * in order to receive the next message. This doesn't need to be immediate:
 * can be delayed if some processing is done on the message.
 *
 * @param cls Closure (set from #GNUNET_CADET_connect).
 * @param channel Connection to the other end.
 * @param channel_ctx Place to store local state associated with the channel.
 * @param message The actual message.
 * @return #GNUNET_OK to keep the channel open,
 *         #GNUNET_SYSERR to close it (signal serious error).
 */
static int
handle_anomaly_report (void *cls, struct GNUNET_CADET_Channel *channel,
                       void **channel_ctx,
                       const struct GNUNET_MessageHeader *message)
{
  struct ClientPeerContext *cp = *channel_ctx;
  struct GNUNET_SENSOR_crypto_pow_block *report_block;
  struct GNUNET_SENSOR_AnomalyReportMessage *anomaly_msg;
  struct GNUNET_SENSOR_SensorInfo *sensor;
  struct GNUNET_SENSOR_DashboardAnomalyEntry *anomaly_entry;
  struct GNUNET_TIME_Absolute expiry;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received an anomaly report message from peer `%s'.\n",
              GNUNET_i2s (&cp->peerid));
  report_block = (struct GNUNET_SENSOR_crypto_pow_block *) &message[1];
  if (sizeof (struct GNUNET_SENSOR_AnomalyReportMessage) !=
      GNUNET_SENSOR_crypto_verify_pow_sign (report_block, pow_matching_bits,
                                            &cp->peerid.public_key,
                                            (void **) &anomaly_msg))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "Received invalid anomaly report from peer `%s'.\n",
                GNUNET_i2s (&cp->peerid));
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  sensor =
      GNUNET_CONTAINER_multihashmap_get (sensors,
                                         &anomaly_msg->sensorname_hash);
  if (NULL == sensor)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  anomaly_entry = GNUNET_new (struct GNUNET_SENSOR_DashboardAnomalyEntry);
  anomaly_entry->anomalous = ntohs (anomaly_msg->anomalous);
  anomaly_entry->anomalous_neighbors = anomaly_msg->anomalous_neighbors;
  expiry =
      (GNUNET_YES ==
       anomaly_entry->anomalous) ? GNUNET_TIME_UNIT_FOREVER_ABS :
      GNUNET_TIME_absolute_get ();
  GNUNET_PEERSTORE_store (peerstore, anomalies_subsystem, &cp->peerid,
                          sensor->name, anomaly_entry,
                          sizeof (struct GNUNET_SENSOR_DashboardAnomalyEntry),
                          expiry, GNUNET_PEERSTORE_STOREOPTION_REPLACE, NULL,
                          NULL);
  GNUNET_free (anomaly_entry);
  GNUNET_CADET_receive_done (channel);
  return GNUNET_OK;
}
Example #5
0
/**
 * Function is called whenever a message is received.
 *
 * @param cls closure (set from GNUNET_CADET_connect)
 * @param channel connection to the other end
 * @param channel_ctx place to store local state associated with the channel
 * @param message the actual message
 *
 * @return GNUNET_OK to keep the connection open,
 *         GNUNET_SYSERR to close it (signal serious error)
 */
static int
data_callback (void *cls, struct GNUNET_CADET_Channel *channel,
               void **channel_ctx,
               const struct GNUNET_MessageHeader *message)
{
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data callback! Shutting down.\n");
  got_data = GNUNET_YES;
  if (NULL != shutdown_task)
    GNUNET_SCHEDULER_cancel (shutdown_task);
  shutdown_task =
    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown,
                                  NULL);
  GNUNET_CADET_receive_done (channel);
  return GNUNET_OK;
}
/**
 * Function to handle a suspend message incoming over cadet
 *
 * @param cls closure, NULL
 * @param channel the channel over which the message arrived
 * @param channel_ctx the channel context, can be NULL
 *                    or point to the `struct Channel`
 * @param message the incoming message
 * @return #GNUNET_OK
 */
static int
handle_cadet_suspend_message (void *cls,
                              struct GNUNET_CADET_Channel *channel,
                              void **channel_ctx,
                              const struct GNUNET_MessageHeader *message)
{
  struct Channel *ch = *channel_ctx;
  struct Line *line = ch->line;
  struct GNUNET_MQ_Envelope *env;
  struct ClientPhoneSuspendMessage *suspend;

  GNUNET_CADET_receive_done (channel);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Suspending channel CID: %u\n",
              ch->cid);
  switch (ch->status)
  {
  case CS_CALLEE_INIT:
    GNUNET_break_op (0);
    break;
  case CS_CALLEE_RINGING:
    GNUNET_break_op (0);
    break;
  case CS_CALLEE_CONNECTED:
    ch->suspended_remote = GNUNET_YES;
    break;
  case CS_CALLEE_SHUTDOWN:
    return GNUNET_OK;
  case CS_CALLER_CALLING:
    GNUNET_break_op (0);
    break;
  case CS_CALLER_CONNECTED:
    ch->suspended_remote = GNUNET_YES;
    break;
  case CS_CALLER_SHUTDOWN:
    return GNUNET_OK;
  }
  env = GNUNET_MQ_msg (suspend,
                       GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
  suspend->cid = ch->cid;
  GNUNET_MQ_send (line->mq,
                  env);
  return GNUNET_OK;
}
/**
 * Function to handle a pickup message incoming over cadet
 *
 * @param cls closure, NULL
 * @param channel the channel over which the message arrived
 * @param channel_ctx the channel context, can be NULL
 *                    or point to the `struct Channel`
 * @param message the incoming message
 * @return #GNUNET_OK if message was OK,
 *         #GNUNET_SYSERR if message violated the protocol
 */
static int
handle_cadet_pickup_message (void *cls,
                             struct GNUNET_CADET_Channel *channel,
                             void **channel_ctx,
                             const struct GNUNET_MessageHeader *message)
{
  struct Channel *ch = *channel_ctx;
  struct Line *line = ch->line;
  struct GNUNET_MQ_Envelope *env;
  struct ClientPhonePickedupMessage *pick;

  GNUNET_CADET_receive_done (channel);
  switch (ch->status)
  {
  case CS_CALLEE_INIT:
  case CS_CALLEE_RINGING:
  case CS_CALLEE_CONNECTED:
    GNUNET_break_op (0);
    destroy_line_cadet_channels (ch);
    return GNUNET_SYSERR;
  case CS_CALLEE_SHUTDOWN:
    GNUNET_break_op (0);
    destroy_line_cadet_channels (ch);
    return GNUNET_SYSERR;
  case CS_CALLER_CALLING:
    ch->status = CS_CALLER_CONNECTED;
    break;
  case CS_CALLER_CONNECTED:
    GNUNET_break_op (0);
    return GNUNET_OK;
  case CS_CALLER_SHUTDOWN:
    GNUNET_break_op (0);
    mq_done_finish_caller_shutdown (ch);
    return GNUNET_SYSERR;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending PICKED UP message to client\n");
  env = GNUNET_MQ_msg (pick,
                       GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP);
  pick->cid = ch->cid;
  GNUNET_MQ_send (line->mq,
                  env);
  return GNUNET_OK;
}
/**
 * Function to handle a hangup message incoming over cadet
 *
 * @param cls closure, NULL
 * @param channel the channel over which the message arrived
 * @param channel_ctx the channel context, can be NULL
 *                    or point to the `struct Channel`
 * @param message the incoming message
 * @return #GNUNET_OK
 */
static int
handle_cadet_hangup_message (void *cls,
                             struct GNUNET_CADET_Channel *channel,
                             void **channel_ctx,
                             const struct GNUNET_MessageHeader *message)
{
  struct Channel *ch = *channel_ctx;
  struct Line *line = ch->line;
  struct GNUNET_MQ_Envelope *env;
  struct ClientPhoneHangupMessage *hup;
  enum ChannelStatus status;
  uint32_t cid;

  GNUNET_CADET_receive_done (channel);
  cid = ch->cid;
  status = ch->status;
  destroy_line_cadet_channels (ch);
  switch (status)
  {
  case CS_CALLEE_INIT:
    GNUNET_break_op (0);
    return GNUNET_OK;
  case CS_CALLEE_RINGING:
  case CS_CALLEE_CONNECTED:
    break;
  case CS_CALLEE_SHUTDOWN:
    return GNUNET_OK;
  case CS_CALLER_CALLING:
  case CS_CALLER_CONNECTED:
    break;
  case CS_CALLER_SHUTDOWN:
    return GNUNET_OK;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending HANG UP message to client\n");
  env = GNUNET_MQ_msg (hup,
                       GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
  hup->cid = cid;
  GNUNET_MQ_send (line->mq,
                  env);
  return GNUNET_OK;
}
/**
 * Called with any sensor list request received.
 *
 * Each time the function must call #GNUNET_CADET_receive_done on the channel
 * in order to receive the next message. This doesn't need to be immediate:
 * can be delayed if some processing is done on the message.
 *
 * @param cls Closure (set from #GNUNET_CADET_connect).
 * @param channel Connection to the other end.
 * @param channel_ctx Place to store local state associated with the channel.
 * @param message The actual message.
 * @return #GNUNET_OK to keep the channel open,
 *         #GNUNET_SYSERR to close it (signal serious error).
 */
static int
handle_sensor_list_req (void *cls, struct GNUNET_CADET_Channel *channel,
                        void **channel_ctx,
                        const struct GNUNET_MessageHeader *message)
{
  struct ClientPeerContext *cp = *channel_ctx;
  struct GNUNET_MessageHeader *end_msg;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received a sensor list request from peer `%s'.\n",
              GNUNET_i2s (&cp->peerid));
  GNUNET_CONTAINER_multihashmap_iterate (sensors, &send_sensor_brief, cp);
  end_msg = GNUNET_new (struct GNUNET_MessageHeader);

  end_msg->size = htons (sizeof (struct GNUNET_MessageHeader));
  end_msg->type = htons (GNUNET_MESSAGE_TYPE_SENSOR_END);
  queue_msg (end_msg, cp);
  GNUNET_CADET_receive_done (channel);
  return GNUNET_OK;
}
/**
 * Called with any request for full sensor information.
 *
 * Each time the function must call #GNUNET_CADET_receive_done on the channel
 * in order to receive the next message. This doesn't need to be immediate:
 * can be delayed if some processing is done on the message.
 *
 * @param cls Closure (set from #GNUNET_CADET_connect).
 * @param channel Connection to the other end.
 * @param channel_ctx Place to store local state associated with the channel.
 * @param message The actual message.
 * @return #GNUNET_OK to keep the channel open,
 *         #GNUNET_SYSERR to close it (signal serious error).
 */
static int
handle_sensor_full_req (void *cls, struct GNUNET_CADET_Channel *channel,
                        void **channel_ctx,
                        const struct GNUNET_MessageHeader *message)
{
  struct ClientPeerContext *cp = *channel_ctx;
  struct GNUNET_SENSOR_SensorBriefMessage *sbm = NULL;
  struct GNUNET_SENSOR_SensorFullMessage *sfm;
  uint16_t msg_size;
  uint16_t sensorname_size;

  msg_size = ntohs (message->size);
  /* parse & error check */
  if (msg_size > sizeof (struct GNUNET_SENSOR_SensorBriefMessage))
  {
    sbm = (struct GNUNET_SENSOR_SensorBriefMessage *) message;
    sensorname_size = ntohs (sbm->name_size);
    if (msg_size !=
        sizeof (struct GNUNET_SENSOR_SensorBriefMessage) + sensorname_size)
      sbm = NULL;
  }
  if (NULL == sbm)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Received an invalid full sensor request from peer `%s'.\n",
                GNUNET_i2s (&cp->peerid));
    return GNUNET_SYSERR;
  }
  /* Create and send msg with full sensor info */
  sfm = create_full_sensor_msg ((char *) &sbm[1]);
  if (NULL == sfm)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Error creating full sensor info msg for sensor `%s'.\n",
                (char *) &sbm[1]);
    return GNUNET_SYSERR;
  }
  queue_msg ((struct GNUNET_MessageHeader *) sfm, cp);
  GNUNET_CADET_receive_done (channel);
  return GNUNET_OK;
}
/**
 * Function to handle an audio message incoming over cadet
 *
 * @param cls closure, NULL
 * @param channel the channel over which the message arrived
 * @param channel_ctx the channel context, can be NULL
 *                    or point to the `struct Channel`
 * @param message the incoming message
 * @return #GNUNET_OK
 */
static int
handle_cadet_audio_message (void *cls,
                            struct GNUNET_CADET_Channel *channel,
                            void **channel_ctx,
                            const struct GNUNET_MessageHeader *message)
{
  struct Channel *ch = *channel_ctx;
  const struct CadetAudioMessage *msg;
  size_t msize = ntohs (message->size) - sizeof (struct CadetAudioMessage);
  struct GNUNET_MQ_Envelope *env;
  struct ClientAudioMessage *cam;

  msg = (const struct CadetAudioMessage *) message;
  GNUNET_CADET_receive_done (channel);
  if ( (GNUNET_YES == ch->suspended_local) ||
       (GNUNET_YES == ch->suspended_remote) )
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Received %u bytes of AUDIO data on suspended channel CID %u; dropping\n",
                (unsigned int) msize,
                ch->cid);
    return GNUNET_OK;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Forwarding %u bytes of AUDIO data to client CID %u\n",
              (unsigned int) msize,
              ch->cid);
  env = GNUNET_MQ_msg_extra (cam,
                             msize,
                             GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
  cam->cid = ch->cid;
  GNUNET_memcpy (&cam[1],
                 &msg[1],
                 msize);
  GNUNET_MQ_send (ch->line->mq,
                  env);
  return GNUNET_OK;
}
/**
 * Callback for set operation results. Called for each element
 * that needs to be removed from the result set.
 *
 * @param cls closure with the `struct BobServiceSession`
 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
 * @param status what has happened with the set intersection?
 */
static void
cb_intersection_element_removed (void *cls,
                                 const struct GNUNET_SET_Element *element,
                                 enum GNUNET_SET_Status status)
{
  struct BobServiceSession *s = cls;
  struct GNUNET_SCALARPRODUCT_Element *se;

  switch (status)
  {
  case GNUNET_SET_STATUS_OK:
    /* this element has been removed from the set */
    se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements,
                                            element->data);
    GNUNET_assert (NULL != se);
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Removed element with key %s and value %lld\n",
         GNUNET_h2s (&se->key),
         (long long) GNUNET_ntohll (se->value));
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements,
                                                         element->data,
                                                         se));
    GNUNET_free (se);
    return;
  case GNUNET_SET_STATUS_DONE:
    s->intersection_op = NULL;
    GNUNET_break (NULL == s->intersection_set);
    GNUNET_CADET_receive_done (s->cadet->channel);
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Finished intersection, %d items remain\n",
         GNUNET_CONTAINER_multihashmap_size (s->intersected_elements));
    if (s->client_received_element_count ==
        GNUNET_CONTAINER_multihashmap_size (s->intersected_elements))
    {
      /* CADET transmission from Alice is also already done,
         start with our own reply */
      transmit_bobs_cryptodata_message (s);
    }
    return;
  case GNUNET_SET_STATUS_HALF_DONE:
    /* unexpected for intersection */
    GNUNET_break (0);
    return;
  case GNUNET_SET_STATUS_FAILURE:
    /* unhandled status code */
    LOG (GNUNET_ERROR_TYPE_DEBUG,
         "Set intersection failed!\n");
    s->intersection_op = NULL;
    if (NULL != s->intersection_set)
    {
      GNUNET_SET_destroy (s->intersection_set);
      s->intersection_set = NULL;
    }
    s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE;
    prepare_client_end_notification (s);
    return;
  default:
    GNUNET_break (0);
    return;
  }
}
/**
 * Handle a multipart-chunk of a request from another service to
 * calculate a scalarproduct with us.
 *
 * @param cls closure (set from #GNUNET_CADET_connect)
 * @param channel connection to the other end
 * @param channel_ctx place to store local state associated with the @a channel
 * @param message the actual message
 * @return #GNUNET_OK to keep the connection open,
 *         #GNUNET_SYSERR to close it (signal serious error)
 */
static int
handle_alices_cryptodata_message (void *cls,
                                  struct GNUNET_CADET_Channel *channel,
                                  void **channel_ctx,
                                  const struct GNUNET_MessageHeader *message)
{
  struct CadetIncomingSession *in = *channel_ctx;
  struct BobServiceSession *s;
  const struct EccAliceCryptodataMessage *msg;
  const struct GNUNET_CRYPTO_EccPoint *payload;
  uint32_t contained_elements;
  size_t msg_length;
  uint16_t msize;
  unsigned int max;
  unsigned int i;
  const struct MpiElement *b_i;
  gcry_mpi_point_t tmp;
  gcry_mpi_point_t g_i;
  gcry_mpi_point_t h_i;
  gcry_mpi_point_t g_i_b_i;
  gcry_mpi_point_t h_i_b_i;

  /* sanity checks */
  if (NULL == in)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  s = in->s;
  if (NULL == s)
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  /* sort our vector for the computation */
  if (NULL == s->sorted_elements)
  {
    s->sorted_elements
      = GNUNET_malloc (GNUNET_CONTAINER_multihashmap_size (s->intersected_elements) *
                       sizeof (struct MpiElement));
    s->used_element_count = 0;
    GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements,
                                           &copy_element_cb,
                                           s);
    qsort (s->sorted_elements,
           s->used_element_count,
           sizeof (struct MpiElement),
           &element_cmp);
  }

  /* parse message */
  msize = ntohs (message->size);
  if (msize <= sizeof (struct EccAliceCryptodataMessage))
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  msg = (const struct EccAliceCryptodataMessage *) message;
  contained_elements = ntohl (msg->contained_element_count);
  /* Our intersection may still be ongoing, but this is nevertheless
     an upper bound on the required array size */
  max = GNUNET_CONTAINER_multihashmap_size (s->intersected_elements);
  msg_length = sizeof (struct EccAliceCryptodataMessage)
    + contained_elements * sizeof (struct GNUNET_CRYPTO_EccPoint) * 2;
  if ( (msize != msg_length) ||
       (0 == contained_elements) ||
       (contained_elements > UINT16_MAX) ||
       (max < contained_elements + s->cadet_received_element_count) )
  {
    GNUNET_break_op (0);
    return GNUNET_SYSERR;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received %u crypto values from Alice\n",
              (unsigned int) contained_elements);
  payload = (const struct GNUNET_CRYPTO_EccPoint *) &msg[1];

  for (i=0;i<contained_elements;i++)
  {
    b_i = &s->sorted_elements[i + s->cadet_received_element_count];
    g_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
                                          &payload[i * 2]);
    g_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
                                          g_i,
                                          b_i->value);
    gcry_mpi_point_release (g_i);
    h_i = GNUNET_CRYPTO_ecc_bin_to_point (edc,
                                          &payload[i * 2 + 1]);
    h_i_b_i = GNUNET_CRYPTO_ecc_pmul_mpi (edc,
                                          h_i,
                                          b_i->value);
    gcry_mpi_point_release (h_i);
    if (0 == i + s->cadet_received_element_count)
    {
      /* first iteration, nothing to add */
      s->prod_g_i_b_i = g_i_b_i;
      s->prod_h_i_b_i = h_i_b_i;
    }
    else
    {
      /* further iterations, cummulate resulting value */
      tmp = GNUNET_CRYPTO_ecc_add (edc,
                                   s->prod_g_i_b_i,
                                   g_i_b_i);
      gcry_mpi_point_release (s->prod_g_i_b_i);
      gcry_mpi_point_release (g_i_b_i);
      s->prod_g_i_b_i = tmp;
      tmp = GNUNET_CRYPTO_ecc_add (edc,
                                   s->prod_h_i_b_i,
                                   h_i_b_i);
      gcry_mpi_point_release (s->prod_h_i_b_i);
      gcry_mpi_point_release (h_i_b_i);
      s->prod_h_i_b_i = tmp;
    }
  }
  s->cadet_received_element_count += contained_elements;
  if ( (s->cadet_received_element_count == max) &&
       (NULL == s->intersection_op) )
  {
    /* intersection has finished also on our side, and
       we got the full set, so we can proceed with the
       CADET response(s) */
    transmit_bobs_cryptodata_message (s);
  }
  GNUNET_CADET_receive_done (s->cadet->channel);
  return GNUNET_OK;
}
Example #14
0
/**
 * Function is called whenever a message is received.
 *
 * @param cls closure (set from GNUNET_CADET_connect, peer number)
 * @param channel connection to the other end
 * @param channel_ctx place to store local state associated with the channel
 * @param message the actual message
 * @return GNUNET_OK to keep the connection open,
 *         GNUNET_SYSERR to close it (signal serious error)
 */
int
data_callback (void *cls, struct GNUNET_CADET_Channel *channel,
               void **channel_ctx,
               const struct GNUNET_MessageHeader *message)
{
  struct GNUNET_CADET_TransmitHandle **pth;
  long client = (long) cls;
  long expected_target_client;
  uint32_t *data;
  uint32_t payload;
  unsigned int counter;

  ok++;
  counter = get_expected_target () == client ? data_received : ack_received;

  GNUNET_CADET_receive_done (channel);

  if ((ok % 10) == 0)
  {
    if (NULL != disconnect_task)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_INFO, " reschedule timeout\n");
      GNUNET_SCHEDULER_cancel (disconnect_task);
      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
                                                      &gather_stats_and_exit,
                                                      (void *) __LINE__);
    }
  }

  switch (client)
  {
  case 0L:
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
    GNUNET_assert (channel == ch);
    pth = &th;
    break;
  case 1L:
  case 4L:
    GNUNET_assert (client == peers_requested - 1);
    GNUNET_assert (channel == incoming_ch);
    pth = &incoming_th;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client %ld got a message.\n",
                client);
    break;
  default:
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Client %ld not valid.\n", client);
    GNUNET_assert (0);
  }
  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
  data = (uint32_t *) &message[1];
  payload = ntohl (*data);
  if (payload == counter)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload);
  }
  else
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " payload %u, expected: %u\n",
                payload, counter);
  }
  expected_target_client = get_expected_target ();

  if (GNUNET_NO == initialized)
  {
    initialized = GNUNET_YES;
    start_time = GNUNET_TIME_absolute_get ();
    if (SPEED == test)
    {
      GNUNET_assert (peers_requested - 1 == client);
      data_job = GNUNET_SCHEDULER_add_now (&data_task, NULL);
      return GNUNET_OK;
    }
  }

  counter++;
  if (client == expected_target_client) /* Normally 4 */
  {
    data_received++;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
    if (SPEED != test || (ok_goal - 2) == ok)
    {
      /* Send ACK */
      GNUNET_assert (NULL == *pth);
      *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
                                                 GNUNET_TIME_UNIT_FOREVER_REL,
                                                 size_payload + ack_sent,
                                                 &tmt_rdy, (void *) client);
      return GNUNET_OK;
    }
    else
    {
      if (data_received < TOTAL_PACKETS)
        return GNUNET_OK;
    }
  }
  else /* Normally 0 */
  {
    if (SPEED_ACK == test || SPEED == test)
    {
      ack_received++;
      GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
      /* send more data */
      GNUNET_assert (NULL == *pth);
      *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
                                                 GNUNET_TIME_UNIT_FOREVER_REL,
                                                 size_payload + data_sent,
                                                 &tmt_rdy, (void *) client);
      if (ack_received < TOTAL_PACKETS && SPEED != test)
        return GNUNET_OK;
      if (ok == 2 && SPEED == test)
        return GNUNET_OK;
      show_end_data();
    }
    if (test == P2P_SIGNAL)
    {
      if (NULL != incoming_th)
      {
        GNUNET_CADET_notify_transmit_ready_cancel (incoming_th);
        incoming_th = NULL;
      }
      GNUNET_CADET_channel_destroy (incoming_ch);
      incoming_ch = NULL;
    }
    else
    {
      if (NULL != th)
      {
        GNUNET_CADET_notify_transmit_ready_cancel (th);
        th = NULL;
      }
      GNUNET_CADET_channel_destroy (ch);
      ch = NULL;
    }
  }

  return GNUNET_OK;
}