// 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); }
// the session event dispatching instance // public event Session.OnPacketReceive sessions; // handle incoming IP packets public NetStatus OnProtocolReceive(NetPacket !pkt) { // handle ICMP messages // --------------------- // start analyzing the request Multiplexer !mux = (!)Core.Instance().GetMuxForAdapter((IAdapter !)pkt.AdapterContext); // IP should have passed us a context which // is the IPHeader... lets see... IPFormat.IPHeader !ipHeader = (IPFormat.IPHeader !)pkt.OverlapContext; // read the icmp header IcmpFormat.IcmpHeader icmpHeader; if (!IcmpFormat.ReadIcmpHeader(pkt, out icmpHeader)) { return(NetStatus.Code.PROTOCOL_OK); } // handle various types switch (icmpHeader.type) { case (byte)IcmpFormat.IcmpType.ECHO_REQUEST: if (icmpHeader.code == 0) { DebugPrint("IcmpModule: Handling ECHO_REQUEST From: {0}", ipHeader.Source); // send reply 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); mux.SendDirect(reply); return(NetStatus.Code.PROTOCOL_OK); } break; default: break; } DebugPrint("IcmpModule: Dispatching packet to Sessions"); // our sessions wants the IP header as well, IP // already shrinked the packet for us so no need // to shrink the packet pkt.Clip(EthernetFormat.Size, ipHeader.totalLength - 1); // fire the event to any interested sessions // (we could also use Core.Instance().Sessions to // choose a specific session...) // if (sessions != null) //{ //sessions(this, pkt, icmpHeader); //} return(NetStatus.Code.PROTOCOL_OK); }