/// <summary>Converts an attribute into a specific type if a parser exists /// for it, otherwise stuffs it into a generic Attribute object.</summary> public static Attribute Parse(MemBlock data) { if (4 > data.Length) { throw new Exception("Poorly formed packet"); } ushort type = (ushort)NumberSerializer.ReadShort(data, 0); ushort length = (ushort)NumberSerializer.ReadShort(data, 2); if (4 + length > data.Length) { throw new Exception("Poorly formed packet"); } MemBlock att_data = MemBlock.Reference(data, 4, length); AttributeType attype = (AttributeType)type; if (attype == AttributeType.MappedAddress || attype == AttributeType.ResponseAddress || attype == AttributeType.ChangeAddress || attype == AttributeType.SourceAddress) { return(new AttributeAddress(attype, att_data)); } switch (attype) { default: return(new Attribute(attype, att_data)); } }
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, new FragmentingSender(DEFAULT_SIZE, return_path)); } }
/// <summary>Parse an Attribute.</summary> public Attribute(MemBlock data) { Data = data; Type = (AttributeType)((ushort)NumberSerializer.ReadShort(data, 0)); ushort length = (ushort)NumberSerializer.ReadShort(data, 2); Value = MemBlock.Reference(data, 4, length); }
/// <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); }
/** * Read the address out of the buffer This makes a copy * and calls Parse on the copy. This is a "convienience" method. * @throw ParseException if the buffer is not a valid address */ static public Address Parse(MemBlock mb) { //Read some of the least significant bytes out, //AHAddress all have last bit 0, so we skip the last byte which //will have less entropy ushort idx = (ushort)NumberSerializer.ReadShort(mb, Address.MemSize - 3); Address a = _mb_cache[idx]; if (a != null) { if (a.ToMemBlock().Equals(mb)) { return(a); } } //Else we need to read the address and put it in the cache try { if (2 * mb.Length < mb.ReferencedBufferLength) { /* * This MemBlock is much smaller than the array * we are referencing, don't keep the big one * in scope, instead make a copy */ mb = MemBlock.Copy((ICopyable)mb); } int add_class = Address.ClassOf(mb); switch (add_class) { case AHAddress.ClassValue: a = new AHAddress(mb); break; case DirectionalAddress.ClassValue: a = new DirectionalAddress(mb); break; default: a = null; throw new ParseException("Unknown Address Class: " + add_class + ", buffer:" + mb.ToString()); } //Cache this result: _mb_cache[idx] = a; return(a); } catch (ArgumentOutOfRangeException ex) { throw new ParseException("Address too short: " + mb.ToString(), ex); } catch (ArgumentException ex) { throw new ParseException("Could not parse: " + mb.ToString(), ex); } }
/** 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 ArpPacket(MemBlock Packet) { _icpacket = _packet = Packet; HardwareType = NumberSerializer.ReadShort(Packet, 0); ProtocolType = NumberSerializer.ReadShort(Packet, 2); int hw_len = Packet[4]; int proto_len = Packet[5]; Operation = (Operations)NumberSerializer.ReadShort(Packet, 6); int pos = 8; SenderHWAddress = MemBlock.Reference(Packet, pos, hw_len); pos += hw_len; SenderProtoAddress = MemBlock.Reference(Packet, pos, proto_len); pos += proto_len; TargetHWAddress = MemBlock.Reference(Packet, pos, hw_len); pos += hw_len; TargetProtoAddress = MemBlock.Reference(Packet, pos, proto_len); }
/** * Factory method to reduce memory allocations by caching * commonly used NodeInfo objects */ public static NodeInfo CreateInstance(Address a) { //Read some of the least significant bytes out, //AHAddress all have last bit 0, so we skip the last byte which //will have less entropy MemBlock mb = a.ToMemBlock(); ushort idx = (ushort)NumberSerializer.ReadShort(mb, Address.MemSize - 3); NodeInfo ni = _mb_cache[idx]; if (ni != null) { if (a.Equals(ni._address)) { return(ni); } } ni = new NodeInfo(a); _mb_cache[idx] = ni; return(ni); }
/// <summary>Parse a Stun packet.</summary> public StunPacket(MemBlock packet) { if ((packet[0] & ZERO_MASK) != 0) { throw new Exception("Invalid packet, initial bits are not 0"); } else if (packet.Length < MINIMUM_SIZE) { throw new Exception("Invalid packet, too small"); } Data = packet; ushort message = (ushort)NumberSerializer.ReadShort(packet, 0); Class = (ClassType)(CLASS_MASK & message); Message = (MessageType)(MESSAGE_MASK & message); TransactionID = MemBlock.Reference(packet, 8, 12); int offset = MINIMUM_SIZE; if (packet.Length > MINIMUM_SIZE) { Attributes = new List <Attribute>(); // Attributes while (offset < packet.Length) { MemBlock attrm = MemBlock.Reference(packet, offset, packet.Length - offset); Attribute attr = Attribute.Parse(attrm); offset += attr.Data.Length; Attributes.Add(attr); } } else { Attributes = EMPTY_ATTRIBUTES; } }
public IcmpPacket(MemBlock Packet) { if (Packet.Length < 4) { throw new Exception("Icmp: Not long enough!"); } _icpacket = Packet; _packet = Packet; Type = (Types)Packet[0]; Code = Packet[1]; if (Packet.Length >= 8) { Identifier = NumberSerializer.ReadShort(Packet, 4); SequenceNumber = NumberSerializer.ReadShort(Packet, 6); } else { Identifier = 0; SequenceNumber = 0; } }
/** * Do as much of a read as we can * @return true if the socket is still ready, false if we should close * the edge. */ public bool Receive() { int got = 0; int avail = 0; do { if (Buffer == null) { //Time to read the size: Reset(_ba.Buffer, _ba.Offset, 2, true); _ba.AdvanceBuffer(2); } try { got = _s.Receive(Buffer, CurrentOffset, RemainingLength, SocketFlags.None); avail = _s.Available; } catch (SocketException) { //Some OS error, just close the edge: Buffer = null; return(false); } if (got == 0) { //this means the edge is closed: return(false); } CurrentOffset += got; RemainingLength -= got; if (RemainingLength == 0) { //Time to do some action: if (ReadingSize) { short size = NumberSerializer.ReadShort(Buffer, Offset); if (size <= 0) { //This doesn't make sense, later we might use this to code //something else return(false); } //Start to read the packet and the duplicate size value at the //end Reset(_ba.Buffer, _ba.Offset, size + 2, false); _ba.AdvanceBuffer(size + 2); } else { try { short size = NumberSerializer.ReadShort(Buffer, Offset + Length - 2); if (size == Length - 2) { Edge.ReceivedPacketEvent(MemBlock.Reference(Buffer, Offset, size)); } else { //The packet seems to have an error: string err_msg = String.Format("ERROR Packet length mismatch: Edge: {0}; size: {1} != {2}; Packet: {3}", Edge, Length - 2, size, System.Convert.ToBase64String(Buffer, Offset, Length)); ProtocolLog.Write(ProtocolLog.Monitor, err_msg); //Close the edge return(false); } } catch (EdgeClosedException) { return(false); } finally { //Drop the reference and signal we are ready to read the next //size Buffer = null; } } } } while(avail > 0); return(true); }
/** * 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); } }