/** * Implements the IReplyHandler (also provides some light-weight statistics) */ public bool HandleReply(ReqrepManager man, ReqrepManager.ReqrepType rt, int mid, PType prot, MemBlock payload, ISender ret_path, ReqrepManager.Statistics statistics, object state) { RpcRequestState rs = (RpcRequestState)state; //ISender target = rs.RpcTarget; Channel bq = rs.Results; if (bq != null) { object data = AdrConverter.Deserialize(payload); RpcResult res = new RpcResult(ret_path, data, statistics); //handle possible exception: try { bq.Enqueue(res); //Keep listening unless the queue is closed return(!bq.Closed); } catch (System.InvalidOperationException) { //The queue is closed, stop listening for more results: return(false); } } else { //If they didn't even pass us a queue, I guess they didn't want to //listen too long return(false); } }
/// <summary>Parse a revocation message.</summary> public UserRevocationMessage(Certificate cacert, MemBlock data) { _data = data; int pos = 0; int length = 0; Username = AdrConverter.Deserialize(data, pos, out length) as string; pos += length; // Random number to reduce likelihood of malicious duplication of messages NumberSerializer.ReadInt(data, pos); pos += 4; // Verify that there is a date contained therein, perhaps we should verify the time new DateTime(NumberSerializer.ReadLong(data, pos)); pos += 8; Signature = new byte[data.Length - pos]; data.Slice(pos).CopyTo(Signature, 0); // hash the data SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); Hash = sha1.ComputeHash(data, 0, data.Length - Signature.Length); if (!cacert.PublicKey.VerifyHash(Hash, CryptoConfig.MapNameToOID("SHA1"), Signature)) { throw new Exception("Invalid UserRevocationMessage signature"); } }
/// <summary>Parses web data and updates the revoked users hashtable if /// successful</summary> protected void UpdateRl(byte[] data) { // message is length (4) + date (8) + data (variable) + hash (~20) int length = data.Length; if (length < 12) { throw new Exception("No data? Didn't get enough data..."); } length = NumberSerializer.ReadInt(data, 0); DateTime date = new DateTime(NumberSerializer.ReadLong(data, 4)); // warn the user that this is an old revocation list, maybe there is an attack if (date < DateTime.UtcNow.AddHours(-24)) { ProtocolLog.WriteIf(IpopLog.GroupVPN, "Revocation list is over 24 hours old"); } // Weird, data length is longer than the data we got if (length > data.Length - 12) { throw new Exception("Missing data? Didn't get enough data..."); } // hash the data and verify the signature SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); byte[] hash = sha1.ComputeHash(data, 4, length); byte[] signature = new byte[data.Length - 4 - length]; Array.Copy(data, 4 + length, signature, 0, signature.Length); if (!_ca_cert.PublicKey.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature)) { throw new Exception("Invalid signature!"); } // convert the data to an array list as it was sent to us MemBlock mem = MemBlock.Reference(data, 12, length - 8); ArrayList rl = AdrConverter.Deserialize(mem) as ArrayList; if (rl == null) { throw new Exception("Data wasn't a list..."); } // convert it into a hashtable for O(1) look ups Hashtable ht = new Hashtable(); foreach (string username in rl) { ht[username] = true; } Interlocked.Exchange(ref _revoked_users, ht); }
public CertificateMaker(byte[] RawData) { _unsigned_data = RawData; Hashtable ht = (Hashtable)AdrConverter.Deserialize(MemBlock.Reference(RawData)); _subject = new DistinguishedName((string)ht["Country"], (string)ht["Organization"], (string)ht["OrganizationalUnit"], (string)ht["Name"], (string)ht["Email"]); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.ImportCspBlob((byte[])ht["PublicKey"]); _public_key = rsa; _node_address = (string)ht["NodeAddress"]; }
/** * <summary>Disk caching is unsupported at this time.</summary> */ /* When we have a cache miss, we should try to load the data from disk, * if we are successful, we should also delete that file from the disk */ public void CacheMiss(Object o, EventArgs args) { Brunet.Collections.Cache.MissArgs margs = (Brunet.Collections.Cache.MissArgs)args; MemBlock key = (MemBlock)margs.Key; string path = GeneratePath(key); if (File.Exists(path)) { using (FileStream fs = File.Open(path, FileMode.Open)) { ArrayList ht_entries = (ArrayList)AdrConverter.Deserialize(fs); Entry[] entries = new Entry[ht_entries.Count]; int index = 0; foreach (Hashtable entry in ht_entries) { entries[index++] = (Entry)entry; } _data[key] = new LinkedList <Entry>(entries); } File.Delete(path); } }
/** * <summary>Retrieves data from the Dht.</summary> * <remarks>First old entries for the key are deleted from the dht, second a * look up is performed, and finally using the token a range of data is * selectively returned.</remarks> * <param name="key">The index used to look up.</summary> * <param name="token">Contains the data necessary to do follow up look ups * if all the data stored in a key is to big for MAX_BYTES.</param> * <returns>IList of hashtables containing the results. Compatible with * DhtGetResult.</returns> */ public IList Get(MemBlock key, byte[] token) { int seen_start_idx = 0; int seen_end_idx = 0; if (token != null) { using (MemoryStream ms = new MemoryStream(token)) { int[] bounds = (int[])AdrConverter.Deserialize(ms); seen_start_idx = bounds[0]; seen_end_idx = bounds[1]; seen_start_idx = seen_end_idx + 1; } } int consumed_bytes = 0; Entry[] data = null; lock (_sync ) { _data.DeleteExpired(key); LinkedList <Entry> ll_data = _data.GetEntries(key); // Keys exist! if (ll_data != null) { data = new Entry[ll_data.Count]; ll_data.CopyTo(data, 0); } } ArrayList result = null; if (data != null) { result = new ArrayList(); ArrayList values = new ArrayList(); int remaining_items = 0; byte[] next_token = null; seen_end_idx = data.Length - 1; for (int i = seen_start_idx; i < data.Length; i++) { Entry e = (Entry)data[i]; if (e.Value.Length + consumed_bytes <= MAX_BYTES) { int age = (int)(DateTime.UtcNow - e.CreateTime).TotalSeconds; int ttl = (int)(e.EndTime - DateTime.UtcNow).TotalSeconds; consumed_bytes += e.Value.Length; Hashtable item = new Hashtable(); item["age"] = age; item["value"] = (byte[])e.Value; item["ttl"] = ttl; values.Add(item); } else { seen_end_idx = i - 1; break; } } remaining_items = data.Length - (seen_end_idx + 1); //Token creation int[] new_bounds = new int[2]; new_bounds[0] = seen_start_idx; new_bounds[1] = seen_end_idx; using (MemoryStream ms = new System.IO.MemoryStream()) { AdrConverter.Serialize(new_bounds, ms); next_token = ms.ToArray(); } result.Add(values); result.Add(remaining_items); result.Add(next_token); } return(result); }
/** * This handles lightweight control messages that may be sent * by UDP */ protected void HandleControlPacket(int remoteid, int n_localid, MemBlock buffer, object state) { int local_id = ~n_localid; UdpEdge e = _id_ht[local_id] as UdpEdge; if (e == null) { return; } if (e.RemoteID == 0) { try { e.RemoteID = remoteid; } catch { return; } } if (e.RemoteID != remoteid) { return; } try { ControlCode code = (ControlCode)NumberSerializer.ReadInt(buffer, 0); if (ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format( "Got control {1} from: {0}", e, code)); } if (code == ControlCode.EdgeClosed) { //The edge has been closed on the other side RequestClose(e); CloseHandler(e, null); } else if (code == ControlCode.EdgeDataAnnounce) { //our NAT mapping may have changed: IDictionary info = (IDictionary)AdrConverter.Deserialize(buffer.Slice(4)); string our_local_ta = (string)info["RemoteTA"]; //his remote is our local if (our_local_ta != null) { //Update our list: TransportAddress new_ta = TransportAddressFactory.CreateInstance(our_local_ta); TransportAddress old_ta = e.PeerViewOfLocalTA; if (!new_ta.Equals(old_ta)) { if (ProtocolLog.UdpEdge.Enabled) { ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format( "Local NAT Mapping changed on Edge: {0}\n{1} => {2}", e, old_ta, new_ta)); } //Looks like matters have changed: this.UpdateLocalTAs(e, new_ta); /** * @todo, maybe we should ping the other edges sharing this * EndPoint, but we need to be careful not to do some O(E^2) * operation, which could easily happen if each EdgeDataAnnounce * triggered E packets to be sent */ } } } else if (code == ControlCode.Null) { //Do nothing in this case } } catch (Exception x) { //This could happen if this is some control message we don't understand if (ProtocolLog.Exceptions.Enabled) { ProtocolLog.Write(ProtocolLog.Exceptions, x.ToString()); } } }
/** * When requests come in this handles it */ public void HandleData(MemBlock payload, ISender ret_path, object state) { Exception exception = null; #if RPC_DEBUG Console.Error.WriteLine("[RpcServer: {0}] Getting method invocation request at: {1}.", _rrman.Info, DateTime.Now); #endif try { object data = AdrConverter.Deserialize(payload); IList l = data as IList; if (l == null) { //We could not cast the request into a list... so sad: throw new AdrException(-32600, "method call not a list"); } string methname = (string)l[0]; #if RPC_DEBUG Console.Error.WriteLine("[RpcServer: {0}] Getting invocation request, method: {1}", _rrman.Info, methname); #endif /* * Lookup this method name in our table. * This uses a cache, so it should be fast * after the first time */ IRpcHandler handler = null; string mname = null; lock ( _sync ) { object[] info = (object[])_method_cache[methname]; if (info == null) { int dot_idx = methname.IndexOf('.'); if (dot_idx == -1) { throw new AdrException(-32601, "No Handler for method: " + methname); } string hname = methname.Substring(0, dot_idx); //Skip the '.': mname = methname.Substring(dot_idx + 1); handler = (IRpcHandler)_method_handlers[hname]; if (handler == null) { //No handler for this. throw new AdrException(-32601, "No Handler for method: " + methname); } info = new object[2]; info[0] = handler; info[1] = mname; _method_cache[methname] = info; } else { handler = (IRpcHandler)info[0]; mname = (string)info[1]; } } ArrayList pa = (ArrayList)l[1]; #if DAVID_ASYNC_INVOKE object[] odata = new object[4]; odata[0] = handler; odata[1] = ret_path; odata[2] = mname; odata[3] = pa; _rpc_command.Enqueue(odata); #else handler.HandleRpc(ret_path, mname, pa, ret_path); #endif } catch (ArgumentException argx) { exception = new AdrException(-32602, argx); } catch (TargetParameterCountException argx) { exception = new AdrException(-32602, argx); } catch (Exception x) { exception = x; } if (exception != null) { //something failed even before invocation began #if RPC_DEBUG Console.Error.WriteLine("[RpcServer: {0}] Something failed even before invocation began: {1}", _rrman.Info, exception); #endif using (MemoryStream ms = new MemoryStream()) { AdrConverter.Serialize(exception, ms); ret_path.Send(new CopyList(PType.Protocol.Rpc, MemBlock.Reference(ms.ToArray()))); } } }
public object Deserialize(Stream stream) { return(AdrConverter.Deserialize(stream)); }
public object Deserialize(byte[] b) { return(AdrConverter.Deserialize(b)); }