diff -r 000000000000 -r af10295192d8 networkprotocols/iphook/inhook6/src/posthook.cpp --- /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 +#include + +#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 only 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), + * and if 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) + * must be closed, 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 NOT 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 SHOULD NOT 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(); + } +