gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

testing_core_cmd_send.c (6814B)


      1 /*
      2       This file is part of GNUnet
      3       Copyright (C) 2024 GNUnet e.V.
      4 
      5       GNUnet is free software: you can redistribute it and/or modify it
      6       under the terms of the GNU Affero General Public License as published
      7       by the Free Software Foundation, either version 3 of the License,
      8       or (at your option) any later version.
      9 
     10       GNUnet is distributed in the hope that it will be useful, but
     11       WITHOUT ANY WARRANTY; without even the implied warranty of
     12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13       Affero General Public License for more details.
     14 
     15       You should have received a copy of the GNU Affero General Public License
     16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18      SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 
     21 /**
     22  * @file src/service/core/testing_core_send.c
     23  * @brief a function to send messages to another peer
     24  * @author ch3
     25  */
     26 
     27 #include "platform.h"
     28 #include "gnunet_util_lib.h"
     29 #include "gnunet_testing_lib.h"
     30 #include "gnunet_core_service.h"
     31 #include "gnunet_testing_core_lib.h"
     32 
     33 
     34 /**
     35  * @brief Generic logging shortcut
     36  */
     37 #define LOG(kind, ...) \
     38         GNUNET_log_from (kind, "testing-core-send", __VA_ARGS__)
     39 
     40 
     41 static void *
     42 connect_cb (void *cls,
     43             const struct GNUNET_PeerIdentity *peer_id,
     44             struct GNUNET_MQ_Handle *mq);
     45 
     46 
     47 struct SendState
     48 {
     49   struct GNUNET_TESTING_CORE_ConnectState *connect_state;
     50   uint64_t num_messages;
     51   enum GNUNET_GenericReturnValue await_new_connection;
     52 };
     53 
     54 
     55 static void
     56 cleanup_callbacks (struct SendState *send_state)
     57 {
     58   struct GNUNET_TESTING_CORE_ConnectState *connect_state =
     59     send_state->connect_state;
     60   struct GNUNET_TESTING_CORE_ConnectCb *connect_cb_iter;
     61 
     62   for (uint64_t i = 0; i < connect_state->connect_cbs_len; i++)
     63   {
     64     connect_cb_iter = &connect_state->connect_cbs[i];
     65     if (connect_cb == connect_cb_iter->callback)
     66     {
     67       /* remove the callback */
     68       GNUNET_memcpy (connect_cb_iter,
     69                      connect_cb_iter + 1,
     70                      (connect_state->connect_cbs_len - i - 1)
     71                      * sizeof (struct GNUNET_TESTING_CORE_ConnectCb));
     72       GNUNET_array_grow (connect_state->connect_cbs,
     73                          connect_state->connect_cbs_len,
     74                          connect_state->connect_cbs_len - 1);
     75       // FIXME the following seems to be a double free, but I currently don't
     76       // know where the other free should be
     77       // GNUNET_free (connect_cb_iter);
     78     }
     79   }
     80 }
     81 
     82 
     83 static void
     84 send_messages (struct SendState *send_state)
     85 {
     86   const struct GNUNET_TESTING_CORE_ConnectState *connect_state =
     87     send_state->connect_state;
     88   struct GNUNET_MQ_Envelope *env;
     89   struct GNUNET_TESTING_CORE_Message *msg;
     90   struct GNUNET_TESTING_CORE_Channel *channel_iter;
     91   uint64_t channel_index = 0;
     92 
     93   LOG (GNUNET_ERROR_TYPE_DEBUG,
     94        "Going to send %" PRIu64 " messages\n",
     95        send_state->num_messages);
     96   GNUNET_assert (NULL != connect_state->channels_head);
     97   /* For now send on all available channels as we don't know at this stage
     98    * which is an usable channel - this should be fine as the unusable channel
     99    * will (probably) be discovered and cleaned up in the process. */
    100   for (channel_iter = connect_state->channels_head;
    101        NULL != channel_iter;
    102        channel_iter = channel_iter->next)
    103   {
    104     for (uint64_t i = 0; i < send_state->num_messages; i++)
    105     {
    106       LOG (GNUNET_ERROR_TYPE_DEBUG,
    107            "Going to send message (type %u) %" PRIu64 ", %s (channel %" PRIu64
    108            ") to %s\n",
    109            MTYPE,
    110            i,
    111            connect_state->node_id,
    112            channel_index,
    113            GNUNET_i2s (&channel_iter->peer_id));
    114       env = GNUNET_MQ_msg (msg, MTYPE); // usually we wanted to keep the
    115                                         // envelopes to potentially cancel the
    116                                         // message
    117       msg->id = GNUNET_htonll (i);
    118       msg->batch = GNUNET_htonll (channel_index);
    119       GNUNET_memcpy (msg->node_id, connect_state->node_id, NODE_ID_LEN);
    120       GNUNET_MQ_send (channel_iter->mq, env);
    121       LOG (GNUNET_ERROR_TYPE_DEBUG,
    122            "Sent message %" PRIu64 " (channel %" PRIu64 ")\n",
    123            i,
    124            channel_index);
    125     }
    126     channel_index++;
    127   }
    128   LOG (GNUNET_ERROR_TYPE_DEBUG, "Sent messages\n");
    129 
    130   cleanup_callbacks (send_state);
    131   GNUNET_free (send_state);
    132 }
    133 
    134 
    135 static void *
    136 connect_cb (
    137   void *cls,
    138   const struct GNUNET_PeerIdentity *peer_id,
    139   struct GNUNET_MQ_Handle *mq)
    140 {
    141   struct SendState *send_state = cls;
    142 
    143   send_messages (send_state);
    144   // FIXME this returns something but the calling function discards the
    145   // returned value anyways
    146   return NULL;
    147 }
    148 
    149 
    150 static void
    151 exec_send_run (void *cls,
    152                struct GNUNET_TESTING_Interpreter *is)
    153 {
    154   struct SendState *send_state = cls;
    155   struct GNUNET_TESTING_CORE_ConnectState *connect_state;
    156 
    157   // TODO make the "connect" label an input to the command
    158   if (GNUNET_OK != GNUNET_CORE_TESTING_get_trait_connect (
    159         GNUNET_TESTING_interpreter_lookup_command (is, "connect"),
    160         &connect_state))
    161   {
    162     GNUNET_assert (0);
    163   }
    164   ;
    165   send_state->connect_state = connect_state;
    166 
    167   LOG (GNUNET_ERROR_TYPE_DEBUG, "Going to (register to) send messages\n");
    168 
    169   if ((NULL != connect_state->channels_head) &&
    170       (GNUNET_NO == send_state->await_new_connection))
    171   {
    172     /* We are connected to a peer - send messages */
    173     send_messages (send_state);
    174   }
    175   else
    176   {
    177     /* We are not connected yet - subscribe via callback */
    178     // FIXME is the following ok?
    179     struct GNUNET_TESTING_CORE_ConnectCb *connect_cb_struct =
    180       GNUNET_new (struct GNUNET_TESTING_CORE_ConnectCb);
    181     LOG (GNUNET_ERROR_TYPE_DEBUG,
    182          "Registering our connect callback with the connect callbacks\n");
    183     connect_cb_struct->callback = connect_cb;
    184     connect_cb_struct->cls = send_state;
    185     GNUNET_array_append (connect_state->connect_cbs,
    186                          connect_state->connect_cbs_len,
    187                          *connect_cb_struct);
    188   }
    189 }
    190 
    191 
    192 static void
    193 exec_send_cleanup (void *cls)
    194 {
    195   // struct GNUNET_TESTING_CORE_ConnectState *connect_state = cls;
    196 
    197 }
    198 
    199 
    200 // TODO add a AWAIT_NEW_CONNECTION flag
    201 const struct GNUNET_TESTING_Command
    202 GNUNET_TESTING_CORE_cmd_send (
    203   const char *label,
    204   uint64_t num_messages,
    205   enum GNUNET_GenericReturnValue await_new_connection)
    206 {
    207   struct SendState *send_state;
    208 
    209   // TODO make struct static global?
    210   send_state = GNUNET_new (struct SendState);
    211   send_state->num_messages = num_messages;
    212   send_state->await_new_connection = await_new_connection;
    213   LOG (GNUNET_ERROR_TYPE_DEBUG, "(Setting up _cmd_send)\n");
    214   return GNUNET_TESTING_command_new (
    215     send_state,   // state
    216     label,
    217     &exec_send_run,
    218     &exec_send_cleanup,
    219     NULL);
    220 }
    221 
    222 
    223 /* end of src/service/core/testing_core_recv.c */