diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2011-06-15 12:24:17 +0200 |
---|---|---|
committer | Patrick Ohly <patrick.ohly@intel.com> | 2011-06-15 12:24:17 +0200 |
commit | 62df728b87da358b497696ced0500ff221ea0979 (patch) | |
tree | fe0b5b7795f4bb81336e4710f4695f9e8d011eb3 | |
parent | e62279538cea575d2e589b8ca0bda396dcbc0352 (diff) |
remote rules: added OverrideDevInf
Many SyncML servers send DevInf without CtCap inside. For those
servers, the engine (often incorrectly) has to assume that they
support all fields.
This patch adds a configuration element "OverrideDevInf" which helps
to address this problem. It may occur in a "RemoteRule". Once that
rule matches a DevInf sent by a peer, processing of CtCap continues
with the CtCap element of the DevInf inside the remote rule. This
allows adding and overriding the CtCap from a peer.
"OverrideDevInf" must contain a complete DevInf, although right now
only the CtCap inside it really matters.
This approach has the advantage that it can reuse the existing and
somewhat documented CtCap format for describing capabilities. The
downside is that not everything can be encoded in that format, for example,
how many components of the ORG field are supported. A possible
solution for that is to extend the format in a way that only the Synthesis
engine understand and/or standardize such extensions.
Right now the "OverrideDevInf" content is only parsed when needed.
Beware that syntax errors will only be found when using the rule!
-rwxr-xr-x | src/sysync/binfileimplclient.cpp | 4 | ||||
-rwxr-xr-x | src/sysync/binfileimplclient.h | 2 | ||||
-rw-r--r-- | src/sysync/localengineds.cpp | 2 | ||||
-rw-r--r-- | src/sysync/syncsession.cpp | 91 | ||||
-rwxr-xr-x | src/sysync/syncsession.h | 7 |
5 files changed, 99 insertions, 7 deletions
diff --git a/src/sysync/binfileimplclient.cpp b/src/sysync/binfileimplclient.cpp index 9b73c9c..e8be70e 100755 --- a/src/sysync/binfileimplclient.cpp +++ b/src/sysync/binfileimplclient.cpp @@ -2525,7 +2525,7 @@ void TBinfileImplClient::saveRemoteParams(void) // check remote devinf to detect special behaviour needed for some servers. -localstatus TBinfileImplClient::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP) +localstatus TBinfileImplClient::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP, SmlDevInfDevInfPtr_t *aOverrideDevInfP) { if (fConfigP->fBinfilesActive && aDevInfP) { // check for some specific servers we KNOW they need special treatment @@ -2577,7 +2577,7 @@ localstatus TBinfileImplClient::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevIn } } // let session handle other details - return inherited::checkRemoteSpecifics(aDevInfP); + return inherited::checkRemoteSpecifics(aDevInfP, aOverrideDevInfP); } // TBinfileImplClient::checkRemoteSpecifics diff --git a/src/sysync/binfileimplclient.h b/src/sysync/binfileimplclient.h index 5ceeb62..d995fab 100755 --- a/src/sysync/binfileimplclient.h +++ b/src/sysync/binfileimplclient.h @@ -550,7 +550,7 @@ public: uInt32 fRemotepartyID; // - check remote devinf to detect special behaviour needed for some servers. Base class // does not do anything on server level (configured rules are handled at session level) - virtual localstatus checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP); + virtual localstatus checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP, SmlDevInfDevInfPtr_t *aOverrideDevInfP); TBinfileDBSyncProfile fProfile; // - remote specific client behaviour flags uInt8 fRemoteFlags; // flags for remote specific behaviour (remotespecs_XXX) diff --git a/src/sysync/localengineds.cpp b/src/sysync/localengineds.cpp index b8289c6..1904670 100644 --- a/src/sysync/localengineds.cpp +++ b/src/sysync/localengineds.cpp @@ -2896,7 +2896,7 @@ localstatus TLocalEngineDS::engInitForSyncOps( // - this is executed only once per session, after that, we'll be fRemoteDevInfLock-ed if (!fSessionP->fRemoteDevInfKnown && !fSessionP->fRemoteDevInfLock) { // detect client specific server behaviour if needed - sta = fSessionP->checkRemoteSpecifics(NULL); + sta = fSessionP->checkRemoteSpecifics(NULL, NULL); fSessionP->remoteAnalyzed(); // analyzed now (accepted or not does not matter) if (sta!=LOCERR_OK) return sta; // not ok, device rejected diff --git a/src/sysync/syncsession.cpp b/src/sysync/syncsession.cpp index 8160c9b..8e7994d 100644 --- a/src/sysync/syncsession.cpp +++ b/src/sysync/syncsession.cpp @@ -26,6 +26,8 @@ #include "platform_thread.h" #endif +#include <xltdec.h> +#include <xltdevinf.h> #ifndef SYNCSESSION_PART1_EXCLUDE @@ -500,6 +502,8 @@ bool TRemoteRuleConfig::localStartElement(const char *aElementName, const char * expectTristate(fForceUTC); else if (strucmp(aElementName,"forcelocaltime")==0) expectTristate(fForceLocaltime); + else if (strucmp(aElementName,"overridedevinf")==0) + expectString(fOverrideDevInfXML); // inclusion of subrules else if (strucmp(aElementName,"include")==0) { // <include rule=""/> @@ -3516,11 +3520,17 @@ localstatus TSyncSession::analyzeRemoteDevInf( )); } // detect remote specific server behaviour if needed - sta = checkRemoteSpecifics(aDevInfP); + SmlDevInfDevInfPtr_t CTCapDevInfP = aDevInfP; + sta = checkRemoteSpecifics(aDevInfP, &CTCapDevInfP); if (sta!=LOCERR_OK) { remoteAnalyzed(); // analyzed to reject goto done; } + // switch to DevInf provided by remote rules + if (CTCapDevInfP != aDevInfP) { + PDEBUGPRINTFX(DBG_REMOTEINFO,("using CTCaps provided in DevInf of remote rule")); + aDevInfP = CTCapDevInfP; + } // Types and datastores may not be changed/added if sync has allready started if (fRemoteDevInfLock) { // Sync already started, in "blind" mode or previously received devInf, @@ -4314,7 +4324,7 @@ bool TSyncSession::SessionLogin( // does not do anything on server level (configured rules are handled at session level) // - NOTE: aDevInfP can be NULL to specify that remote device has not sent any devInf at all // and this is a blind sync attempt (so best-guess workaround settings might apply) -localstatus TSyncSession::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP) +localstatus TSyncSession::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP, SmlDevInfDevInfPtr_t *aOverrideDevInfP) { #if defined(SYSER_REGISTRATION) || !defined(NO_REMOTE_RULES) localstatus sta = LOCERR_OK; @@ -4426,6 +4436,80 @@ localstatus TSyncSession::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP) for(pos=fActiveRemoteRules.begin();pos!=fActiveRemoteRules.end();pos++) { // activate this rule TRemoteRuleConfig *ruleP = *pos; + if (!ruleP->fOverrideDevInfXML.empty()) { + // SMLTK expects full SyncML message + string buffer = + "<SyncML><SyncHdr>" + "<VerDTD>1.2</VerDTD>" + "<VerProto>SyncML/1.2</VerProto>" + "<SessionID>1</SessionID>" + "<MsgID>1</MsgID>" + "<Target><LocURI>foo</LocURI></Target>" + "<Source><LocURI>bar</LocURI></Source>" + "</SyncHdr>" + "<SyncBody>" + "<Results>" + "<CmdID>1</CmdID>" + "<MsgRef>1</MsgRef>" + "<CmdRef>1</CmdRef>" + "<Meta>" + "<Type>application/vnd.syncml-devinf+xml</Type>" + "</Meta>" + "<Item>" + "<Source>" + "<LocURI>./devinf12</LocURI>" + "</Source>" + "<Data>" + ; + buffer += ruleP->fOverrideDevInfXML; + buffer += + "</Data>" + "</Item>" + "</Results>" + "</SyncBody>" + "</SyncML>"; + MemPtr_t xml = (unsigned char *)buffer.c_str(); + XltDecoderPtr_t decoder = NULL; + SmlSyncHdrPtr_t hdr = NULL; + Ret_t ret = xltDecInit(SML_XML, + xml + buffer.size(), + &xml, + &decoder, + &hdr); + if (ret != SML_ERR_OK) { + sta = LOCERR_BADCONTENT; + PDEBUGPRINTFX(DBG_ERROR,("initializing scanner for DevInf in %s failed",ruleP->getName())); + } else { + SmlProtoElement_t element; + VoidPtr_t content = NULL; + ret = xltDecNext(decoder, + xml + buffer.size(), + &xml, + &element, + &content); + if (ret != SML_ERR_OK) { + sta = LOCERR_BADCONTENT; + PDEBUGPRINTFX(DBG_ERROR,("parsing of DevInf in %s failed",ruleP->getName())); + } else if (element != SML_PE_RESULTS || + !((SmlResultsPtr_t)content)->itemList || + !((SmlResultsPtr_t)content)->itemList->item || + !((SmlResultsPtr_t)content)->itemList->item->data || + ((SmlResultsPtr_t)content)->itemList->item->data->contentType != SML_PCDATA_EXTENSION || + ((SmlResultsPtr_t)content)->itemList->item->data->extension != SML_EXT_DEVINF) { + sta = LOCERR_BADCONTENT; + PDEBUGPRINTFX(DBG_ERROR,("parsing of DevInf in %s returned unexpected result",ruleP->getName())); + } else if (aOverrideDevInfP) { + // processing in caller will continue with updated DevInf + *aOverrideDevInfP = (SmlDevInfDevInfPtr_t)((SmlResultsPtr_t)content)->itemList->item->data->content; + } + } + if (decoder) + xltDecTerminate(decoder); + if (sta!=LOCERR_OK) { + AbortSession(sta,true); + break; + } + } // - apply options that have a value if (ruleP->fLegacyMode>=0) fLegacyMode = ruleP->fLegacyMode; if (ruleP->fLenientMode>=0) fLenientMode = ruleP->fLenientMode; @@ -4485,6 +4569,9 @@ localstatus TSyncSession::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP) #endif } // for all activated rules PDEBUGENDBLOCK("RemoteRules"); + // something failed in applying remote rules? + if (sta!=LOCERR_OK) + return sta; #endif // NO_REMOTE_RULES // Final adjustments #ifndef NO_REMOTE_RULES diff --git a/src/sysync/syncsession.h b/src/sysync/syncsession.h index 958c7df..1e92321 100755 --- a/src/sysync/syncsession.h +++ b/src/sysync/syncsession.h @@ -155,6 +155,11 @@ public: #ifdef SCRIPT_SUPPORT string fRuleScriptTemplate; // template for rule script #endif + // DevInf in XML format which is to be used instead of the one sent by peer. + // If set, it is evaluated after identifying the peer based on the DevInf + // that it has sent and before applying other remote rule workarounds. + // XML DevInf directly from XML config. + string fOverrideDevInfXML; // list of subrules to activate TRemoteRulesList fSubRulesList; // flag if this is a final rule (if matches, no more rules will be checked) @@ -827,7 +832,7 @@ protected: virtual SmlPcdataPtr_t newHeaderMeta(void); // - check remote devinf to detect special behaviour needed for some clients. Base class // does not do anything on server level (configured rules are handled at session level) - virtual localstatus checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP); + virtual localstatus checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP, SmlDevInfDevInfPtr_t *aOverrideDevInfP); // - remote device is analyzed, possibly save status virtual void remoteAnalyzed(void) { /* nop */ }; // SyncML Toolkit interface |