/** * This handles the packet forwarding protocol */ public void HandleData(MemBlock b, ISender ret_path, object state) { /* * Check it */ AHSender ahs = ret_path as AHSender; if( ahs != null ) { //This was an AHSender: /* * This goes A -> B -> C */ if( b[0] == 0 ) { int offset = 1; //This is the first leg, going from A->B Address add_c = AddressParser.Parse(b.Slice(offset, Address.MemSize)); offset += Address.MemSize; //Since ahs a sender to return, we would be the source: Address add_a = ahs.Destination; short ttl = NumberSerializer.ReadShort(b, offset);//2 bytes offset += 2; ushort options = (ushort) NumberSerializer.ReadShort(b, offset);//2 bytes offset += 2; MemBlock payload = b.Slice(offset); MemBlock f_header = MemBlock.Reference( new byte[]{1} ); /* * switch the packet from [A B f0 C] to [B C f 1 A] */ ICopyable new_payload = new CopyList(PType.Protocol.Forwarding, f_header, add_a, payload); /* * ttl and options are present in the forwarding header. */ AHSender next = new AHSender(_n, ahs.ReceivedFrom, add_c, ttl, options); next.Send(new_payload); } else if ( b[0] == 1 ) { /* * This is the second leg: B->C * Make a Forwarding Sender, and unwrap the inside packet */ Address add_a = AddressParser.Parse(b.Slice(1, Address.MemSize)); Address add_b = ahs.Destination; MemBlock rest_of_payload = b.Slice(1 + Address.MemSize); //Here's the return path: ISender new_ret_path = new ForwardingSender(_n, add_b, add_a); _n.HandleData(rest_of_payload, new_ret_path, this); } } else { //This is not (currently) supported. Console.Error.WriteLine("Got a forwarding request from: {0}", ret_path); } }
/// <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"); } }
public void HandleData(MemBlock b, ISender return_path, object state) { byte b0 = b[0]; if( b0 == 0 ) { //This is a request: MemBlock data = b.Slice(1); //Make sure node to reply with a zero return_path.Send( new CopyList( PType.Protocol.Echo, REPLY_HEADER, data) ); } }
/** Parse the first LENGTH bytes to get the AHHeader */ public AHHeader(MemBlock mb) { Hops = NumberSerializer.ReadShort(mb, 0); Ttl = NumberSerializer.ReadShort(mb, 2); //We parse the Address objects lazily Opts = (ushort)NumberSerializer.ReadShort(mb, 2 * Address.MemSize + 4); if( mb.Length != LENGTH ) { mb = mb.Slice(0,LENGTH); } _data = mb; }
public override string ToString() { if (_string_rep != null) { return(_string_rep); } else if (_type_num == -2) { //Unitialized string type: _string_rep = System.String.Intern( _raw_data.Slice(0, _raw_data.Length - 1).GetString(System.Text.Encoding.UTF8) ); } else { //Unitialized int type: _string_rep = "_" + _type_num.ToString(); } return(_string_rep); }
/** * 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()); } }
public void Test() { System.Random r = new System.Random(); byte[] data; for(int i = 0; i < 100; i++) { data = new byte[ r.Next(1024) ]; r.NextBytes(data); int offset = r.Next(data.Length); MemBlock mb1 = new MemBlock(data, 0, data.Length); MemBlock mb1a = MemBlock.Copy(data, 0, data.Length); Assert.IsTrue(mb1.Equals(mb1a), "MemBlock.Copy"); Assert.IsTrue(mb1.Equals(data), "MemBlock == byte[]"); MemBlock mb2 = new MemBlock(data, offset, data.Length - offset); MemBlock mb2a = mb1.Slice(offset); MemBlock mb3 = new MemBlock(data, 0, offset); MemBlock mb3a = mb1.Slice(0, offset); Assert.IsTrue(mb3.Equals( mb3a ), "mb3.Equals(mb3a)"); Assert.IsTrue(mb3a.Equals( mb3 ), "mb3a.Equals(mb3)"); Assert.IsTrue(mb3.CompareTo(mb2) + mb2.CompareTo(mb3) == 0, "CompareTo"); Assert.IsTrue(mb2.Equals( mb2a ), "mb2.Equals(mb2a)"); Assert.IsTrue(mb2a.Equals( mb2 ), "mb2a.Equals(mb2)"); MemBlock cat = MemBlock.Concat(mb3, mb2); MemBlock cata = MemBlock.Concat(mb3a, mb2a); Assert.IsTrue(cat.Equals(cata), "Concat Equals"); Assert.IsTrue(cata.Equals(cat), "Concat a Equals"); Assert.IsTrue(mb1.Equals(cat), "Concat Equals Original"); if( offset != 0 ) { //These should not be equal Assert.IsFalse(mb2.Equals(mb1), "mb2 != mb1"); } int mb2a_l = mb2a.Length; byte[] tmp_data = new byte[mb2a_l]; mb2a.CopyTo(tmp_data, 0); MemBlock mb2b = new MemBlock(tmp_data, 0, tmp_data.Length); Assert.IsTrue(mb2a.Equals(mb2b), "mb2a.Equals(mb2b)"); Assert.IsTrue(mb2b.Equals(mb2a), "mb2b.Equals(mb2a)"); //Check the Hash: Assert.IsTrue(mb2b.GetHashCode() == mb2a.GetHashCode(), "GetHashCode"); //Here are some manual equality testing using the indexer bool all_equals = true; int j = 0; while( all_equals && (j < mb1.Length) ) { all_equals = (mb1[ j ] == cat[ j ]); j++; } Assert.IsTrue(all_equals, "Manual equality test mb1"); all_equals = true; j = 0; while( all_equals && (j < mb2.Length) ) { all_equals = (mb2[ j ] == mb2a[ j ]); j++; } Assert.IsTrue(all_equals, "Manual equality test mb2"); all_equals = true; j = 0; while( all_equals && (j < mb2.Length) ) { all_equals = (mb2[ j ] == mb2b[ j ]); j++; } Assert.IsTrue(all_equals, "Manual equality test mb2b"); } }
/** * 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(); byte[] data; for (int i = 0; i < 100; i++) { data = new byte[r.Next(1024)]; r.NextBytes(data); int offset = r.Next(data.Length); MemBlock mb1 = new MemBlock(data, 0, data.Length); MemBlock mb1a = MemBlock.Copy(data, 0, data.Length); Assert.IsTrue(mb1.Equals(mb1a), "MemBlock.Copy"); Assert.IsTrue(mb1.Equals(data), "MemBlock == byte[]"); MemBlock mb2 = new MemBlock(data, offset, data.Length - offset); MemBlock mb2a = mb1.Slice(offset); MemBlock mb3 = new MemBlock(data, 0, offset); MemBlock mb3a = mb1.Slice(0, offset); Assert.IsTrue(mb3.Equals(mb3a), "mb3.Equals(mb3a)"); Assert.IsTrue(mb3a.Equals(mb3), "mb3a.Equals(mb3)"); Assert.IsTrue(mb3.CompareTo(mb2) + mb2.CompareTo(mb3) == 0, "CompareTo"); Assert.IsTrue(mb2.Equals(mb2a), "mb2.Equals(mb2a)"); Assert.IsTrue(mb2a.Equals(mb2), "mb2a.Equals(mb2)"); MemBlock cat = MemBlock.Concat(mb3, mb2); MemBlock cata = MemBlock.Concat(mb3a, mb2a); Assert.IsTrue(cat.Equals(cata), "Concat Equals"); Assert.IsTrue(cata.Equals(cat), "Concat a Equals"); Assert.IsTrue(mb1.Equals(cat), "Concat Equals Original"); if (offset != 0) { //These should not be equal Assert.IsFalse(mb2.Equals(mb1), "mb2 != mb1"); } int mb2a_l = mb2a.Length; byte[] tmp_data = new byte[mb2a_l]; mb2a.CopyTo(tmp_data, 0); MemBlock mb2b = new MemBlock(tmp_data, 0, tmp_data.Length); Assert.IsTrue(mb2a.Equals(mb2b), "mb2a.Equals(mb2b)"); Assert.IsTrue(mb2b.Equals(mb2a), "mb2b.Equals(mb2a)"); //Check the Hash: Assert.IsTrue(mb2b.GetHashCode() == mb2a.GetHashCode(), "GetHashCode"); //Here are some manual equality testing using the indexer bool all_equals = true; int j = 0; while (all_equals && (j < mb1.Length)) { all_equals = (mb1[j] == cat[j]); j++; } Assert.IsTrue(all_equals, "Manual equality test mb1"); all_equals = true; j = 0; while (all_equals && (j < mb2.Length)) { all_equals = (mb2[j] == mb2a[j]); j++; } Assert.IsTrue(all_equals, "Manual equality test mb2"); all_equals = true; j = 0; while (all_equals && (j < mb2.Length)) { all_equals = (mb2[j] == mb2b[j]); j++; } Assert.IsTrue(all_equals, "Manual equality test mb2b"); } }
/** * This is either a request or response. Look up the handler * for it, and pass the packet to the handler */ public void HandleData(MemBlock p, ISender from, object state) { //Is it a request or reply? ReqrepType rt = (ReqrepType)((byte)p[0]); int idnum = NumberSerializer.ReadInt(p,1); MemBlock rest = p.Slice(5); //Skip the type and the id if( rt == ReqrepType.Request || rt == ReqrepType.LossyRequest ) { HandleRequest(rt, idnum, rest, from); } else if( rt == ReqrepType.Reply ) { HandleReply(rt, idnum, rest, from); } else if (rt == ReqrepType.ReplyAck ) { HandleReplyAck(rt, idnum, rest, from); } else if (rt == ReqrepType.RequestAck ) { HandleRequestAck(rt, idnum, rest, from); } else if( rt == ReqrepType.Error ) { HandleError(rt, idnum, rest, from); } }
public void HandleData(MemBlock mb, ISender from, object state) { int len = Header.Length; if( mb.Length >= len ) { var temph = mb.Slice(0, len); if( temph.Equals( Header) ) { Handle(mb.Slice(len), from); return; } } WithoutHeader.Handle(mb, from); }
private static object Deserialize(MemBlock b, int offset, byte term, out bool finished, out int size) { byte typecode = b[offset]; finished = false; //By default, we're not finished switch( typecode ) { case STRING_S: int count; string s = NumberSerializer.ReadString(b, offset + 1, out count); size = count + 1; //add one for the STRING_S byte return s; case LIST_S: IList lst = new ArrayList(); bool lfin; int lsize; size = 1; offset++; //Skip the LIST_S do { object o = Deserialize(b, offset, LIST_E, out lfin, out lsize); if( !lfin ) { //If we are finished, tmp holds a meaningless null lst.Add(o); } offset += lsize; size += lsize; } while( ! lfin ); return lst; case LIST_E: if( term == LIST_E ) { finished = true; size = 1; } else { throw new Exception( String.Format("terminator mismatch: found: {0} expected: {1}", term, LIST_E)); } return null; case MAP_S: //Start of a map: IDictionary dresult = new Hashtable(); bool mfinished = false; int msize; size = 1; offset++; do { //Magical recursion strikes again object key = Deserialize(b, offset, MAP_E, out mfinished, out msize); offset += msize; size += msize; if( !mfinished ) { object valu = Deserialize(b, offset, out msize); offset += msize; size += msize; dresult.Add(key, valu); } } while (false == mfinished); return dresult; case MAP_E: //End of a map: if (term == MAP_E) { //We were reading a list and now we are done: finished = true; size = 1; } else { throw new Exception( String.Format("terminator mismatch: found: {0} expected: {1}", term, MAP_E)); } return null; case TRUE: size = 1; return true; case FALSE: size = 1; return false; case NULL: size = 1; return null; case SBYTE: size = 2; return (sbyte)b[offset + 1]; case BYTE: size = 2; return b[offset + 1]; case SHORT: size = 3; return NumberSerializer.ReadShort(b, offset + 1); case USHORT: size = 3; return (ushort)NumberSerializer.ReadShort(b, offset + 1); case INT: size = 5; return NumberSerializer.ReadInt(b, offset + 1); case UINT: size = 5; return (uint)NumberSerializer.ReadInt(b, offset + 1); case LONG: size = 9; return NumberSerializer.ReadLong(b, offset + 1); case ULONG: size = 9; return (ulong)NumberSerializer.ReadLong(b, offset + 1); case FLOAT: size = 5; return NumberSerializer.ReadFloat(b, offset + 1); case DOUBLE: size = 9; return NumberSerializer.ReadDouble(b, offset + 1); case EXCEPTION_S: //Start of a map: Hashtable eresult = new Hashtable(); bool efinished = false; int esize; size = 1; offset++; do { //Magical recursion strikes again object key = Deserialize(b, offset, EXCEPTION_E, out efinished, out esize); offset += esize; size += esize; if( !efinished ) { object valu = Deserialize(b, offset, out esize); offset += esize; size += esize; eresult.Add(key, valu); } } while (false == efinished); return new AdrException(eresult); case EXCEPTION_E: //End of a map: if (term == EXCEPTION_E) { //We were reading a list and now we are done: finished = true; size = 1; } else { throw new Exception( String.Format("terminator mismatch: found: {0} expected: {1}", term, EXCEPTION_E)); } return null; case ARRAY: //Read length: int asize; object olength = Deserialize(b, offset + 1, out asize); //Due to boxing here, we have to be careful about unboxing, //this will get easier with generics: int length = (int)UnboxToLong(olength); offset += 1 + asize; byte atype = b[offset]; offset++; switch (atype) { case BYTE: byte[] aBresult = new byte[length]; MemBlock b_a = b.Slice(offset, length); b_a.CopyTo(aBresult, 0); size = 1 + asize + 1 + length; return aBresult; case INT: int[] airesult = new int[length]; for(int i = 0; i < airesult.Length; i++) { airesult[i] = NumberSerializer.ReadInt(b, offset); offset += 4; } size = 1 + asize + 1 + 4 * length; return airesult; ///@todo add more array types default: throw new Exception("Unsupported array type code: " + atype); } default: throw new Exception(String.Format("Unrecognized type code: {0}", typecode)); } }
/** * 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; }
/// <summary>Parse an AttributeAddress.</summary> public AttributeAddress(AttributeType type, MemBlock data) : base(type, data) { Family = (FamilyType) data[1]; Port = (ushort) NumberSerializer.ReadShort(data, 2); byte[] addr = new byte[data.Length - 4]; data.Slice(4).CopyTo(addr, 0); IP = new IPAddress(addr); }
/* * Handle the data from our underlying edge */ public void HandleData(MemBlock b, ISender ret, object state) { MemBlock tmp = b.Slice(0, PType.Protocol.Pathing.Length); if(tmp.Equals(PType.Protocol.Pathing.ToMemBlock())) { _pem.HandleData(b, ret, null); return; } ReceivedPacketEvent(b); }
/** * Here we handle routing AHPackets */ public void HandleData(MemBlock data, ISender ret_path, object st) { var header = new AHHeader(data); var payload = data.Slice(header.Length); HandleData(header, payload, ret_path, st); }
/** * Here we handle routing AHPackets */ public void HandleData(MemBlock data, ISender ret_path, object st) { AHState state = _state; //Read the state, it can't change after the read var header = new AHHeader(data); var payload = data.Slice(header.Length); Connection next_con; //Check to see if we can use a Leaf connection: int dest_idx = state.Leafs.IndexOf(header.Destination); if( dest_idx >= 0 ) { next_con = state.Leafs[dest_idx]; } else { var alg = state.GetRoutingAlgo(header); Pair<Connection, bool> result = alg.NextConnection(ret_path as Edge, header); if( result.Second ) { //Send a response exactly back to the node that sent to us var resp_send = new AHSender(_n, ret_path, header.Source, AHSender.DefaultTTLFor(_n.NetworkSize), AHHeader.Options.Exact); _n.HandleData( payload, resp_send, this); } next_con = result.First; } //Send it on: if( next_con != null ) { //Now we do the sending: var new_packet = new CopyList(PType.Protocol.AH, header.IncrementHops(), payload); try { next_con.Edge.Send(new_packet); } catch(EdgeException) { //Just drop the packet... } } }
public void HandleData(MemBlock b, ISender return_path, object state) { //Read the header: uint crc32 = (uint)NumberSerializer.ReadInt(b, 0); int id = NumberSerializer.ReadInt(b, 4); ushort block = (ushort)NumberSerializer.ReadShort(b, 8); MemBlock data = b.Slice(10); var cachekey = new Triple<uint, int, ushort>(crc32, id, block); MemBlock packet = null; lock(_sync) { if( false == _fragments.Contains(cachekey) ) { //This is a new block: _fragments.Add(cachekey, data); var fc_key = new Pair<uint, int>(crc32, id); Fragments this_fc; if( false == _frag_count.TryGetValue(fc_key, out this_fc) ) { this_fc = new Fragments(); _frag_count.Add(fc_key, this_fc); } if( this_fc.AddBlock(block) ) { //We have all of them, decode and clean up: packet = DecodeAndClear(crc32, id, (ushort)this_fc.Total); } } } if( null != packet ) { Handle(packet, return_path); } }