On Fri, 2010-02-26 at 06:51 +, Patrick Ohly wrote:
The only implementation of canBufferRetryAnswer() that I find returns
false, so we end up in the else branch and indeed, in some cases the
state gets messed up.
I'll keep looking into how I can enable this. Hints welcome.
I've got it working, but only in a hackish way. See
libsynthesis-resend.patch. It depends on the app knowing about
STEPCMD_RESENDDATA *and* buffering the last reply itself. I consider
this a hack a) because canBufferRetryAnswer() can't know whether the app
is capable of resending and b) the buffering should be inside the
engine, using the normal STEPCMD_SENDDATA.
I also tried STEPCMD_SENDDATA, but found that the content of the SML
message buffer was too messed up to get the old reply.
I'm also attaching the SyncEvolution patch necessary to support the hack
above. This is only for future reference, because I am not going to
commit it to our repo.
With these patches I get our tests to pass mostly, but the known issue
with not being able to resend the last reply in a session still breaks
it. This can only be fixed inside libsynthesis and/or SyncEvolution by
keeping sessions alive after the server considers them done, which
complicates the session handling considerably.
I found it easier to add caching of the last reply to our
syncevo-http-server.py script. It does not depend on the SyncML message
number (server cannot parse the message), instead it does a byte
comparison of the incoming message. Obviously that depends on the client
sending exactly the same data, but for SyncEvolution as client that
works. Lukas, do you know whether other clients (like the Nokia phones)
do the same?
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.
diff --git a/src/sysync/syncagent.cpp b/src/sysync/syncagent.cpp
index bc0f4e0..3cd3ccc 100755
--- a/src/sysync/syncagent.cpp
+++ b/src/sysync/syncagent.cpp
@@ -3053,6 +3053,14 @@ TSyError TSyncAgent::ServerProcessingStep(uInt16 aStepCmd, TEngineProgressInfo
fServerEngineState = ses_generating;
sta = LOCERR_OK;
}
+ else if (rc==LOCERR_RETRYMSG) {
+// Resend existing reply. Note that the app must have buffered the
+// reply, because writing into the SML buffer wiped out the
+// old response.
+aStepCmd = STEPCMD_RESENDDATA;
+fServerEngineState = ses_dataready;
+sta = LOCERR_OK;
+ }
else {
// processing failed
PDEBUGPRINTFX(DBG_ERROR,(=== smlProcessData failed, returned 0x%hX,(sInt16)rc));
diff --git a/src/sysync/syncappbase.h b/src/sysync/syncappbase.h
index caa1b6c..c2be374 100755
--- a/src/sysync/syncappbase.h
+++ b/src/sysync/syncappbase.h
@@ -501,7 +501,7 @@ public:
SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the SyncHdr element
) = 0;
// test if message buffering is available
- virtual bool canBufferRetryAnswer(void) { return false; }; // must be set in server bases
+ virtual bool canBufferRetryAnswer(void) { return true; }; // must be set in server bases
// non-virtual handlers, are always called with userData containing valid session pointer
// - end of message
Ret_t EndMessage(VoidPtr_t userData, Boolean_t aFinal);
diff --git a/src/syncevo/SyncContext.cpp b/src/syncevo/SyncContext.cpp
index c72bddc..492e975 100644
--- a/src/syncevo/SyncContext.cpp
+++ b/src/syncevo/SyncContext.cpp
@@ -3008,7 +3008,7 @@ SyncMLStatus SyncContext::doSync()
sysync::STEPCMD_GOTDATA :
sysync::STEPCMD_CLIENTSTART;
SharedSession session = m_engine.OpenSession(m_sessionID);
-SharedBuffer sendBuffer;
+SharedBuffer sendBuffer, sendBufferCopy;
SessionSentinel sessionSentinel(*this, session);
if (m_serverMode) {
@@ -3236,7 +3236,14 @@ SyncMLStatus SyncContext::doSync()
resendStart = time(NULL);
/* We are resending previous message, just read from the
* previous buffer */
-m_agent-send(sendBuffer.get(), sendBuffer.size());
+const char *data = sendBuffer.get();
+size_t size = sendBuffer.size();
+if (!data) {
+// server mode, use fallback copy
+data = sendBufferCopy.get();
+size = sendBufferCopy.size();
+}
+m_agent-send(data, size);
stepCmd = sysync::STEPCMD_SENTDATA; // we have sent the data
break;
}
@@ -3279,6 +3286,14 @@ SyncMLStatus SyncContext::doSync()
contentType.find(application/vnd.syncml+xml) != contentType.npos) {
// put answer received earlier into SyncML engine's buffer
m_retries = 0;
+// sendBuffer points to memory