CProtocolPosthook Class Reference

class CProtocolPosthook : public CIp6Hook

Base class for the hooks between IP and NIF.

This is the base class for hooks that live between the IP and NIF layer (post-processing and pre-processing hooks). However, this is also suitable for the base class of any hook. The class provides automatic "network service detection", and supports both binding to and binding from IP6.

The implementations of CProtocolPosthook::BindL and CProtocolPosthook::Unbind handle the "chaining" feature of the post processing hooks. The stack uses a sequence of BindL and Unbind calls when inserting or removing a protocol.

Outbound (MIp6Hook::BindPostHook()):
 U ---> IP6          F ---> NIF
 ..Send.. \         /
           \   ....P ->
            \                      |
             H1 --> H2 --> ... --> T
             ...Send...Send...Send
The MNetworkService::Send passes the packet (P) to the CProtocolBase::Send of the first post processing hook (H1). It is the responsibility of H1 to pass the packet to the next post-processing hook (H2). The stack maintains an internal chain terminator (T), which will pass the packet to the NIF using the flow context (F) attached to the packet. The Send does the packet forwarding to the next linked hook automaticly.

The information block associated with the packet is defined by RMBufSendPacket , which always includes a reference to the flow context (F). If a hook before the terminator (T) does not pass the packet forward in chain, then it must also take care of releasing the flow context (RMBufSendInfo::iFlow.Close()).

The flow context is the only way for the terminator (T) to know the target NIF. If the packet has not flow context, the terminator drops the packet. The flow context is detached from the packet before it is passed to the NIF.

Inbound (MIp6Hook::BindPreHook()):
   NIF --> IP6                     IP6 ---> U
  ..Process..\                      |
              \   ......P ->        |
               \     src=NIF        |
               H1 --> H2 --> .. --> T
            ..Process..Process..Process
The MNetworkService::Process passes the incoming packet to the CProtocolBase::Process of the first pre-processing hook (H1). It is the responsibility of the H1 to pass the packet to the next pre-processing hook (H2). The stack maintains an internal terminator (T), which will pass the packet upwards in the protocol stack. The CProtocolPosthook::Process does the packet forwarding to the next linked hook automaticly.

In the Process chain, the source (CProtocolBase *) is actually a pointer to the NIF object (CNifIfBase). Upon arriving to the terminator (T), the source must still be a valid and known to stack as a NIF (successfully introduced as documented in nif_binding at some earlier point). Otherwise packet is not accepted. The information block is defined by the RMBufPktInfo class. The information block "changes into" RMBufRecvInfo after the terminator (T).

CProtocolPosthook can also be used as a generic base for any hook. Then the following protocol ids for the BindL will become reserved:

BindToL implementation handles KProtocolInet6Ip and KProtocolInetIp targets. This does not do automatic CProtcolBase::BindL to the target (see DoBindToL). The hook binds, if needed, should be done in the NetworkAttachedL function.

Inherits from

Public Member Functions
TInt ApplyL(RMBufHookPacket &, RMBufRecvInfo &)
IMPORT_C voidBindL(CProtocolBase *, TUint)
IMPORT_C voidBindToL(CProtocolBase *)
voidNetworkAttachedL()
voidNetworkDetached()
MNetworkService *NetworkService()
IMPORT_C voidProcess(RMBufChain &, CProtocolBase *)
IMPORT_C TIntSend(RMBufChain &, CProtocolBase *)
IMPORT_C voidUnbind(CProtocolBase *, TUint)
Protected Member Functions
~CProtocolPosthook()
IMPORT_C TIntDoBindToL(CProtocolBase *)
Inherited Functions
CBase::CBase()
CBase::Delete(CBase *)
CBase::Extension_(TUint,TAny *&,TAny *)
CBase::operator new(TUint)
CBase::operator new(TUint,TAny *)
CBase::operator new(TUint,TLeave)
CBase::operator new(TUint,TLeave,TUint)
CBase::operator new(TUint,TUint)
CBase::~CBase()
CIp6Hook::Identify(struct TServerProtocolDesc *)const
CProtocolBase::CProtocolBase()
CProtocolBase::CanClose()
CProtocolBase::Close()
CProtocolBase::CloseNow()
CProtocolBase::Error(TInt,CProtocolBase *)
CProtocolBase::GetOption(TUint,TUint,TDes8 &,CProtocolBase *)
CProtocolBase::InitL(TDesC &)
CProtocolBase::NewHostResolverL()
CProtocolBase::NewNetDatabaseL()
CProtocolBase::NewSAPL(TUint)
CProtocolBase::NewServiceResolverL()
CProtocolBase::Open()
CProtocolBase::Process(TDes8 &,TSockAddr *,TSockAddr *,CProtocolBase *)
CProtocolBase::ProtocolFamily()
CProtocolBase::RefCount()const
CProtocolBase::Send(TDes8 &,TSockAddr *,TSockAddr *,CProtocolBase *)
CProtocolBase::SetOption(TUint,TUint,const TDesC8 &,CProtocolBase *)
CProtocolBase::StartL()
CProtocolBase::StartSending(CProtocolBase *)
CProtocolBase::Tag()
CProtocolBase::~CProtocolBase()
Private Attributes
TUint iBindToNet
CProtocolBase *iInboundHook
MNetworkService *iNetwork
CProtocolBase *iPostHook

Constructor & Destructor Documentation

~CProtocolPosthook()

IMPORT_C~CProtocolPosthook()[protected, virtual]

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.

Member Functions Documentation

ApplyL(RMBufHookPacket &, RMBufRecvInfo &)

TInt ApplyL(RMBufHookPacket &,
RMBufRecvInfo &
)[inline, virtual]
Default ApplyL. The default ApplyL does nothing to the packets.
Note:

If the only hook binding is post or pre-preprocessing, the ApplyL is never called.

BindL(CProtocolBase *, TUint)

IMPORT_C voidBindL(CProtocolBase *aProtocol,
TUintaId
)[virtual]

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:

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.
[yourposthook]
filename= yourposthook.prt
index= 1
bindfrom= ip6
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:
	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);
		}

Parameters

CProtocolBase * aProtocolThe protocol binding to this.
TUint aIdThe bind id.

BindToL(CProtocolBase *)

IMPORT_C voidBindToL(CProtocolBase *aProtocol)[virtual]

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

Parameters

CProtocolBase * aProtocol

DoBindToL(CProtocolBase *)

IMPORT_C TIntDoBindToL(CProtocolBase *aProtocol)[protected]

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.

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.

Parameters

CProtocolBase * aProtocolThe protocol to bind to.

NetworkAttachedL()

voidNetworkAttachedL()[pure virtual]

Network layer has been attached.

This function is called when the network layer is detected and attached to this protocol object (NetworkService() returns non-null). The implementation in the derived class can now do the hook specific binds and unbinds using:
	// request inbound packets to my Process()
	NetworkService()->BindL(this, MIp6Hook::BindPreHook());
	// request outbound packets to my Send().
	NetworkService()->BindL(this, MIp6Hook::BindPostHook());
	...
	// stop getting inbound packets to my Process()
	NetworkService()->Unbind(this, MIp6Hook::BindPreHook());
	// stop getting outbound packets to my Send()
	NetworkService()->Unbind(this, MIp6Hook::BindPostHook());
	// ..or, to rip off all my hooks
	NetworkService()->Unbind(this);

NetworkDetached()

voidNetworkDetached()[inline, virtual]

Network layer is being detached.

This function is called when the hook is losing the connection to the network instance (the network instance has issued Unbind request, because it is shutting down).

Derived class does not need to implement this, unless it caches network layer dependent data internally. Otherwise, it must implement the function and cleanup all such data.

During the call NetworkService returns the service instance that is going away. However, it should not be used for any binding or unbinding. the detach process does the unbindings automaticly.

Note:

The desctuctor can be called while network is attached. CProtocolPosthook destructor will unbind this object automaticly from the network (cancel all binds), and then detaches withouth calling NetworkDetached. Thus, the destructor of the derived class must do the cleanup of cached data, but it does not need to worry about the binds to the network.

NetworkService()

MNetworkService *NetworkService()const [inline]

Gets the network service.

This returns the network service, if any is currently attached. The network is attached after NetworkAttachedL call until the next NetworkDetached or destruction. Otherwise, network is not attached and return is always NULL.

Process(RMBufChain &, CProtocolBase *)

IMPORT_C voidProcess(RMBufChain &aPacket,
CProtocolBase *aSrc
)[virtual]

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).
	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);
		}
Hook will receive and pass forward inbound packets only if it has bound as pre-processing hook:
	NetworkService()->BindL(this, MIp6Hook::BindPreHook());
Note:

For inbound packets, the aSrc is the NIF object (derived from CNifIfBase and not from CProtocolBase.).

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.

Parameters

RMBufChain & aPacketThe inbound packet
CProtocolBase * aSrcThe originating NIF

Send(RMBufChain &, CProtocolBase *)

IMPORT_C TIntSend(RMBufChain &aPacket,
CProtocolBase *aSrc
)[virtual]

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):
	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);
		}
Hook will receive and pass forward the outbound packets only if it has a binding to the network layer as a post-processinghook:
	NetworkService()->BindL(this, MIp6Hook::BindPostHook());
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.

Pre-condition
RMBufSendPacket::PeekInfoInChain(aPacket).iFlow.IsOpen()

Parameters

RMBufChain & aPacketThe outbound packet.
CProtocolBase * aSrcThe originating protocol (or NULL).

Unbind(CProtocolBase *, TUint)

IMPORT_C voidUnbind(CProtocolBase *aProtocol,
TUintaId
)[virtual]

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:

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

Parameters

CProtocolBase * aProtocolThe protocol unbinding from this.
TUint aIdThe bind id.

Member Data Documentation

TUint iBindToNet

TUint iBindToNet[private]

The network attachment type. This base class supports both "bind" and "bindto" attachments to the network layer.

The value is significant only if iNetwork is non-NULL.

CProtocolBase * iInboundHook

CProtocolBase *iInboundHook[private]

Inbound posthook chain. The next protocol in list. The CProtocolPosthook::BindL and CProtocolPosthook::Unbind implementions maintain this chain based on the calls coming from the network layer. The id reference in the chaining calls is MIp6Hook::BindPreHook().

MNetworkService * iNetwork

MNetworkService *iNetwork[private]

The attached network layer (IP layer). The CProtocolPosthook::DoBindToL, CProtocolPosthook::BindL and CProtocolPosthook::Unbind implementations maintain this pointer.

CProtocolBase * iPostHook

CProtocolBase *iPostHook[private]

Outbound posthook chain. The next protocol in list. The CProtocolPosthook::BindL and CProtocolPosthook::Unbind implementions maintain this chain based on the calls coming from the network layer. The id reference in the chaining calls is MIp6Hook::BindPostHook().