applayerprotocols/telnetengine/SRC/IOBUFFER.CPP
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2003-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 // Telnet Protocol API
       
    15 // CIOBufferControl implementation
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #include "IOBUFFER.H"
       
    24 #include "ACTIVEIO.H"
       
    25 #include "TELDEBUG.H"
       
    26 
       
    27 CIOBufferControl::CIOBufferControl()
       
    28 /**
       
    29 Constructor
       
    30 */
       
    31 	{
       
    32 	}
       
    33 
       
    34 CIOBufferControl::~CIOBufferControl()
       
    35 /**
       
    36 Destructor
       
    37 */
       
    38 	{
       
    39 	Reset();
       
    40 	__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CIOBufferControl::D'Tor"));
       
    41 	}
       
    42 
       
    43 CIOBufferControl* CIOBufferControl::NewL(MIONotifier* aNotifier)
       
    44 	{
       
    45 	CIOBufferControl* self = new(ELeave) CIOBufferControl;
       
    46 	CleanupStack::PushL(self);
       
    47 	self->ConstructL(aNotifier);
       
    48 	CleanupStack::Pop();
       
    49 	return self;
       
    50 	}
       
    51 
       
    52 void CIOBufferControl::ConstructL(MIONotifier* aNotifier)
       
    53 	{
       
    54 	iNotifier = aNotifier;
       
    55 
       
    56 	iWriter = NULL;
       
    57 	iReader = NULL;
       
    58 
       
    59 	iQueueIndex = 0;
       
    60 	iLiveIndex = 0;
       
    61 	
       
    62 	iUrgent = NULL;
       
    63 	iWriteBuffers[0] = NULL;
       
    64 	iWriteBuffers[1] = NULL;
       
    65 	}
       
    66 
       
    67 TInt CIOBufferControl::WriteUrgent(HBufC8* aBuffer)
       
    68 /**
       
    69 Caller requests to send data as TCP urgent
       
    70 */
       
    71 	{
       
    72 	TInt err = KErrNone;
       
    73 	// Check to see if write is already outstanding
       
    74 	if(iLiveIndex == iQueueIndex)
       
    75 		{
       
    76 		// No write outstanding
       
    77 		// Just set the live index to point to the heap buffer
       
    78 		iWriteBuffers[iLiveIndex] = aBuffer;
       
    79 		// Make indexes different so if the next write call comes before completion of this one
       
    80 		// then it can append to the queue buffer
       
    81 		(iLiveIndex == 0) ? (iQueueIndex = 1) : (iQueueIndex = 0);
       
    82 		iWriter->IssueUrgentWrite(*(iWriteBuffers[iLiveIndex]));
       
    83 		err = KErrNone;
       
    84 		}
       
    85 	else
       
    86 		{
       
    87 		// Check for existing queued urgent
       
    88 		if(iUrgent)
       
    89 			// DON'T permit queued urgents
       
    90 			err = KErrInUse;
       
    91 		else
       
    92 			{
       
    93 			// Data will be sent on next write completion
       
    94 			iUrgent = aBuffer;
       
    95 			err = KErrNone;
       
    96 			}
       
    97 		}
       
    98 	return(err);
       
    99 	}
       
   100 
       
   101 TInt CIOBufferControl::Write(HBufC8* aBuffer)
       
   102 /**
       
   103 Writes issued into this object send it to the active writer
       
   104 Ownership of the buffer is transferred
       
   105 */
       
   106 	{
       
   107 	TInt ret = KErrNone;
       
   108 
       
   109 	TPtr8 ptr = aBuffer->Des();
       
   110 
       
   111 	// iLiveIndex = iQueueIndex means there are no outstanding writes on the socket
       
   112 	if(iLiveIndex == iQueueIndex)
       
   113 		{			
       
   114 		iWriteBuffers[iLiveIndex] = aBuffer;
       
   115 		// Make indexes different so if the next write call comes before completion of this one
       
   116 		// then it can append to the queue buffer
       
   117 		(iLiveIndex == 0) ? (iQueueIndex = 1) : (iQueueIndex = 0);
       
   118 		iWriter->IssueWrite(*(iWriteBuffers[iLiveIndex]));
       
   119 		}
       
   120 	else
       
   121 		{
       
   122 		__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CIOBufferControl() Write Queue"));
       
   123 		// There is already a buffer loaded on the socket
       
   124 		if(iWriteBuffers[iQueueIndex])
       
   125 			// Append this data to the iQueueIndex buffer
       
   126 			// Overflow check first
       
   127 			{
       
   128 			HBufC8* qBuf = iWriteBuffers[iQueueIndex];
       
   129 			TPtr8 qPtr = qBuf->Des();
       
   130 			if((qPtr.MaxLength() - qPtr.Length()) < ptr.Length())
       
   131 				// Not enough room to append
       
   132 				{
       
   133 				qBuf = iWriteBuffers[iQueueIndex]->ReAlloc(qPtr.Length() + ptr.Length());
       
   134 				if(qBuf==NULL)
       
   135 					return KErrNoMemory;		//Return error and don't take ownership of aBuffer
       
   136 				iWriteBuffers[iQueueIndex] = qBuf;
       
   137 				qPtr = qBuf->Des();
       
   138 				}
       
   139 			qPtr.Append(ptr);
       
   140 			delete aBuffer;
       
   141 			}
       
   142 		else
       
   143 			// Nothing queued just assign the pointer
       
   144 			// Data will be sent on next write completion
       
   145 			{
       
   146 			iWriteBuffers[iQueueIndex] = aBuffer;
       
   147 			}
       
   148 		}
       
   149 	return(ret);
       
   150 	}
       
   151 
       
   152 
       
   153 TInt CIOBufferControl::Read(TDes8& aBuffer)
       
   154 	{
       
   155 	return(iReader->IssueRead(aBuffer));
       
   156 	}
       
   157 
       
   158 void CIOBufferControl::SetWriter(CActiveWriter* aWriter)
       
   159 	{
       
   160 	iWriter = aWriter;
       
   161 	}
       
   162 
       
   163 void CIOBufferControl::SetReader(CActiveReader* aReader)
       
   164 	{
       
   165 	iReader = aReader;
       
   166 	}
       
   167 
       
   168 
       
   169 // MIONotifier 
       
   170 
       
   171 void CIOBufferControl::Event(TInt aEvent,TInt aEventCode)
       
   172 	{
       
   173 	iNotifier->Event(aEvent,aEventCode);
       
   174 	}
       
   175 
       
   176 void CIOBufferControl::WriteComplete()
       
   177 /**
       
   178 Normal asynchronous completion to a write request to the active writer
       
   179 The data we transmitted will always be pointed to by iLiveIndex
       
   180 On completion there could be Urgent or ordinary data queued
       
   181 Submit any queued urgent first
       
   182 */
       
   183 	{
       
   184 	// Free the HBufC8* we loaded for transmit the last time
       
   185 	delete iWriteBuffers[iLiveIndex];
       
   186 	iWriteBuffers[iLiveIndex] = NULL;
       
   187 	// First check to see if we have any urgent data queued
       
   188 	if(iUrgent)
       
   189 		{
       
   190 		// Urgent data queued, move the urgent pointer to the live index
       
   191 		iWriteBuffers[iLiveIndex] = iUrgent;
       
   192 		// Free the pointer
       
   193 		iUrgent = NULL;
       
   194 		// Send the queued urgent data
       
   195 		iWriter->IssueUrgentWrite(*(iWriteBuffers[iLiveIndex]));
       
   196 		}
       
   197 	else if(iWriteBuffers[iQueueIndex])
       
   198 		// Check to see if any data is on the normal queue
       
   199 		{
       
   200 		// Data queued
       
   201 		// Swap the indexes
       
   202 		iLiveIndex = iQueueIndex;
       
   203 		(iLiveIndex == 0) ? (iQueueIndex = 1) : (iQueueIndex = 0); 		
       
   204 		// Issue the next write
       
   205 		__FLOG_STATIC(KTelnetLoggingCompnt(),KTelnetLoggingTag(),_L("CIOBufferControl() WriteComplete() Write Queue Data"));
       
   206 		iWriter->IssueWrite(*(iWriteBuffers[iLiveIndex]));
       
   207 		// complete the write
       
   208 		}
       
   209 	else
       
   210 		{
       
   211 		// No data queued, set the transmitter empty condition
       
   212 		iLiveIndex = iQueueIndex;
       
   213 		}
       
   214 	iNotifier->WriteComplete();
       
   215 	}
       
   216 
       
   217 void CIOBufferControl::WriteError(TInt aError)
       
   218 /**
       
   219 Write completion with an error, just pass the code up in a notification
       
   220 */
       
   221 	{
       
   222 	Reset();
       
   223 	iNotifier->WriteError(aError);
       
   224 	}
       
   225 
       
   226 void CIOBufferControl::ReadCompleteL()
       
   227 	{
       
   228 	iNotifier->ReadCompleteL();
       
   229 	}
       
   230 
       
   231 void CIOBufferControl::ReadComplete(TInt aError)
       
   232 	{
       
   233 	Reset();
       
   234 	iNotifier->ReadComplete(aError);
       
   235 	}
       
   236 
       
   237 void CIOBufferControl::Reset()
       
   238 	{
       
   239 	delete iWriteBuffers[0];
       
   240 	delete iWriteBuffers[1];
       
   241 	delete	iUrgent;
       
   242 
       
   243 	iUrgent = NULL;
       
   244 	iWriteBuffers[0] = NULL;
       
   245 	iWriteBuffers[1] = NULL;
       
   246 
       
   247 	iQueueIndex = iLiveIndex = 0;
       
   248 	iWriter = NULL;
       
   249 	iReader = NULL;
       
   250 	}