Wiselib
wiselib.testing/algorithms/gke/keylevels_main.h
Go to the documentation of this file.
00001 #ifndef _KEYLEVELS_MAIN_H
00002 #define _KEYLEVELS_MAIN_H
00003 
00004 // maximal connectivity (key-wise) that can be reached by a node
00005 #define NODES_MAX 50
00006 
00007 #define WAIT_FOR_ROUTING 20000
00008 
00009 #include "util/serialization/simple_types.h"
00010 #include "util/base_classes/radio_base.h"
00011 
00012 #include "keylevels_message.h"
00013 #include "keylevels_share.h"
00014 #include "ttl_flooding.h"
00015 
00016 namespace wiselib {
00017 
00018 template<typename OsModel_P,
00019       typename Radio_P,
00020       typename Routing_P,
00021       typename Crypto_P,
00022       typename Clustering_P,
00023       typename Debug_P = typename OsModel_P::Debug,
00024       typename Timer_P = typename OsModel_P::Timer,
00025       typename Random_P = typename OsModel_P::Rand>
00026 class Keylevels: public RadioBase<OsModel_P, typename Radio_P::node_id_t,
00027       typename Radio_P::size_t, typename Radio_P::block_data_t> {
00028 public:
00029    typedef OsModel_P OsModel;
00030    typedef Radio_P Radio;
00031    typedef Routing_P Routing;
00032    typedef Crypto_P Crypto;
00033    typedef Debug_P Debug;
00034    typedef Timer_P Timer;
00035    typedef Random_P Random;
00036    typedef Clustering_P Clustering;
00037 
00038    typedef Keylevels<OsModel, Radio, Routing, Crypto, Clustering, Debug, Timer, Random> self_type;
00039    typedef self_type* self_pointer_t;
00040 
00041    typedef typename Radio::node_id_t node_id_t;
00042    typedef typename Radio::size_t size_t;
00043    typedef typename Radio::block_data_t block_data_t;
00044    typedef typename Radio::message_id_t message_id_t;
00045 
00046    typedef KeylevelsMessage<OsModel, Radio> KeylevelMessage;
00047 
00048    typedef KeyShare<OsModel, Radio> keyshare_t;
00049    typedef TTLFlooding<OsModel, Radio, Debug, NODES_MAX> radio_ttl_t;
00050 
00051    enum ReturnValues {
00052       SUCCESS = OsModel::SUCCESS
00053    };
00054 
00055    Keylevels() 
00056    {
00057       keyOfferMsgCnt_in  = 0;
00058       keyOfferMsgCnt_out = 0;
00059       groupKeyMsgCnt_in  = 0; 
00060       groupKeyMsgCnt_out = 0;
00061       neighborMsgCnt_in  = 0;
00062       neighborMsgCnt_out = 0;
00063    }
00064 
00065    int init(Radio& radio, Routing& routing, Crypto& crypto, Clustering& clustering, Debug& debug,
00066          Timer& timer, Random& random) {
00067       radio_ = &radio;
00068       routing_ = &routing;
00069       crypto_ = &crypto;
00070       debug_ = &debug;
00071       timer_ = &timer;
00072       random_ = &random;
00073       clustering_ = &clustering;
00074       if ( clustering_->cluster_head() )
00075       {
00076          debug_->debug("[KL] {%d} leader\n", radio_->id());
00077          group_key_.leader_init(random_);
00078       }
00079       else
00080       {
00081          debug_->debug("[KL] {%d} not a leader\n", radio_->id());
00082          group_key_.init(random_);
00083       }
00084 
00085       keyshare_.init(*radio_, *debug_, *random_);
00086 
00087 #ifdef KEYLEVELS_DEBUG
00088       keyshare_.listKeyshare();
00089 #endif
00090 
00091       routing_->template reg_recv_callback<self_type,
00092             &self_type::message_received> (this);
00093 
00094       /*
00095        *  PTB: odkomentuj init_ttl_op() zakomentuj timer_-> ... zeby wylaczyc czekanie na sasiadow
00096        */
00097 /*
00098       have_neighbors = true;
00099       timer_->template set_timer<self_type,
00100             &self_type::init_ttl_op> (10, this, 0);
00101 */
00102       timer_->template set_timer<self_type,
00103             &self_type::start_neighbor_seek_init> (10, this, 0);
00104 
00105       return SUCCESS;
00106    }
00107 
00108 
00109    /* prepare neighborhood discovery */
00110    void start_neighbor_seek_init(void*) {
00111       have_neighbors = false;
00112       radio_->template reg_recv_callback<self_type, &self_type::neighbor_message_received> (this);
00113       start_neighbor_seek(this);
00114    }
00115 
00116    void neighbor_message_received(node_id_t from, size_t size,
00117          block_data_t* data) {
00118       KeylevelMessage* message = (KeylevelMessage *) data;
00119       show_keylevels_message(message,0);
00120       if (message->message_type() == NEIGHBORHOOD_ACK) {
00121 #ifdef KEYLEVELS_DEBUG
00122          debug_->debug("[KL] {%d} received NEIGHBORHOOD_ACK from %d\n", radio_->id(), from);
00123 #endif
00124          // counting ---------------------------------------------
00125          neighborMsgCnt_in++;
00126          if (have_neighbors) {
00127             return;
00128          }
00129          have_neighbors = true;
00130          init_ttl_op();
00131       } else if (message->message_type() == NEIGHBORHOOD_SEEK) {
00132          if (from != radio_->id()) {
00133 #ifdef KEYLEVELS_DEBUG
00134             debug_->debug("[KL] {%d} sending NEIGHBORHOOD_ACK to %d\n", radio_->id(), from);
00135 #endif
00136             KeylevelMessage msg;
00137             msg.set_message_type(NEIGHBORHOOD_ACK);
00138             msg.set_source(radio_->id());
00139             msg.set_destination(from);
00140             msg.set_payload(0, NULL);
00141             show_keylevels_message(&msg, 1);
00142             radio_->send(from, msg.buffer_size(), (block_data_t*) &msg);
00143             // counting ---------------------------------------------
00144             neighborMsgCnt_out++;
00145             if (have_neighbors) {
00146                return;
00147             }
00148             have_neighbors = true;
00149             init_ttl_op();
00150          }
00151       }
00152    }
00153 
00154    /* do neighbor discovery */
00155    void start_neighbor_seek(void*)
00156    {
00157       if (have_neighbors) { return; } // okay, we've already got someone to talk to
00158 
00159       /* prepare neighbor seek message and send it; go to sleep waiting for response */
00160 #ifdef KEYLEVELS_DEBUG
00161       debug_->debug("[KL] {%d} broadcasting NEIGHBORHOOD_SEEK\n", radio_->id());
00162 #endif
00163       KeylevelMessage message;
00164       message.set_message_type(NEIGHBORHOOD_SEEK);
00165       message.set_source(radio_->id());
00166       message.set_destination(radio_->BROADCAST_ADDRESS);
00167       message.set_payload(0, NULL);
00168       show_keylevels_message(&message,1);
00169       radio_->send(radio_->BROADCAST_ADDRESS, message.buffer_size(),(block_data_t*) &message);
00170       // counting ---------------------------------------------
00171       neighborMsgCnt_out++;
00172       timer_->template set_timer<self_type, &self_type::start_neighbor_seek> (
00173             15000, this, 0);
00174    }
00175 
00176    void init_ttl_op()
00177    { 
00178       // PTB: added launching via timer 
00179       //init_ttl_op(NULL); 
00180       timer_->template set_timer<self_type, &self_type::init_ttl_op> ( 5, this, 0 );
00181    }
00182 
00183    /* run this after a neighbor is found */
00184    void init_ttl_op(void*)
00185    {
00186       ttl_.init(*radio_, *debug_);
00187       ttl_.set_notify_all_on_path(true);
00188       ttl_.enable_radio();
00189       ttl_.template reg_recv_callback<self_type,
00190             &self_type::key_offer_received> (this);
00191       timer_->template set_timer<self_type, &self_type::seek_for_group_key> (
00192             WAIT_FOR_ROUTING, this, 0);
00193    }
00194 
00195    void seek_for_group_key(void*)
00196    {
00197       if (!group_key_found())
00198       {
00199          increase_seek_ttl();
00200 
00201 #ifdef KEYLEVELS_DEBUG
00202          debug_->debug("[KL] {%d} seeking for group key with TTL = %d\n", radio_->id(), ttl_.get_ttl());
00203 #endif
00204 
00205          broadcast_all_keys_with_ttl();
00206 
00207          timer_->template set_timer<self_type,
00208                &self_type::seek_for_group_key> (
00209                get_current_seek_timeout(), this, 0);
00210       }
00211    }
00212 
00213    group_key* get_group_key()
00214    {
00215       if (group_key_.have_key)
00216          return &group_key_;
00217 
00218       return NULL;
00219    }
00220 
00221    inline int get_current_seek_timeout()
00222    {
00223       return (3 * get_current_ttl() * 1000) + 2000;
00224    }
00225 
00226    inline int get_current_ttl()
00227    {
00228       return ttl_.get_ttl();
00229    }
00230 
00231    inline void increase_seek_ttl()
00232    {
00233       return ttl_.set_ttl(ttl_.get_ttl() + 1);
00234    }
00235 
00236    inline bool group_key_found()
00237    {
00238       return group_key_.have_key;
00239    }
00240 
00241    void enable_radio() {   radio_->enable_radio();    }
00242 
00243    void disable_radio()
00244    { }
00245 
00246    void broadcast_all_keys_with_ttl()
00247    {
00248       for (unsigned int i = 0; i < keyshare_.get_keyshare_size(); ++i)
00249       {
00250          key_info x;
00251          x.key_index = keyshare_.keyshare[i].key_index;
00252          x.key_level = keyshare_.keyshare[i].key_level;
00253          ttl_.send(1000 * ttl_.get_ttl() + 100 * radio_->id() + x.key_index,
00254                sizeof(key_info), (block_data_t*) &x);
00255          // counting ---------------------------------------------
00256          keyOfferMsgCnt_out++;
00257 #ifdef KEYLEVELS_DEBUG
00258          debug_->debug("[KL] {%d} sending key offer (%d,%d) with MSG_ID = %d\n", 
00259                radio_->id(), 
00260                x.key_index, 
00261                x.key_level, 
00262                1000*ttl_.get_ttl()+100*radio_->id()+x.key_index
00263                  );
00264 #endif
00265       }
00266    }
00267 
00268    void send_group_key_to_all_trusted_neighbors()
00269    {
00270       for (node_id_t i = 0; i < NODES_MAX; i++)
00271       {
00272          key* pairwise_key = keyshare_.get_key_info(i);
00273 
00274          if (pairwise_key != NULL)
00275          {
00276             //TODO this can return false if no route to $i'th node available
00277             send_group_key(i);
00278             // counting ---------------------------------------------
00279             groupKeyMsgCnt_out++;
00280          }
00281       }
00282    }
00283 
00284    /* builds a KEY_ACK message and tries to send it to $receiver
00285     * @return true if message was properly routed
00286     *          false if routing does not reach $receiver
00287     */
00288    bool send_key_ack(node_id_t receiver, key_info* key_info)
00289    {
00290 #ifdef KEYLEVELS_DEBUG
00291       debug_->debug("[KL] {%d} sending ACK (%d,%d) to node %d\n", 
00292             radio_->id(), 
00293             key_info->key_index, 
00294             key_info->key_level, 
00295             receiver
00296               );
00297 #endif
00298 
00299       KeylevelMessage message;
00300       message.set_message_type(KEY_ACK);
00301       message.set_source(radio_->id());
00302       message.set_destination(receiver);
00303       message.set_payload(sizeof(key_info), (block_data_t*) key_info);
00304       show_keylevels_message(&message,1);
00305 
00306       // check if we can route msg to $receiver
00307       if(Routing::SUCCESS != routing_->send(receiver, message.buffer_size(),
00308             (block_data_t*) &message))
00309          return false;
00310       // counting ---------------------------------------------
00311       keyOfferMsgCnt_out++;
00312       return true;
00313    }
00314 
00315    bool send_group_key(node_id_t receiver)
00316    {
00317 #ifdef KEYLEVELS_DEBUG
00318       debug_->debug("[KL] {%d} sending group key to node %d\n", radio_->id(), receiver);
00319 #endif
00320 
00321       KeylevelMessage message;
00322       message.set_message_type(GROUP_KEY);
00323       message.set_source(radio_->id());
00324       message.set_destination(receiver);
00325       uint8_t enc_key_data[GROUP_KEY_SIZE];
00326       crypto_->enable();
00327       crypto_->key_setup(SMALL_KEY_SIZE * 8,
00328             keyshare_.get_key_info(receiver)->key_value);
00329       crypto_->encrypt(group_key_.key_data, enc_key_data);
00330       message.set_payload(sizeof(enc_key_data),(block_data_t*) (enc_key_data));
00331       show_keylevels_message(&message,1);
00332       if(Routing::SUCCESS != routing_->send(receiver, message.buffer_size(),(block_data_t*) &message))
00333       {
00334          return false;
00335       }
00336       // counting ---------------------------------------------
00337       groupKeyMsgCnt_out++;
00338       return true;
00339    }
00340 
00341    void message_received(node_id_t from, size_t size, block_data_t* data)
00342    {
00343       KeylevelMessage* message = (KeylevelMessage *) data;
00344       show_keylevels_message(message,0);
00345       if (message->message_type() == KEY_ACK)
00346       {
00347 #ifdef KEYLEVELS_DEBUG
00348          debug_->debug("[KL] {%d} received KEY_ACK from %d\n", radio_->id(), from);
00349 #endif
00350          // counting ---------------------------------------------
00351          keyOfferMsgCnt_in++;
00352          key_info* key_ack = (key_info*) message->payload();
00353          key k;
00354          k.key_index = key_ack->key_index;
00355          memcpy(k.key_value,
00356                keyshare_.get_key(key_ack->key_index)->key_value,
00357                SMALL_KEY_SIZE);
00358          int ld = key_ack->key_level
00359                - keyshare_.get_key(key_ack->key_index)->key_level;
00360          if (ld >= 0)
00361          {
00362             k.key_level = key_ack->key_level;
00363             for (int i = 0; i < ld; i++)
00364                keyshare_.variation_on_SDBMHash(k.key_value, SMALL_KEY_SIZE);
00365          }
00366          else
00367          {
00368             k.key_level = keyshare_.get_key(key_ack->key_index)->key_level;
00369          }
00370          store_new_trusted_link(from, &k);
00371 
00372       }
00373       else if (message->message_type() == GROUP_KEY)
00374       {
00375 #ifdef KEYLEVELS_DEBUG
00376          debug_->debug("[KL] {%d} received GROUP_KEY message from %d: ", radio_->id(), from);
00377 #endif
00378          // counting ---------------------------------------------
00379          groupKeyMsgCnt_in++;
00380          uint8_t dec_key_data[SMALL_KEY_SIZE];
00381          uint8_t* enc_key_data;
00382          enc_key_data = (uint8_t*) message->payload();
00383          crypto_->enable();
00384          crypto_->key_setup(SMALL_KEY_SIZE * 8,
00385                (uint8_t*) keyshare_.get_key_info(from)->key_value);
00386 
00387          crypto_->decrypt(enc_key_data, dec_key_data);
00388 
00389          if (!group_key_.have_key)
00390          {
00391             group_key_.set_key(dec_key_data);
00392 #ifdef KEYLEVELS_DEBUG
00393             print_key_value(group_key_.key_data, GROUP_KEY_SIZE);
00394 #endif
00395             send_group_key_to_all_trusted_neighbors();
00396 
00397             notify_receivers(0, (size_t) GROUP_KEY_SIZE,
00398                   (block_data_t*) &(group_key_.key_data));
00399          }
00400       }
00401       else
00402       {
00403 #ifdef KEYLEVELS_DEBUG
00404          debug_->debug("[KL] {%d} message_received: received UNKNOWN message from %d\n", 
00405                   radio_->id(), 
00406                   from);
00407 #endif
00408       }
00409    }
00410 
00411    void key_offer_received(node_id_t from, size_t size, block_data_t* data)
00412    {
00413 #ifdef KEYLEVELS_DEBUG
00414       debug_->debug("[KL] {%d} received key offer from Node %d", radio_->id(), from);
00415 #endif
00416       // counting ---------------------------------------------
00417       keyOfferMsgCnt_in++;
00418       key_info key_offer_o, *key_offer;
00419       key_offer = &key_offer_o;
00420       memcpy(key_offer, data, size);
00421 
00422       if (keyshare_.owns_key(key_offer->key_index))
00423       {
00424 #ifdef KEYLEVELS_DEBUG
00425          debug_->debug("[KL] {%d} found common key with Node %d (%d,%d):(%d,%d)\n",
00426                radio_->id(),
00427                from,
00428                keyshare_.get_key(key_offer->key_index)->key_index,
00429                keyshare_.get_key(key_offer->key_index)->key_level,
00430                key_offer->key_index,
00431                key_offer->key_level
00432                );
00433 #endif
00434          key k;
00435          k.key_index = key_offer->key_index;
00436          memcpy(k.key_value,
00437                keyshare_.get_key(key_offer->key_index)->key_value,
00438                SMALL_KEY_SIZE);
00439          int ld = key_offer->key_level - keyshare_.get_key(
00440                key_offer->key_index)->key_level;
00441          if (ld >= 0)
00442          {
00443             k.key_level = key_offer->key_level;
00444             for (int i = 0; i < ld; i++)
00445             {
00446                keyshare_.variation_on_SDBMHash(k.key_value, SMALL_KEY_SIZE);
00447             }
00448          }
00449          else
00450          {
00451             k.key_level = keyshare_.get_key(key_offer->key_index)->key_level;
00452          }
00453          key_info key_ack;
00454          key_ack.key_index = k.key_index;
00455          key_ack.key_level = k.key_level;
00456          // check if sending ACK is possible, abort if not [PTB]
00457          if(!send_key_ack(from, &key_ack))
00458          {
00459             return;
00460          }
00461          // okay, ACK sent, assume we have link with $from [PTB]
00462          store_new_trusted_link(from, &k);
00463          if (group_key_found())
00464          {
00465             //TODO this can return false if no route to $from available [PTB]
00466             if(!send_group_key(from))
00467             { }
00468          }
00469       }
00470    }
00471 
00472    void store_new_trusted_link(node_id_t node, key* key)
00473    {
00474       if (!keyshare_.trusted_link_exists(node))
00475       {
00476 #ifdef KEYLEVELS_DEBUG
00477          debug_->debug("[KL] {%d} established new secure link with Node %d\n", radio_->id(), node);
00478 #endif
00479          keyshare_.put_trusted_link(node, *key);
00480       }
00481       else
00482       {
00483          if (key->key_index < keyshare_.get_key_info(node)->key_index)
00484          {
00485             keyshare_.put_trusted_link(node, *key);
00486          }
00487       }
00488    }
00489 
00490    void print_key_value(uint8_t* value, uint8_t size)
00491    {
00492       for (int i = 0; i < size; i++)
00493       {
00494          debug_->debug("%d:", value[i]);
00495       }
00496       debug_->debug("\n");
00497    }
00498 
00499    void print_all_key_info(key* k)
00500    {
00501       debug_->debug("[KL] {%d} KEY: (%d,%d) ", radio_->id(), k->key_index, k->key_level);
00502       print_key_value(k->key_value, SMALL_KEY_SIZE);
00503    }
00504 
00505    void show_keylevels_message(KeylevelMessage* msg, int dir)
00506    {
00507 #ifndef KL_EXTREME
00508       return;
00509 #endif
00510       uint8_t* temp = (uint8_t*) msg;
00511       if(dir)
00512          debug_->debug("[KL] {%d} outgoing kl message[0]: [%d]", radio_->id(), temp[0]);
00513       else
00514          debug_->debug("[KL] {%d} incoming kl message[0]: [%d]", radio_->id(), temp[0]);
00515       return;
00516 
00517       debug_->debug("[");
00518       int i=0;
00519       for(i=0;i<msg->buffer_size();i++){
00520          debug_->debug("%d, ",temp[i]);
00521       }
00522       debug_->debug("]");
00523    }
00524    // --------- access functions for stat fields [PTB] -----------------------------
00525    int getNeighMsgCnt_in()    { return neighborMsgCnt_in; }
00526    int getNeighMsgCnt_out()   { return neighborMsgCnt_out; }
00527    int getKeyOfferMsgCnt_in() { return keyOfferMsgCnt_in; }
00528    int getKeyOfferMsgCnt_out(){ return keyOfferMsgCnt_out; }
00529    int getGroupKeyMsgCnt_in() { return groupKeyMsgCnt_in; }
00530    int getGroupKeyMsgCnt_out(){ return groupKeyMsgCnt_out; }
00531 
00532 private:
00533    typename Radio::self_pointer_t radio_;
00534    typename Debug::self_pointer_t debug_;
00535    typename Timer::self_pointer_t timer_;
00536    typename Routing::self_pointer_t routing_;
00537    typename Random::self_pointer_t random_;
00538 
00539    keyshare_t keyshare_;
00540    group_key group_key_;
00541    Crypto* crypto_;
00542    Clustering* clustering_;
00543 
00544    radio_ttl_t ttl_;
00545 
00546    bool have_neighbors;
00547    //------------ fields for stats [PTB] -------------------------------------------
00548    int neighborMsgCnt_in, neighborMsgCnt_out;   // messages for seeking neighbors
00549    int keyOfferMsgCnt_in, keyOfferMsgCnt_out;   // messages with key offer
00550    int groupKeyMsgCnt_in, groupKeyMsgCnt_out;   // messages referring to groupkey
00551 };
00552 
00553 } /* namespace wiselib */
00554 
00555 #endif  /* _KEYLEVELS_MAIN_H  */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines