/// <summary>Create a DtlsFilter.</summary> /// <param name="key">A CryptoKey initialized by the OpenSSL.NET library.</param> /// <param name="cert">The path to the certificate to use.</param> /// <param name="ca_cert">The path to the ca certificate to use.</param> /// <param name="client">Use client initialization parameters.</param> public DtlsAssociation(ISender sender, CertificateHandler ch, PType ptype, Ssl ssl, bool client) : base(sender, ch) { _ip = new IdentifierPair(); PType = ptype; _ssl = ssl; _client = client; _ssl.SetReadAhead(1); // Buggy SSL versions have issue with compression and dtls _ssl.SetOptions((int) SslOptions.SSL_OP_NO_COMPRESSION); if(client) { _ssl.SetConnectState(); } else { _ssl.SetAcceptState(); } // The ssl object will take control _read = BIO.MemoryBuffer(false); _read.NonBlocking = true; _write = BIO.MemoryBuffer(false); _write.NonBlocking = true; _ssl.SetBIO(_read, _write); _ssl.DoHandshake(); _buffer = new byte[Int16.MaxValue]; _buffer_sync = new object(); _fe_lock = 0; }
/// <summary>Constructor for an outgoing edge, since we don't know the remote /// id yet, it must be outgoing!</summary> public SubringEdge(TransportAddress local_ta, TransportAddress remote_ta, bool inbound, ISender sender, PType ptype) : base(null, inbound) { _ip = new IdentifierPair(); _local_ta = local_ta; _remote_ta = remote_ta; _ptype = ptype; _overlay_sender = sender; }
public ConnectionHandler(PType ptype, StructuredNode node) { _node = node; _ondemand = new OnDemandConnectionOverlord(node); _node.AddConnectionOverlord(_ondemand); _ptype = ptype; _ptype_mb = ptype.ToMemBlock(); _address_to_sender = new Dictionary<Address, ISender>(); _sender_to_address = new Dictionary<ISender, Address>(); node.GetTypeSource(_ptype).Subscribe(this, null); node.ConnectionTable.ConnectionEvent += HandleConnection; node.ConnectionTable.DisconnectionEvent += HandleDisconnection; }
public override bool Equals(object o) { if (o == this) { return(true); } PType other = o as PType; if (other != null) { return(other.ToMemBlock().Equals(ToMemBlock())); } return(false); }
/// <summary>Create a SubringEdgeListener.</summary> /// <param name="shared_node">The overlay used for the transport.</param> /// <param name="private_node">The overlay needing edges.</param> public SubringEdgeListener(Node shared_node, Node private_node) { _shared_node = shared_node; _private_node = private_node; _it = new IdentifierTable(); _local_ta = new SubringTransportAddress(shared_node.Address as AHAddress, shared_node.Realm); _ptype = new PType("ns:" + shared_node.Realm); shared_node.DemuxHandler.GetTypeSource(_ptype).Subscribe(this, null); _running = 0; _started = 0; }
public ReqrepManager(object info, PType prefix) { ReqrepManager existing; lock( _inst_tab_sync ) { if(_instance_table.TryGetValue(info, out existing) ) { throw new Exception("Already an existing ReqrepManager for: " + info.ToString()); } else { _instance_table[info] = this; } } _info = info.ToString(); _prefix = prefix; _req_handler_table = new Hashtable(); Random r = new Random(); //Don't use negative numbers: _req_state_table = new UidGenerator<RequestState>(r, true); //Don't use negative numbers: _reply_id_table = new UidGenerator<ReplyState>(r, true); _rep_handler_table = new Hashtable(); /** * We keep a list of the most recent 1000 replies until they * get too old. If the reply gets older than reptimeout, we * remove it */ _reply_cache = new Cache(1000); _reply_cache.EvictionEvent += HandleReplyCacheEviction; /* * Here we set the timeout mechanisms. There is a default * value, but this is now dynamic based on the observed * RTT of the network */ //resend the request after 5 seconds. _edge_reqtimeout = new TimeSpan(0,0,0,0,5000); _nonedge_reqtimeout = new TimeSpan(0,0,0,0,5000); //Start with 50 sec timeout _acked_reqtimeout = new TimeSpan(0,0,0,0,50000); //Here we track the statistics to improve the timeouts: _nonedge_rtt_stats = new TimeStats(_nonedge_reqtimeout.TotalMilliseconds, 0.98); _edge_rtt_stats = new TimeStats(_edge_reqtimeout.TotalMilliseconds, 0.98); _acked_rtt_stats = new TimeStats(_acked_reqtimeout.TotalMilliseconds, 0.98); _last_check = DateTime.UtcNow; }
static Protocol() { //Here are all the defined protocols PType[] prots = new PType[] { Linking, AH, Connection, Forwarding, Relaying, Echo, IP, ReqRep, Rpc }; foreach (PType p in prots) { PType.AddToTable(p); } }
static PType() { //Initialize the _table: _table = new PType[ASCII_UPPER_BOUND]; }
public ReqrepManager(string info, PType prefix) { lock( _inst_tab_sync ) { _instance_table.Replace(info, this); } _info = info; _prefix = prefix; _req_handler_table = new Hashtable(); #if BRUNET_SIMULATOR Random r = Node.SimulatorRandom; #else Random r = new Random(); #endif //Don't use negative numbers: _req_state_table = new UidGenerator<RequestState>(r, true); //Don't use negative numbers: _reply_id_table = new UidGenerator<ReplyState>(r, true); _rep_handler_table = new Hashtable(); /** * We keep a list of the most recent 1000 replies until they * get too old. If the reply gets older than reptimeout, we * remove it */ _reply_cache = new Cache(1000); _reply_cache.EvictionEvent += HandleReplyCacheEviction; /* * Here we set the timeout mechanisms. There is a default * value, but this is now dynamic based on the observed * RTT of the network */ //resend the request after 5 seconds. _edge_reqtimeout = new TimeSpan(0,0,0,0,5000); _nonedge_reqtimeout = new TimeSpan(0,0,0,0,5000); //Start with 50 sec timeout _acked_reqtimeout = new TimeSpan(0,0,0,0,50000); //Here we track the statistics to improve the timeouts: _nonedge_rtt_stats = new TimeStats(_nonedge_reqtimeout.TotalMilliseconds, 0.98); _edge_rtt_stats = new TimeStats(_edge_reqtimeout.TotalMilliseconds, 0.98); _acked_rtt_stats = new TimeStats(_acked_reqtimeout.TotalMilliseconds, 0.98); _last_check = DateTime.UtcNow; }
/** * Parse the PType starting at mb, and return all of mb <b>after</b> * the PType. */ public static PType Parse(MemBlock mb, out MemBlock rest) { PType result = null; byte fb = mb[0]; bool is_v_n = IsValidNumeric((int)fb); /** * Since ptypes must be valid UTF8 strings, * if the second byte is null, the first byte is an ascii character * and hence has a value less than ASCII_UPPER_BOUND */ bool store_in_tbl = (is_v_n || (mb[1] == 0)); if (store_in_tbl) { //This is stored in our table: result = _table[fb]; if (result != null) { if (is_v_n) { //There is no null rest = mb.Slice(1); } else { //Skip the null rest = mb.Slice(2); } return(result); } } //Otherwise we have to make it: MemBlock raw_data = null; result = new PType(); if (is_v_n) { /* * Don't set the raw_data since it is only one byte and we may not need * it */ rest = mb.Slice(1); result._type_num = (int)fb; } else { int null_pos = mb.IndexOf(0); if (null_pos > 0) { //Include the "null", but make a copy so we don't keep some data in //scope for ever raw_data = MemBlock.Copy((ICopyable)mb.Slice(0, null_pos + 1)); rest = mb.Slice(null_pos + 1); } else { //There is no terminating Null, panic!! throw new ParseException( System.String.Format("PType not null terminated: {0}", mb.ToBase16String())); } result._type_num = -2; result._raw_data = raw_data; } if (store_in_tbl) { //Make sure we don't have to create an object like this again _table[fb] = result; } return(result); }
public void Test() { System.Random r = new System.Random(); //Test numeric type codes: for (int i = 1; i < 32; i++) { PType p = new PType(i); MemBlock b = p.ToMemBlock(); byte[] buf = new byte[100]; r.NextBytes(buf); //Get some junk: MemBlock junk = MemBlock.Reference(buf); MemBlock b1 = MemBlock.Concat(b, junk); MemBlock rest = null; PType pp = PType.Parse(b1, out rest); byte[] buf2 = new byte[1]; buf2[0] = (byte)i; MemBlock b2 = MemBlock.Reference(buf2); Assert.AreEqual(p, pp, System.String.Format("Round trip int: {0}", i)); Assert.AreEqual(b, b2, System.String.Format("Convert to MemBlock int: {0}", i)); Assert.AreEqual(i, pp.TypeNumber, "Typenumber equality"); Assert.AreEqual(rest, junk, "rest in int PType"); } //Test string types: for (int i = 0; i < 1000; i++) { //Make a random string: // byte[] buf = new byte[r.Next(1, 100)]; r.NextBytes(buf); string s = Base32.Encode(buf); PType p1 = new PType(s); r.NextBytes(buf); //Get some junk: MemBlock b = MemBlock.Copy(buf); MemBlock combine = MemBlock.Concat(p1.ToMemBlock(), b); MemBlock b2 = null; PType p2 = PType.Parse(combine, out b2); Assert.AreEqual(p1, p2, "Round trip string: " + s); Assert.AreEqual(b, b2, "Round trip rest"); Assert.AreEqual(s, p2.ToString(), "Round trip to string"); Assert.AreEqual(s, p1.ToString(), "Round trip to string"); Assert.AreEqual(p1.TypeNumber, p2.TypeNumber, "RT: TypeNumber test"); } //Test all one byte ascii strings: for (byte b = 32; b < ASCII_UPPER_BOUND; b++) { MemBlock raw = MemBlock.Reference(new byte[] { b, 0 }); MemBlock rest; PType p1 = PType.Parse(raw, out rest); Assert.AreEqual(rest, MemBlock.Null, "Rest is null"); PType p2 = PType.Parse(raw, out rest); Assert.AreEqual(rest, MemBlock.Null, "Rest is null"); Assert.IsTrue(p1 == p2, "reference equality of single byte type"); Assert.AreEqual(p1, p2, "equality of single byte type"); Assert.AreEqual(p1, new PType(p1.ToString()), "Round trip string"); } //Test TypeNumber of string types: for (int i = 0; i < 100; i++) { byte[] buf = new byte[20]; r.NextBytes(buf); for (int j = 1; j < 4; j++) { string s = Base32.Encode(buf).Substring(0, j); PType p1 = new PType(s); byte[] buf2 = System.Text.Encoding.UTF8.GetBytes(s); int t = 0; for (int k = 0; k < buf2.Length; k++) { t = t | buf2[k]; t <<= 8; } Assert.AreEqual(t, p1.TypeNumber, System.String.Format("String type number: {0}, s={1}", t, s)); } } //Console.Error.WriteLine("Tested PType"); }
public ReqrepManager(string info, PType prefix) { lock( _inst_tab_sync ) { _instance_table.Replace(info, this); } _info = info; _prefix = prefix; #if BRUNET_SIMULATOR Random r = Node.SimulatorRandom; #else Random r = new Random(); #endif //Don't use negative numbers: _req_state_table = new UidGenerator<RequestState>(r, true); //Don't use negative numbers: _reply_id_table = new UidGenerator<ReplyState>(r, true); /** * We keep a list of the most recent 1000 replies until they * get too old. If the reply gets older than reptimeout, we * remove it */ _reply_cache = new Cache(1000); _reply_cache.EvictionEvent += HandleReplyCacheEviction; _to_mgr = new TimeOutManager(); }
public void Test() { System.Random r = new System.Random(); //Test numeric type codes: for(int i = 1; i < 32; i++ ) { PType p = new PType(i); MemBlock b = p.ToMemBlock(); byte[] buf = new byte[100]; r.NextBytes(buf); //Get some junk: MemBlock junk = MemBlock.Reference(buf); MemBlock b1 = MemBlock.Concat(b, junk); MemBlock rest = null; PType pp = PType.Parse(b1, out rest); byte[] buf2 = new byte[1]; buf2[0] = (byte)i; MemBlock b2 = MemBlock.Reference(buf2); Assert.AreEqual(p, pp, System.String.Format("Round trip int: {0}", i)); Assert.AreEqual( b, b2, System.String.Format("Convert to MemBlock int: {0}", i) ); Assert.AreEqual(i, pp.TypeNumber, "Typenumber equality"); Assert.AreEqual(rest, junk, "rest in int PType"); } //Test string types: for(int i = 0; i < 1000; i++) { //Make a random string: // byte[] buf = new byte[ r.Next(1, 100) ]; r.NextBytes(buf); string s = Base32.Encode(buf); PType p1 = new PType(s); r.NextBytes(buf); //Get some junk: MemBlock b = MemBlock.Copy(buf); MemBlock combine = MemBlock.Concat( p1.ToMemBlock(), b); MemBlock b2 = null; PType p2 = PType.Parse(combine, out b2); Assert.AreEqual( p1, p2, "Round trip string: " + s); Assert.AreEqual( b, b2, "Round trip rest" ); Assert.AreEqual( s, p2.ToString(), "Round trip to string"); Assert.AreEqual( s, p1.ToString(), "Round trip to string"); Assert.AreEqual( p1.TypeNumber, p2.TypeNumber, "RT: TypeNumber test"); } //Test all one byte ascii strings: for(byte b = 32; b < ASCII_UPPER_BOUND; b++) { MemBlock raw = MemBlock.Reference( new byte[]{ b, 0 } ); MemBlock rest; PType p1 = PType.Parse(raw, out rest); Assert.AreEqual(rest, MemBlock.Null, "Rest is null"); PType p2 = PType.Parse(raw, out rest); Assert.AreEqual(rest, MemBlock.Null, "Rest is null"); Assert.IsTrue(p1 == p2, "reference equality of single byte type"); Assert.AreEqual(p1, p2, "equality of single byte type"); Assert.AreEqual(p1, new PType(p1.ToString()), "Round trip string"); } //Test TypeNumber of string types: for(int i = 0; i < 100; i++) { byte[] buf = new byte[20]; r.NextBytes(buf); for( int j = 1; j < 4; j++) { string s = Base32.Encode(buf).Substring(0, j); PType p1 = new PType(s); byte[] buf2 = System.Text.Encoding.UTF8.GetBytes(s); int t = 0; for(int k = 0; k < buf2.Length; k++) { t = t | buf2[k]; t <<= 8; } Assert.AreEqual(t, p1.TypeNumber, System.String.Format("String type number: {0}, s={1}", t, s) ); } } //Console.Error.WriteLine("Tested PType"); }
/** * Parse the PType starting at mb, and return all of mb <b>after</b> * the PType. */ public static PType Parse(MemBlock mb, out MemBlock rest) { PType result = null; byte fb = mb[0]; bool is_v_n = IsValidNumeric( (int)fb ); /** * Since ptypes must be valid UTF8 strings, * if the second byte is null, the first byte is an ascii character * and hence has a value less than ASCII_UPPER_BOUND */ bool store_in_tbl = ( is_v_n || (mb[1] == 0) ); if( store_in_tbl ) { //This is stored in our table: result = _table[ fb ]; if( result != null ) { if( is_v_n ) { //There is no null rest = mb.Slice(1); } else { //Skip the null rest = mb.Slice(2); } return result; } } //Otherwise we have to make it: MemBlock raw_data = null; result = new PType(); if( is_v_n ) { /* * Don't set the raw_data since it is only one byte and we may not need * it */ rest = mb.Slice(1); result._type_num = (int)fb; } else { int null_pos = mb.IndexOf(0); if( null_pos > 0 ) { //Include the "null", but make a copy so we don't keep some data in //scope for ever raw_data = MemBlock.Copy( (ICopyable)mb.Slice(0, null_pos + 1) ); rest = mb.Slice(null_pos + 1); } else { //There is no terminating Null, panic!! throw new ParseException( System.String.Format("PType not null terminated: {0}", mb.ToBase16String())); } result._type_num = -2; result._raw_data = raw_data; } if( store_in_tbl ) { //Make sure we don't have to create an object like this again _table[ fb ] = result; } return result; }
// Methods ///// /** Create a ReplyState for a new Request * Note, this is not synchronized, you must hold the lock when calling! */ protected ReplyState GenerateReplyState(PType prefix, RequestKey rk) { var rs = new ReplyState(_prefix, rk); _reply_cache[rk] = rs; rs.LocalID = _reply_id_table.GenerateID(rs); return rs; }
static PType() { //Initialize the _table: _table = new PType[ ASCII_UPPER_BOUND ]; }
/** * 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; } }
public SecureConnectionHandler(PType ptype, StructuredNode node, SymphonySecurityOverlord so) : base(ptype, node) { _so = so; _registered = new Dictionary<SecurityAssociation, bool>(); }
static Protocol() { //Here are all the defined protocols PType[] prots = new PType[]{ Linking, AH, Connection, Forwarding, Relaying, Echo, IP, ReqRep, Rpc }; foreach(PType p in prots) { PType.AddToTable(p); } }
protected static void AddToTable(PType p) { if (0 <= p.TypeNumber && p.TypeNumber < _table.Length) { _table[ p.TypeNumber ] = p; } }
public bool HandleReply(ReqrepManager man, ReqrepManager.ReqrepType rt, int mid, PType prot, MemBlock payload, ISender returnpath, ReqrepManager.Statistics statistics, object state) { DateTime reply_time = DateTime.UtcNow; ListDictionary res_dict = new ListDictionary(); AHSender ah_rp = returnpath as AHSender; if( ah_rp != null ) { res_dict["target"] = ah_rp.Destination.ToString(); } //Here are the number of microseconds res_dict["musec"] = (int)( 1000.0 * ((reply_time - _start_time).TotalMilliseconds) ); //Send the RPC result now; RpcManager my_rpc = System.Threading.Interlocked.Exchange(ref _rpc, null); if( my_rpc != null ) { //We have not sent any reply yet: my_rpc.SendResult(_req_state, res_dict); } return false; }
public ReplyState(PType prefix, RequestKey rk) { _prefix = prefix; RequestKey = rk; RequestDate = DateTime.UtcNow; _reply_timeouts = 0; _uri = new WriteOnce<string>(); _lid = 0; }