Keith Willis wrote:
> Hi Arno,
> 
>> You never check PostedDataSize, the size of your receive buffer.
>> The pascal demo allocates this buffer dynamically depending on the
> RequestContentLength plus one byte for the null terminator in the
> OnPostDocument event handler.
>> What is the value of RcvdByteCount when the error happens?
> 
> 
> I originally did it like that, but it kept crashing with AV's so I
> embarked on a process of elimination of suspect code until I ended up
> with an (almost) stable version where PostedDataBuffer  was
> statically allocated in the class declaration.

It's probably stable unless posted data size exceeds receive buffer size.  

Also the MemoryManager should be instantiated once (on application start),
and memory allocated by the MemoryManager should be freed by the manager.

In my sample below I use malloc and free (stdlib.h) which is most 
likely slower than proper use of MemoryManager.

{code}

class TMyHttpConnection : public THttpConnection
{
public:
 char *PostedDataBuffer;     // Will hold dynamically allocated buffer
 int  PostedDataSize;        // Databuffer size
 int  DataLen;               // Keep track of received byte count.
public:
 virtual __fastcall ~TMyHttpConnection();
};

//---


// We need to override parent class destructor because we have allocated
// memory for our data buffer.
__fastcall TMyHttpConnection::~TMyHttpConnection()
{
 if (PostedDataBuffer != NULL) {
  free(PostedDataBuffer);
  PostedDataBuffer = NULL;
    }
}
//---------------------------------------------------------------------------
[..] 

void __fastcall TWebServForm::HttpServer1PostDocument(
 TObject *Sender,
 TObject *Client,
 THttpGetFlag &Flags)
{
 TMyHttpConnection* ClientCnx = (TMyHttpConnection*)Client;

 // We only accept data for '/post.bin'
 if (CompareText(ClientCnx->Path, "/post.bin") == 0)
 {
  // Tell HTTP server that we will accept posted data
  // OnPostedData event will be triggered when data comes in
  Flags = hgAcceptData;

  // We want to receive any data type. So we turn line mode off
  ClientCnx->LineMode = false;

  // We need a buffer to store posted data. We allocate as much as the
  // size of posted data plus one byte for the terminating nul char
  // since we expect just a few bytes posted in this sample. 
  // We should also check for ContentLength = 0 and handle this case...
  if (ClientCnx->PostedDataSize < ClientCnx->RequestContentLength + 1)
  {
   if (ClientCnx->PostedDataBuffer)
    free(ClientCnx->PostedDataBuffer);
   ClientCnx->PostedDataBuffer = (char*)malloc(ClientCnx->RequestContentLength 
+ 1);
   if (ClientCnx->PostedDataBuffer)
    ClientCnx->PostedDataSize = ClientCnx->RequestContentLength + 1;
   else
   {
    ClientCnx->PostedDataSize = 0;
    // ERROR!
   }
  }
  // Clear received length
  ClientCnx->DataLen = 0;
 }
 else
  Flags = hg404;
}
//---------------------------------------------------------------------------
void __fastcall TWebServForm::HttpServer1PostedData(
 TObject *Sender,
 TObject *Client,
 WORD Error)
{
 int Len, Remains;
 char Junk [1024];
 THttpGetFlag Dummy = hgSendDoc;

 TMyHttpConnection* ClientCnx = (TMyHttpConnection*)Client;

 Remains = ClientCnx->RequestContentLength - ClientCnx->DataLen;

 // We MUST receive any data and throw away the garbage!
 if (Remains <= 0)
 {
  ClientCnx->Receive(&Junk, sizeof(Junk));
  return;
 }

 Len = ClientCnx->Receive(&ClientCnx->PostedDataBuffer[ClientCnx->DataLen],
                          Remains);
 if (Len <= 0)
  return;

 ClientCnx->DataLen += Len;

 // Everything received? If true, let's process the stuff
 if (ClientCnx->DataLen == ClientCnx->RequestContentLength)
 {
        // First we must tell the component that we've got all the data
  ClientCnx->PostedDataReceived();

  // Do something with the received data, here we just display, we expect
  // just short text data in this demo!
        ClientCnx->PostedDataBuffer[ClientCnx->DataLen] = 0;
  Display(ClientCnx->PostedDataBuffer);

  // Send the response
  ClientCnx->AnswerString(Dummy,
  "",           // Default Status '200 OK'
  "",           // Default Content-Type: text/html
  "",           // Default header
  "<HTML><HEAD>"
  "<TITLE>ICS WebServer POST Demo</TITLE>"
  "</HEAD><BODY>"
  "<H1>Your data has been recorded</H1>"
  "</BODY></HTML>\r\n");
  }
}
//---------------------------------------------------------------------------

{code}

--
Arno Garrels
-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to