diff -r f742655b05bf -r d38647835c2e voipplugins/dhcppositionprovider/src/dhcpocationinformationparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/voipplugins/dhcppositionprovider/src/dhcpocationinformationparser.cpp Wed Sep 01 12:29:57 2010 +0100 @@ -0,0 +1,885 @@ +/* +* Copyright (c) 2007 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: Parses location information from DHCP message to LCI +* +*/ + + +#include +#include "dhcplocationinformationparser.h" +#include "dhcppsylogging.h" + +// Dynamic Host Configuration Protocol (DHCPv4 and DHCPv6) Option for Civic +// Addresses Configuration Information +// draft-ietf-geopriv-dhcp-civil-09 + +// Civic Address CAtypes +const TUint8 KDhcpState = 1; +const TUint8 KDhcpCounty = 2; +const TUint8 KDhcpCity = 3; +const TUint8 KDhcpBorough = 4; +const TUint8 KDhcpBlock = 5; +const TUint8 KDhcpGroupOfStreets = 6; + +// Civic Address Additional CAtypes +// const TUint8 KLanguage = 0; +const TUint8 KDhcpLeadingStreetDirection = 16; +const TUint8 KDhcpTrailingStreetDirection = 17; +const TUint8 KDhcpStreetSuffix = 18; +const TUint8 KDhcpHouseNumber = 19; +const TUint8 KDhcpHouseNumberSuffix = 20; +const TUint8 KDhcpVanityAddress = 21; +const TUint8 KDhcpAdditionalLocationInformation = 22; +const TUint8 KDhcpName = 23; +const TUint8 KDhcpPostalCode = 24; +const TUint8 KDhcpFloor = 27; +const TUint8 KDchpCASeat = 33; + +// XML civilLoc elements +_LIT8( KDhcpCountry, "country" ); +_LIT8( KDhcpA1, "A1" ); // state +_LIT8( KDhcpA2, "A2" ); // county +_LIT8( KDhcpA3, "A3" ); // city +_LIT8( KDhcpA4, "A4" ); // borough +_LIT8( KDhcpA5, "A5" ); // block +_LIT8( KDhcpA6, "A6" ); // street +_LIT8( KDhcpPRD, "PRD" ); // leading street direction +_LIT8( KDhcpPOD, "POD" ); // trailing street direction +_LIT8( KDhcpSTS, "STS" ); // street suffix +_LIT8( KDhcpHNO, "HNO" ); // house number +_LIT8( KDhcpHNS, "HNS" ); // house number suffix +_LIT8( KDhcpLMK, "LMK" ); // landmark or vanity address +_LIT8( KDhcpLOC, "LOC" ); // additional location information +_LIT8( KDhcpNAM, "NAM" ); // name +_LIT8( KDhcpPC, "PC" ); // postal code +_LIT8( KDhcpFLR, "FLR" ); // floor +_LIT8( KDhcpSEAT, "SEAT" ); // seat + + +// XML message parsing + +// General +_LIT8( KOpenBracket, "<" ); +_LIT8( KCloseBracket, ">" ); +_LIT8( KForwardSlash, "/" ); +_LIT8( KQuotationMark, "\"" ); +_LIT8( KColon, ":" ); +_LIT8( KSpaceChar, " " ); +_LIT8( KHyphen, "-" ); + +// XML (RFC 4119) +_LIT8( KXMLBegin, "?xml version=\"1.0\" encoding=\"UTF-8\"?" ); +_LIT8( KPresence, "presence" ); +_LIT8( KTuple, "tuple" ); +_LIT8( KStatus, "status" ); +_LIT8( KTimeStamp, "" ); +_LIT8( KTimeStampEnd, "" ); +_LIT8( KXmlnsNamespace, " xmlns=\"urn:ietf:params:xml:ns:pidf\"" ); +_LIT8( KId, " id=\"" ); +_LIT8( KTupleId1, "tuple1" ); +_LIT8( KT, "T" ); +_LIT8( KZ, "Z" ); + +// gp namespace (RFC 4119) +_LIT8( KGpNamespace, " xmlns:gp=\"urn:ietf:params:xml:ns:pidf:geopriv10\"" ); +_LIT8( KGp, " aInput.Length() ) + { + return KErrNotFound; + } + + // The LCI form is of fixed length (16 bytes). The last byte of the input + // contains the datum value. + switch ( ( TUint8 )aInput[ 15 ] ) + { + case 1: + { + // WGS 84, 2D only (For 3D: WGS84 (Geographical 3D)) + aOutput.Append( KSrsName ); + aOutput.Append( KEpsg4326 ); + aOutput.Append( KQuotationMark ); + return KErrNone; + } + case 2: + { + // NAD83, 2D only (For 3D: NAD83 & NAVD88) + aOutput.Append( KSrsName ); + aOutput.Append( KEpsg4269 ); + aOutput.Append( KQuotationMark ); + return KErrNone; + } + case 3: + { + // NAD83, 2D only (For 3D: NAD83 & MLLW) + aOutput.Append( KSrsName ); + aOutput.Append( KEpsg4269 ); + aOutput.Append( KQuotationMark ); + return KErrNone; + } + default: + { + return KErrNotSupported; + } + } + } + + +// --------------------------------------------------------------------------- +// Parses the input to the LCI form +// --------------------------------------------------------------------------- +// +void TDhcpLocationInformationParser::ParseLCI( + const TDesC8& aInput, TDes8& aOutput ) + { + TRACESTRING( "TLocationInformationParser::ParseLCI" ); + + TLex8 input( aInput ); + + // Latitude + + // Latitude resolution (6 bits) + TUint8 laRes = ( TUint8 )input.Peek(); + laRes >>= 2; + + // Latitude (9 bits integer, 25 bits fraction) + TUint16 laInt = ( TUint16 )input.Get(); + laInt <<= 14; + laInt >>= 6; + laInt += ( TUint8 )input.Peek(); + laInt >>= 1; + + TUint32 laFra = ( TUint32 )input.Get(); + laFra <<= 8; + laFra += ( TUint8 )input.Get(); + laFra <<= 8; + laFra += ( TUint8 )input.Get(); + laFra <<= 8; + laFra += ( TUint8 )input.Get(); + laFra <<= 7; + laFra >>= 7; + + ParseDMS( ETrue, laRes, laInt, laFra, aOutput ); + + aOutput.Append( KSpaceChar ); + + // Longitude + + // Longitude resolution (6 bits) + TUint8 loRes = ( TUint8 )input.Peek(); + loRes >>= 2; + + // Longitude (9 bits integer, 25 bits fraction) + TUint16 loInt = ( TUint16 )input.Get(); + loInt <<= 14; + loInt >>= 6; + loInt += ( TUint8 )input.Peek(); + loInt >>= 1; + + TUint32 loFra = ( TUint32 )input.Get(); + loFra <<= 8; + loFra += ( TUint8 )input.Get(); + loFra <<= 8; + loFra += ( TUint8 )input.Get(); + loFra <<= 8; + loFra += ( TUint8 )input.Get(); + loFra <<= 7; + loFra >>= 7; + + ParseDMS( EFalse, loRes, loInt, loFra, aOutput ); + + // Altitude + if ( 15 <= aInput.Length() ) + { + // AT (4 bits) + // 1 for meters, 2 for floors + TUint8 AT = ( TUint8 )input.Peek(); + AT >>= 4; + + // Altitude resolution (6 bits) + TUint16 altRes = ( TUint16 )input.Get(); + altRes <<= 8; + altRes += ( TUint8 )input.Peek(); + altRes >>= 6; + + // Altitude (30 bits) + TUint32 alt = ( TUint32 )input.Get(); + alt <<= 26; + alt >>= 18; + alt += ( TUint8 )input.Get(); + alt <<= 8; + alt += ( TUint8 )input.Get(); + alt <<= 8; + alt += ( TUint8 )input.Get(); + alt <<= 8; + + TRACESTRING2( "AT: %d", AT ); + TRACESTRING2( "altRes: %d", altRes ); + TRACESTRING2( "alt: %d", alt ); + } + + // No support for parsing altitude to XML yet + } + + +// --------------------------------------------------------------------------- +// Parses the input to the DMS coordinate form +// --------------------------------------------------------------------------- +// +void TDhcpLocationInformationParser::ParseDMS( + TBool aIsLatitude, + TUint8 aResolution, + TUint16 aInteger, + TUint32 aFraction, + TDes8& aOutput ) + { + TRACESTRING( "TLocationInformationParser::ParseDMS" ); + + TRACESTRING2( "aResolution: %d", aResolution ); + TRACESTRING2( "aInteger: %d", aInteger ); + TRACESTRING2( "aFraction: %d", aFraction ); + + // Check the first bit for sign + TUint16 sign = aInteger; // 9 bits + sign >>= 8; + + // 2s complement + if ( sign ) + { + aInteger = ~aInteger; + aInteger <<= 7; + aInteger >>= 7; + aFraction = ~aFraction; + aFraction <<= 7; + aFraction >>= 7; + } + + // Apply resolution + if ( 9 < aResolution ) + { + // Fractional part + aFraction >>= ( 34 - aResolution ); + aFraction <<= ( 34 - aResolution ); + } + else + { + // No fractional part + aFraction = 0; + // Integer part + aInteger >>= ( 9 - aResolution ); + aInteger <<= ( 9 - aResolution ); + } + + // Fractional part + TReal minutes( 0.0 ); + TReal seconds( 0.0 ); + if ( aFraction ) + { + TReal frac = ( TReal )aFraction / KDhcp25BitDivisor; + Math::Int( minutes, 60.0 * frac ); + frac = 60.0 * frac - minutes; + Math::Int( seconds, 60.0 * frac ); + } + + // Parse the result + aOutput.AppendNum( aInteger ); + aOutput.Append( KColon ); + aOutput.AppendNum( ( TUint8 )minutes ); + aOutput.Append( KColon ); + aOutput.AppendNum( ( TUint8 )seconds ); + if ( aIsLatitude ) + { + if ( sign ) + { + aOutput.Append( KSouth ); + } + else + { + aOutput.Append( KNorth ); + } + } + else + { + if ( sign ) + { + aOutput.Append( KWest ); + } + else + { + aOutput.Append( KEast ); + } + } + } + + +// --------------------------------------------------------------------------- +// Parse XML description of civic address elements +// Correspondence of tags can be found in Ch.3.4 Civic Address Components in +// http://www.ietf.org/internet-drafts/draft-ietf-geopriv-dhcp-civil-09.txt +// --------------------------------------------------------------------------- +// +void TDhcpLocationInformationParser::ParseCivicAddressElements( + const TDesC8& aInput, TDes8& aOutput ) + { + TRACESTRING( "TLocationInformationParser::ParseCivicAddressElements" ); + + TLex8 input( aInput ); + + // Skip what + input.Inc(); + + // country code, two letters long + aOutput.Append( KCl ); + aOutput.Append( KDhcpCountry ); + aOutput.Append( KCloseBracket ); + aOutput.Append( input.Get() ); + aOutput.Append( input.Get() ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpCountry ); + aOutput.Append( KCloseBracket ); + + // civicAddress elements + while ( !input.Eos() ) + { + TInt type = ( TUint8 )input.Get(); + switch ( type ) + { + case KDhcpState: + { + TRACESTRING( "KDhcpState" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpA1 ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpA1 ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpCounty: + { + TRACESTRING( "KDhcpCounty" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpA2 ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpA2 ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpCity: + { + TRACESTRING( "KDhcpCity" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpA3 ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpA3 ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpBorough: + { + TRACESTRING( "KDhcpBorough" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpA4 ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpA4 ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpBlock: + { + TRACESTRING( "KBlock" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpA5 ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpA5 ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpGroupOfStreets: + { + TRACESTRING( "KGroupOfStreets" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpA6 ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpA6 ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpLeadingStreetDirection: + { + TRACESTRING( "KLeadingStreetDirection" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpPRD ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpPRD ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpTrailingStreetDirection: + { + TRACESTRING( "KTrailingStreetDirection" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpPOD ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpPOD ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpStreetSuffix: + { + TRACESTRING( "KStreetSuffix" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpSTS ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpSTS ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpHouseNumber: + { + TRACESTRING( "KHouseNumber" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpHNO ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpHNO ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpHouseNumberSuffix: + { + TRACESTRING( "KHouseNumberSuffix" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpHNS ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpHNS ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpVanityAddress: + { + TRACESTRING( "KVanityAddress" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpLMK ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpLMK ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpAdditionalLocationInformation: + { + TRACESTRING( "KAdditionalLocationInformation" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpLOC ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpLOC ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpName: + { + TRACESTRING( "KName" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpNAM ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpNAM ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpPostalCode: + { + TRACESTRING( "KPostalCode" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpPC ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpPC ); + aOutput.Append( KCloseBracket ); + break; + } + case KDchpCASeat: + { + TRACESTRING( "KCASeat" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpSEAT ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpSEAT ); + aOutput.Append( KCloseBracket ); + break; + } + case KDhcpFloor: + { + TRACESTRING( "KFloor" ); + aOutput.Append( KCl ); + aOutput.Append( KDhcpFLR ); + aOutput.Append( KCloseBracket ); + ExtractCivicAddressElement( input, aOutput ); + aOutput.Append( KClEnd ); + aOutput.Append( KDhcpFLR ); + aOutput.Append( KCloseBracket ); + break; + } + default: + { + TRACESTRING2( "Not a supported CAtype: %d", type ); + input.Inc( ( TInt )input.Get() ); // Skip value + break; + } + } + } + } + +// --------------------------------------------------------------------------- +// Extract a single civic address element from the input +// --------------------------------------------------------------------------- +// +void TDhcpLocationInformationParser::ExtractCivicAddressElement( + TLex8& aInput, TDes8& aOutput ) + { + TRACESTRING( "TLocationInformationParser::ExtractCivicAddressElement" ); + + // Extract data length + TInt length = ( TInt )aInput.Get(); + // Extract data + while ( length ) + { + if ( KDhcpMinAsciiValue < ( TUint8 )aInput.Peek() && + KDhcpMaxAsciiValue > ( TUint8 )aInput.Peek() ) + { + aOutput.Append( aInput.Get() ); + } + length--; + } + } + + +// --------------------------------------------------------------------------- +// Parses the timestamp +// --------------------------------------------------------------------------- +// +void TDhcpLocationInformationParser::ParseTimeStamp( TDes8& aTimeStamp ) + { + TRACESTRING( "TLocationInformationParser::ParseTimeStamp" ); + + TDateTime timeStamp = iTimeStamp.DateTime(); + aTimeStamp.AppendNum( timeStamp.Year() ); + aTimeStamp.Append( KHyphen ); + aTimeStamp.AppendNum( timeStamp.Month() + 1 ); + aTimeStamp.Append( KHyphen ); + aTimeStamp.AppendNum( timeStamp.Day() + 1 ); + aTimeStamp.Append( KT ); + aTimeStamp.AppendNum( timeStamp.Hour() ); + aTimeStamp.Append( KColon ); + aTimeStamp.AppendNum( timeStamp.Minute() ); + aTimeStamp.Append( KColon ); + aTimeStamp.AppendNum( timeStamp.Second() ); + aTimeStamp.Append( KZ ); + } + +// --------------------------------------------------------------------------- +// Parses the retention expiry. It is the timestamp value plus one day +// --------------------------------------------------------------------------- +// +void TDhcpLocationInformationParser::ParseRetentionExpiry( TDes8& aTargetBfr ) + { + TRACESTRING( "TLocationInformationParser::ParseRetentionExpiry" ); + // Define the retention-expiry + TTime expiryTime( iTimeStamp ); + TTimeIntervalDays day( 1 ); + expiryTime += day; + TDateTime retentionExpiry = expiryTime.DateTime(); + + // Parse the retention-expiry + aTargetBfr.AppendNum( retentionExpiry.Year() ); + aTargetBfr.Append( KHyphen ); + aTargetBfr.AppendNum( retentionExpiry.Month() + 1 ); + aTargetBfr.Append( KHyphen ); + aTargetBfr.AppendNum( retentionExpiry.Day() + 1 ); + aTargetBfr.Append( KT ); + aTargetBfr.AppendNum( retentionExpiry.Hour() ); + aTargetBfr.Append( KColon ); + aTargetBfr.AppendNum( retentionExpiry.Minute() ); + aTargetBfr.Append( KColon ); + aTargetBfr.AppendNum( retentionExpiry.Second() ); + aTargetBfr.Append( KZ ); + }