diff -r 000000000000 -r 29b1cd4cb562 irda/irdastack/irtranp/SCEP.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/irda/irdastack/irtranp/SCEP.CPP Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,922 @@ +// Copyright (c) 1997-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: +// + +#include "debug.h" + +#include +#include +#include "comreadwrite.h" +#include "tranp.h" +#include "tranpprot.h" +#include "SCEP.H" +#include "COMMANDP.H" +#include "ABSTRACT.H" +#include "SCONREQC.H" +#include "SCONCONC.H" +#include "SRPSCOMM.H" +#include "GLOBAL.H" +#include "BFTP.H" + + +SCEP::SCEP() + { + } + +/* +* Method description: Leavable constructor for the SCEP layer +* +*/ + +SCEP* SCEP::NewL(CTranpProtocol* aTranpProtocol, BFTP* a_oBFTP, const MTranpNotification* aNotifier) + { + DEBUG_OPEN(); + SCEPPRINT(_L("SCEP::NewL()\n")); + + SCEP* self = new(ELeave) SCEP(); + CleanupStack::PushL(self); + self->ConstructL(aTranpProtocol, a_oBFTP, aNotifier); + CleanupStack::Pop(); + return self; + } + +/* +* Method description: Second part of the SCEP construction - creates the CommandProcessor and CComReadWrite. +* +* Parameter: Pointer to the BFTP class +* +*/ + +void SCEP::ConstructL(CTranpProtocol* aTranpProtocol, BFTP* a_oBFTP, const MTranpNotification* aNotifier) + { + + SCEPPRINT(_L("SCEP::ConstructL()\n")); + iNotifier = const_cast(aNotifier); + iState = EWaiting; + + m_uiMaxPDU = 4; + + m_oCommandP = new(ELeave) CommandProcessor(); + iComReadWrite = CComReadWrite::NewL(*this); + + m_oBFTP = a_oBFTP; + iTranpProtocol = aTranpProtocol; + + m_packet = NULL; + m_iPicSize = 0; + } + +SCEP::~SCEP() + { + delete m_oCommandP; + delete iComReadWrite; + //delete m_packet; Ownership now belongs to TTranpPicture Object + } + +/* +* Method description: Pump - receives and sends data, should be called periodically. Due to the way IrTran-P and +* serial communication works, it also tries to check when it has received a complete SCEP +* packet. This should be handled in a differerent (and more nice) way. +* +* Returns: An integer containing the progress from 0 to 100 +*/ + +void SCEP::Abort() + { + iComReadWrite->Cancel(); + iComReadWrite->Signal(KErrNone); + } + +TInt SCEP::Pump() + { + // Set up the IR port connection with a null write + //delete m_packet; + //m_packet = NULL; + //iState = EWaiting; + //iSCEPFrame.SetLength(0); + iComReadWrite->Open(); + return 0; + } + +void SCEP::ReceiveComplete(TDesC8& aBuffer) + { + SCEPPRINT_2(_L("SCEP::ReceiveComplete(%d)\n"),aBuffer.Length()); + + iSCEPFrame.Append(aBuffer); // Add new data to cached packet + + TBool loopagain; + do + { + loopagain = EFalse; + + if ((iSCEPFrame[0]==0x00)&&(iSCEPFrame.Length()>=3)) + { + TInt tempLength = 0; + TInt additionalLength = 0; + TInt lengthPos = 3; + + if ((iSCEPFrame[1]==KTranpMsgTypeCER) && (iSCEPFrame[2]==KTranpInfTypeVer)) + { + lengthPos = 5; + additionalLength = 4; // ... and that same packet has 4 trailing bytes + } + + if (iSCEPFrame.Length()>lengthPos+2)// Otherwise we might miss out on the last packet + { + if(iSCEPFrame[0] == 0x00) // Let's guess it's an SCEP header - HARDCODED AND UGLY!!! + { + tempLength = iSCEPFrame[lengthPos]; + if(tempLength == 0xff) + { + tempLength = IrTranpUtil::DExtract(iSCEPFrame, lengthPos+1); + lengthPos = 5; + } + SCEPPRINT_2(_L("tempLength = %d"), tempLength); + } + + tempLength += ((lengthPos+1) + additionalLength); + + SCEPPRINT_3(_L("iSCEPFrame.length(%d) >= templength(%d)"),iSCEPFrame.Length(),tempLength); + + switch (iSCEPFrame[1]) + { + case KTranpMsgTypeCER: // MsgType = Connection establishment request + case KTranpMsgTypeCEC: // MsgType = Connection establishment confirmation + case KTranpMsgTypeData: // Data (Command) + case KTranpMsgTypeDisc: // Disconnection + { + switch (iSCEPFrame[2]) + { + case KTranpInfTypeVer: // Version of MsgType + case KTranpInfTypeNeg: // Negotiation Information + case KTranpInfTypeUser: // UserData + case KTranpInfTypeExt: // Extend in the future + case KTranpInfTypeRsn: // Reason + break; + default: + // bogus frame + SCEPPRINT(_L("SCEP::Bogus Inf Type in frame\n")); + iSCEPFrame.SetLength(0); + } + } + break; + default: + // bogus frame + SCEPPRINT(_L("SCEP::Bogus Msg Type in frame\n")); + iSCEPFrame.SetLength(0); + } + + if(iSCEPFrame.Length() >= tempLength) // yes, complete packet + { + TInt oldLength = iSCEPFrame.Length(); + iSCEPFrame.SetLength(tempLength); // We only want exactly one packet + ParseCommand(iSCEPFrame); + + iSCEPFrame.SetLength(oldLength); + iSCEPFrame.Delete(0, tempLength); // The surplus data belongs to the next packet + SCEPPRINT(_L("\r\n***\r\n")); + //IrTranpUtil::HexOut(iSCEPFrame); + SCEPPRINT(_L("***\r\n")); + loopagain = (oldLength > tempLength) ? ETrue : EFalse; + } + } + } + else + { + SCEPPRINT(_L("SCEP:: Bogus Frame header\n")); + iSCEPFrame.SetLength(0); + } + } while (loopagain); + + + // let the commandprocessor send whatever's in queue + + m_oCommandP->DoCommand(); + + if ( (!(iComReadWrite->IsActive())) && !(iState == EError) ) //Make sure that thre is always an outstanding request + iComReadWrite->Receive(); + + switch(iState) + { + case EConnected: + iNotifier->Connected(); + iState = EProgress; + SCEPPRINT(_L("SCEP: EConnected -> EProgress\r\n")); + break; + case EDisconnected: + iNotifier->Disconnected(); + iComReadWrite->Close(); + iState = EWaiting; + SCEPPRINT(_L("SCEP: EDisconnected -> EWaiting\r\n")); + break; + case EProgress: + { + SCEPPRINT(_L("SCEP: EProgress\r\n")); + + TInt32 progress = 0; + if(m_packet!=NULL) + { + if(m_packet->Length() != 0) + { + Math::Int(progress, m_packet->Length()*100 / m_iPicSize); + } + iNotifier->ProgressIndication(progress); + } + } + break; + case EWaiting: + SCEPPRINT(_L("SCEP: EWaiting\r\n")); + break; + case EError: + SCEPPRINT(_L("SCEP: EError\r\n")); + break; + case ECommunicationInt: + SCEPPRINT(_L("SCEP: ECommunicationInt\r\n")); + iNotifier->Disconnected(); + iComReadWrite->Close(); + iState = EWaiting; + break; + default: + SCEPPRINT(_L("SCEP: Unknown state\r\n")); + break; + } + SCEPPRINT(_L("SCEP: Exit ReceiveComplete\r\n")); + } + +void SCEP::SendComplete() + { + // Post Read Request + SCEPPRINT(_L("SCEP: Send Complete\n")); + iComReadWrite->Receive(); + } + +void SCEP::SendError(TInt aError) + { + SCEPPRINT_2(_L("SCEP: Send Error %d\n"), aError); + iNotifier->Error(aError); + iState = EError; + } + +void SCEP::ReceiveError(TInt aError) + { + SCEPPRINT_2(_L("SCEP: Receive Error %d\n"), aError); + iNotifier->Error(aError); + iState = EError; + } +void SCEP::Error(TInt aError) + { + SCEPPRINT_2(_L("SCEP: Error %d\n"), aError); + iNotifier->Error(aError); + iState = EError; + } + + +/* +* Method description: Called from BFTP when a connection request should be sent +* +*/ + +void SCEP::SCONreqL() + { + SCONreqCommand* command = new(ELeave) SCONreqCommand(iComReadWrite); + command->SetPMID(m_PMID.Des()); + command->SetSMID(m_SMID.Des()); + command->SetPDU(m_uiMaxPDU); + command->Create(); + //IrTranpUtil::HexOut(command->GetData()); + m_oCommandP->Add(command); + } + +/* +* Method description: Called from BFTP when a connection confirmed should be sent +* +*/ + +void SCEP::SCONconL() + { + SCONconCommand* command = new(ELeave) SCONconCommand(iComReadWrite); + command->SetPMID(m_PMID.Des()); + command->SetSMID(m_SMID.Des()); + command->SetPDU(m_uiMaxPDU); + command->Create(); +// IrTranpUtil::HexOut(command->GetData()); + m_oCommandP->Add(command); + } + +/* +* Method description: Called from BFTP when a common BFTP packet should be sent +* +*/ + +void SCEP::SCEPSendCommand(TDes8& a_userData, TUint8 a_pduType) + { + SRPSCommand* command = new (ELeave) SRPSCommand(iComReadWrite); + command->SetPMID(m_PMID.Des()); + command->SetSMID(m_SMID.Des()); + command->SetDPID(m_DPID); + command->SetSPID(m_SPID); + command->SetCmdId(m_CmdId); + command->SetPDUType(a_pduType); + command->SetUserData(a_userData); + command->Create(); +// IrTranpUtil::HexOut(command->GetData()); + m_oCommandP->Add(command); + } + +/* +* Method description: Private method called when a Connection Request packet should be parsed +* +* Parameter: a_Header - pointer to the packet buffer +* Parameter: offset - where in the buffer to start parsing +*/ + +void SCEP::SCEPConRequest(TDes8& a_Header, TInt offset) + { + SCEPPRINT(_L("Inside SCEPConRequest\n")); + + TInt length = a_Header.Length(); + + while(offsetError(KErrIrtranpPeerDoesNotHaveIrtranp); //KErrIrtranpPeerDoesNotHaveIrtranp + break; + } + } + SCEPPRINT(_L("Exiting SCEPConRequest\n")); + } + +/* +* Method description: Private method called when a commond Data packet should be parsed +* +* Parameter: a_Header - pointer to the packet buffer +* Parameter: offset - where in the packet to start parsing +*/ + +void SCEP::SCEPDataCommand(TDes8& a_Header, TInt offset) + { + SCEPPRINT(_L("Inside SCEPDataCommand\n")); + + if(a_Header[offset] == KTranpInfTypeUser) + { + // Always InfTypeUser when in SCEPDataCommand + TInt packetLength = a_Header[offset+1]; + if(packetLength == 0xff) + { + // since length1 was 0xff, look at length2 + packetLength = ((a_Header[offset+2] << 8) + (a_Header[offset+3])); // 16bit + offset+=4; // include inftype and length2 + } + else + { + offset+=2; // include inftype and length1 + } + + // TUint8 InfVer = a_Header[offset]; + TUint8 DFLG = a_Header[offset+1]; + // TUint16 length3 = IrTranpUtil::DExtract(a_Header, offset+2); + + if(DFLG == KTranpDFLGrcon) + { + // Reject to request connection + SCEPPRINT(_L("Connection rejected\n")); + } + else if(DFLG == KTranpDFLGnseg) + { + // PDU not segmented (single PDU) + DoCommand(a_Header, offset+4); + // break; + } + else if(DFLG == KTranpDFLGfPDU) + { + // First segmented PDU + // We do all reassembling in SCEP, and then send the complete (big) packet to bFTP + // restno * PDU must be able to hold the complete packet, right? + + // Ownership of this data [m_packet] belongs to the TTranpPicture object + // so must ask the correct object to delete its heap. + // If we were already building a packet, get rid of it + iTranpProtocol->DeleteHeapData(); + + TUint32 seqno = IrTranpUtil::LExtract(a_Header, offset+4); + TUint32 restno = IrTranpUtil::LExtract(a_Header, offset+8); + + TUint32 PDUSize; + switch(m_uiMaxPDU) + { + case '1': + { + PDUSize = 512; + break; + } + case '2': + { + PDUSize = 1024; + break; + } + case '3': + { + PDUSize = 2048; + break; + } + case '4': + { + PDUSize = 4096; + break; + } + default: + { + PDUSize = 512; + break; + } + } + + // This should not leave and report an error back... + //__UHEAP_FAILNEXT(1); + TRAPD( err , m_packet = HBufC8::NewL(PDUSize*restno)); // should be enough + if (err != KErrNone) + { + iNotifier->Error(err); + iState = EError; + return; + } + else + iTranpProtocol->SetHeapData(m_packet); + + m_iPicSize = PDUSize*restno; + + SCEPPRINT(_L("ResizeL went well\n")); + + m_seq = seqno; + AddSegment(a_Header, offset+12); + } + else if(DFLG == KTranpDFLGiPDU) + { + // Intermediate segmented PDUs + + TUint32 seqno = IrTranpUtil::LExtract(a_Header, offset+4); + if(seqno == m_seq+1) + { + AddSegment(a_Header, offset+12); + m_seq++; + } + else + { + SCEPPRINT(_L("Error in intermediate PDU\n")); + } + } + else if(DFLG == KTranpDFLGlPDU) + { + // Last segmented PDU + + m_seq++; + TUint32 restno = IrTranpUtil::LExtract(a_Header, offset+8); + if(restno == 1) + { + AddSegment(a_Header, offset+12); + //TPtr8 packetPtr = m_packet->Des(); + DoCommand(*m_packet, 0); // Now let's play + iNotifier->ProgressIndication(100); // Makes sure 100% is reached + iNotifier->GetComplete(); + TPtr8 temp2 = m_packet->Des(); + temp2.Zero(); + } + else + { + SCEPPRINT(_L("Error in last PDU\n")); + } + } + else if(DFLG == KTranpDFLGcint) + { + SCEPPRINT(_L("Communication interrupted\n")); + iState = ECommunicationInt; + } + else + { + // Ooops. + } + } + else + { + // oops + } + + SCEPPRINT(_L("Exiting SCEPDataCommand\n")); +} + +/* +* Method description: Adds segmented packets into a complete packet +* +* Parameter: a_Header - pointer to the segment +* Parameter: a_offset - where in the segment data to be assembled is +*/ + +void SCEP::AddSegment(TDes8& a_Header, TInt a_offset) + { + SCEPPRINT(_L("Entered AddSegment\n")); + TPtr8 temp((unsigned char*)a_Header.Ptr()+a_offset, a_Header.Length()-a_offset, a_Header.MaxLength()); + TPtr8 temp2 = m_packet->Des(); + temp2.Append(temp); + SCEPPRINT(_L("Exited AddSegment\n")); + } + + /* + * Method description: Private method called to parse an SCEP disconnetion packet + * + * Parameter: a_Header - pointer to the packet + * Parameter: offset - where in the packet to start parsing +*/ + +void SCEP::SCEPDisconnect(TDes8& a_Header, TInt offset) + { + SCEPPRINT(_L("SCEP: SCEPDisconnect\n")); + SCEPPRINT_2(_L("SCEP: %d -> EDisconnected\r\n"), iState); + + if(a_Header[offset] == KTranpInfTypeRsn) + { + TUint16 reason = IrTranpUtil::DExtract(a_Header, offset+2); + if(reason == KTranpDisPDUrsnUR) + { + SCEPPRINT(_L("SCEP: Disconnect: Unspecified Reason\n")); + iState = EDisconnected; + + } + else if(reason == KTranpDisPDUrsnUD) + { + SCEPPRINT(_L("SCEP: Disconnect: User Disconnect\n")); + iState = EDisconnected; + + } + else if(reason == KTranpDisPDUrsnPD) + { + SCEPPRINT(_L("SCEP: Disconnect: Provider Disconnect\n")); + iState = EDisconnected; + + } + else + { + // reserved + } + } + else + { + // oops + } + SCEPPRINT(_L("SCEP: Exiting SCEPDisconnect\n")); + return; + } + +/* +* Method description: Private method called when parsing a Connection Confirmed packet +* +* Parameter: a_Header - pointer to the packet +* Parameter: offset - where in the packet to start parsing +*/ + +void SCEP::SCEPConConfirm(TDes8& a_Header, TInt offset) + { + SCEPPRINT(_L("Inside SCEPConConfirm\n")); + + TInt length = a_Header.Length(); + + while(offsetReqPDU(a_Header, a_offset + 28); // hardcoded, but always 28 + } + else if(switchVar == KTranpPduTypeRplAck) + { + SCEPPRINT(_L("SCEP: PduTypeRplAck\n")); + } + else if(switchVar == KTranpPduTypeRplNack) + { + SCEPPRINT(_L("SCEP: PduTypeRplNack\n")); + } + else if(switchVar == KTranpPduTypeAbt) + { + SCEPPRINT(_L("SCEP: PduTypeAbt\n")); + } + else + { + SCEPPRINT(_L("SCEP: PduType Broken\n")); + } + + SCEPPRINT(_L("SCEP: Exiting DoCommand\n")); + } + +/* +* Method description: Private method called to parse the NegInf section of a packet +* +* Parameter: a_Header - pointer to the packet +* Parameter: a_offset - where in the packet the NegInf is +*/ + +void SCEP::NegInf(TDes8& a_Header, TInt a_offset) + { + SCEPPRINT(_L("SCEP: NegInf\n")); + + if(a_Header[a_offset] != KTranpNegVer) + { + return; // skip the NegInf totally + } + TInt length = a_Header.Length(); + while(a_offset l(8); + l.Num(a_offset); + TBuf<8> k(8); + k.Num(length); + + TBufC8<4> temp; + TPtr8 temp2 = temp.Des(); + for(TInt j=0;j<3;j++) // we don't like it .. hardcoded + { + temp2.Append(a_Header[a_offset+1+j]); + } + + TInt valueOffset = a_offset+1+temp.Length(); + if(temp.Compare(KTranpFR) == 0) + { + SCEPPRINT(_L("SCEP: Found FR attribute\n")); + // pump whitespace + if(a_Header[valueOffset] == ' ') + { + valueOffset++; + } + + m_uiMaxPDU = a_Header[valueOffset]; + + // Now skip CRLF - pump + TBool found = FALSE; + while(found == FALSE) + { + if(a_Header[valueOffset] == KTranpLF) // Why look for both CR and LF? LF always follows CR .. + { + found = TRUE; + } + else + valueOffset++; + } + } + else if(temp.Compare(KTranpID) == 0) + { + SCEPPRINT(_L("SCEP: Found ID attribute\n")); + TBool found = FALSE; + TPtr8 temp = m_szPIS.Des(); + temp.Zero(); + do + { + if(a_Header[valueOffset] != KTranpCR) + { + temp.Append(a_Header[valueOffset++]); + } + else + { + found = TRUE; + valueOffset+=2; // skip LF too + } + } + while(found == FALSE); + } + else if(temp.Compare(KTranpNM) == 0) + { + SCEPPRINT(_L("SCEP: Found NM attribute\n")); + TBool found = FALSE; + TPtr8 temp = m_szUserName.Des(); + temp.Zero(); + do + { + if(a_Header[valueOffset] != KTranpCR) + { + temp.Append(a_Header[valueOffset++]); + } + else + { + found = TRUE; + valueOffset+=2; // skip LF too + } + } + while(found == FALSE); + } + else if(temp.Compare(KTranpPW) == 0) + { + SCEPPRINT(_L("SCEP: Found PW attribute\n")); + TBool found = FALSE; + TPtr8 temp = m_szPassword.Des(); + temp.Zero(); + do + { + if(a_Header[valueOffset] != KTranpCR) + { + temp.Append(a_Header[valueOffset++]); + } + else + { + found = TRUE; + valueOffset+=2; // skip LF too + } + } + while(found == FALSE); + } + else + { + // Something that wasn't an attribute + } + a_offset = valueOffset; + + } + iState = EConnected; + //iNotifier->Connected(); + SCEPPRINT(_L("SCEP: Exiting NegInf\n")); +} + +// +// Method description: Private method called when a packet has been received. Here is where the parsing begins. +// Also creates the necessary reply-commands at SCEP level. +// +// Parameter: a_TempBuffer - the packet itself +// + +void SCEP::ParseCommand(TDes8& a_TempBuffer) + { + SCEPPRINT(_L("SCEP: ParseCommand\n")); + // parse the incoming buffer and see what command we're talking about. Return an instance of such a command. + + // Look at the first bytes, see what command it might be, call the correct private method and let it take care of the rest? + + if(a_TempBuffer[1] == KTranpMsgTypeCER) + // MsgType = Connection establishment request + { + SCEPPRINT(_L("SCEP: Got a connection request")); + SCEPConRequest(a_TempBuffer, 2); + + // Create and add a SCEPConConfirm! + SCONconL(); + } + else if(a_TempBuffer[1] == KTranpMsgTypeCEC) + // MsgType = Connection establishment confirmation + { + SCEPPRINT(_L("SCEP: Got a connect ack")); + SCEPConConfirm(a_TempBuffer, 2); + } + else if(a_TempBuffer[1] == KTranpMsgTypeData) + // Data (Command) + { + SCEPPRINT(_L("SCEP: Got a data packet\n")); + SCEPDataCommand(a_TempBuffer, 2); + } + else if(a_TempBuffer[1] == KTranpMsgTypeDisc) + // Disconnection + { + SCEPPRINT(_L("SCEP: Got a disconnect packet\n")); + SCEPDisconnect(a_TempBuffer, 2); + if (m_packet != NULL) + m_iPicSize = m_packet->Length(); // Otherwise we'll never get to 100% + iSCEPFrame.Zero(); + } + else + { + SCEPPRINT(_L("SCEP: Wacko! Default!\n")); + // Reserved + } + + + SCEPPRINT(_L("SCEP: Exiting ParseCommand\n")); + + return; + } + +// +// Method description: Sets the Primary Machine ID +// +// Parameter: a_PMID - the new Machine ID +// + +void SCEP::SetPMID(const TDesC8& aPMID) + { + m_PMID = aPMID; + } + +// +// Method description: Sets the Secondary Machine ID +// +// Parameter: a_SMID - the new Machine ID +// + +void SCEP::SetSMID(const TDesC8& aSMID) + { + m_SMID = aSMID; + } + +// +// Method description: Sets the maximum receivable PDU size +// +// Parameter: a_PDU - the new PDU size +// +void SCEP::SetPDU(TUint8 a_PDU) + { + m_uiMaxPDU = a_PDU; + } +