// 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); }
// 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); }