Hi Thomas
Yes, the define HTTP_DYNAMIC_CONTENT is intended for generation of content which is not predefined. There is no demo of this in the project but generating tables of variable lengths is a good example of where it can be useful.
You have probably seen that a counter is added to the HTTP structure (each HTTP session has its own counter)
unsigned short usDynamicCnt; // reference during dynamic content generation
This is used later to manage the progress of the build up of dynamic content.
Here is how it can work:
1. When the parser encounters the escape sequence for dynamic content ($Hxx for example) it calls fnInsertString() from the applications webInterface.c. Rather than calling this with length = 0 (as is the case when strings are to be inserted) it calls it with a length (!= 0) - this is the length remaining in the current TCP transmit buffer.
2. fnInsertString() then can insert the correct contents. If there is not enough space for a line of table it can skip until the next frame. It can use the session counter to keep track of now many lines of the table have already been generated (for example).
3. For the start of the table (when usDynamicCnt is zero) it first inserts the HTML code for the table start.
4. For each line of the table it copies HTML code for the content (strings derived from variable values for example). It fits as many lines into the TCP tx buffer space as possible.
5. When all variables have been added, it adds the end of the table.
Here is an extract of some old code which was used to build up a table of temperature values collected over a period of time - the table increased in size over time. It was inserted in fnInsertString() and added the temperature plus a time stamp per line.
static const signed char cStartTable[] = "<TABLE border=""1""><CAPTION><EM>Temperature history</EM></CAPTION><TR><TH>Date<TH>Time<TH>Temperature<br>(Celcius)";
static const signed char cEndTable[] = "</TABLE><br><br>";
// We can add our own content here.
// we don't try to shift inside of the buffer since our data will generally fill several buffers. Instead
// we halt the html file at its present location and fill as many frames as possible. At the end we restart html
// possibly after short last frame.
http_session->usDynamicCnt++;
if (http_session->usDynamicCnt == 1) {
usLen++;
*usMaxLen -= (usLen);
return (usFrameLength - usLen); // parameter list cut off, handle it next time around
}
else if (http_session->usDynamicCnt >= 2) {
static signed char cTableLine[] = "<TR><TD>14.10.2005<TD>12:24:50<TD>+25";
unsigned short usTableLength = 0;
ptrBuffer--; // overwrite the Dynamic data field
http_session->usUnacked = 0;
if (http_session->usDynamicCnt == 2) {
// create a table
memcpy(ptrBuffer, (unsigned char *)cStartTable, (sizeof(cStartTable)-1));
usTableLength += (sizeof(cStartTable)-1);
ptrBuffer += (sizeof(cStartTable)-1);
}
while (usTableLength < (HTTP_BUFFER_LENGTH - sizeof(cTableLine)-1)) {
if (fnGetTempLog((unsigned short)((http_session->usDynamicCnt)++ - 2), &cTableLine[8], &cTableLine[22], &cTableLine[34])) {
// close table
if (usTableLength < (HTTP_BUFFER_LENGTH - sizeof(cEndTable)-1)) {
memcpy(ptrBuffer, (unsigned char *)cEndTable, (sizeof(cEndTable)-1));
usTableLength += (sizeof(cEndTable)-1);
http_session->usDynamicCnt = 0; // terminated
http_session->usUnacked = 2; // complete buffer was overwritten
}
break;
}
memcpy(ptrBuffer, (unsigned char *)cTableLine, (sizeof(cTableLine)-1));
usTableLength += (sizeof(cTableLine)-1);
ptrBuffer += (sizeof(cTableLine)-1);
}
return usTableLength;
}
}
Unfortunately this technique has not been used in the project for a very long time and the code is almost certainly no longer compatible. In addition I am not sure that it correctly handles repetitions of TCP frames (it may lose lines in (?)).
I hope that gives you an idea of how it could work. I will try to get a tested example added to the project in the near future, including correct handling of TCP repetitions if it proves to be flawed at the moment.
Regards
Mark