예제 #1
0
        // override the OnReceive
        override internal NetStatus OnReceive(object sender, NetPacket pkt, object ctx)
        {
#if DEBUG
            Console.Out.WriteLine("PrivateIcmpSession:OnReceived, flow capacity={0}", capacity);
#endif
            Debug.Assert(ctx != null);
            NetStatus             res        = NetStatus.Code.PROTOCOL_OK;
            IcmpFormat.IcmpHeader icmpHeader = (IcmpFormat.IcmpHeader)ctx;
            IPFormat.IPHeader     ipHeader   = pkt.OverlapContext as IPFormat.IPHeader;
            Multiplexer           mux        = pkt.AdapterContext as Multiplexer; // source mux
            Debug.Assert(ipHeader != null && mux != null);
            bool handled = false;

            // handle various types
            switch (icmpHeader.type)
            {
            case (byte)IcmpFormat.IcmpType.ECHO_REQUEST:
                if (icmpHeader.code == 0)
                {
#if DEBUG_IP
                    Console.WriteLine("PrivateIcmpSession: Handling ECHO_REQUEST From: {0}", ipHeader.srcAddrIP);
#endif
                    // send reply
                    // clone it since some session may use it (it is readonly!)
                    int     length  = pkt.Length();
                    byte [] pktData = new byte [length];
                    Array.Copy(pkt.GetRawData(), 0, pktData, 0, length);

                    IcmpFormat.CreateFastEchoReply(
                        pktData,
                        ipHeader.totalLength - IPFormat.Size
                        );
                    NetPacket reply = new NetPacket(pktData);
                    reply.SessionContext = this;
                    mux.Send(reply);
                    handled = true;
                }
                break;

            default:
                break;
            }
            // return the original packet (no use for it anymore)
            pkt.ReleaseRef();
            // only increment the session capacity
            // if this is not ours..
            // this way we apply back pressure and only
            // increase the capacity once sending is done!
            if (!handled)
            {
                capacity++;
            }
#if DEBUG
            Console.Out.WriteLine("PrivateIcmpSession:OnReceived FINISHED, flow capacity={0}", capacity);
#endif
            return(res);
        }
예제 #2
0
        // Find the relevant session for this connection
        protected TcpSession FindSession(IPFormat.IPHeader !ipHeader,
                                         ref TcpFormat.TcpHeader tcpHeader)
        {
            // Get the session table
            ArrayList sessions = Core.Instance().GetSessions(this);

            if (sessions == null)
            {
                return(null);
            }

            // First priority is a full match (Loc/Rem X Addr/Port all match),
            //  but next priority is a "passive" match (a Broadcast to "me").
            TcpSession passiveSession = null;  // this is the passive session

            lock (sessions.SyncRoot) {
                // BUGBUG: This should use HashTables (KeyedCollections  // TODO
                // BUGBUG:  if we get Generics) for Performance reasons. // TODO
                // BUGBUG:  We need one for full and one for passive.    // TODO
                // BUGBUG:  The full hashtable uses local and remote     // TODO
                // BUGBUG:  addresses as the keys and can be limited to  // TODO
                // BUGBUG:  sessions without Remote Broadcast addresses; // TODO
                // BUGBUG:  the passive hashtable is limited to sessions // TODO
                // BUGBUG:  with Remote Broadcast addresses and uses the // TODO
                // BUGBUG:  local address only as the key.               // TODO
                // BUGBUG: Note that this is done for every TCP Packet.  // TODO
                foreach (TcpSession !tcpSession in sessions)
                {
                    bool matchLocal =
                        (tcpSession.LocalAddress == ipHeader.Destination) &&
                        (tcpSession.LocalPort == tcpHeader.destPort);

                    // Both full and passive matches require full Local match.
                    if (matchLocal)
                    {
                        // Check the Remote Match for a Full Match
                        bool matchRemote =
                            (tcpSession.RemoteAddress == ipHeader.Source) &&
                            (tcpSession.RemotePort == tcpHeader.sourcePort);

                        // If a full match (local && remote) return the session.
                        if (matchRemote)
                        {
                            return(tcpSession);
                        }

                        // Check for "Broadcast" address.
                        bool matchBroadcast =
                            (tcpSession.RemoteAddress == IPv4.Broadcast) &&
                            (tcpSession.RemotePort == 0);

                        // No full match, but save passiveSession
                        //  if matchLocal && matchBroadcast.
                        if (matchBroadcast)
                        {
                            passiveSession = tcpSession;
                        }
                    }
                }
            }

            // If we didn't find an exact match, return
            //  the passive match, if any (may be null).
            return(passiveSession);
        }