Exemple #1
0
            /// <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));
                }
            }
Exemple #2
0
        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));
            }
        }
Exemple #3
0
            /// <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);
            }
Exemple #4
0
 /// <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);
 }
Exemple #5
0
        /**
         * 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);
            }
        }
Exemple #6
0
 /** 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;
 }
Exemple #7
0
        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);
        }
Exemple #8
0
        /**
         * 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);
        }
Exemple #9
0
        /// <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;
            }
        }
Exemple #10
0
        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;
            }
        }
Exemple #11
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);
            }
        }