diff -r 000000000000 -r af10295192d8 networkprotocols/iphook/inhook6/include/flow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkprotocols/iphook/inhook6/include/flow.h Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,1097 @@ +// 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: +// flow.h - IPv6/IPv4 flow information +// IPv6/IPv4 flow information. +// + + + +/** + @file flow.h + @publishedPartner + @released +*/ + +#ifndef __FLOW_H__ +#define __FLOW_H__ + +#define SYMBIAN_NETWORKING_UPS + +#include +#include +#include "in_pkt.h" +#include "apibase.h" + +// +// TFlowStatus +// +/** +* Type of the flow status (some symbolic enum names). +* @since v7.0 +* @publishedPartner +* @released +*/ +enum TFlowStatus + { + /** + * (< 0) Flow is in error state. + * + * All other system wide error codes also indicate a flow error state. + * To recover, the flow must be reconnected. + */ + EFlow_DOWN = KErrNotReady, + /** + * (= 0) Flow is ready to send data. + */ + EFlow_READY = 0, + /** + * (= 1) Flow is temporarily blocked. + * + * This is used when the flow is waiting for the connection setup. + * When there is a possibility that flow could change into EFLow_READY + * state, the notifier is notified with MProviderNotify::CanSend(). + */ + EFlow_PENDING = 1, + /** + * (= 2) Flow is temporarily blocked. + * + * This is used when the flow is blocked due to congestion (e.g. lower level + * buffers are full). When congestion clears and if there is a possibility + * that flow could change into EFLow_READY state, the notifier is notified + * with MProviderNotify::CanSend(). + */ + EFlow_HOLD = 2 +#ifdef SYMBIAN_TCPIPDHCP_UPDATE + , + EFlow_NOTCONFIGURE = 3 +#endif //SYMBIAN_TCPIPDHCP_UPDATE + }; + +// MProviderNotify +// *************** +class MProviderNotify : public MInetBase + /** + * Receiver of the notifications of the status changes in the flow. + * + * Note that the two functions CanSend() and Error() are a subset of MSocketNotify. This allows + * a Service Access Point to implement the interface just by calling the equivalent + * MSocketNotify functions. + * @since v7.0 + * @publishedPartner + * @released + */ + { +public: + /** + * Flags that the flow might be ready to change into the EFlow_READY status + * + * The flow is (or has been) in EFlow_PENDING or EFlow_HOLD state. The flow + * owner can now check if flow really can be changed into EFlow_READY state. + * The state is updated by calling RFlowContext::Status (or some other functions + * that implicitly refresh the flow state by calling internally the + * CFlowContext::RefreshFlow function). + * + * Even if this function is called, the flow can still be in error or blocked + * state. This is because, for example, when congestion clears, all flows + * waiting for that event are notified, but some earlier notified flow may + * already have refilled all the buffers. + */ + virtual void CanSend() = 0; + /** + * The flow has entered an error state. + * + * Error state in a flow is permanent and requires a new connect (CFlowContext::Connect) + * to be cleared. A new connect occurs implicitly at FlowContext::Status (or some + * at some other functions), if flows connection parameters have been modified + * since the last connect (CFlowContext::iChanged is 1). + * + * @param aError Flow error code + * @param anOperationMask A bitmask of MSocketNotify::TOperationBitmasks values + * specifying which pending operations are affected by the error up-call. + */ + virtual void Error(TInt aError, TUint anOperationMask=MSocketNotify::EErrorAllOperations) = 0; + virtual void NoBearer(const TDesC8& aConnectionParams) = 0; + virtual void Bearer(const TDesC8 &aConnectionInfo) = 0; + virtual TInt CheckPolicy(const TSecurityPolicy&, const char *) + { + return KErrNone; + }; + }; + + +// +// RFlowContext +// ************ +// +class MFlowManager; +class CFlowContext; +class CNifIfBase; + +// *WARNING*: +// Because RFlowContext is used as a member of RMBufSendInfo, which may +// get moved around, the RFlowContext handle *MUST* not contain anything +// that breaks if it is copied bit-by-bit from one memory area to another! +// (for example don't even think of adding link fields and linking +// RFlowContext's into a list!) -- msa +// +class RFlowContext + /** + * A handle to a flow context. + * + * The main purpose of this class is to provide automatic reference counting + * for flow context users. + * + * A typical use for a RFlowContext object is to: + * @li allocate a context to a handle through the flow manager (Open()) + * @li set appropriate flow parameters (the upper layer protocol associated with + * the flow, destination and source addresses) + * @li use the flow to send packets out + * @li release the context (Close()) from the handle. + * @since v7.0 + * @publishedPartner + * @released + */ + { +public: + inline RFlowContext() : iFlow(0) + /** + * Default constructor. + * + * This creates a handle without any assigned flow context. + */ + {} + IMPORT_C TInt Open(MFlowManager *aManager, const TSockAddr &aDst, const TSockAddr &aSrc, TUint aProtocol = 0, TUint aIcmpType = 0, TUint aIcmpCode = 0); + IMPORT_C TInt Open(MFlowManager *aManager, TUint aProtocol = 0); + IMPORT_C TInt Open(RFlowContext &aContext, RMBufPktInfo *aInfo = NULL); + IMPORT_C TInt Clone(const RFlowContext &aFlow); + IMPORT_C TInt ReOpen(); + IMPORT_C TInt Connect(); + + inline TBool IsOpen() + /** + * Tests if context is attached + */ + {return iFlow != NULL;} + + IMPORT_C void SetRemoteAddr(const TSockAddr &aAddr); + IMPORT_C void SetLocalAddr(const TSockAddr &aAddr); + IMPORT_C void SetProtocol(TUint aProtocol); + IMPORT_C void SetIcmpType(TUint aType, TUint aCode = 0); + IMPORT_C MProviderNotify *SetNotify(MProviderNotify *aProvider); + IMPORT_C TInt Status(); + IMPORT_C void Grab(RFlowContext &aContext); + IMPORT_C void Copy(RFlowContext &aContext); + IMPORT_C void Close(); + IMPORT_C CNifIfBase *Interface() const; + +#ifdef SYMBIAN_TCPIPDHCP_UPDATE + IMPORT_C TBool IsNdResolutionPending(); //RFC 4861 - Section 7.2.2 +#endif //SYMBIAN_TCPIPDHCP_UPDATE + inline CFlowContext *FlowContext() const + /** Gets a pointer to the flow context object (CFlowContext) + * attached to the handle. + * + * This can be used for more detailed control of the flow parameters. + * + * The returned pointer has limited validity, + * and it should not be stored in any members of permanent objects. + * In addition, care must be taken not to call any operation that could + * destroy the flow context as a side effect. + * + * If there is a need for longer validity of the retrieved pointer, + * the CFlowContext::Open and CFlowContext::Close methods can be used + * to protect it. + * + * @return + * The flow context object. + */ + { return iFlow; } +private: + /** The flow context. */ + CFlowContext *iFlow; + }; + + + +// ****************************** +// RMBufSendInfo, RMBufSendPacket +// ****************************** +class RMBufSendInfo : public RMBufPktInfo + /** + * Information for outgoing packets. + * + * This extends the packet information class to record the flow context. + * @since v7.0 + * @publishedPartner + * @released + */ + { +public: + /** Flow context for the packet. */ + RFlowContext iFlow; + }; + +/** @since v5.0 */ +typedef class RMBufInfoPacketBase RMBufSendPacket; + +// TFlowInfo +// ********* +class TFlowInfo + /** + * Collects the information which defines a flow + * (The Upper Layer Flow Information). This is a + * member of CFlowContext. + * + * @since v7.0s + */ + { +public: + /** + * Current remote addess as set by upper layer. + * + * Must always be specified before a flow can be connecte or + * used for sending packets. + * + * See RFlowContext::SetRemoteAddr, CFlowContext::RemoteAddr + */ + TInetAddr iRemote; + /** + * Current local address (system or application selected). + * + * See RFlowContext::SetLocalAddr, CFlowContext::LocalAddr + */ + TInetAddr iLocal; + /** + * The protocol associated with the flow. + * + * See RFlowContext::SetProtocol, CFlowContext::Protocol + */ + TUint8 iProtocol; + /** + * ICMP type, when protocol is ICMP (or similar). + * + * See RFlowContext::SetIcmpType, CFlowContext::GetIcmpTypeCode + */ + TUint8 iIcmpType; + /** + * ICMP code, when protocol is ICMP (or similar). + * + * See RFlowContext::SetIcmpType, CFlowContext::GetIcmpTypeCode + */ + TUint8 iIcmpCode; + /** + * Set when upper layer set the local address. + * + * When set, the stack assumes the upper layer has specified + * the source address of the flow. When not set, the stack + * chooses the source address. + * + * This flag is cleared or set by the RFlowContext::SetLocalAddr(). + * The flag is cleared when address is unspecified and set otherwise. + * Initial value is unset, if SetLocalAddr is never called. + * + * See also CFlowContext::IsLocalSet + */ + TUint iLocalSet:1; + /** + * Set when interface errors should not affect the flow. + * + * When an interface goes down (or reports an error), all flows + * that are currently connected (routed) to this interface, are + * also set into error error state (effectively, causing a + * socket error to the applications). + * + * When this flag is set, flow is not set to the error state. However, + * if interface is going down, the flow is put into hold/pending + * state (until another or same interface becomes again available). + * + * See also the socket option: #KSoNoInterfaceError + */ + TUint iNoInterfaceError:1; + /** + * Set when this flow should not try to bring up the interface. + * + * When a connect is attempted on a flow and it fails due to + * missing routes (no suitable interfaces up or configured yet), the + * stack signals the NIFMAN (NoBearer notify function). + * + * When this flag is set, NIFMAN is not notified and the flow is + * just placed into hold/pending state to wait for possible interface + * or route to appear. + * + * @note + * NoBearer does not exisit in pre 7.0s systems. In such + * systems the stack itself activates the "netdial process" in + * this situation. + */ + TUint iNoInterfaceUp:1; + /** + * Set when flow is used for packet forwarding. + * + * This flag, when set, disables the source address checking. + * Normally the stack works in "strong model" and requires that + * a packet has a valid source address on the interface. + * Forwarded packets have other than local source address and + * the check must be disabled. + * + * This can only be set internally or from the hooks. There is no + * application level socket option to set this. + */ + TUint iForwardingFlow:1; + // Note! Cannot use TScopeType below, because it would make the + // bitfield into signed and fail on tests like: + // x.iLockType == EScopeType_NET + // even if x.iLockType has value EScopeType_NET!!! -- msa + /** + * Locked scope-1 (0..15) [TScopeType]. + * + * This valid only when iLockId is non-zero. + */ + TUint iLockType:4; + /** + * Current Locking Id. + * + * Value ZERO is unlocked. Non-Zero value is a zone id in the scope + * specified by iLockType. + */ + TUint32 iLockId; + }; + + +// ************ +// CFlowContext +// ************ +// A base class of the Flow Context, cannot be instantiated as is +// +class COptionValue; +class MFlowHook; +class MInterfaceManager; + +class CFlowContext : public CBase + /** + * The flow context instance. + * + * The CFlowContext has several public methods, but not all of them are safe + * (or even legal) to use in all situations. + * + * CFlowContext is a reference counted object. Whenever a pointer is + * stored for long term duration, the Open() must be called, and when + * pointer is no more used, a close must be called. This object is only + * deleted indirectly via use of Close(). The delete operator is never + * used explicitly from outside. + * + * Base class for a flow context. + * @since v7.0 + * @publishedPartner + * @released + */ + { + friend class MFlowManager; + friend class RFlowContext; +protected: + IMPORT_C CFlowContext(const void *aOwner, MFlowManager *aManager); + IMPORT_C CFlowContext(const void *aOwner, MFlowManager *aManager, CFlowContext &aFlow); + // Destructor should not be exported, it should be private! -- msa + IMPORT_C virtual ~CFlowContext(); + +#ifdef SYMBIAN_NETWORKING_UPS + /** + Indicate whether the flow has a provider above it. + @return ETrue if it has, else EFalse. + */ + inline TBool HasProvider() const; + + + inline void *GetProviderApiL(const TDesC8& aApiName, TUint* aVersion); +#endif //SYMBIAN_NETWORKING_UPS + +public: + IMPORT_C void Close(); + + inline void Open() + /** + * Increments a reference count on the context + */ + { iRefs++; } + IMPORT_C TInt Status(); + IMPORT_C void SetStatus(TInt aStatus); + IMPORT_C TInt StoreOption(TUint aLevel, TUint aName, const TDesC8 &aOption); + IMPORT_C TInt RetrieveOption(TUint aLevel, TUint aName, TDes8 &aOption) const; + + inline TPacketHead &Head() + /** + * Gets access to precomputed information for the outbound packet flow. + * + * @return Precomputed information for the outbound packet flow + */ + { return iHead; } + + /** + * @defgroup getselectors Retrieve current selector fields + * + * @{ + */ + + inline TUint LocalPort() const + /** + * Gets the flow's local port. + * @return current local port + */ + { return iInfo.iLocal.Port(); } + + inline TUint RemotePort() const + /** + * Gets the flow's remote port. + * @return current remote port + */ + { return iInfo.iRemote.Port(); } + + inline TUint Protocol() const + /** + * Gets the flow protocol. + * @return current protocol + */ + { return iInfo.iProtocol; } + + inline const TInetAddr &LocalAddr() const + /** + * Gets the flow's local address. + * + * The local address may have been selected by the system, if + * the transport layer didn't set it (left it unspecified or + * explicitly set unspecified address to it). + * + * @note + * All addresses in the flow context are kept in IPv6 format + * (using IPv4 mapped addresses for IPv4 flows). + * + * @return Local address. + */ + { return iInfo.iLocal; } + + inline TBool IsLocalSet() const + /** + * Gets the flow's local address status. + * + * The local address can be selected by the stack, or application + * can have set it into a specific value. When this address status + * have value ETrue, the stack assumes that the local address has + * been chosen by the application or upper layer protocol. When + * status is EFalse, the stack selects the source + * address for the flow when the flow is connected + * (CFlowContext::Connect). + * + * The RFlowContext::SetLocalAddress will set this status to EFalse, + * if the address is unspecified address, and to ETrue otherwise. + * + * @note + * If an application requires using the unspecified source address + * in packets (IPv4 0.0.0.0 or IPv6 ::), it must use + * the socket option #KSoNoSourceAddressSelect (level #KSolInetIp) + * after it has performed the RSocket::Bind() to uspecified + * address. + * + * Some upper layer protocols may also set this status, after the + * connection is established (TCP). + * + * @return ETrue, if local addr is set + */ + { return iInfo.iLocalSet != 0; } + + inline const TInetAddr &RemoteAddr() const + /** + * Gets the flow's remote address. + * + * @return Remote address. + */ + { return iInfo.iRemote; } + + inline void GetIcmpTypeCode(TUint8 &aType, TUint8 &aCode) const + /** + * Gets the flow's ICMP type and code. + * + * @retval aType Icmp (or other) type + * @retval aCode Icmp (or other) code + */ + { aType = iInfo.iIcmpType; aCode = iInfo.iIcmpCode; } + + inline TScopeType LockType() const + /** + * Gets the flow's locking type [0..15]. + * + * The locking type tells the type of the lock id. The type has no + * meaning if the lock id has zero value (= flow is not locked).. + * + * @return current type of LockId (IF=0, IAP=1, NET=15). + */ + { return (TScopeType)iInfo.iLockType; } + + inline TUint32 LockId() const + /** + * Gets the flows lock id. + * + * A flow can be locked to a specified scope. When locked (non-zero), + * the flow can only be connected to an interface within the locked + * scope. + * + * The id value is a plain 32 bit number and the domain of this + * value is defined by the locking type (CFlowContext::LockType). + * + * @return current lock id (IAP, NET or IF). Not locked, if ZERO + */ + { return iInfo.iLockId; } + + /** @} */ + + /** + * @defgroup packetsize Accessing parameters of the packet size + * + * In all, return + * @li < 0, indicates an error or value not known + * @li = 0, (interpretation not fixed) + * @li > 0, the indicated value + * + * Some assertations that should be true + * @li PathMtu() > HeaderSize() + * @li HeaderSize() >= sizeof(TInet6HeaderIP) + * @li InterfaceSMtu() >= PathMTU() + * @li InterfaceRMtu() > sizeof(TInet6HeaderIP) + * + * @{ + */ + + inline TInt PathMtu() const + /** + * Gets the Path MTU of the flow. + * + * @return + * @li < 0, indicates an error or value not yet known (for example, + * if accessed before the flow is connected or interface is up) + * @li = 0, value not known + * + * @li > 0, a real value + */ + { return iPathMtu; } + + inline TInt HeaderSize() const + /** + * Gets the amount of the protocol overhead in the packet from all of the lower layers. + * + * The value is defined only for a flow that has been connected. + * (CFlowContext::Connect). + * + * HeaderSize () > 0 (at least IPv4 or IPv6 header size) + * + * @return + * @li < 0, indicates an error or value not yet known (for example, + * if accessed before the flow is connected or interface is up) + * @li = 0, value not known + * @li > 0, a real value + */ + { return iHdrSize; } + + /** + * Gets the raw send MTU of the attached interface. + * + * The value is defined only for a flow that has been connected. + * (CFlowContext::Connect). + * + * @return + * @li < 0, indicates an error or value not yet known (for example, + * if accessed before the flow is connected or interface is up) + * @li = 0, value not known + * @li > 0, a real value + */ + virtual TInt InterfaceSMtu() const = 0; + /** + * Gets the raw receive MTU of the interface. + * + * The value is defined only for a flow that has been connected. + * (CFlowContext::Connect). + * + * @return + * @li < 0, indicates an error or value not yet known (for example, + * if accessed before the flow is connected or interface is up) + * @li = 0, value not known + * @li > 0, a real value + */ + virtual TInt InterfaceRMtu() const = 0; + /** @} */ + + /** + * Gets an option from the flow context. + * + * A set of options can be read from the flow context. + * + * In addition to internally supported options, + * any registered outbound hook can add support for additional options + * (see MIp6Hook::GetFlowOption documentation). + * + * The function is called part of the normal option processing. + * + * @param aLevel The option level + * @param aName The option name + * @param aOption The option value + * @return + * KErrNone, or KErrNotSuppoted if option cannot be read from the flow context. + */ + virtual TInt GetOption(TUint aLevel, TUint aName, TDes8 &aOption) const = 0; + + /** + * Sets an option to the flow context. + * + * A set of options can be set to the flow context. + *. + * In addition to internally supported options, + * any registered outbound hook can add support for additional options + * (see MIp6Hook::SetFlowOption documentation). + * + * The function is called part of the normal option processing. + * + * @param aLevel The option level + * @param aName The option name + * @param aOption The option value + * @return + * KErrNone, or KErrNotSuppoted if option cannot be set from the flow context. + */ + virtual TInt SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption) = 0; + + /** + * Gets the currently connected interface. + * + * @return + * The currently connected interface, + * if the flow is properly connected, otherwise NULL. + * The returned pointer has limited validity, and it should not be stored + * in any members of permanent objects. + */ + virtual CNifIfBase *Interface() const = 0; + + /** + * Gets the interface manager of the TCP/IP stack.. + * + * @return + * The interface manager. + */ + virtual MInterfaceManager *Interfacer() const = 0; + + /** + * Sends a packet to the attached interface. + * + * This is a low level function intended for the IP layer itself. + * Send bypasses all the installed hooks and path mtu processing. + * The raw data in the packet is passed to the interface as is. + * (for the normal way of sending a packet, see MNetworkService::Send). + * + * If the flow is not connected, the Send drops the packet and the + * return is KErrNotReady. + * + * The destination address of the information block may get changed + * into link layer destination address, if the stack is handling the + * neighbour discovery on the link (ARP for IPv4, ICMPv6 Neighbor + * discovery for IPv6). + * + * If the destination is a multicast address, and if that address + * is also joined by some application(s), then a copy of the packet + * is sent to the inbound direction (MNetworkService::Process), + * unless disabled by #KSoIp6MulticastLoop socket option. + * + * @param aPacket + * The data packet (assumed to be RMBufInfoPktBase in "packed" state) + * @param aSource + * The source protocol instance (passed as is to the interface). Optional, + * and usually NULL. + * @return + * is defined similarly as the equivalent methods of the interfaces and + * protocols, as follows: + * @li < 0, + * an error: the packet is not sent, but is dropped by Send(). + * @li = 0, + * indicates that the interface received the packet, but is also signaling + * that its reluctance to receive more packets. All flows attached to this + * interface are automatically set into EFlow_HOLD state. + * @li > 0, + * indicates that the interface received the packet and is willing to + * receive more after this. + */ + virtual TInt Send(RMBufChain &aPacket, CProtocolBase* aSource = NULL) = 0; + + /** Attaches a flow to a route and an interface. */ + virtual void Connect() = 0; + /** Disconnects the flow, and remove all hooks. */ + virtual void Disconnect() = 0; + /** Recomputes the current flow status. */ + virtual void RefreshFlow() = 0; + /** + * Sets "changed" state to flow(s). + * + * Sets the iChanged flag that indicates that connect information has changed. + * + * When any component of the system determines that a flow or set + * of flows require an open phase (reconnect), the component can use the + * this function to force a reconnect of the flow on the next outgoing packet. + * + * @param aScope determines what flows are affected: + * @li 0: set iChanged on current flow + * @li 1: set iChanged on all flows with same route entry, + * @li 2: set iChanged on all flows with same interface, + * @li > 2: set iChanged on all existing flows + * + * @return + * Number of flows affected (regardless of their previous iChanged state) + */ + virtual TInt SetChanged(const TInt aScope = 0) = 0; +#ifdef SYMBIAN_TCPIPDHCP_UPDATE + /* RFC 4861: Sec 7.2.2 Verifies any pending ND packets exists on a route during ND + */ + virtual TBool IsNdPacketPendingResolution() {return EFalse; } ; // Base implementation +#endif //SYMBIAN_TCPIPDHCP_UPDATE + inline void NoBearer(const TDesC8& aConnectionParams); + inline void Bearer(const TDesC8 &aConnectionInfo); + inline TInt CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic); + +protected: + /** The owner of the flow (untyped ID data). */ + const void *const iOwner; + /** The flow manager that created this object. */ + MFlowManager *const iMgr; + + /** Contains the object reference count. + * + * For a single reference, this is 0. + */ + TInt iRefs; + /** The flow's status. + * + * @li = 0: up and running + * @li > 0: pending + * @li < 0: error. + */ + TInt iStatus; +public: + /** The Upper Layer Flow Information */ + TFlowInfo iInfo; +protected: + /** + * Set when flow needs a reconnect (selector information changed). + * + * When this is set (1), RFlowContext::Status (and some other methods) will + * automaticly call CFlowContext::Connect for the flow. Primary reason for + * this to be set is that the flow selector information has been changed + * (@ref setselectors). + * + * This can be set explicitly by the CFlowContext::SetChanged function (or + * MFlowManager::SetChanged). + */ + TUint iChanged:1; +public: + /** + * Flag that indicates that NIF HOLD return should not block the flow. + * + * After a packet send a NIF can return a value that indicates that no + * more packets are to be sent to it, until it allows it again via + * the CProtocolBase::StartSending call. Normally, such indication + * sets the flow into HOLD state. + * + * When this flag is set, flow is not put into HOLD. This flag should + * only be used by a hook that have other means of enforcing the flow + * control (for example QOS). + */ + TUint iIgnoreFlowControl:1; + /** Precomputed packet header information. */ + TPacketHead iHead; + /** + * The current Path MTU + * + * Set from the path MTU of the connected interface. May change + * dynamically due to ICMP "packet too big" or other events. + */ + TUint iPathMtu; + /** + * The header overhead by IP layer and hooks + * + * The iHdrSize is initialized to 0 at the beginning of the MIp6Hook::OpenL + * phase. + * The final value at the end of the OpenL phase is saved, and this value + * will be the initial value at the beginning of the MFlowHook::ReadyL phase. + * + * The final value at the end of the ReadyL phase must be the total amount + * of header space required by the layers below the transport (upper layer + * protocol). The space available for the upper layer header and payload + * is: iPathMtu - iHdrSize. + * + * The hook can add the header space requirement in OpenL or ReadyL + * method. If it does it in OpenL, it does not need to touch the + * iHdrSize in ReadyL method (for example, IPSEC only knows the + * exact required header space at ReadyL phase). + * + * If a hook uses the TPacketHead::iPacket member to store precomputed + * headers, which are automaticly appended to each packet, it must include + * the amount into iHdrSize (it must carefully compute the change of length + * in iPacket, if it adds new data there). + * + * The stack includes implicitly the header space for INNERMOST IP header + * (which is also the final IP header, if no tunneling is present). Any hook, + * that does tunneling, must include the OUTER IP header requirements into + * the iHdrSize (a tunneling hook is ADDING the outer header!). + */ + TUint iHdrSize; +private: + /** Receives state change upcalls. Also the owner of the flow. */ + MProviderNotify *iProvider; + /** Storage for any other options. */ + COptionValue *iStorage; + }; + + +inline void CFlowContext::NoBearer(const TDesC8& aConnectionParams) + /** Passes NoBearer call to owner, if present. */ + { + if (iProvider) + iProvider->NoBearer(aConnectionParams); + } +inline void CFlowContext::Bearer(const TDesC8 &aConnectionInfo) + /** Passes Bearer call to owner, if present. */ + { + if (iProvider) + iProvider->Bearer(aConnectionInfo); + } + +inline TInt CFlowContext::CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic) + { + return iProvider ? iProvider->CheckPolicy(aPolicy, aDiagnostic) : KErrNone; + } + +#ifdef SYMBIAN_NETWORKING_UPS +inline TBool CFlowContext::HasProvider() const + { + return (iProvider != NULL); + } + +inline void *CFlowContext::GetProviderApiL(const TDesC8& aApiName, TUint* aVersion) + { + if (iProvider == NULL) + { + return NULL; + } + else + { + return iProvider->GetApiL(aApiName, aVersion); + } + } + +#endif //SYMBIAN_NETWORKING_UPS + +// ********* +// MFlowHook +// ********* +class MFlowHook : public MInetBase + /** + * Abstract base class for flow hooks. + * + * Flow hook providers implement this class. They register the hook using + * MIp6Hook::BindFlowHook(), and return an instance from MIp6Hook::OpenL(). + * + * @note + * The same instance of MFlowHook can be returned for multiple flows, + * if the logic of the hook does not require unique instance for each flow. + * + * The object can be implemented as reference counted object: last reference + * removed by Close deletes the object. + * + * @since v7.0 + * @publishedPartner + * @released + * + * Example: + * @dontinclude mflowhook.cpp + * @skip MFlowHook + * @until //- + */ + { +public: + /** + * Increment reference count. + * + * The Open and Close functions must implement a reference + * counting system. The Close function must destroy the current + * instance, when the last reference is removed. + * + * Non-NULL return from MIp6Hook::OpenL() counts as one reference, and + * the stack is guaranteed to call the matching Close exactly once. + * + * If a hook creates a new instance for each flow at OpenL, it can + * leave the reference count as initial ZERO, if it implements a + * Close, which deletes the object when the count goes negative. + * + * If a hook returns an existing instance at OpenL, it must + * increment the reference count by one. + * + * Example: + * @dontinclude mflowhook.cpp + * @skip ::Open( + * @until //- + */ + virtual void Open() = 0; + /** + * On an interface connecting, asks the hook if a flow is ready. + * + * The ReadyL calls propagate interface ready state up the + * flow. The calls to hooks are made in reverse order; + * the closest to interface is called first. The call informs + * this hook that everything is ready from this hook to the interface. + * Now it this hooks turn to check the ready state of the flow. + * + * @param aHead + * Address information of the flow. + * @return + * from the ReadyL is the new status of the flow and has the following + * implications + * @li == 0, hook is ready, proceed to the next one or mark the flow + * as READY, if this was the first hook. + * @li > 0, hook is not ready, the ready calling is stopped and the + * returned value is the (pending) state of the flow. + * The hook MUST send a signal later to release this state to + * reactivate the ReadyL call chain. + * @li < 0, hook detected an unrecoverable error on flow + * + * @exception + * If the ReadyL leaves, the leave status will become + * the flow status (the leave status must be negative, or KErrGeneral + * is substituted for it) + * + * Example: + * @dontinclude mflowhook.cpp + * @skip ::ReadyL( + * @until //- + */ + virtual TInt ReadyL(TPacketHead &aHead) = 0; + /** + * Apply send transformations. + * + * The ApplyL is called by IP protocol for outbound packet. The aPacket + * is in "unpacked" state (RMBufPacketBase::Unpack). + * + * @param aPacket + * a complete packet to be processed (if needed) by the hook. + * The packet includes the IP header. + * @param aInfo + * information block associated with the packet (a hook must not + * break this association!) + * @return + * @li = 0, (KErrNone) hook processed the packet, proceed with the next. + * @li < 0, (error code) hook discarded the packet for some reason, send is + * aborted. + * @li > 0, restart hook processing [the actual utility of this is + * still under consideration, maybe removed if no sensible + * use found.] + * + * @exception + * if ApplyL leaves, the packet is dropped. + * + * Example: + * @dontinclude mflowhook.cpp + * @skip ::ApplyL( + * @until //- + */ + virtual TInt ApplyL(RMBufSendPacket &aPacket, RMBufSendInfo &aInfo) = 0; + /** + * Decrement references and destroy if last. + * + * Example: + * @dontinclude mflowhook.cpp + * @skip ::Close( + * @until //- + */ + virtual void Close() = 0; + }; + +class CFlowInternalContext; + +class MFlowManager : public MInetBase + /** + * The flow manager interface. + * + * The use of MFlowManager is mostly hidden behind the RFlowContext, + * but the upper layer must be aware of its existence. + * Currently, the MFlowManager interface is included into the MnetworkService + * (and is implemented by the IP6 protocol instance), + * which must be used whenever an instance of MFlowManager is required. + * @since v7.0 + * @publishedPartner + * @released + */ + { +public: + /** + * Increase the "users" counter. + * + * The count of current "users" is used in determining whether to + * keep or release resources. This in turn, may cause the disconnect + * of a data connection. + * + * The stack leaves it up to the upper layers to decide what is counted as a + * "user". IncUsers() and DecUsers() should be used to give this information + * to the underlying system. By default, each opened socket is counted as + * one user. + */ + virtual void IncUsers() = 0; + /** + * Decrease the "users" counter. + * For details, see IncUsers(). + */ + virtual void DecUsers() = 0; + // + // Use of the following methods is through the + // RFlowContext handle + // + /** + * Creates a new (empty) instance of a CFlowContext. + * + * @param aOwner Identifies the flow's owner (typically an RFlowContext handle) + * @param aProtocol Protocol ID + * @return New object + */ + virtual CFlowContext *NewFlowL(const void *aOwner, TUint aProtocol) = 0; + /** + * Creates a copy of an instance of a CFlowContext. + * + * @param aOwner Identifies the flow's owner (typically an RFlowContext handle) + * @param aFlow Object to copy + * @return New object + */ + virtual CFlowContext *NewFlowL(const void *aOwner, CFlowContext &aFlow) = 0; + /** + * Sets the connect information changed flag on all flows. + * @return Number of flows. + */ + virtual TInt SetChanged() const = 0; + + +//protected: + + /** Internal API between flow and flow manager. @publishedPartner */ + virtual TInt FlowSetupHooks(CFlowInternalContext &aFlow) = 0; + /** Internal API between flow and flow manager. @publishedPartner */ + virtual void FlowStartRefresh(CFlowInternalContext &aFlow) = 0; + // + // Flow option handling + // + /** Internal API between flow and flow manager. @publishedPartner */ + virtual TInt GetFlowOption(TUint aLevel, TUint aName, TDes8 &aOption, const CFlowContext &aFlow) const = 0; + /** Internal API between flow and flow manager. @publishedPartner */ + virtual TInt SetFlowOption(TUint aLevel, TUint aName, const TDesC8 &aOption, CFlowContext &aFlow) = 0; + }; + +#endif