--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/iphook/inhook6/src/posthook.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,381 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// posthook.cpp - Base class for post hooks (implementation)
+//
+
+#include <e32std.h>
+#include <e32base.h>
+
+#include "posthook.h"
+
+EXPORT_C CProtocolPosthook::~CProtocolPosthook()
+ /**
+ * Destructor
+ *
+ * If this object is still attached to the network layer,
+ * the attachement and all bindings to the network layer
+ * from this protocol object are cancelled.
+ */
+ {
+ if (iNetwork != NULL)
+ {
+ CProtocolInet6Binder *const prt = iNetwork->Protocol();
+ iNetwork = NULL;
+ prt->Unbind(this);
+ if (iBindToNet)
+ prt->Close();
+ }
+ }
+
+EXPORT_C void CProtocolPosthook::BindL(CProtocolBase* aProtocol, TUint aId)
+ /**
+ * Handles network layer binds.
+ *
+ * This function handles the network layer detection and posthook
+ * chaining binds. The processing is based on the following
+ * "well known" id values:
+ *
+ * - MIp6Hook::BindPostHook() (for outbound posthook chaining)
+ * - MIp6Hook::BindPreHook() (for inbound posthook chaining)
+ * - #KProtocolInet6Ip (aProtocol must be network instance)
+ * - #KProtocolInetIp (aProtocol must be network instance, deprecated)
+ *
+ * If the aId does not match any of the above, the BindL is
+ * silently ignored (just return happens). This is quite OK,
+ * there is no need to generate an error in such case.
+ *
+ * This network layer detection is only used in a configuration, where
+ * this protocol is bound from the network layer (ip6). Such configuration
+ * will keep this protocol module installed whenever the network is loaded.
+@verbatim
+[yourposthook]
+filename= yourposthook.prt
+index= 1
+bindfrom= ip6
+@endverbatim
+ *
+ * @note
+ * This protocol can be loaded even if network is not. If the
+ * protocol provides a SAP functionality, an application can
+ * open a socket to this protocol without the network layer
+ * being started.
+ *
+ * The derived class <b>only</b> needs to override the default
+ * implementation if it appears as a target of "bindto" directive
+ * in a ESK file of another protocol (except the network layer),
+ * <b>and if</b> the implementation needs to store a reference
+ * to this protocol. In such case the BindL could be, for example:
+@code
+ CProtocolBase *iAnother;
+
+ CProtocolDerivedHook::BindL(CProtocolBase *aProtocol, TUint aId)
+ {
+ if (aId == your_special_binding_protocol)
+ {
+ // handle your bind
+ iAnother = aProtocol;
+ }
+ // The default should always be called,
+ CProtocolPosthook::BindL(aProtocol, aId);
+ }
+@endcode
+ * @param aProtocol The protocol binding to this.
+ * @param aId The bind id.
+ */
+ {
+ if (iNetwork == NULL && // Only the first network bind is accepted here
+ (aId == KProtocolInet6Ip || aId == KProtocolInetIp))
+ {
+ // Make sure the aProtocol is really the network layer: require
+ // that the aId the is same as the one defined in protocol
+ // description.
+ TServerProtocolDesc info;
+ aProtocol->Identify(&info);
+ if (info.iProtocol == aId)
+ {
+ //
+ // Hook is loaded via a bindto from network layer
+ //
+ iNetwork = ((CProtocolInet6Binder *)aProtocol)->NetworkService();
+ NetworkAttachedL();
+ return;
+ }
+ }
+ if (aId == MIp6Hook::BindPostHook())
+ {
+ // Maintain outbound post hook chaining
+ iPostHook = aProtocol;
+ return;
+ }
+ if (aId == MIp6Hook::BindPreHook())
+ {
+ // Maintain inbound post hook chaining
+ iInboundHook = aProtocol;
+ return;
+ }
+ }
+
+EXPORT_C void CProtocolPosthook::Unbind(CProtocolBase *aProtocol, TUint aId)
+ /**
+ * Handles network layer unbinds.
+ *
+ * This function handles the network layer unbind and posthook
+ * chaining unbinds. The processing is based on the following
+ * "well known" bind id values:
+ *
+ * - MIp6Hook::BindPostHook() (for outbound posthook chaining)
+ * - MIp6Hook::BindPreHook() (for inbound posthook chaining)
+ * - #KProtocolInet6Ip (for the network intance)
+ * - #KProtocolInetIp (for network instance, deprecated)
+ * - 0 (unbind all)
+ *
+ * If the aId does not match any of the above, the Unbind is
+ * silently ignored (just return happens). This is quite OK,
+ * there is no need to generate an error in such case.
+ *
+ * The derived class needs to override the default implementation
+ * only if it is bound from another protocol (except the network layer)
+ * and if class also overrode the CProtocolPosthook::BindL and saved
+ * a pointer to this protocol. For example:
+@code
+ CProtocolDerivedHook::Unbind(CProtocolBase *aProtocol, TUint aId)
+ {
+ if (iAnother == aProtocol &&
+ (aId == 0 || aId == your_special_binding_protocol))
+ {
+ // handle your unbind
+ iAnotherProtocol = NULL;
+ }
+ // The default should always be called,
+ CProtocolPosthook::Unbind(aProtocol, aId);
+ }
+@endcode
+ * @param aProtocol The protocol unbinding from this.
+ * @param aId The bind id.
+ */
+ {
+ if (!iBindToNet &&
+ iNetwork != NULL &&
+ iNetwork->Protocol() == aProtocol &&
+ (aId == 0 || aId == KProtocolInet6Ip || aId == KProtocolInetIp))
+ {
+ NetworkDetached();
+ iNetwork = 0;
+ }
+ if (iPostHook == aProtocol && (aId == 0 || aId == MIp6Hook::BindPostHook()))
+ iPostHook = 0;
+ if (iInboundHook == aProtocol && (aId == 0 || aId == MIp6Hook::BindPostHook()+1))
+ iInboundHook = 0;
+ }
+
+// CProtocolPosthook::DoBindToL
+// ****************************
+
+EXPORT_C TInt CProtocolPosthook::DoBindToL(CProtocolBase *aProtocol)
+ /**
+ * Handle network layer bindto.
+ *
+ * Performs the BindToL processing for the network detection.
+ * This network layer detection is only used in a configuration,
+ * where the "bindto" list of this protocol includes the network
+ * layer (ip6). In this configuration, the network layer
+ * stays installed whenever this protocol is loaded.
+ *
+ * @note
+ * Network can be loaded without this protocol being loaded.
+ *
+ * @param aProtocol The protocol to bind to.
+ * @return KErrNone or the id of the protocol.
+ * - KErrNone (= 0),
+ * BindTo processed (it was the network bind, NetworkAttachedL has
+ * been called.)
+ * - protocol id ( != 0) from the aProtocol, which was not the network
+ *
+ * @note
+ * The protocol id is TUint. However, this method is defined
+ * to return TInt The function should be considered to return
+ * TUint and any non-zero value means that the protocol was not
+ * the network. [returning TInt instead of TUint is a mistake].
+ *
+ * This function exists for derived classes that override the default
+ * BindToL for their own processing. See ::BindToL for example.
+ */
+ {
+ TServerProtocolDesc info;
+ aProtocol->Identify(&info);
+ const TUint id = info.iProtocol;
+ if (iNetwork == NULL && (id == KProtocolInetIp || id == KProtocolInet6Ip))
+ {
+ iNetwork = ((CProtocolInet6Binder *)aProtocol)->NetworkService();
+ aProtocol->Open();
+ iBindToNet = 1; // Network layer bind via BindTo.
+ // Note: when the hook binds to network, NetworkDetached is never
+ // called, because network can never exit before this hook, the
+ // event never happens while this hook is running.
+ NetworkAttachedL();
+ return KErrNone;
+ }
+ return id;
+ }
+
+// CProtocolPosthook::BindToL
+// **************************
+EXPORT_C void CProtocolPosthook::BindToL(CProtocolBase *aProtocol)
+ /**
+ * The default implementation.
+ *
+ * This implemenation only handles the network bind and leaves
+ * with #KErrNotSupported if the protocol is not the network
+ * instance.
+ *
+ * If the "bindto" list of this protocol can have other protocols
+ * than the network (ip6), then the derived class must implement the
+ * support for it. For example
+@code
+ CProtocolDerivedHook::BindToL(CProtocolBase *aProtocol)
+ {
+ const TInt id = DoBindToL(aProtocol);
+ if (id == (TInt)your_special_protocol)
+ {
+ //
+ if (iBindTo)
+ iBindTo->Close();
+ iBindTo = aProtocol;
+ iBindTo->Open();
+ // Destructor must issue Close, if iBindTo is non-NULL
+ }
+ else if (id != KErrNone)
+ User::Leave(KErrNotSupported);
+ }
+@endcode
+ */
+ {
+ if (DoBindToL(aProtocol) != KErrNone)
+ User::Leave(KErrNotSupported);
+ }
+
+EXPORT_C TInt CProtocolPosthook::Send(RMBufChain &aPacket, CProtocolBase* aSrc)
+ /**
+ * Send packet to the next protocol.
+ *
+ * Send passes the outbound packet to the next post-processing hook
+ * (#iPostHook).
+ * The derived post-processing hook can ímplement own Send, After
+ * processing the packet, it would normally call CProtocolPosthook::Send
+ * to pass the packet forward (note that the information block is
+ * RMBufSendInfo and the attached flow context (RFlowContext)
+ * <b>must be closed</b>, if the packet is deleted):
+@code
+ TInt CProtocolDerivedHook::Send(RMBufChain &aPacket, CProtocolBase *aSrc)
+ {
+ ...
+ // Do own packet processing
+
+ if (packet_is_dropped)
+ {
+ RMBufSendInfo *info = RMBufSendPacket::PeekInfoInChain(aPacket);
+ if (info)
+ info->iFlow.Close();
+ aPacket.Free();
+ return 1;
+ }
+ else
+ return CProtocolPosthook::Send(aPacket, aSrc);
+ }
+@endcode
+ * Hook will receive and pass forward the outbound packets only if
+ * it has a binding to the network layer as a post-processinghook:
+@code
+ NetworkService()->BindL(this, MIp6Hook::BindPostHook());
+@endcode
+ *
+ * @note
+ * The network layer currently sends packets with aSrc == NULL.
+ * This may change in future (the network instance is used
+ * instead).
+ *
+ * If hook is configured to receive packets to Send function from some
+ * other protocol than the network layer, then it can use the aSrc to
+ * detect this and <b>NOT</B> call this default implementation for such
+ * packets (unless it intends to inject them to the outbound packet
+ * stream).
+ *
+ * Hook will receive outbound packets from the network layer only if
+ * it binds as post-processing hook.
+ *
+ * @param aPacket The outbound packet.
+ * @param aSrc The originating protocol (or NULL).
+ *
+ * @pre RMBufSendPacket::PeekInfoInChain(aPacket).iFlow.IsOpen()
+ */
+ {
+ if (iPostHook)
+ return iPostHook->Send(aPacket, aSrc);
+
+ //
+ // Nobody to forward, consume the packet
+ //
+ RMBufSendInfo *info = RMBufSendPacket::PeekInfoInChain(aPacket);
+ if (info)
+ info->iFlow.Close();
+ aPacket.Free();
+ return 1;
+ }
+
+EXPORT_C void CProtocolPosthook::Process(RMBufChain &aPacket, CProtocolBase* aSrc)
+ /**
+ * Process incoming packet.
+ *
+ * Process passes the inbound packet to the next pre-processing hook
+ * (#iInboundHook).
+ * The derived pre-processing hook can implement own Process. After processing
+ * the packet, it would normally call CProtocolPosthook::Process to pass
+ * the packet forward (note that the information block is the basic RMBufPktInfo).
+@code
+ TInt CProtocolDerivedHook::Process(RMBufChain &aPacket, CProtocolBase *aSrc)
+ {
+ // Do own packet processing.
+
+ RMBufPktInfo *info = RMBufPacketBase::PeekInfoInChain(aPacket);
+ ...
+ if (packet_is_dropped)
+ aPacket.Free();
+ else
+ CProtocolPosthook::Process(aPacket, aSrc);
+ }
+@endcode
+ * Hook will receive and pass forward inbound packets only if it has
+ * bound as pre-processing hook:
+@code
+ NetworkService()->BindL(this, MIp6Hook::BindPreHook());
+@endcode
+ *
+ * @note
+ * For inbound packets, the aSrc is the NIF object (derived from
+ * CNifIfBase and not from CProtocolBase.).
+ * @note
+ * The implementation <b>SHOULD NOT</b> change the aSrc. But, if it
+ * does change the source, the new source must also be a NIF pointer,
+ * and that NIF must also be known to the TCP/IP stack.
+ *
+ * @param aPacket The inbound packet
+ * @param aSrc The originating NIF
+ */
+ {
+ if (iInboundHook)
+ iInboundHook->Process(aPacket, aSrc);
+ else
+ aPacket.Free();
+ }
+