networkprotocols/iphook/inhook6/src/posthook.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // posthook.cpp - Base class for post hooks (implementation)
       
    15 //
       
    16 
       
    17 #include <e32std.h>
       
    18 #include <e32base.h>
       
    19 
       
    20 #include "posthook.h"
       
    21 
       
    22 EXPORT_C CProtocolPosthook::~CProtocolPosthook()
       
    23 	/**
       
    24 	* Destructor
       
    25 	*
       
    26 	* If this object is still attached to the network layer,
       
    27 	* the attachement and all bindings to the network layer
       
    28 	* from this protocol object are cancelled.
       
    29 	*/
       
    30 	{
       
    31 	if (iNetwork != NULL)
       
    32 		{
       
    33 		CProtocolInet6Binder *const prt = iNetwork->Protocol();
       
    34 		iNetwork = NULL;
       
    35 		prt->Unbind(this);
       
    36 		if (iBindToNet)
       
    37 			prt->Close();
       
    38 		}
       
    39 	}
       
    40 
       
    41 EXPORT_C void CProtocolPosthook::BindL(CProtocolBase* aProtocol, TUint aId)
       
    42 	/**
       
    43 	* Handles network layer binds.
       
    44 	*
       
    45 	* This function handles the network layer detection and posthook
       
    46 	* chaining binds. The processing is based on the following
       
    47 	* "well known" id values:
       
    48 	*
       
    49 	* - MIp6Hook::BindPostHook() (for outbound posthook chaining)
       
    50 	* - MIp6Hook::BindPreHook() (for inbound posthook chaining)
       
    51 	* - #KProtocolInet6Ip (aProtocol must be network instance)
       
    52 	* - #KProtocolInetIp (aProtocol must be network instance, deprecated)
       
    53 	*
       
    54 	* If the aId does not match any of the above, the BindL is
       
    55 	* silently ignored (just return happens). This is quite OK,
       
    56 	* there is no need to generate an error in such case.
       
    57 	*
       
    58 	* This network layer detection is only used in a configuration, where
       
    59 	* this protocol is bound from the network layer (ip6). Such configuration
       
    60 	* will keep this protocol module installed whenever the network is loaded.
       
    61 @verbatim
       
    62 [yourposthook]
       
    63 filename= yourposthook.prt
       
    64 index= 1
       
    65 bindfrom= ip6
       
    66 @endverbatim
       
    67 	*
       
    68 	* @note
       
    69 	*	This protocol can be loaded even if network is not. If the
       
    70 	*	protocol provides a SAP functionality, an application can
       
    71 	*	open a socket to this protocol without the network layer
       
    72 	*	being started.
       
    73 	*
       
    74 	* The derived class <b>only</b> needs to override the default
       
    75 	* implementation if it appears as a target of "bindto" directive
       
    76 	* in a ESK file of another protocol (except the network layer),
       
    77 	* <b>and if</b> the implementation needs to store a reference
       
    78 	* to this protocol. In such case the BindL could be, for example:
       
    79 @code
       
    80 	CProtocolBase *iAnother;
       
    81 
       
    82 	CProtocolDerivedHook::BindL(CProtocolBase *aProtocol, TUint aId)
       
    83 		{
       
    84 		if (aId == your_special_binding_protocol)
       
    85 			{
       
    86 			// handle your bind
       
    87 			iAnother = aProtocol;
       
    88 			}
       
    89 		// The default should always be called,
       
    90 		CProtocolPosthook::BindL(aProtocol, aId);
       
    91 		}
       
    92 @endcode
       
    93 	* @param aProtocol	The protocol binding to this.
       
    94 	* @param aId		The bind id.
       
    95 	*/
       
    96 	{
       
    97 	if (iNetwork == NULL &&	// Only the first network bind is accepted here
       
    98 		(aId == KProtocolInet6Ip || aId == KProtocolInetIp))
       
    99 		{
       
   100 		// Make sure the aProtocol is really the network layer: require
       
   101 		// that the aId the is same as the one defined in protocol
       
   102 		// description.
       
   103 		TServerProtocolDesc info;
       
   104 		aProtocol->Identify(&info);
       
   105 		if (info.iProtocol == aId)
       
   106 			{
       
   107 			//
       
   108 			// Hook is loaded via a bindto from network layer
       
   109 			//
       
   110 			iNetwork = ((CProtocolInet6Binder *)aProtocol)->NetworkService();
       
   111 			NetworkAttachedL();
       
   112 			return;
       
   113 			}
       
   114 		}
       
   115 	if (aId == MIp6Hook::BindPostHook())
       
   116 		{
       
   117 		// Maintain outbound post hook chaining
       
   118 		iPostHook = aProtocol;
       
   119 		return;
       
   120 		}
       
   121 	if (aId == MIp6Hook::BindPreHook())
       
   122 		{
       
   123 		// Maintain inbound post hook chaining
       
   124 		iInboundHook = aProtocol;
       
   125 		return;
       
   126 		}
       
   127 	}
       
   128 
       
   129 EXPORT_C void CProtocolPosthook::Unbind(CProtocolBase *aProtocol, TUint aId)
       
   130 	/**
       
   131 	* Handles network layer unbinds.
       
   132 	*
       
   133 	* This function handles the network layer unbind and posthook
       
   134 	* chaining unbinds. The processing is based on the following
       
   135 	* "well known" bind id values:
       
   136 	*
       
   137 	* - MIp6Hook::BindPostHook()  (for outbound posthook chaining)
       
   138 	* - MIp6Hook::BindPreHook() (for inbound posthook chaining)
       
   139 	* - #KProtocolInet6Ip (for the network intance)
       
   140 	* - #KProtocolInetIp (for network instance, deprecated)
       
   141 	* - 0 (unbind all)
       
   142 	*
       
   143 	* If the aId does not match any of the above, the Unbind is
       
   144 	* silently ignored (just return happens). This is quite OK,
       
   145 	* there is no need to generate an error in such case.
       
   146 	*
       
   147 	* The derived class needs to override the default implementation
       
   148 	* only if it is bound from another protocol (except the network layer)
       
   149 	* and if class also overrode the CProtocolPosthook::BindL and saved
       
   150 	* a pointer to this protocol. For example:
       
   151 @code
       
   152 	CProtocolDerivedHook::Unbind(CProtocolBase *aProtocol, TUint aId)
       
   153 		{
       
   154 		if (iAnother == aProtocol &&
       
   155 			(aId == 0 || aId == your_special_binding_protocol))
       
   156 			{
       
   157 			// handle your unbind
       
   158 			iAnotherProtocol = NULL;
       
   159 			}
       
   160 		// The default should always be called,
       
   161 		CProtocolPosthook::Unbind(aProtocol, aId);
       
   162 		}
       
   163 @endcode	
       
   164 	* @param aProtocol	The protocol unbinding from this.
       
   165 	* @param aId		The bind id.
       
   166 	*/
       
   167 	{
       
   168 	if (!iBindToNet &&
       
   169 		iNetwork != NULL &&
       
   170 		iNetwork->Protocol() == aProtocol && 
       
   171 		(aId == 0 || aId == KProtocolInet6Ip || aId == KProtocolInetIp))
       
   172 		{
       
   173 		NetworkDetached();
       
   174 		iNetwork = 0;
       
   175 		}
       
   176 	if (iPostHook == aProtocol && (aId == 0 || aId == MIp6Hook::BindPostHook()))
       
   177 		iPostHook = 0;
       
   178 	if (iInboundHook == aProtocol && (aId == 0 || aId == MIp6Hook::BindPostHook()+1))
       
   179 		iInboundHook = 0;
       
   180 	}
       
   181 
       
   182 // CProtocolPosthook::DoBindToL
       
   183 // ****************************
       
   184 
       
   185 EXPORT_C TInt CProtocolPosthook::DoBindToL(CProtocolBase *aProtocol)
       
   186 	/**
       
   187 	* Handle network layer bindto.
       
   188 	*
       
   189 	* Performs the BindToL processing for the network detection.
       
   190 	* This network layer detection is only used in a configuration,
       
   191 	* where the "bindto" list of this protocol includes the network
       
   192 	* layer (ip6). In this configuration, the network layer
       
   193 	* stays installed whenever this protocol is loaded.
       
   194 	*
       
   195 	* @note
       
   196 	*	Network can be loaded without this protocol being loaded.
       
   197 	*
       
   198 	* @param aProtocol	The protocol to bind to.
       
   199 	* @return KErrNone or the id of the protocol.
       
   200 	*  - KErrNone (= 0),
       
   201 	*	 BindTo processed (it was the network bind, NetworkAttachedL has
       
   202 	*	 been called.)
       
   203 	*  - protocol id ( != 0) from the aProtocol, which was not the network
       
   204 	*
       
   205 	* @note
       
   206 	*	The protocol id is TUint. However, this method is defined
       
   207 	*	to return TInt  The function should be considered to return
       
   208 	*	TUint and any non-zero value means that the protocol was not
       
   209 	*	the network. [returning TInt instead of TUint is a mistake].
       
   210 	*
       
   211 	* This function exists for derived classes that override the default
       
   212 	* BindToL for their own processing. See ::BindToL for example.
       
   213 	*/
       
   214 	{
       
   215 	TServerProtocolDesc info;
       
   216 	aProtocol->Identify(&info);
       
   217 	const TUint id = info.iProtocol;
       
   218 	if (iNetwork == NULL && (id == KProtocolInetIp || id == KProtocolInet6Ip))
       
   219 		{
       
   220 		iNetwork = ((CProtocolInet6Binder *)aProtocol)->NetworkService();
       
   221 		aProtocol->Open();
       
   222 		iBindToNet = 1;	// Network layer bind via BindTo.
       
   223 		// Note: when the hook binds to network, NetworkDetached is never
       
   224 		// called, because network can never exit before this hook, the
       
   225 		// event never happens while this hook is running.
       
   226 		NetworkAttachedL();
       
   227 		return KErrNone;
       
   228 		}
       
   229 	return id;
       
   230 	}
       
   231 
       
   232 // CProtocolPosthook::BindToL
       
   233 // **************************
       
   234 EXPORT_C void CProtocolPosthook::BindToL(CProtocolBase *aProtocol)
       
   235 	/**
       
   236 	* The default implementation.
       
   237 	*
       
   238 	* This implemenation only handles the network bind and leaves
       
   239 	* with #KErrNotSupported if the protocol is not the network
       
   240 	* instance.
       
   241 	*
       
   242 	* If the "bindto" list of this protocol can have other protocols
       
   243 	* than the network (ip6), then the derived class must implement the
       
   244 	* support for it. For example
       
   245 @code
       
   246 	CProtocolDerivedHook::BindToL(CProtocolBase *aProtocol)
       
   247 		{
       
   248 		const TInt id = DoBindToL(aProtocol);
       
   249 		if (id == (TInt)your_special_protocol)
       
   250 			{
       
   251 			//
       
   252 			if (iBindTo)
       
   253 				iBindTo->Close();
       
   254 			iBindTo = aProtocol;
       
   255 			iBindTo->Open();
       
   256 			// Destructor must issue Close, if iBindTo is non-NULL
       
   257 			}
       
   258 		else if (id != KErrNone)
       
   259 			User::Leave(KErrNotSupported);
       
   260 		}
       
   261 @endcode
       
   262 	*/
       
   263 	{
       
   264 	if (DoBindToL(aProtocol) != KErrNone)
       
   265 		User::Leave(KErrNotSupported);
       
   266 	}
       
   267 
       
   268 EXPORT_C TInt CProtocolPosthook::Send(RMBufChain &aPacket, CProtocolBase* aSrc)
       
   269 	/**
       
   270 	* Send packet to the next protocol.
       
   271 	*
       
   272 	* Send passes the outbound packet to the next post-processing hook
       
   273 	* (#iPostHook).
       
   274 	* The derived post-processing hook can ímplement own Send, After
       
   275 	* processing the packet, it would normally call CProtocolPosthook::Send
       
   276 	* to pass the packet forward (note that the information block is
       
   277 	* RMBufSendInfo and the attached flow context (RFlowContext)
       
   278 	* <b>must be closed</b>, if the packet is deleted):
       
   279 @code
       
   280 	TInt CProtocolDerivedHook::Send(RMBufChain &aPacket, CProtocolBase *aSrc)
       
   281 		{
       
   282 		...
       
   283 		// Do own packet processing
       
   284 
       
   285 		if (packet_is_dropped)
       
   286 			{
       
   287 			RMBufSendInfo *info = RMBufSendPacket::PeekInfoInChain(aPacket);
       
   288 			if (info)
       
   289 				info->iFlow.Close();
       
   290 			aPacket.Free();
       
   291 			return 1;
       
   292 			}
       
   293 		else
       
   294 			return CProtocolPosthook::Send(aPacket, aSrc);
       
   295 		}
       
   296 @endcode
       
   297 	* Hook will receive and pass forward the outbound packets only if
       
   298 	* it has a binding to the network layer as a post-processinghook:
       
   299 @code
       
   300 	NetworkService()->BindL(this, MIp6Hook::BindPostHook());
       
   301 @endcode
       
   302 	*
       
   303 	* @note
       
   304 	*	The network layer currently sends packets with aSrc == NULL.
       
   305 	*	This may change in future (the network instance is used
       
   306 	*	instead).
       
   307 	*
       
   308 	* If hook is configured to receive packets to Send function from some
       
   309 	* other protocol than the network layer, then it can use the aSrc to
       
   310 	* detect this and <b>NOT</B> call this default implementation for such
       
   311 	* packets (unless it intends to inject them to the outbound packet
       
   312 	* stream).
       
   313 	*
       
   314 	* Hook will receive outbound packets from the network layer only if
       
   315 	* it binds as post-processing hook.
       
   316 	*
       
   317 	* @param aPacket	The outbound packet.
       
   318 	* @param aSrc		The originating protocol (or NULL).
       
   319 	*
       
   320 	* @pre	RMBufSendPacket::PeekInfoInChain(aPacket).iFlow.IsOpen()
       
   321 	*/
       
   322 	{
       
   323 	if (iPostHook)
       
   324 		return iPostHook->Send(aPacket, aSrc);
       
   325 
       
   326 	//
       
   327 	// Nobody to forward, consume the packet
       
   328 	//
       
   329 	RMBufSendInfo *info = RMBufSendPacket::PeekInfoInChain(aPacket);
       
   330 	if (info)
       
   331 		info->iFlow.Close();
       
   332 	aPacket.Free();
       
   333 	return 1;
       
   334 	}
       
   335 
       
   336 EXPORT_C void CProtocolPosthook::Process(RMBufChain &aPacket, CProtocolBase* aSrc)
       
   337 	/**
       
   338 	* Process incoming packet.
       
   339 	*
       
   340 	* Process passes the inbound packet to the next pre-processing hook
       
   341 	* (#iInboundHook).
       
   342 	* The derived pre-processing hook can implement own Process. After processing
       
   343 	* the packet, it would normally call CProtocolPosthook::Process to pass
       
   344 	* the packet forward (note that the information block is the basic RMBufPktInfo).
       
   345 @code
       
   346 	TInt CProtocolDerivedHook::Process(RMBufChain &aPacket, CProtocolBase *aSrc)
       
   347 		{
       
   348 		// Do own packet processing.
       
   349 
       
   350 		RMBufPktInfo *info = RMBufPacketBase::PeekInfoInChain(aPacket);
       
   351 		...
       
   352 		if (packet_is_dropped)
       
   353 			aPacket.Free();
       
   354 		else
       
   355 			CProtocolPosthook::Process(aPacket, aSrc);
       
   356 		}
       
   357 @endcode
       
   358 	* Hook will receive and pass forward inbound packets only if it has
       
   359 	* bound as pre-processing hook:
       
   360 @code
       
   361 	NetworkService()->BindL(this, MIp6Hook::BindPreHook());
       
   362 @endcode
       
   363 	*
       
   364 	* @note
       
   365 	*	For inbound packets, the aSrc is the NIF object (derived from
       
   366 	*	CNifIfBase and not from CProtocolBase.).
       
   367 	* @note
       
   368 	*	The implementation <b>SHOULD NOT</b> change the aSrc. But, if it
       
   369 	*	does change the source, the new source must also be a NIF pointer,
       
   370 	*	and that NIF must also be known to the TCP/IP stack.
       
   371 	*
       
   372 	* @param aPacket	The inbound packet
       
   373 	* @param aSrc		The originating NIF
       
   374 	*/
       
   375 	{
       
   376 	if (iInboundHook)
       
   377 		iInboundHook->Process(aPacket, aSrc);
       
   378 	else
       
   379 		aPacket.Free();
       
   380 	}
       
   381