--- a/telephonyprotocols/rawipnif/src/BcaIoController.cpp Fri Apr 16 16:12:37 2010 +0300
+++ b/telephonyprotocols/rawipnif/src/BcaIoController.cpp Mon May 03 13:37:20 2010 +0300
@@ -21,12 +21,23 @@
#include <e32uid.h>
#include <nifmbuf.h>
+#include <e32svr.h>
+#include <u32hal.h>
#include "Constants.h"
#include "BcaIoController.h"
#include "Sender.h"
#include "Receiver.h"
+const TUint KDefaultSendQueueSize=5;
+
+#ifdef __EABI__
+// Patch data is used and KMaxTxIPPacketSize and KMaxRxIPPacketSize can be modified to a different value in RawIpNif.iby file
+extern const TInt KMaxSendQueueLen = KDefaultSendQueueSize;
+extern const TInt KMaxTxIPPacketSize = KMaxIPPacket + KIPTagHeaderLength;
+extern const TInt KMaxRxIPPacketSize = KMaxIPPacket + KIPTagHeaderLength;
+#endif
+
CBcaIoController::CBcaIoController(MControllerObserver& aObserver,
CBttLogger* aTheLogger)
/**
@@ -35,14 +46,17 @@
* @param aObserver Reference to the observer of this state machine
* @param aTheLogger The logging object
*/
- :
- CBcaController(aObserver, aTheLogger),
- iMBca(NULL),
- iSender(NULL),
- iReceiver(NULL),
- iLoader(NULL)
- {
- }
+ : iTheLogger(aTheLogger),
+ iSendState(EIdle),
+ iFlowBlocked(EFalse),
+ iNumPacketsInSendQueue(0),
+ iObserver(aObserver),
+ iMBca(NULL),
+ iSender(NULL),
+ iReceiver(NULL),
+ iLoader(NULL)
+ {
+ }
CBcaIoController* CBcaIoController::NewL(MControllerObserver& aObserver, CBttLogger* aTheLogger)
/**
@@ -53,25 +67,49 @@
* @param aTheLogger The logging object
* @return A newly constructed CBcaIoController object
*/
- {
- CBcaIoController* self = new (ELeave) CBcaIoController(aObserver, aTheLogger);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop(self);
- return self;
- }
+ {
+ CBcaIoController* self = new (ELeave) CBcaIoController(aObserver, aTheLogger);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
void CBcaIoController::ConstructL()
/**
* Second-phase constructor. Creates all the state objects it owns.
*/
- {
- _LOG_L1C1(_L8("CBcaIoController::ConstructL"));
- BaseConstructL();
- iSender = CSender::NewL(*this, iTheLogger, iMaxPacketSise);
- iReceiver = CReceiver::NewL(*this, iTheLogger, iMaxPacketSise);
- iLoader = new (ELeave) CBcaControl(*this, iTheLogger);
- }
+ {
+ _LOG_L1C1(_L8("CBcaIoController::ConstructL"));
+
+#ifdef RAWIP_HEADER_APPENDED_TO_PACKETS
+ iIPTagHeader = new (ELeave) CIPTagHeader(iTheLogger);
+#endif // RAWIP_HEADER_APPENDED_TO_PACKETS
+
+#if defined __EABI__
+ // Default value for queue length
+ iMaxSendQueueLen = KMaxSendQueueLen;
+ // Default value for Tx and Rx packet size
+ iMaxTxPacketSize = KMaxTxIPPacketSize;
+ iMaxRxPacketSize = KMaxRxIPPacketSize;
+#else // WINS
+ // Set default values in case patch is not present in epocrawip.ini
+ iMaxSendQueueLen = KDefaultSendQueueSize;
+ iMaxTxPacketSize = KMaxIPPacket + KIPTagHeaderLength;
+ iMaxRxPacketSize = KMaxIPPacket + KIPTagHeaderLength;
+
+ // for the emulator process is patched via the epocrawip.ini file
+ UserSvr::HalFunction(EHalGroupEmulator,EEmulatorHalIntProperty,(TAny*)"rawip_KMaxSendQueueLen",&iMaxSendQueueLen);
+ UserSvr::HalFunction(EHalGroupEmulator,EEmulatorHalIntProperty,(TAny*)"rawip_KMaxTxIPPacketSize",&iMaxTxPacketSize);
+ UserSvr::HalFunction(EHalGroupEmulator,EEmulatorHalIntProperty,(TAny*)"rawip_KMaxRxIPPacketSize",&iMaxRxPacketSize);
+#endif
+
+ // end note
+
+ iSender = CSender::NewL(*this, iTheLogger, iMaxTxPacketSize);
+ iReceiver = CReceiver::NewL(*this, iTheLogger, iMaxRxPacketSize);
+ iLoader = new (ELeave) CBcaControl(*this, iTheLogger);
+ }
CBcaIoController::~CBcaIoController()
@@ -79,10 +117,16 @@
* Destructor.
*/
{
+ iSendQueue.Free();
+ iNumPacketsInSendQueue = 0;
+
delete iReceiver;
delete iSender;
delete iLoader;
-
+
+#ifdef RAWIP_HEADER_APPENDED_TO_PACKETS
+ delete iIPTagHeader;
+#endif // RAWIP_HEADER_APPENDED_TO_PACKETS
}
/** sets the BCA Stack name
@@ -103,7 +147,7 @@
{
_LOG_L1C1(_L8("CBcaIoController::StartL is called."));
- InitialiseBcaL();
+ iLoader->StartLoadL();
}
void CBcaIoController::Stop(TInt aError)
@@ -118,7 +162,7 @@
//Stop all the active objects
iReceiver->Cancel();
- if(GetSendState() == ESending)
+ if (iSendState == ESending)
{
iSender->Cancel();
}
@@ -129,61 +173,269 @@
iLoader->ShutdownBca(aError);
}
-void CBcaIoController::InitialiseBcaL()
-/**
- * Load & Initialise Bca.
- */
- {
- _LOG_L1C1(_L8("<<CBcaIoController::InitialiseBcaL"));
- iLoader->StartLoadL();
- }
-void CBcaIoController::BcaProcess(TDesC8& aPdu)
+ESock::MLowerDataSender::TSendResult CBcaIoController::Send(RMBufChain& aPdu)
/**
- * This method will pass on the received data to CRawIPNifMain.
+ * This method is called by CRawIPFlow in order to send a packet down
+ * to the BCA.
*
- * @param aPdu a data packet
+ * @param aPdu a data packet
*/
- {
- _LOG_L1C1(_L8(">>CBcaIoController::Process"));
+ {
+ _LOG_L1C1(_L8(">>CBcaIoController::Send"));
+
+ // Check if flow is shutting down
+ if (iSendState == EShuttingDown)
+ {
+ _LOG_L2C1(_L8(" ERROR: Nif is shutting down"));
+
+ // when the flow is destroyed the memory for this packet will be
+ // cleaned up - just tell the layers above to stop sending.
+ aPdu.Free();
+
+ return ESock::MLowerDataSender::ESendBlocked;
+ }
+
+ // check that this packet isnt too big - If it is, we dont want to send it or
+ // add it to our queue
+ if ((aPdu.Length() - aPdu.First()->Length()) > iMaxTxPacketSize)
+ {
+ _LOG_L2C1(_L8("Packet is too large - discarding"));
+ _LOG_L1C1(_L8("<<CSender::Send -> Error"));
- Process(aPdu);
+ // in debug panic - this should not happen, MTU on the uplink should
+ // be strictly enforced
+ __ASSERT_DEBUG(ETrue,Panic(KFlowInvalidULPacketSize));
+
+ aPdu.Free();
+
+ // may be counter intuitive, however the only options here are either
+ // send accepted or blocked (MLowerDataSender).
+
+ _LOG_L2C1(_L8("<<CBcaIoController::Send - return ContinueSending"));
+ return ESock::MLowerDataSender::ESendAccepted;
+ }
+
+ // transmit flow control.
+ if (iFlowBlocked)
+ {
+ // Transmit is off for this flow - we must have received a block
+ // message from our control. append this message to the queue
+ // and tell the layer above it to kindly stop sending.
+ _LOG_L1C1(_L8(" Sender blocked, appending packet to queue"));
+
+ AppendToSendQueue(aPdu);
+
+ // may be a bit counter-intuitive, however, even if the flow is blocked
+ // there is no reason not to ask for more data as long as our send
+ // queue isn't full.
+
+ if (IsSendQueueFull())
+ {
+ _LOG_L2C1(_L8("<<CBcaIoController::Send - return StopSending"));
+ return ESock::MLowerDataSender::ESendBlocked;
+ }
+ else
+ {
+ _LOG_L2C1(_L8("<<CBcaIoController::Send - return ContinueSending"));
+ return ESock::MLowerDataSender::ESendAccepted;
+ }
+ }
+
+ // transmit is on for this flow. send a packet or queue it
+ // if we're already sending one.
- _LOG_L1C1(_L8("<<CBcaIoController::Process"));
- }
+ if (iSendState == ESending)
+ // If this happens, it means that TCP/IP has sent us an IP packet
+ // while we're still sending the previous one.
+ {
+ _LOG_L1C1(_L8(" Sender busy, appending packet to queue"));
+ AppendToSendQueue(aPdu);
+
+ if (IsSendQueueFull())
+ {
+ _LOG_L2C1(_L8("<<CBcaIoController::Send - return StopSending"));
+ return ESock::MLowerDataSender::ESendBlocked;
+ }
+ }
+ else
+ {
+ // if we're idle, then we must not be sending. If we're not idle
+ // then the SendComplete() will handle sending any additional
+ // packets that might have been queued onto the send queue.
+
+ // Update module state
+ _LOG_L2C1(_L8(" set State to ESending"));
+ iSendState = ESending;
+
+ iSender->Send(aPdu);
+ }
-void CBcaIoController::BcaSend(RMBufChain& aPdu)
+ // if our send queue isn't full, then the send is accepted
+ // otherwise, block this flow until we have room for the next
+ // packet
+
+ _LOG_L2C1(_L8("<<CBcaIoController::Send - return ContinueSending"));
+
+ return ESock::MLowerDataSender::ESendAccepted;
+ }
+
+void CBcaIoController::SendComplete()
/**
- * This method is called by CRawIPNifMain in order to send a packet down
- * to the BCA. The CSender active object will be activated by calling the send
- * method.
- *
- * @param aPdu a data packet
+ * A packet has finished sending - check to see if we need
+ * to process more packets.
*/
- {
- _LOG_L1C1(_L8("CBcaIoController::BcaSend"));
+ {
+ _LOG_L1C1(_L8(">>CBcaIoController::SendComplete"));
+
+ // if we've been blocked while in the middle of a
+ // send - don't continue sending, this will happen
+ // when the flow is resumed.
+
+ iSendState = EIdle;
- iSender->Send(aPdu);
- }
+ // are we available to transmit?
+
+ if (iFlowBlocked == EFalse)
+ {
+ // flow transmit is on
+
+ TBool resumeSending = EFalse;
+
+ // if the queue is full, it means that while a packet was
+ // outstanding in BCA, we've filled up our send queue and
+ // informed the upper layers to stop sending.
+
+ if (IsSendQueueFull())
+ {
+ resumeSending = ETrue;
+ }
+
+ // if the queue has anything inside it, we need to send the
+ // first packet in the queue. note: the resumeSending check is to
+ // short circuit this so we don't check the queue length twice
+ // in the case that it is full
+
+ if ((resumeSending) || (!IsSendQueueEmpty()))
+ {
+ iSendState = ESending;
+
+ RMBufChain tmpPdu;
+ _LOG_L1C1(_L8(" Packet removed from queue to send"));
+ RemoveFromSendQueue(tmpPdu);
+
+ // Update module state
+ _LOG_L2C1(_L8(" set State to ESending"));
+
+ iSender->Send(tmpPdu);
+
+ // if the queue was full, again, we told the upper layers
+ // to stop sending, we need to resume this flow. order is
+ // important as we don't want to get a packet before we've
+ // given one to BCA to send.
+ if (resumeSending)
+ {
+ iObserver.ResumeSending();
+ }
+ }
+ }
+
+ _LOG_L1C1(_L8("<<CBcaIoController::SendComplete"));
+ }
+
+
+void CBcaIoController::ResumeSending()
+/**
+ * Flow is being unblocked this will resume sending.
+ */
+ {
+ _LOG_L1C1(_L8(">>CBcaIoController::ResumeSending"));
-TInt CBcaIoController::BcaSendBufferLength()
- {
- return iSender->SendBufferLength();
- }
+ // allows for normal SendComplete behaviour if there is
+ // a packet outstanding with BCA
+ iFlowBlocked = EFalse;
+
+ // If the send state is idle, then there isn't a packet
+ // outstanding, check the send queue to see if there are
+ // packets to send.
+
+ if (iSendState == EIdle)
+ {
+ // flow transmit is on
+
+ TBool resumeSending = EFalse;
+
+ if (IsSendQueueFull())
+ {
+ resumeSending = ETrue;
+ }
+
+ // if the queue has anything inside it, we need to send the
+ // first packet in the queue. note: the resumeSending check is to
+ // short circuit this so we don't check the queue length twice
+ // in the case that it is full
+
+ if ((resumeSending) || (!IsSendQueueEmpty()))
+ {
+ RMBufChain tmpPdu;
+ _LOG_L1C1(_L8(" Packet removed from queue to send"));
+ RemoveFromSendQueue(tmpPdu);
+
+ // Update module state
+ _LOG_L2C1(_L8(" set State to ESending"));
+ iSendState = ESending;
+
+ iSender->Send(tmpPdu);
+
+ // if the queue was full, again, we told the upper layers
+ // to stop sending, we need to resume this flow. order is
+ // important as we don't want to get a packet before we've
+ // given one to BCA to send.
+ if (resumeSending)
+ {
+ iObserver.ResumeSending();
+ }
+ }
+ }
+
+ _LOG_L1C1(_L8("<<CBcaIoController::ResumeSending"));
+ }
-void CBcaIoController::BcaSendComplete()
+#ifdef RAWIP_HEADER_APPENDED_TO_PACKETS
+void CBcaIoController::SetType(TUint16 aType)
+ {
/**
- * This method is called after a packet was sent to the board.
- * If allowed by flow contol flags the NIF can signal the TCP/IP
- * protocol indicating that is available to send more packets.
+ * Used to specify the type of the IP header.
+ */
+ _LOG_L1C1(_L8("CBcaController::SetType"));
+
+ iIPTagHeader->SetType(aType);
+ }
+
+void CBcaIoController::AddHeader(TDes8& aDes)
+/**
+ * Used to add the IP header to the packet before sending to the BCA.
*/
- {
- _LOG_L1C1(_L8("CBcaController::SendComplete"));
+ {
+ _LOG_L1C1(_L8("CBcaController::AddHeader"));
+
+ iIPTagHeader->AddHeader(aDes);
+ }
- SendComplete();
- }
+TUint16 CBcaIoController::RemoveHeader(RMBufChain& aPdu)
+/**
+ * Used to remove the IP header from the received the packet before sending to the
+ * TCP/IP layer.
+ * @return The IP header that has been removed from the packet
+ */
+ {
+ _LOG_L1C1(_L8("CBcaController::RemoveHeader"));
-
+ return (iIPTagHeader->RemoveHeader(aPdu));
+ }
+#endif // RAWIP_HEADER_APPENDED_TO_PACKETS
+
+
CBcaControl::CBcaControl(CBcaIoController& aObserver, CBttLogger* aTheLogger)
/**
* Constructor. Performs standard active object initialisation.