1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/epoc32/include/in_pkt.h Tue Mar 16 16:12:26 2010 +0000
1.3 @@ -0,0 +1,713 @@
1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Symbian Foundation License v1.0" to Symbian Foundation members and "Symbian Foundation End User License Agreement v1.0" to non-members
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.symbianfoundation.org/legal/licencesv10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// in_pkt.h - packet handling routines
1.18 +// Generic packet handling utility for mapping packet handling to the RMBufChain.
1.19 +//
1.20 +
1.21 +
1.22 +
1.23 +/**
1.24 + @file in_pkt.h
1.25 + @publishedAll
1.26 + @released
1.27 +*/
1.28 +
1.29 +#ifndef __IN_PKT_H__
1.30 +#define __IN_PKT_H__
1.31 +
1.32 +#include <nifmbuf.h>
1.33 +#include "ip6_hdr.h" // ..should eventually be <inet/ip6_hdr.h>? -- msa
1.34 +#include "ip4_hdr.h"
1.35 +
1.36 +#define TPACKETHEAD_FRAGMENT 1 ///< Enable iFragment in TPacketHead
1.37 +
1.38 +/**
1.39 + TScopeType is only provided so that "magic" constants can be
1.40 + avoided in the source code. However, the max value cannot be changed
1.41 + to anything from 0xF. The scope type is assumed to be 4 bits long
1.42 + in many occasions.
1.43 +
1.44 + The value of the scope type is directly bound the the IPv6 Scope
1.45 + level - 1. This can be done, as IPv6 Scope level 0 is not legal
1.46 + (or usable) in any context within the stack.
1.47 + This allows our non-standard network scope (= 0x10) to
1.48 + be coded internally in 4 bits (as 0xF).
1.49 +
1.50 + @publishedAll
1.51 + @released
1.52 + @since v7.0s
1.53 +*/
1.54 +enum TScopeType
1.55 + {
1.56 + EScopeType_IF = 0x0, ///< (= #KIp6AddrScopeNodeLocal - 1), id is interface index
1.57 + EScopeType_IAP = 0x1, ///< (= #KIp6AddrScopeLinkLocal - 1). id is IAP number
1.58 + EScopeType_GLOBAL = 0xD,///< (= #KIp6AddrScopeGlobal - 1). id is global scope id
1.59 + //
1.60 + // no symbols defined for types 2..14 (they are also valid)
1.61 + //
1.62 + EScopeType_NET = 0xF ///< (= #KIp6AddrScopeNetwork - 1), id is network number (must be the last entry)
1.63 + };
1.64 +
1.65 +//
1.66 +// TIpHeader
1.67 +// *********
1.68 +class TIpHeader
1.69 + /**
1.70 + A simple help class that uses a union to merge handling of either an IPv4 or
1.71 + an IPv6 header.
1.72 + @since v7.0
1.73 + @publishedAll
1.74 + @released
1.75 + */
1.76 + {
1.77 +public:
1.78 + /**
1.79 + Gets the minimum header length.
1.80 +
1.81 + IPv6 header is longer than minimum IPv4 header, thus
1.82 + returned value is for IPv4. This function only defined
1.83 + because it is required when this class is used as template
1.84 + parameter in TInet6Packet.
1.85 +
1.86 + @return Minimum IPv4 header length
1.87 + */
1.88 + inline static TInt MinHeaderLength() {return TInet6HeaderIP4::MinHeaderLength(); }
1.89 + /**
1.90 + Gets the maximum header length.
1.91 +
1.92 + IPv6 header always shorter than maximum IPv4 header, thus
1.93 + returned value is for IPv4. This function is only defined
1.94 + because "header mapping" classes are expected to have it.
1.95 +
1.96 + @return Maximum IPv4 header length
1.97 + */
1.98 + inline static TInt MaxHeaderLength() {return TInet6HeaderIP4::MaxHeaderLength(); }
1.99 +
1.100 + union
1.101 + {
1.102 + TInet6HeaderIP4 ip4;
1.103 + TInet6HeaderIP ip6;
1.104 + };
1.105 + };
1.106 +
1.107 +
1.108 +// RMBufPacketPeek
1.109 +// ***************
1.110 +class RMBufPacketPeek : public RMBufChain
1.111 + /**
1.112 + Extends RMBufChain to add functions to read packet data as a descriptor
1.113 + and as an IP header.
1.114 +
1.115 + The RMBufChain is assumed to contain the raw packet, without
1.116 + the info block prepended (e.g. if this class is used for RMBufPacketBase
1.117 + derived handle, it must be in "unpacked" state).
1.118 +
1.119 + @since v7.0
1.120 + @publishedAll
1.121 + @released
1.122 + */
1.123 + {
1.124 +public:
1.125 + IMPORT_C TPtr8 Access(TInt aSize, TUint aOffset = 0);
1.126 + IMPORT_C TIpHeader *GetIpHeader();
1.127 + };
1.128 +
1.129 +// TPacketHead
1.130 +// ***********
1.131 +class TPacketHead
1.132 + /**
1.133 + Storage for some precomputed information for an outbound packet flow.
1.134 +
1.135 + The outbound TPacketHead is part of the flow context (CFlowContext).
1.136 +
1.137 + The CFlowContext::Connect initializes the content from the parameters
1.138 + of the flow (TFlowInfo) and runs the connection process.. The connection
1.139 + process (MIp6Hook::OpenL and MFlowHook::ReadyL phases) completes the
1.140 + information. After this, as long as the flow is connected, the content
1.141 + is mostly frozen and <b>must not be modified by anyone</b>.
1.142 +
1.143 + When there is a need to change any flow information, the changes must
1.144 + be done to the flow parameters (and not to TPacketHead). The change of
1.145 + flow parameters also sets the CFlowContext::iChanged flag, and this
1.146 + eventually causes a new CFlowContext::Connect, which re-initializes
1.147 + the TPacketHead with the new information.
1.148 +
1.149 + For each field in the TPacketHead, the hook writer must follow the
1.150 + basic rule (only for fields that it intends to change):
1.151 +
1.152 + - if some field is changed in MIp6Hook::OpenL, then the previous
1.153 + value should be restored in the MFlowHook::ReadyL.
1.154 + - an exeception: the hook must omit the restore, if the
1.155 + previous value was unspecified value (for example, the source
1.156 + address).
1.157 + - the content of #iPacket (and #iOffset) are special: they cannot
1.158 + be modified in the MIp6Hook::OpenL phase. A hook can
1.159 + modify them only in the MFlowHook::ReadyL phase. And, if the hook
1.160 + is adding an IP header for tunneling, it must save the current content
1.161 + of these fields in the ReadyL function, and then clear out the fields
1.162 + (it must make the iPacket empty and zero iOffset). The hook must add
1.163 + the saved iPacket content below the added tunnel header in
1.164 + MFlowHook::ApplyL .
1.165 +
1.166 + @since v7.0
1.167 + @publishedAll
1.168 + @released
1.169 + */
1.170 + {
1.171 +public:
1.172 + IMPORT_C TBool ExtHdrGet(TInt aType, TInt& aOfs, TInt& aLen);
1.173 + IMPORT_C TBool ExtHdrGetOrPrependL(TInt aType, TInt& aOfs, TInt& aLen);
1.174 + IMPORT_C TBool ExtHdrGetOrAppendL(TInt aType, TInt& aOfs, TInt& aLen);
1.175 + IMPORT_C void AddDestinationOptionL(const TPtrC8& aOption, TUint8 aAlign=0, TUint8 aModulo=4);
1.176 + IMPORT_C void AddDestinationOptionL(const TUint8* aOption, TUint8 aLen, TUint8 aAlign=0, TUint8 aModulo=4);
1.177 +
1.178 +public:
1.179 + /**
1.180 + "Virtual" IP header. The IPv6 header stucture is used, but the same
1.181 + format is <b>also</b> used for the IPv4 destinations (Version() == 4,
1.182 + even though the header format is still IPv6!)
1.183 +
1.184 + This header is initialized in the beginning of the OpenL phase
1.185 + as follows:
1.186 + @li Version = 0
1.187 + @li Traffic Class, copied from the flow iOptions.iTrafficClass
1.188 + @li Flow Label = 0
1.189 + @li Payload Length = 0 (dummy field, not used)
1.190 + @li Next Header, copied from the flow iProtocol
1.191 + @li Hop Limit, copied from the flow iOptions.iHopLimit
1.192 + @li Src Address, copied from the flow Local Address (usually unspecified)
1.193 + @li Dst Address, copied from the flow Remote Address
1.194 +
1.195 + At beginning of the ReadyL phase (= at end of OpenL), the destination
1.196 + address (and iDstId) are used to find a route on the interface. Depending
1.197 + on whether this address is IPv4 (mapped) or IPv6, the Version field is set
1.198 + accordingly to either 4 or 6.
1.199 +
1.200 + After succesfull completion of the ReadyL, this used for *each* packet
1.201 + which needs an IP header to be generated on send. The Version() determines
1.202 + whether IPv4 or IPv6 frame is to be generated (this is the initial
1.203 + header in the packet, *before* running outbound ApplyL hooks):
1.204 +
1.205 + @verbatim
1.206 + IPv6 IPv4
1.207 + Version == 6 ==4
1.208 + Traffic Class used as is used as TOS
1.209 + Flow Label used as is ignored
1.210 + Payload Length ignored ignored
1.211 + Next Header used as is used as Protocol
1.212 + Hop Limit used as is used as TTL
1.213 + Src Address used as is used as IPv4 mapped
1.214 + Dst Address used as is used as IPv4 mapped
1.215 + @endverbatim
1.216 + */
1.217 + TInet6HeaderIP ip6;
1.218 + /**
1.219 + Contains the scope id associated with the destination address
1.220 + which is stored in #ip6 Dst Address. This id and address must
1.221 + always be considered as a unit. Logically, any change changes
1.222 + both values.
1.223 +
1.224 + iDstId is initialized from the flow context TFlowInfo::iRemote.Scope() at
1.225 + beginning of the flow connect phase. If application does not define
1.226 + this scope id, then the system will attempt to choose a default value
1.227 + at beginning of the connect phase. If the default cannot be determined,
1.228 + the flow is put into pending state (and no connect happens).
1.229 +
1.230 + @par MIp6Hook::OpenL
1.231 + On entry to the OpenL, the iDstId is always non-zero and destination
1.232 + address is specified. If a hook changes the destination address in
1.233 + OpenL method, it must provide the correct id value
1.234 + which goes with the new destination. If it cannot do this, it
1.235 + must either abort the connect by leaving with an error state, or it
1.236 + can leave with PENDING (> 0) status to signal there is no route
1.237 + for the new destination.
1.238 + If the stack cannot find suitable interface for the destination, then
1.239 + it aborts the connect phase, and the flow is placed into holding state.
1.240 +
1.241 + @note
1.242 + Only a tunneling hook can safely change the destination
1.243 + address (a use of routing header can also be a kind of
1.244 + tunneling).
1.245 +
1.246 + @par MFlowHook::ReadyL
1.247 + If the hook changed the destination address (or id) in the OpenL,
1.248 + the ReadyL must restore the original values back.
1.249 +
1.250 + */
1.251 + TUint32 iDstId;
1.252 + /**
1.253 + Contains the scope id associated with the source address
1.254 + which is stored in #ip6 Src address. This is defined when the source
1.255 + address is defined, and otherwise undefined.
1.256 +
1.257 + iSrcId is initialized from TFlowInfo::iLocal.Scope() at beginning of the
1.258 + flow connect phase. If application defines the source address,
1.259 + but does not specify this scope id, then the system chooses
1.260 + the id based on the interface defined by the source address.
1.261 + If scope and address are both specified, they must match the
1.262 + selected interface.
1.263 +
1.264 + @par MIp6Hook::OpenL
1.265 + On entry to the OpenL, the iSrcId (and source address) may be
1.266 + undefined (#iSourceSet = 0). If defined (iSourceSet = 1), then
1.267 + both address and iSrcId are defined (iSrcId != 0). A hook may
1.268 + force a reselection of the source just by zeroing the
1.269 + iSourceSet.
1.270 +
1.271 + @par MFlowHook::ReadyL
1.272 + If the hook changed the source address (or id) in the OpenL,
1.273 + the ReadyL must restore the original values back, but only
1.274 + if the original value was defined (#iSourceSet = 1 in OpenL).
1.275 + */
1.276 + TUint32 iSrcId;
1.277 + /**
1.278 + The source address has been set.
1.279 +
1.280 + This bit indicates whether the value stored in #ip6 src field
1.281 + and #iSrcId is to be used as a source address as is.
1.282 +
1.283 + Initialized from TFlowInfo::iLocalSet, which tells whether user
1.284 + specified tbe source address or not (e.g used RSocket Bind method).
1.285 + The stack checks the value after each MIp6Hook::OpenL call, and
1.286 + if the flag is set, the source in ip6 is used as is. If the flag
1.287 + is zero, then the stack performs the normal source address selection
1.288 + based on the current destination address (#iSrcId and destination
1.289 + address).
1.290 +
1.291 + @par MIp6Hook::OpenL
1.292 + On entry, this flag is always set and source address is defined.
1.293 + A hook may clear this flag, if it wants the
1.294 + stack choose the source address based on current destination.
1.295 + The clearing operation is normally needed only by a tunneling
1.296 + hook.
1.297 +
1.298 + @note
1.299 + If the hook specifies the source address, it must be either
1.300 + a valid source address for the interface or unspecified
1.301 + address.
1.302 +
1.303 + @par MFlowHook::ReadyL
1.304 + Upon entry to the ReadyL, the source address is always fully
1.305 + known (the hook can assume that #iSrcId and the #ip6 source
1.306 + addresses are valid).
1.307 + If the source address was set before the OpenL, then this
1.308 + must restore the original value (along with the #iSrcId
1.309 + and source address).
1.310 + */
1.311 + TUint iSourceSet:1;
1.312 +#ifdef TPACKETHEAD_FRAGMENT
1.313 + /**
1.314 + The fragment processing alredy done.
1.315 +
1.316 + This bit is meaningful only in OpenL phase. If already set,
1.317 + then some ealier hook has requested that the packet must
1.318 + be fragmented to fit the mtu.
1.319 +
1.320 + A tunneling hook can set this bit in OpenL, if it needs
1.321 + the fragmenting to happen before the ApplyL is called (e.g.
1.322 + the fragments are tunneled instead of fragmenting the
1.323 + tunneling).
1.324 +
1.325 + This bit can only be set or left as is. It cannot be cleared
1.326 + once set.
1.327 + */
1.328 + TUint iFragment:1;
1.329 +#endif
1.330 + /**
1.331 + Selector info, the upper layer protocol.
1.332 +
1.333 + iProtocol has the same value as ip6.NextHeader() when iPacket is empty,
1.334 + and otherwise it is the same as NextHeader() of the last extension
1.335 + header in the iPacket.
1.336 +
1.337 + The values of the other selector fields: #iIcmpType, #iIcmpCode
1.338 + #iSrcPort and #iDstPort depend on iProtocol. Whenever iProtocol
1.339 + is changed, the other fields must be updated accordingly.
1.340 +
1.341 + @par MIp6Hook::OpenL
1.342 + Because iPacket cannot be modified during the OpenL phase, the
1.343 + content of this field and the Next Header (protocol) field in
1.344 + the #ip6 pseudoheader must always be the same. This field should
1.345 + be considered as <b>read-only</b>, unless the hook intends to
1.346 + apply IP-in-IP tunneling, in which case the hook <b>must</b>
1.347 + change the value to the appropriate tunneling protocol
1.348 + (#KProtocolInet6Ipip or #KProtocolInetIpip).
1.349 +
1.350 + @par MFlowHook::ReadyL
1.351 + Only a tunneling hook needs to restore the value here to match
1.352 + the original upper layer protocol. See #iPacket for
1.353 + more detailed information.
1.354 + */
1.355 + TUint8 iProtocol;
1.356 + /**
1.357 + Selector field whose value depends on #iProtocol.
1.358 +
1.359 + If this field does not have meaning with the protocol,
1.360 + the field content should be set to ZERO.
1.361 + */
1.362 + TUint8 iIcmpType;
1.363 + /**
1.364 + Selector field whose value depends on #iProtocol.
1.365 +
1.366 + If this field does not have meaning with the protocol,
1.367 + the field content should be set to ZERO.
1.368 + */
1.369 + TUint8 iIcmpCode;
1.370 + /**
1.371 + Selector field whose value depends on #iProtocol.
1.372 +
1.373 + If this field does not have meaning with the protocol,
1.374 + the field content should be set to ZERO.
1.375 + */
1.376 + TUint16 iSrcPort;
1.377 + /**
1.378 + Selector field whose value depends on #iProtocol.
1.379 +
1.380 + If this field does not have meaning with the protocol,
1.381 + the field content should be set to ZERO.
1.382 + */
1.383 + TUint16 iDstPort;
1.384 + /**
1.385 + The amount of pre-computed IPv6 extension headers in iPacket which
1.386 + are copied to the beginning of each outgoing packet
1.387 +
1.388 + If iOffset > 0, then #iPacket includes that much of extension
1.389 + headers that are copied in front of each packet.
1.390 + */
1.391 + TInt iOffset;
1.392 + /**
1.393 + Pre-computed extension headers for all packets in this flow.
1.394 +
1.395 + These can only be added in the ReadyL phase. If any of the
1.396 + ReadyL's adds extension headers into this, it must take care
1.397 + of maintaining the correct Next Header in the virtual IP header
1.398 + (and the original upper layer protocol must be placed in the
1.399 + next header of the last extension header added.
1.400 +
1.401 + Stack copies the content of this to each outgoing packet, just below
1.402 + the IP header, before running the ApplyL functions of the outbound
1.403 + flow hooks.
1.404 +
1.405 + @par MIp6Hook::OpenL
1.406 + The iPacket <b>must not</b> be modified during the OpenL phase.
1.407 +
1.408 + @par MFlowHook::ReadyL
1.409 + A non-tunneling hook may add extension headers into the current
1.410 + iPacket. A tunneling hook has more complex requirements:
1.411 + it must save the current iPacket and #iOffset and initialize
1.412 + iOffset = 0, and iPacket as empty.
1.413 +
1.414 + @par MFlowHook::ApplyL
1.415 + When a tunneling hook adds the tunneling IP header, it
1.416 + must also copy the saved iPacket below the added IP header.
1.417 + */
1.418 + RMBufPacketPeek iPacket;
1.419 + /**
1.420 + The received packet which caused an ICMP error reply to be sent.
1.421 +
1.422 + This is only used for ICMP error repply flows, and should be
1.423 + ignored by others -- mainly for IPSEC hook. The packet, if
1.424 + present, is in unpacked state.
1.425 + */
1.426 + RMBufPacketBase iIcmp;
1.427 + /**
1.428 + The current destination interface.
1.429 +
1.430 + This is ONLY used during connect/OpenL phase.
1.431 +
1.432 + The value is maintained by the stack, and is intended as
1.433 + read-only information for the hooks that have a use for
1.434 + it (for example, IPSEC implementing VPN specific policies).
1.435 +
1.436 + A hook must not modify this value (the stack will recompute
1.437 + the value after each OpenL, based on the possibly changed
1.438 + address parameters in the TPacketHead)
1.439 +
1.440 + @par MIp6Hook::OpenL
1.441 + <b>read-only</b>
1.442 + @par MFlowHook::ReadyL
1.443 + <b>read-only</b>
1.444 + */
1.445 + TUint32 iInterfaceIndex;
1.446 + };
1.447 +
1.448 +class TInet6PacketBase
1.449 + /**
1.450 + * Thin base class for the TInet6Packet.
1.451 + */
1.452 + {
1.453 +public:
1.454 + enum TAlign
1.455 + {
1.456 + EAlign1 = 0, ///< Align to byte (no align requirement)
1.457 + EAlign2 = 1, ///< Align to 2 byte unit (even address)
1.458 + EAlign4 = 3, ///< Align to 4 byte unit
1.459 + EAlign8 = 7 ///< Align to 8 byte unit
1.460 + };
1.461 +
1.462 + /**
1.463 + Constructor.
1.464 +
1.465 + @param aAlign The align requirement.
1.466 + */
1.467 + TInet6PacketBase(TAlign aAlign) : iLength(0), iAlign(aAlign) {}
1.468 +
1.469 + /**
1.470 + Length of the mapped region.
1.471 +
1.472 + The real mapped length as computed by the Access function.
1.473 + If access returned non-NULL, the following is always TRUE:
1.474 +
1.475 + @li aMin <= iLength
1.476 + */
1.477 + TInt iLength;
1.478 +
1.479 + IMPORT_C TUint8 *Access(RMBufChain &aPacket, TInt aOffset, TInt aSize, TInt aMin);
1.480 +
1.481 + inline void SetAlign(TAlign aAlign)
1.482 + /**
1.483 + * Changes the align requirement.
1.484 + *
1.485 + * @param aAlign The new align requirement.
1.486 + */
1.487 + {
1.488 + iAlign = aAlign;
1.489 + }
1.490 +protected:
1.491 + /**
1.492 + The align requirement.
1.493 + */
1.494 + TAlign iAlign;
1.495 + };
1.496 +
1.497 +// TInet6Packet template
1.498 +// *********************
1.499 +template <class T>
1.500 +class TInet6Packet : public TInet6PacketBase
1.501 + /**
1.502 + Encapsulates an IPv6 packet header as a section of an RMBufChain.
1.503 +
1.504 + The T template parameter should represent a packet header type. It should
1.505 + support static functions MaxHeaderLength() and MinHeaderLength() that return
1.506 + TInt values for maximum and minimum header lengths respectively.
1.507 +
1.508 + @publishedAll
1.509 + @released
1.510 + @since v7.0
1.511 + */
1.512 + {
1.513 +public:
1.514 + TInet6Packet(TAlign aAlign = EAlign4) : TInet6PacketBase(aAlign), iHdr(NULL)
1.515 + /**
1.516 + Default constructor.
1.517 +
1.518 + Construct an empty mapping. To be usable, the Set() function
1.519 + must be used.
1.520 + */
1.521 + {}
1.522 + TInet6Packet(RMBufChain &aPacket) : TInet6PacketBase(EAlign4)
1.523 + /**
1.524 + Constructor specifying a RMBufChain object.
1.525 +
1.526 + Verify and arrange it so that a class T can be mapped
1.527 + to a contiguous octets from the beginning of the RMBufChain
1.528 + content, and set iHdr to point this area.
1.529 +
1.530 + If this is not possible, iHdr is initialized to NULL.
1.531 +
1.532 + @param aPacket
1.533 + Packet containing the header T at offset = 0
1.534 + */
1.535 + {
1.536 + iHdr = (T *)Access(aPacket, 0, T::MaxHeaderLength(), T::MinHeaderLength());
1.537 + }
1.538 +
1.539 + TInet6Packet(RMBufChain &aPacket, TInt aOffset, TAlign aAlign = EAlign4) : TInet6PacketBase(aAlign)
1.540 + /**
1.541 + Constructor specifying a RMBufChain object and an offset.
1.542 +
1.543 + Verify and arrange it so that a class T can be mapped
1.544 + to a contiguous octets starting at specified offset of
1.545 + the RMBufChain content, and set iHdr to point this area.
1.546 +
1.547 + If this is not possible, iHdr is initialized to NULL.
1.548 +
1.549 + @param aPacket
1.550 + Packet containing the header T at aOffset
1.551 + @param aOffset
1.552 + Offset of the header to be mapped.
1.553 + @param aAlign
1.554 + The alignement requirement.
1.555 + */
1.556 + {
1.557 + iHdr = (T *)Access(aPacket, aOffset, T::MaxHeaderLength(), T::MinHeaderLength());
1.558 + }
1.559 +
1.560 + void Set(RMBufChain &aPacket, TInt aOffset, TInt aSize)
1.561 + /**
1.562 + Sets the packet header from a specified RMBufChain object.
1.563 +
1.564 + Verify and arrange it so that a aSize octets can be mapped
1.565 + to a contiguous octets starting at specified offset of
1.566 + the RMBufChain content, and set iHdr to point this area.
1.567 +
1.568 + If this is not possible, iHdr is initialized to NULL.
1.569 +
1.570 + Note that this differs from the contructors: the required
1.571 + size is a parameter, and not determined by the T::MinHeaderLength().
1.572 + However, the "T* iHdr" is set to point the start of the requested
1.573 + area. It's a responsibility of the user of this method to know
1.574 + whether using this pointer is safe with the specified size parameter.
1.575 +
1.576 + @param aPacket
1.577 + Packet containing the header T at aOffset
1.578 + @param aOffset
1.579 + Offset (position) of the header to be mapped
1.580 + @param aSize
1.581 + Length of required contiguous memory
1.582 + */
1.583 + {
1.584 + iHdr = (T *)Access(aPacket, aOffset, aSize, aSize);
1.585 + }
1.586 +
1.587 + inline T& operator()()
1.588 + {
1.589 + return *iHdr;
1.590 + }
1.591 + /**
1.592 + The pointer to the mapped region (if non-NULL). If NULL,
1.593 + then there is no mapping, and iLength == 0.
1.594 + */
1.595 + T *iHdr;
1.596 + };
1.597 +
1.598 +
1.599 +// TPacketPoker
1.600 +// ************
1.601 +class TPacketPoker
1.602 + /**
1.603 + Provides a utility for linear scanning of a chain of RMBuf objects (an RMBufChain).
1.604 +
1.605 + An object of this type maintains a current point in the RMBufChain. This point
1.606 + can only move forward, and a leave occurs if the point advances beyond the
1.607 + end of the chain.
1.608 +
1.609 + Any pointers and aligns arranged before the current point, remain valid: for
1.610 + example, you can save a reference and advance the pointer, and the reference
1.611 + remains usable.
1.612 +
1.613 + If instead you need to go to a single specified offset, then use
1.614 + RMBufChain::Goto() or RMBufPacketPeek::Access().
1.615 +
1.616 + @post
1.617 + A Generic implementation assert:
1.618 + after construct, iTail == 0 iff iCurrent == 0 (all scanned), or
1.619 + in other words: as long as there are bytes after current point,
1.620 + iTail will be non-zero (and More() returns ETrue).
1.621 + All methods maintain this invariant or leave, if impossible.
1.622 +
1.623 + Some other utility methods, not directly related to scanning, are also included.
1.624 + @since v7.0
1.625 + @publishedAll
1.626 + @released
1.627 + */
1.628 + {
1.629 +public:
1.630 + IMPORT_C TPacketPoker(RMBufChain &aChain);
1.631 +
1.632 + inline void SkipL(TInt aSize)
1.633 + /**
1.634 + Moves the current point forward a specified number of bytes.
1.635 +
1.636 + @param aSize Number of bytes to move forward
1.637 + @leave KErrEof
1.638 + if the request cannot be satisfied.
1.639 + */
1.640 + { if (aSize < iTail) { iTail -= aSize; iOffset += aSize; } else OverL(aSize); }
1.641 +
1.642 + inline TUint8 *Ptr() const
1.643 + /**
1.644 + Raw pointer to the current point (can be invalid, if iTail = 0).
1.645 +
1.646 + @note Internal "unsafe" method
1.647 + */
1.648 + {return iCurrent->Ptr() + iOffset; }
1.649 +
1.650 + inline TUint8 *ReferenceL(TInt aSize = 1)
1.651 + /**
1.652 + Gets a pointer to the current point, such that
1.653 + at least the specified minimum number of bytes can be read.
1.654 +
1.655 + @param aSize
1.656 + Specified minimum number of bytes to be read through
1.657 + the returned pointer.
1.658 + @return Raw data pointer
1.659 + @leave KErrEof
1.660 + if the request cannot be satisfied.
1.661 + */
1.662 + { if (iTail >= aSize) return Ptr(); else return AdjustL(aSize); }
1.663 +
1.664 + inline TUint8 *ReferenceAndSkipL(TInt aSize)
1.665 + /**
1.666 + Gets a pointer to the current point, such that at least the
1.667 + specified minimum number of bytes can be read,
1.668 + and moves the point the specified number of bytes forward.
1.669 +
1.670 + @param aSize
1.671 + Specified minimum number of bytes to be read through the returned
1.672 + pointer, and the number of bytes to move forward
1.673 + @return
1.674 + Raw data pointer
1.675 + @leave KErrEof
1.676 + if the request cannot be satisfied.
1.677 + */
1.678 + { TUint8 *x = ReferenceL(aSize); SkipL(aSize); return x; }
1.679 +
1.680 + inline TInt Remainder() const
1.681 + /**
1.682 + Gets the length of the contiguous space after the current point.
1.683 +
1.684 + @return Length after the current point
1.685 + */
1.686 + { return iTail; }
1.687 +
1.688 + inline TBool AtBegin() const
1.689 + /**
1.690 + Tests whether the current point is at the beginning of an RMBuf.
1.691 +
1.692 + @return ETrue if current point is at the beginning
1.693 + */
1.694 + { return iOffset == 0; }
1.695 +
1.696 + inline TBool More() const
1.697 + /**
1.698 + Tests whether there is more data to scan.
1.699 +
1.700 + @return ETrue if there is more data to scan
1.701 + */
1.702 + { return iTail > 0; }
1.703 +
1.704 + IMPORT_C static TBool IsExtensionHeader(TInt aProtocolId);
1.705 +private:
1.706 + IMPORT_C void OverL(TInt aSize);
1.707 + IMPORT_C TUint8 *AdjustL(TInt aSize);
1.708 + /** The RMBuf of the current point. */
1.709 + RMBuf *iCurrent;
1.710 + /** The offset of the current point in the RMBuf. */
1.711 + TInt iOffset;
1.712 + /** Remaining bytes starting from the current point in the RMBuf. */
1.713 + TInt iTail;
1.714 + };
1.715 +
1.716 +#endif