Esempio n. 1
0
        /**
         * Implements the EdgeListener function to
         * create edges of this type.
         */
        public override void CreateEdgeTo(TransportAddress ta, EdgeCreationCallback ecb)
        {
            Edge      e  = null;
            Exception ex = null;

            if (!IsStarted)
            {
                ex = new EdgeException("UdpEdgeListener is not started");
            }
            else if (ta.TransportAddressType != this.TAType)
            {
                ex = new EdgeException(ta.TransportAddressType.ToString()
                                       + " is not my type: " + this.TAType.ToString());
            }
            else if (_ta_auth.Authorize(ta) == TAAuthorizer.Decision.Deny)
            {
                ex = new EdgeException(ta.ToString() + " is not authorized");
            }
            else
            {
                IPAddress  first_ip = ((IPTransportAddress)ta).GetIPAddress();
                IPEndPoint end      = new IPEndPoint(first_ip, ((IPTransportAddress)ta).Port);
                /* We have to keep our mapping of end point to edges up to date */
                lock ( _id_ht ) {
                    //Get a random ID for this edge:
                    int id;
                    do
                    {
                        id = _rand.Next();
                        //Make sure we don't have negative ids
                        if (id < 0)
                        {
                            id = ~id;
                        }
                    } while(_id_ht.Contains(id) || id == 0);
                    e          = new UdpEdge(this, false, end, _local_ep, id, 0);
                    _id_ht[id] = e;
                }
                NatDataPoint dp = new NewEdgePoint(DateTime.UtcNow, e);
                Interlocked.Exchange <NatHistory>(ref _nat_hist, _nat_hist + dp);
                Interlocked.Exchange <IEnumerable>(ref _nat_tas, new NatTAs(_tas, _nat_hist));

                try {
                    /* Tell me when you close so I can clean up the table */
                    e.CloseEvent += this.CloseHandler;
                } catch (Exception x) {
                    e  = null;
                    ex = x;
                }
            }

            if (e != null)
            {
                ecb(true, e, null);
            }
            else
            {
                ecb(false, null, ex);
            }
        }
Esempio n. 2
0
        /**
         * This reads a packet from buf which came from end, with
         * the given ids
         */
        protected void HandleDataPacket(int remoteid, int localid,
                                        MemBlock packet, EndPoint end, object state)
        {
            bool read_packet = true;
            bool is_new_edge = false;
            //It is threadsafe to read from Hashtable
            UdpEdge edge = (UdpEdge)_id_ht[localid];

            if (localid == 0)
            {
                //This is a potentially a new incoming edge
                is_new_edge = true;

                //Check to see if it is a dup:
                UdpEdge e_dup = (UdpEdge)_remote_id_ht[remoteid];
                if (e_dup != null)
                {
                    //Lets check to see if this is a true dup:
                    if (e_dup.End.Equals(end))
                    {
                        //Same id from the same endpoint, looks like a dup...
                        is_new_edge = false;
                        //Reuse the existing edge:
                        edge = e_dup;
                    }
                    else
                    {
                        //This is just a coincidence.
                    }
                }
                if (is_new_edge)
                {
                    TransportAddress rta = TransportAddressFactory.CreateInstance(this.TAType, (IPEndPoint)end);
                    if (_ta_auth.Authorize(rta) == TAAuthorizer.Decision.Deny)
                    {
                        //This is bad news... Ignore it...
                        ///@todo perhaps we should send a control message... I don't know
                        is_new_edge = false;
                        read_packet = false;
                        if (ProtocolLog.UdpEdge.Enabled)
                        {
                            ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format(
                                                  "Denying: {0}", rta));
                        }
                    }
                    else
                    {
                        //We need to assign it a local ID:
                        lock ( _id_ht ) {
                            /*
                             * Now we need to lock the table so that it cannot
                             * be written to by anyone else while we work
                             */
                            do
                            {
                                localid = _rand.Next();
                                //Make sure not to use negative ids
                                if (localid < 0)
                                {
                                    localid = ~localid;
                                }
                            } while(_id_ht.Contains(localid) || localid == 0);

                            /*
                             * We copy the endpoint because (I think) .Net
                             * overwrites it each time.  Since making new
                             * edges is rare, this is better than allocating
                             * a new endpoint each time
                             */
                            IPEndPoint this_end = (IPEndPoint)end;
                            IPEndPoint my_end   = new IPEndPoint(this_end.Address,
                                                                 this_end.Port);
                            edge = new UdpEdge(_send_handler, true, my_end,
                                               _local_ep, localid, remoteid);
                            _id_ht[localid]         = edge;
                            _remote_id_ht[remoteid] = edge;
                        }
                    }
                }
            }
            else if (edge == null)
            {
                /*
                 * This is the case where the Edge is not a new edge,
                 * but we don't know about it.  It is probably an old edge
                 * that we have closed.  We can ignore this packet
                 */
                read_packet = false;
                //Send a control packet
                SendControlPacket(end, remoteid, localid, ControlCode.EdgeClosed, state);
            }
            else if (edge.RemoteID == 0)
            {
                /* This is the response to our edge creation */
                edge.RemoteID = remoteid;
            }
            else if (edge.RemoteID != remoteid)
            {
                /*
                 * This could happen as a result of packet loss or duplication
                 * on the first packet.  We should ignore any packet that
                 * does not have both ids matching.
                 */
                read_packet = false;
                //Tell the other guy to close this ignored edge
                SendControlPacket(end, remoteid, localid, ControlCode.EdgeClosed, state);
                edge = null;
            }
            if ((edge != null) && !edge.End.Equals(end))
            {
                //This happens when a NAT mapping changes
                if (ProtocolLog.UdpEdge.Enabled)
                {
                    ProtocolLog.Write(ProtocolLog.UdpEdge, String.Format(
                                          "Remote NAT Mapping changed on Edge: {0}\n{1} -> {2}",
                                          edge, edge.End, end));
                }
                //Actually update:
                TransportAddress rta = TransportAddressFactory.CreateInstance(this.TAType, (IPEndPoint)end);
                if (_ta_auth.Authorize(rta) != TAAuthorizer.Decision.Deny)
                {
                    IPEndPoint this_end = (IPEndPoint)end;
                    edge.End = new IPEndPoint(this_end.Address, this_end.Port);
                    NatDataPoint dp = new RemoteMappingChangePoint(DateTime.UtcNow, edge);
                    Interlocked.Exchange <NatHistory>(ref _nat_hist, _nat_hist + dp);
                    Interlocked.Exchange <IEnumerable>(ref _nat_tas, new NatTAs(_tas, _nat_hist));
                    //Tell the other guy:
                    SendControlPacket(end, remoteid, localid, ControlCode.EdgeDataAnnounce, state);
                }
                else
                {
                    /*
                     * Looks like the new TA is no longer authorized.
                     */
                    SendControlPacket(end, remoteid, localid, ControlCode.EdgeClosed, state);
                    RequestClose(edge);
                    CloseHandler(edge, null);
                }
            }
            if (is_new_edge)
            {
                try {
                    NatDataPoint dp = new NewEdgePoint(DateTime.UtcNow, edge);
                    Interlocked.Exchange <NatHistory>(ref _nat_hist, _nat_hist + dp);
                    Interlocked.Exchange <IEnumerable>(ref _nat_tas, new NatTAs(_tas, _nat_hist));
                    edge.CloseEvent += this.CloseHandler;
                    //If we make it here, the edge wasn't closed, go ahead and process it.
                    SendEdgeEvent(edge);
                    // Stun support
                    SendControlPacket(end, remoteid, localid, ControlCode.EdgeDataAnnounce, state);
                }
                catch {
                    //Make sure this edge is closed and we are done with it.
                    RequestClose(edge);
                    CloseHandler(edge, null);
                    read_packet = false;
                    //This was a new edge, so the other node has our id as zero, send
                    //with that localid:
                    SendControlPacket(end, remoteid, 0, ControlCode.EdgeClosed, state);
                }
            }
            if (read_packet)
            {
                //We have the edge, now tell the edge to announce the packet:
                try {
                    edge.ReceivedPacketEvent(packet);
                }
                catch (EdgeClosedException) {
                    SendControlPacket(end, remoteid, localid, ControlCode.EdgeClosed, state);
                    //Make sure we record that this edge has been closed
                    CloseHandler(edge, null);
                }
            }
        }