Beispiel #1
0
 /**
  * Add friend by retreiving certificate from DHT.
  * @param key the DHT key for friend's certificate.
  * @param access determines to give user network access.
  */
 public void AddDhtFriend(string key, bool access)
 {
     if(key != _local_user.DhtKey && !_friends.ContainsKey(key) &&
      key.Length >= 45 ) {
     ProtocolLog.WriteIf(SocialLog.SVPNLog,
                     String.Format("ADD DHT FETCH: {0} {1}",
                     DateTime.Now.TimeOfDay, key));
     Channel q = new Channel();
     q.CloseAfterEnqueue();
     q.CloseEvent += delegate(Object o, EventArgs eargs) {
       try {
     Hashtable result = (Hashtable) q.Dequeue();
     byte[] certData = (byte[]) result["value"];
     string tmp_key = SocialUtils.GetHashString(certData);
     tmp_key = SocialUser.DHTPREFIX + tmp_key;
     if(key == tmp_key) {
       ProtocolLog.WriteIf(SocialLog.SVPNLog,
                           String.Format("ADD DHT SUCCESS: {0} {1}",
                           DateTime.Now.TimeOfDay, key));
       if(access) {
         _queue.Enqueue(new QueueItem(
                        QueueItem.Actions.AddCertTrue, certData));
       }
       else {
         _queue.Enqueue(new QueueItem(
                        QueueItem.Actions.AddCertFalse, certData));
       }
     }
       } catch (Exception e) {
     ProtocolLog.WriteIf(SocialLog.SVPNLog,e.Message);
     ProtocolLog.WriteIf(SocialLog.SVPNLog,
                         String.Format("ADD DHT FAILURE: {0} {1}",
                         DateTime.Now.TimeOfDay, key));
       }
     };
     byte[] key_bytes = Encoding.UTF8.GetBytes(key);
     MemBlock keyb = MemBlock.Reference(key_bytes);
     this.Dht.AsyncGet(keyb, q);
       }
 }
Beispiel #2
0
        /**
         * Add local certificate to the DHT.
         */
        public void PublishCertificate()
        {
            byte[] key_bytes = Encoding.UTF8.GetBytes(_local_user.DhtKey);
              MemBlock keyb = MemBlock.Reference(key_bytes);
              MemBlock valueb = MemBlock.Reference(_local_cert.X509.RawData);

              Channel q = new Channel();
              q.CloseAfterEnqueue();
              q.CloseEvent += delegate(Object o, EventArgs eargs) {
            try {
              bool success = (bool) (q.Dequeue());
              if(success) {
            _cert_published = true;
            ProtocolLog.WriteIf(SocialLog.SVPNLog,
                                String.Format("PUBLISH CERT SUCCESS: {0} {1}",
                                DateTime.Now.TimeOfDay, _local_user.DhtKey));
              }
            } catch (Exception e) {
              ProtocolLog.WriteIf(SocialLog.SVPNLog,e.Message);
              ProtocolLog.WriteIf(SocialLog.SVPNLog,
                              String.Format("PUBLISH CERT FAILURE: {0} {1}",
                              DateTime.Now.TimeOfDay, _local_user.DhtKey));
            }
              };
              this.Dht.AsyncPut(keyb, valueb, DHTTTL, q);
        }
 protected void FriendPing(string address)
 {
     Address addr = AddressParser.Parse(address);
       Channel q = new Channel();
       q.CloseAfterEnqueue();
       q.CloseEvent += delegate(object obj, EventArgs eargs) {
     try {
       RpcResult res = (RpcResult) q.Dequeue();
       string result = (string) res.Result;
       string[] parts = result.Split(DELIM);
       string dht_key = parts[0];
       string response = parts[1];
       if(response == "online") {
     SocialUser friend = _friends[dht_key];
     friend.Time = DateTime.Now.ToString();
       }
       ProtocolLog.Write(SocialLog.SVPNLog, "PING FRIEND REPLY: " +
                     result);
     } catch(Exception e) {
       ProtocolLog.Write(SocialLog.SVPNLog, e.Message);
       ProtocolLog.Write(SocialLog.SVPNLog, "PING FRIEND FAILURE: " +
                     address);
     }
       };
       ISender sender = new AHExactSender(_node, addr);
       _rpc.Invoke(sender, q, "SocialVPN.FriendPing", _local_user.DhtKey);
 }
Beispiel #4
0
        /**
         * Add friend by retreiving certificate from DHT.
         * @param key the DHT key for friend's certificate.
         */
        public void AddDhtFriend(string key)
        {
            if(key == _local_user.DhtKey || _friends.ContainsKey(key)) {
            if(key != _local_user.DhtKey) {
              _srh.PingFriend(_friends[key]);
            }
            return;
              }

              Channel q = new Channel();
              q.CloseAfterEnqueue();
              q.CloseEvent += delegate(Object o, EventArgs eargs) {
            try {
              DhtGetResult dgr = (DhtGetResult) q.Dequeue();
              byte[] certData = dgr.value;
              AddCertificate(certData, key);
              ProtocolLog.Write(SocialLog.SVPNLog, "ADD DHT SUCCESS: " +
                            key);
            } catch (Exception e) {
              ProtocolLog.Write(SocialLog.SVPNLog,e.Message);
              ProtocolLog.Write(SocialLog.SVPNLog,"ADD DHT FAILURE: " +
                            key);
            }
              };
              this.Dht.AsGet(key, q);
        }
    public static void Main(string []args) {
      if (args.Length < 1) {
	Console.WriteLine("please specify the number edge protocol."); 
        Environment.Exit(0);
      }
      if (args.Length < 2) {
        Console.WriteLine("please specify the number of p2p nodes."); 
        Environment.Exit(0);
      }
      if (args.Length < 3) {
        Console.WriteLine("please specify the number of missing edges."); 
        Environment.Exit(0);
      }
      string proto = "function";
      try {
	proto = args[0].Trim();
      } catch(Exception) {}

      bool tunnel = false;
      int base_port = 54000;
      int network_size = Int32.Parse(args[1]);
      int missing_count = Int32.Parse(args[2]);
      try {
	tunnel = args[3].Trim().Equals("tunnel");
      } catch (Exception) {}

      Console.WriteLine("use tunnel edges: {0}", tunnel);

      Random rand = new Random();

      ArrayList missing_edges = new ArrayList();
      for (int i = 0; i < missing_count; i++) {
	int idx = -1;
	int left, right;
	do {
	  idx = rand.Next(0, network_size);
	  left = (idx + 1)%network_size;
	  if (idx == 0) {
	    right = network_size - 1;
	  } else {
	    right = idx - 1;
	  }
	} while (missing_edges.Contains(idx));// ||
	//missing_edges.Contains(left) ||
	//missing_edges.Contains(right));
	
	Console.WriteLine("Will drop a left edge on idx {0}: ", idx);
	missing_edges.Add(idx);
      }
      
      //
      // Sort missing edges.
      //
      missing_edges.Sort();
      SortedList dist = new SortedList();
      //
      // Compute the average distance between missing edges. 
      //
      if (missing_count > 1) {
	for (int i = 0; i < missing_count; i++) {
	  int idx = (int) missing_edges[i];
	  int idx_next;
	  int d;
	  if (i == missing_count - 1) {
	    idx_next = (int) missing_edges[0];
	    d = (network_size - 1) - idx + idx_next;
	  } else {
	    idx_next = (int) missing_edges[i+1];
	    d = idx_next - idx - 1;
	  }
	  if (!dist.Contains(d)) {
	    dist[d] = 0;
	  } else {
	    int c = (int) dist[d];
	    dist[d] = c + 1;
	  }
	}
      }
      double sum = 0.0;
      int num = 0;
      Console.WriteLine("distribution of missing edges separation");
      foreach(DictionaryEntry de in dist) {
	int k = (int) de.Key;
	int c = (int) de.Value;
	Console.WriteLine("{0} {1}", k, c);
	sum = sum + k*c;
	num = num + c;
      }

      Console.WriteLine("average separation: {0}", (double) sum/num);
      string brunet_namespace = "testing";
      Console.WriteLine("Initializing...");

      ArrayList RemoteTA = new ArrayList();
      for(int i = 0; i < network_size; i++) {
	if (proto.Equals("udp")) {
	  RemoteTA.Add(TransportAddressFactory.CreateInstance("brunet.udp://localhost:" + (base_port + i)));
	} else if (proto.Equals("function")) { 
	  RemoteTA.Add(TransportAddressFactory.CreateInstance("brunet.function://localhost:" + (base_port + i)));
	}
      }

      for(int i = 0; i < network_size; i++) {
        AHAddress address = new AHAddress(new RNGCryptoServiceProvider());
        Node node = new StructuredNode(address, brunet_namespace);
        _sorted_node_list.Add((Address) address, node);
	_node_list.Add(node);
	RouteTestHandler test_handler = new RouteTestHandler();
	node.GetTypeSource(new PType(routing_test)).Subscribe(test_handler, address.ToMemBlock());
	RpcManager rpc_man = RpcManager.GetInstance(node);
	rpc_man.AddHandler("rpc_routing_test", new  RpcRoutingTestHandler(node));
      }

      for (int i = 0; i < network_size; i++) {
	Node node = (Node) _sorted_node_list.GetByIndex(i);
	Console.WriteLine("Configuring node: {0} ", node.Address);
	TAAuthorizer ta_auth = null;
	if (missing_edges.Contains(i)) {
	  int remote_port;
	  if (i == network_size - 1) {
	    remote_port = base_port;
	  } else {
	    remote_port = base_port + i + 1;
	  }

	  PortTAAuthorizer port_auth = new PortTAAuthorizer(remote_port);
	  Console.WriteLine("Adding a port TA authorizer at: {0} for remote port: {1}", base_port + i, remote_port);
	  ArrayList arr_tas = new ArrayList();
	  arr_tas.Add(port_auth);
	  arr_tas.Add(new ConstantAuthorizer(TAAuthorizer.Decision.Allow));
	  ta_auth = new SeriesTAAuthorizer(arr_tas);
	}
	
	if (proto.Equals("udp")) { 
	  node.AddEdgeListener(new UdpEdgeListener(base_port + i, null, ta_auth));
	} else if(proto.Equals("function")) {
	  node.AddEdgeListener(new FunctionEdgeListener(base_port + i, -1.00, ta_auth));
	}
	
	if (tunnel) {
	  Console.WriteLine("Adding a tunnel edge listener");
	  node.AddEdgeListener(new Tunnel.TunnelEdgeListener(node));
	}
	_node_to_port[node] = base_port + i;
        node.RemoteTAs = RemoteTA;	
      }

      //start nodes one by one.
      for (int i  = 0; i < network_size; i++) {
	Node node = (Node) _node_list[i];
	Console.WriteLine("Starting node: {0}, {1}", i, node.Address);
        node.Connect();
	Console.WriteLine("Going to sleep for 2 seconds.");
        System.Threading.Thread.Sleep(2000);
      }

      //wait for 300000 more seconds
      Console.WriteLine("Going to sleep for 300000 seconds.");
      System.Threading.Thread.Sleep(300000);
      bool complete = CheckStatus();

      int count = 0;
      //
      // Send a large number of packets as exact packets to random destinations
      // and make sure exact routing is perfect.
      //
      
      for (int i = 0; i < network_size; i++) {
	for (int j = 0; j < network_size; j++) {
	  
	  int src_idx = i;
	  int dest_idx = j;
	  Node src_node = (Node) _sorted_node_list.GetByIndex(src_idx);
	  Node dest_node = (Node) _sorted_node_list.GetByIndex(dest_idx);
	  //Console.WriteLine("{0} -> {1}", src_idx, dest_idx);
	  Address dest_address = (Address) dest_node.Address;
	  ISender s = new AHExactSender(src_node, dest_address);
	  MemBlock p = dest_address.ToMemBlock();
	  s.Send(new CopyList(new PType(routing_test), p));
	  _sent++;
	  //System.Threading.Thread.Sleep(10);
	  s.Send(new CopyList(new PType(routing_test), p));
	  _sent++;
	  //System.Threading.Thread.Sleep(10);
	}
      }
      //wait for 10 more seconds
      Console.WriteLine("Going to sleep for 10 seconds.");
      System.Threading.Thread.Sleep(10000);      
      Console.WriteLine("Final statistics");
      lock(_class_lock) {
	Console.WriteLine("Sent: {0}, Received: {1}, Wrongly routed: {2}", 
			  _sent, _received, _wrongly_routed);
      }

      int missing_rpcs = 0;
      int correct_rpcs = 0;
      int incorrect_rpcs = 0;
      Hashtable queue_to_address = new Hashtable();
      for (int i = 0; i < network_size; i++) {
	for (int j = 0; j < network_size; j++) {
	  
	  int src_idx = i;
	  int dest_idx = j;
	  Node src_node = (Node) _sorted_node_list.GetByIndex(src_idx);
	  Node dest_node = (Node) _sorted_node_list.GetByIndex(dest_idx);
	  //Console.WriteLine("{0} -> {1}", src_idx, dest_idx);
	  Address dest_address = (Address) dest_node.Address;
	  ISender s = new AHExactSender(src_node, dest_address);
	  RpcManager rpc_man = RpcManager.GetInstance(src_node);
	  Channel q = new Channel();
	  lock (_class_lock) {
	    queue_to_address[q] = dest_address;
	  }
	  q.CloseAfterEnqueue();
	  q.CloseEvent += delegate(object o, EventArgs cargs) {
	    lock(_class_lock) {
	      Channel qu = (Channel) o;
	      if (qu.Count == 0) {
		missing_rpcs++;
	      }
	      queue_to_address.Remove(qu);
	    }
	  };
	  q.EnqueueEvent += delegate(object o, EventArgs cargs) {
	    lock(_class_lock) {
	      Channel qu = (Channel) o;
	      RpcResult rpc_reply = (RpcResult) qu.Peek();
	      byte []result = (byte[]) rpc_reply.Result;
	      Address target = new AHAddress(result);
	      if (target.Equals(queue_to_address[qu])) {
		correct_rpcs++;
	      } else {
		incorrect_rpcs++;
	      }
	    }
	  };
	  rpc_man.Invoke(s, q, "rpc_routing_test.GetIdentification", new object[]{});
	}
      }
      
      //wait for 10 more seconds
      while (true) {
	int c = -1;
	lock(_class_lock) {
	  c = incorrect_rpcs + missing_rpcs + correct_rpcs;
	}
	if (c < network_size*network_size) {
	  Console.WriteLine("Going to sleep for 10 seconds.");
	  System.Threading.Thread.Sleep(10000);
	} else {
	  break;
	}
      }
      
      Console.WriteLine("Final statistics");
      Console.WriteLine("correct rpcs: {0}, incorrect rpcs: {1}, missing rpcs: {2}", 
			correct_rpcs, incorrect_rpcs, missing_rpcs);
      
      System.Environment.Exit(1);
    }
Beispiel #6
0
 /**
  * Recursive function to compute the latency of an Rpc call
  * by accumulating measured latencies of individual hops.
  * @param target address of the target
  */
 public void ComputePathLatencyTo(AHAddress a, object req_state) {
   /*
    * First find the Connection pointing to the node closest to dest, if
    * there is one closer than us
    */
   
   ConnectionTable tab = _node.ConnectionTable;
   ConnectionList structs = tab.GetConnections(ConnectionType.Structured);
   Connection next_closest = structs.GetNearestTo((AHAddress) _node.Address, a);
   //Okay, we have the next closest:
   ListDictionary my_entry = new ListDictionary();
   my_entry["node"] = _node.Address.ToString();
   if( next_closest != null ) {
     my_entry["next_latency"] = GetMeasuredLatency(next_closest.Address);
     my_entry["next_contype"] = next_closest.ConType;
     Channel result = new Channel();
     //We only want one result, so close the queue after we get the first
     result.CloseAfterEnqueue();
     result.CloseEvent += delegate(object o, EventArgs args) {
       Channel q = (Channel)o;
       if( q.Count > 0 ) {
         try {
           RpcResult rres = (RpcResult)q.Dequeue();
           IList l = (IList) rres.Result;
           ArrayList results = new ArrayList( l.Count + 1);
           results.Add(my_entry);
           results.AddRange(l);
           _rpc.SendResult(req_state, results);
         }
         catch(Exception x) {
           string m = String.Format("<node>{0}</node> trying <connection>{1}</connection> got <exception>{2}</exception>", _node.Address, next_closest, x);
           Exception nx = new Exception(m);
           _rpc.SendResult(req_state, nx);
         }
       }
         else {
           //We got no results.
           IList l = new ArrayList(1);
           l.Add( my_entry );
           _rpc.SendResult(req_state, l);
         }
     };
     _rpc.Invoke(next_closest.Edge, result, "ncserver.ComputePathLatencyTo", a.ToString());
   }
   else {
     //We are the end of the line, send the result:
     ArrayList l = new ArrayList();
     l.Add(my_entry);
     _rpc.SendResult(req_state, l);  
   }
 }
Beispiel #7
0
    /**
    <summary>This is the generic Put that is used by both the regular Put and
    Create methods.  The use of the unique variable differentiates the two.
    This is asynchronous.  Results are stored in the Channel returns.
    Creates and Puts return true if successful or exception if there are
    network errors in adding the entry, creates also fail if a previous
    entry exists.  The work of determining success is handled in
    PutEnqueueHandler and PutCloseHandler.</summary>
    <param name="key">The index to store the value at.</param>
    <param name="value">The value to store.</param>
    <param name="ttl">The dht lease time for the key:value pair.</param>
    <param name="returns">The Channel where the result will be placed.</param>
    <param name="unique">True to do a create, false otherwise.</param>
    */
    public void AsPut(MemBlock key, MemBlock value, int ttl, Channel returns, bool unique) {
      if (!Activated) {
        throw new Exception("DhtClient: Not yet activated.");
      }

      returns.CloseAfterEnqueue();
      AsDhtPutState adps = new AsDhtPutState(returns);

      MemBlock[] brunet_address_for_key = MapToRing(key);
      Channel[] q = new Channel[DEGREE];
      lock(_adps_table.SyncRoot) {
        for (int k = 0; k < DEGREE; k++) {
          Channel queue = new Channel();
          queue.CloseAfterEnqueue();
          queue.CloseEvent += this.PutCloseHandler;
          _adps_table[queue] = adps;
          q[k] = queue;
        }
      }

      for (int k = 0; k < DEGREE; k++) {
        Address target = new AHAddress(brunet_address_for_key[k]);
        AHSender s = new AHSender(node, target, AHPacket.AHOptions.Greedy);
        _rpc.Invoke(s, q[k], "dht.Put", brunet_address_for_key[k], value, ttl, unique);
      }
    }
      /**
      <summary>Begins a new transfer state to the neighbor connected via con.
      </summary>
      <param name="con">The connection to the neigbhor we will be transferring
      data to.</param>
      <param name="ts">The table server we're providing the transfer for.  C#
      does not allow sub-class objects to have access to their parent objects
      member variables, so we pass it in like this.</param>
      <remarks>
      Step 1:

      Get all the keys between me and my new neighbor.

      Step 2:

      Get all values for those keys, we copy so that we don't worry about
      changes to the dht during this interaction.  This is only a pointer
      copy and since we let the OS deal with removing the contents of an
      entry, we don't need to make copies of the actual entry.

      Step 3:

      Generate another list of keys of up to max parallel transfers and begin
      transferring, that way we do not need to lock access to the entry
      enumerator until non-constructor puts.

      Step 4:

      End constructor, results from puts, cause the next entry to be sent.
      */
      public TransferState(Connection con, TableServer ts) {
        this._ts = ts;
        this._con = con;
        // Get all keys between me and my new neighbor
        LinkedList<MemBlock> keys;
        lock(_ts._sync) {
          keys = _ts._data.GetKeysBetween((AHAddress) _ts._node.Address,
                                      (AHAddress) _con.Address);
        }
        if(Dht.DhtLog.Enabled) {
          ProtocolLog.Write(Dht.DhtLog, String.Format(
                            "Starting transfer from {0} to {1}", 
                            _ts._node.Address, _con.Address));
        }
        int total_entries = 0;
        /* Get all values for those keys, we copy so that we don't worry about
         * changes to the dht during this interaction.  This is only a pointer
         * copy and since we let the OS deal with removing the contents of an
         * entry, we don't need to make copies of the actual entry.
         */
        foreach(MemBlock key in keys) {
          Entry[] entries;
          lock(_ts._sync) {
            LinkedList<Entry> llentries = _ts._data.GetEntries(key);
            if(llentries == null) {
              continue;
            }
            entries = new Entry[llentries.Count];
            total_entries += llentries.Count;
            llentries.CopyTo(entries, 0);
          }
          key_entries.AddLast(entries);
        }
        if(Dht.DhtLog.Enabled) {
          ProtocolLog.Write(Dht.DhtLog, String.Format(
                            "Total keys: {0}, total entries: {1}.", 
                            key_entries.Count, total_entries));
        }
        _entry_enumerator = GetEntryEnumerator();

        /* Here we generate another list of keys that we would like to 
         * this is done here, so that we can lock up the _entry_enumerator
         * only during this stage and not during the RpcManager.Invoke
         */
        LinkedList<Entry> local_entries = new LinkedList<Entry>();
        for(int i = 0; i < MAX_PARALLEL_TRANSFERS && _entry_enumerator.MoveNext(); i++) {
          local_entries.AddLast((Entry) _entry_enumerator.Current);
        }

        foreach(Entry ent in local_entries) {
          Channel queue = new Channel();
          queue.CloseAfterEnqueue();
          queue.CloseEvent += this.NextTransfer;
          int ttl = (int) (ent.EndTime - DateTime.UtcNow).TotalSeconds;
          try {
            _ts._rpc.Invoke(_con.Edge, queue, "dht.PutHandler", ent.Key, ent.Value, ttl, false);
          }
          catch {
            if(_con.Edge.IsClosed) {
              _interrupted = true;
              Done();
              break;
            }
          }
        }
      }
Beispiel #9
0
    /**
    <summary>Asynchronous get.  Results are stored in the Channel returns.
    </summary>
    <remarks>This starts the get process by sending dht.Get to all the remote
    end points that contain the key we're looking up.  The next step is
    is when the results are placed in the channel and GetEnqueueHandler is
    called or GetCloseHandler is called.  This means the get needs to be
    stateful, that information is stored in the _adgs_table.</remarks>
    <param name="key">The index to look up.</param>
    <param name="returns">The channel for where the results will be stored
    as they come in.</param>
    */
    public void AsGet(MemBlock key, Channel returns) {
      if (!Activated) {
        throw new Exception("DhtClient: Not yet activated.");
      }

      // create a GetState and map in our table map its queues to it
      // so when we get a GetHandler we know which state to load
      AsDhtGetState adgs = new AsDhtGetState(returns);
      Channel[] q = new Channel[DEGREE];
      lock(_adgs_table.SyncRoot) {
        for (int k = 0; k < DEGREE; k++) {
          Channel queue = new Channel();
          _adgs_table[queue] = adgs;
          q[k] = queue;
        }
      }

      // Setting up our Channels
      for (int k = 0; k < DEGREE; k++) {
        Channel queue = q[k];
        queue.CloseAfterEnqueue();
        queue.EnqueueEvent += this.GetEnqueueHandler;
        queue.CloseEvent += this.GetCloseHandler;
        adgs.queueMapping[queue] = k;
      }

      // Sending off the request!
      adgs.brunet_address_for_key = MapToRing(key);
      for (int k = 0; k < DEGREE; k++) {
        Address target = new AHAddress(adgs.brunet_address_for_key[k]);
        AHSender s = new AHSender(node, target, AHPacket.AHOptions.Greedy);
        // 1024 is in there for backwards compatibility
        _rpc.Invoke(s, q[k], "dht.Get", adgs.brunet_address_for_key[k], 1024, null);
      }
    }
Beispiel #10
0
    /**
    <summary>This is called as a result of a successful retrieval of data from
    a remote end point and performs follow up gets for remaining values
    </summary>
    <remarks>This adds the results to the entry in the _adgs_table.  Once a
    value has been received by a majority of nodes, it is enqueued into the
    requestors returns channel.  If not all results were retrieved follow up
    gets are performed, this is determined by looking at the state of the
    token, a non-null token implies there are remaining results.</remarks>
    </summary>
    <param name="o">The channel used to store the results.</param>
    <param name="args">Unused.</param>
    */

    public void GetEnqueueHandler(Object o, EventArgs args) {
      Channel queue = (Channel) o;
      // Looking up state
      AsDhtGetState adgs = (AsDhtGetState) _adgs_table[queue];

      if(adgs == null) {
        return;
      }

      int idx = (int) adgs.queueMapping[queue];
      // Test to see if we got any results and place them into results if necessary
      ISender sendto = null;
      MemBlock token = null;
      try {
        RpcResult rpc_reply = (RpcResult) queue.Dequeue();
        ArrayList result = (ArrayList) rpc_reply.Result;
        //Result may be corrupted
        ArrayList values = (ArrayList) result[0];
        int remaining = (int) result[1];
        if(remaining > 0) {
          token = (byte[]) result[2];
          sendto = rpc_reply.ResultSender;
        }

        // Going through the return values and adding them to our
        // results, if a majority of our servers say a data exists
        // we say it is a valid data and return it to the caller
        foreach (Hashtable ht in values) {
          MemBlock mbVal = (byte[]) ht["value"];
          int count = 1;
          Hashtable res = null;
          lock(adgs.SyncRoot) {
            res = (Hashtable) adgs.results[mbVal];
            if(res == null) {
              res = new Hashtable();
              adgs.results[mbVal] = res;
              adgs.ttls[mbVal] = ht["ttl"];
            }
            else {
              adgs.ttls[mbVal] = (int) adgs.ttls[mbVal] + (int) ht["ttl"];
            }

            res[idx] = true;
            count = ((ICollection) adgs.results[mbVal]).Count;
          }
          if(count == MAJORITY) {
            ht["ttl"] = (int) adgs.ttls[mbVal] / MAJORITY;
            adgs.returns.Enqueue(new DhtGetResult(ht));
          }
        }
      }
      catch (Exception) {
        sendto = null;
        token = null;
      }

    // We were notified that more results were available!  Let's go get them!
      if(token != null && sendto != null) {
        Channel new_queue = new Channel();
        lock(adgs.SyncRoot) {
          adgs.queueMapping[new_queue] = idx;
        }
        lock(_adgs_table.SyncRoot) {
          _adgs_table[new_queue] = adgs;
        }
        new_queue.CloseAfterEnqueue();
        new_queue.EnqueueEvent += this.GetEnqueueHandler;
        new_queue.CloseEvent += this.GetCloseHandler;
        try {
          _rpc.Invoke(sendto, new_queue, "dht.Get", 
                    adgs.brunet_address_for_key[idx], token);
        }
        catch(Exception) {
          lock(adgs.SyncRoot) {
            adgs.queueMapping.Remove(new_queue);
          }
          lock(_adgs_table.SyncRoot) {
            _adgs_table.Remove(new_queue);
          }
          new_queue.EnqueueEvent -= this.GetEnqueueHandler;
          new_queue.CloseEvent -= this.GetCloseHandler;
        }
      }
    }
Beispiel #11
0
        /**
         * Makes the ping request to a friend.
         * @param address the address of the friend.
         * @param dhtKey the friend's dhtkey.
         */
        protected void FriendSearch(string address, string dhtKey, 
      string query)
        {
            Address addr = AddressParser.Parse(address);
              Channel q = new Channel();
              q.CloseAfterEnqueue();
              q.CloseEvent += delegate(object obj, EventArgs eargs) {
            try {
              RpcResult res = (RpcResult) q.Dequeue();
              string result = (string) res.Result;
              UpdateDnsMapping(dhtKey, result);
              ProtocolLog.WriteIf(SocialLog.SVPNLog,
                          String.Format("SEARCH FRIEND REPLY: {0} {1} {2} {3}",
                          DateTime.Now.TimeOfDay, dhtKey, address, result));
            } catch(Exception e) {
              _friends[dhtKey].Time = SocialUser.TIMEDEFAULT;
              ProtocolLog.WriteIf(SocialLog.SVPNLog, e.Message);
              ProtocolLog.WriteIf(SocialLog.SVPNLog,
                             String.Format("SEARCH FRIEND FAILURE: {0} {1} {2}",
                             DateTime.Now.TimeOfDay, dhtKey, address));
            }
              };
              ProtocolLog.WriteIf(SocialLog.SVPNLog,
                          String.Format("SEARCH FRIEND REQUEST: {0} {1} {2}",
                          DateTime.Now.TimeOfDay, dhtKey, address));

              ISender sender = new AHExactSender(_node, addr);
              _rpc.Invoke(sender, q, "SocialVPN.GetDnsMapping", _local_user.DhtKey,
                  query);
        }
Beispiel #12
0
    /// <summary>
    /// Asynchronous get address method, use when making asynchronous calls
    /// </summary>
    public void AsGetAddress()
    {
        Channel q = new Channel();
        q.CloseAfterEnqueue();

        // Delegate function gets called when close event occurs
        q.CloseEvent += delegate(Object o, EventArgs eargs) {
          RpcResult res = (RpcResult)q.Dequeue();
          Hashtable hash = (Hashtable)res.Result;
          Console.WriteLine(_remEP + ":" + ((UnicastSender)res.ResultSender).EndPoint);
          foreach (DictionaryEntry de in hash) {
        Console.WriteLine("{0} = {1}", de.Key, de.Value);
          }
        };
        _brpc.Rpc.Invoke(_brpc.IPHandler.CreateUnicastSender(_remEP), q, "sys:link.GetNeighbors");
    }
      /**
      <summary>This is called by all completed transfers.  It checks to see if
      there is another value to transfer, transfers it if there is.  Otherwise
      it calls Done.</summary>
      <param name="o">The Channel where the result of the previous transfer is
      stored.</param>
      <param name="eargs">Null</param>
      */
      protected void NextTransfer(Object o, EventArgs eargs) {
        Channel queue = (Channel) o;
        queue.CloseEvent -= this.NextTransfer;
        /* No point in dequeueing, if we've been interrupted, we most likely
         * will get an exception!
         */
        if(_interrupted) {
          return;
        }
        try {
          queue.Dequeue();
        }
        catch (Exception){
          if(_con.Edge.IsClosed) {
            _interrupted = true;
            Done();
            return;
          }
        }

        /* An exception could be thrown if Done is called in another thread or
        there are no more entries available. */
        Entry ent = null;
        try {
          lock(_sync) {
            if(_entry_enumerator.MoveNext()) {
              ent = (Entry) _entry_enumerator.Current;
            }
          }
        }
        catch{}
        if(ent != null) {
          queue = new Channel();
          queue.CloseAfterEnqueue();
          queue.CloseEvent += this.NextTransfer;
          int ttl = (int) (ent.EndTime - DateTime.UtcNow).TotalSeconds;
          try {
            _ts._rpc.Invoke(_con.Edge, queue, "dht.PutHandler", ent.Key, ent.Value, ttl, false);
          }
          catch {
            if(_con.Edge.IsClosed) {
              _interrupted = true;
            }
          }
        }
        else {
          Done();
          if(Dht.DhtLog.Enabled) {
            ProtocolLog.Write(Dht.DhtLog, String.Format(
                              "Successfully complete transfer from {0} to {1}",
                              _ts._node.Address, _con.Address));
          }
        }
      }
    public override void Start() {
      //Make sure the Node is listening to this node
      try {
        //This will throw an exception if _e is already closed:
        _e.CloseEvent += this.CloseHandler; 
        //_e must not be closed, let's start listening to it:
        _e.Subscribe(_node, _e);
        /* Make the call */
        Channel results = new Channel();
        results.CloseAfterEnqueue();
        results.CloseEvent += this.LinkCloseHandler;
        RpcManager rpc = RpcManager.GetInstance(_node);
	if(ProtocolLog.LinkDebug.Enabled) {
	  ProtocolLog.Write(ProtocolLog.LinkDebug, 
			    String.Format("LPS target: {0} Invoking Start() over edge: {1}", _linker.Target, _e));
	}
        rpc.Invoke(_e, results, "sys:link.Start", MakeLM().ToDictionary() );
      }
      catch (Exception e) {
        //The Edge must have closed, move on to the next TA
	if(ProtocolLog.LinkDebug.Enabled) {
	  ProtocolLog.Write(ProtocolLog.LinkDebug, 
			    String.Format("LPS target: {0} Start() over edge: {1}, hit exception: {2}", 
					  _linker.Target, _e, e));
	}
        Finish(Result.MoveToNextTA);
      }
    }
  public void ChannelTests() {
    Channel c0 = new Channel();
    bool e_event_fired = false;
    c0.EnqueueEvent += delegate(object o, EventArgs arg) {
      e_event_fired = true;
    };
    c0.Enqueue(0);
    bool c_event_fired = false;
    c0.CloseEvent += delegate(object o, EventArgs arg) {
      c_event_fired = true;
    };
    c0.Close();
    Assert.IsTrue(c_event_fired, "CloseEvent");

    c0 = new Channel();
    c0.CloseAfterEnqueue();
    c_event_fired = false;
    c0.CloseEvent += delegate(object o, EventArgs arg) {
      c_event_fired = true;
    };
    c0.Enqueue(1); //This should close the channel:
    Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue");
    Assert.IsTrue(c0.Closed, "Closed");
    
    c0 = new Channel(1);
    c_event_fired = false;
    c0.CloseEvent += delegate(object o, EventArgs arg) {
      c_event_fired = true;
    };
    c0.Enqueue(1); //This should close the channel:
    Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue");
    Assert.IsTrue(c0.Closed, "Closed");
    //Try with different starting values:
    Random r = new Random();
    int en_count;
    for(int i = 0; i < 100; i++) {
      int max_enqueues = r.Next(1, 1000);
      c0 = new Channel(max_enqueues);
      c_event_fired = false;
      en_count = 0;
      c0.CloseEvent += delegate(object o, EventArgs arg) {
        c_event_fired = true;
      };
      c0.EnqueueEvent += delegate(object o, EventArgs arg) {
        en_count++;
      };
      for(int j = 0; j < max_enqueues; j++) {
        c0.Enqueue(j);
      }
      Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue");
      Assert.AreEqual(en_count, max_enqueues, "EnqueueEvent count");
      Assert.IsTrue(c0.Closed, "Closed");
      try {
        c0.Enqueue(null);
        Assert.IsTrue(false, "Enqueue after close didn't fail");
      }
      catch {
        Assert.IsTrue(true, "Enqueue after close Got exception");
      }
    }

  }
    /**
     * When we get a response to the sys:link method, this handled
     * is called
     */
    protected void LinkCloseHandler(object q, EventArgs args) {
      try {
        Channel resq = (Channel)q;
        //If the Channel is empty this will throw an exception:
        RpcResult res = (RpcResult)resq.Dequeue();
        /* Here's the LinkMessage response */
        LinkMessage lm = new LinkMessage( (IDictionary)res.Result );
        /**
         * This will set our LinkMessageReply variable.  It can
         * only be set once, so all future sets will fail.  It
         * will also make sure we have the lock on the target.
         * If we don't, that will throw an exception
         */
        SetAndCheckLinkReply(lm);
        //If we got here, we have our response and the Lock on _target_address
        StatusMessage sm = _node.GetStatus(_contype, lm.Local.Address);
        /* Make the call */
        Channel results = new Channel();
        results.CloseAfterEnqueue();
        results.CloseEvent += this.StatusCloseHandler;
        RpcManager rpc = RpcManager.GetInstance(_node);
	if (ProtocolLog.LinkDebug.Enabled) {
	      ProtocolLog.Write(ProtocolLog.LinkDebug, 
                String.Format(
                  "LPS target: {0} Invoking GetStatus() over edge: {1}",
                  _linker.Target, _e));
	}
        /*
         * This could throw an exception if the Edge is closed
         */
        rpc.Invoke(_e, results, "sys:link.GetStatus", sm.ToDictionary() );
      }
      catch(AdrException x) {
        /*
         * This happens when the RPC call has some kind of issue,
         * first we check for common error conditions:
         */
        _x.Value = x;
        Finish( GetResultForErrorCode(x.Code) );
      }
      catch(ConnectionExistsException x) {
        /* We already have a connection */
        _x.Value = x;
        Finish( Result.ProtocolError );
      }
      catch(CTLockException x) {
        //This is thrown when ConnectionTable cannot lock.  Lets try again:
        _x.Value = x;
        Finish( Result.RetryThisTA );
      }
      catch(LinkException x) {
        _x.Value = x;
        if( x.IsCritical ) { Finish( Result.MoveToNextTA ); }
        else { Finish( Result.RetryThisTA ); }
      }
      catch(InvalidOperationException) {
        //The queue never got anything
        Finish(Result.MoveToNextTA);
      }
      catch(EdgeException) {
        //The Edge is goofy, let's move on:
        Finish(Result.MoveToNextTA);
      }
      catch(Exception x) {
        //The protocol was not followed correctly by the other node, fail
        _x.Value = x;
        Finish( Result.RetryThisTA );
      } 
    }
    /**
    <summary>Called by a Dht client to store data here, this supports both Puts
    and Creates by using the unique parameter.</summary>
    <remarks>Puts will store the value no matter what, Creates will only store
    the value if they are the first ones to store data on that key.  This is
    the first part of a Put operation.  This calls PutHandler on itself and
    the neighbor nearest to the key, which actually places the data into the
    store.  The result is returned to the client upon completion of the call
    to the neighbor, if that fails the data is removed locally and an exception
    is sent to the client indicating failure.</remarks>
    <param name="key">The index to store the data at.</param>
    <param name="value">Data to store at the key.</param>
    <param name="ttl">Dht lease time in seconds</param>
    <param name="unique">True if this should perform a create, false otherwise.
    </param>
    <param name="rs">The return state sent back to the RpcManager so that it
    knows who to return the result to.</param>
    <returns>True on success, thrown exception on failure</returns>
    <exception cref="Exception">Data is too large, unresolved remote issues,
    or the create is no successful</exception>
    */

    public bool Put(MemBlock key, MemBlock value, int ttl, bool unique, object rs) {
      if(value.Length > MAX_BYTES) {
        throw new Exception(String.Format(
          "Dht only supports storing data smaller than {0} bytes.", MAX_BYTES));
      }
      PutHandler(key, value, ttl, unique);
      Channel remote_put = new Channel();
      remote_put.CloseAfterEnqueue();
      remote_put.CloseEvent += delegate(Object o, EventArgs eargs) {
        object result = false;
        try {
          result = remote_put.Dequeue();
          RpcResult rpcResult = (RpcResult) result;
          result = rpcResult.Result;
          if(result.GetType() != typeof(bool)) {
            throw new Exception("Incompatible return value.");
          }
          else if(!(bool) result) {
            throw new Exception("Unknown error!");
          }
        }
        catch (Exception e) {
          lock(_sync) {
            _data.RemoveEntry(key, value);
          }
          result = new AdrException(-32602, e);
        }
        _rpc.SendResult(rs, result);
      };

      try {
        Address key_address = new AHAddress(key);
        ISender s = null;
        // We need to forward this to the appropriate node!
        if(((AHAddress)_node.Address).IsLeftOf((AHAddress) key_address)) {
          Connection con = _node.ConnectionTable.GetRightStructuredNeighborOf((AHAddress) _node.Address);
          s = con.Edge;
        }
        else {
          Connection con = _node.ConnectionTable.GetLeftStructuredNeighborOf((AHAddress) _node.Address);
          s = con.Edge;
        }
        _rpc.Invoke(s, remote_put, "dht.PutHandler", key, value, ttl, unique);
      }
      catch (Exception) {
        lock(_sync) {
          _data.RemoveEntry(key, value);
        }
        throw;
      }
      return true;
    }