[prev in list] [next in list] [prev in thread] [next in thread] 

List:       axis-c-dev
Subject:    Re: SoapSerializer buffer allocation code is broken
From:       Alexei Dets <adets () idsk ! com>
Date:       2004-07-27 22:59:54
Message-ID: 200407271859.54521.adets () idsk ! com
[Download RAW message or body]

Hi!
On Tuesday 27 July 2004 00:19, damitha kumarage wrote:
> I think we need to get rid of this double buffering thing. Axis C++ do

I'm attaching the patch to SoapSerializer class that completely eliminates the 
buffering and all code associated with it (callback functions etc.). This 
fixes the problem of the long strings output from the server - it is not 
crashing it anymore.

However, it is not possible to use Axis C++ client to receive these strings, 
it catches an exception: "AxisTransportException:Transport buffer is empty". 
Axis Java or PHP nuSOAP clients work fine. I suspect that transport layer are 
using some buffers in the manner similiar to SoapSerializer and also suffer 
from some type of buffer overflow problems. I'll try to find the problem.

	Alexei

["SoapSerializer.patch" (text/x-diff)]

diff -ub axis-c-src-1-2-linux.orig/include/axis/server/SoapSerializer.h \
                axis-c-src-1-2-linux/include/axis/server/SoapSerializer.h
--- axis-c-src-1-2-linux.orig/include/axis/server/SoapSerializer.h	2004-07-09 \
                03:22:03.000000000 -0400
+++ axis-c-src-1-2-linux/include/axis/server/SoapSerializer.h	2004-07-27 \
18:18:07.000000000 -0400 @@ -43,11 +43,6 @@
 
 class SoapSerializer : public IHandlerSoapSerializer
 {
-    typedef struct
-    {
-        volatile unsigned char inuse;
-        volatile char* buffer;
-    } SerializeBuffers;
 private:
     int m_nCounter;
     AxisChar m_Buf[8];
@@ -55,18 +50,6 @@
     int m_iSoapVersion;
     /* Current Serialization Style */
     AXIS_BINDING_STYLE m_nStyle;
-    /* Table that keeps all allocated buffers */
-    volatile SerializeBuffers* m_pSZBuffers;
-    /* Size of the initial buffer created.*/
-    int m_nInitialBufferSize;
-    /* Size of the m_SZBuffers array.*/
-    int m_nMaxBuffersToCreate;
-    /* Maximum size of the buffer that is being filled */
-    int m_nCurrentBufferSize;
-    /* How much charators has been filled to the currently selected buffer */
-    int m_nFilledSize;
-    /* Currently selected buffer index*/
-    int m_nCurrentBufferIndex;
     /* Overall status of Serializer. If anything goes wrong this is not 
      * AXIS_SUCCESS 
      */
@@ -153,8 +136,6 @@
     void setCurrentProviderType(PROVIDERTYPE nType) { m_ProviderType = nType;};
 
 private:
-    int sendSerializedBuffer();
-    int setNextSerilizeBuffer();
     IArrayBean* makeArrayBean(XSDTYPE nType, void* pArray);
     IArrayBean* makeArrayBean(void* pObject, void* pSZFunct, void* pDelFunct, 
         void* pSizeFunct);
@@ -189,8 +170,6 @@
     int AXISCALL setBodyAsHexBinary(xsd__hexBinary body);
     int AXISCALL setBodyAsBase64Binary(xsd__base64Binary body);
     const AxisChar* AXISCALL getBodyAsString();
-	static void AXISCALL releaseBufferCallBack(const char* buffer,
-        const void* bufferid);
 	int addOutputAnyObject(AnyType* pAnyObject);
 	int serializeAnyObject(AnyType* pAnyObject);
 };
diff -ub axis-c-src-1-2-linux.orig/src/soap/SoapSerializer.cpp \
                axis-c-src-1-2-linux/src/soap/SoapSerializer.cpp
--- axis-c-src-1-2-linux.orig/src/soap/SoapSerializer.cpp	2004-07-09 \
                03:22:04.000000000 -0400
+++ axis-c-src-1-2-linux/src/soap/SoapSerializer.cpp	2004-07-27 18:44:02.000000000 \
-0400 @@ -43,9 +43,6 @@
 extern AxisTrace* g_pAT;
 extern AxisConfig* g_pConfig;
 
-/* Following values should come from axis configuration files. */
-#define INITIAL_SERIALIZE_BUFFER_SIZE 1024
-
 IWrapperSoapSerializerFunctions IWrapperSoapSerializer::ms_VFtable;
 
 SoapSerializer::SoapSerializer()
@@ -53,24 +50,11 @@
     m_pSoapEnvelope = NULL;
     m_iSoapVersion = SOAP_VER_1_1;
     m_pOutputStream = NULL;
-    m_nMaxBuffersToCreate = NO_OF_SERIALIZE_BUFFERS;
-    m_nInitialBufferSize = INITIAL_SERIALIZE_BUFFER_SIZE;
-    m_pSZBuffers = new SerializeBuffers[m_nMaxBuffersToCreate];
-    for (int x=0; x<m_nMaxBuffersToCreate; x++)
-    {
-        m_pSZBuffers[x].inuse = 0;
-        m_pSZBuffers[x].buffer = NULL;
-    }
 }
 
 SoapSerializer::~SoapSerializer()
 {
     if (m_pSoapEnvelope) delete m_pSoapEnvelope;
-   for (int x=0; x<m_nMaxBuffersToCreate; x++)
-   {
-       delete [] (char*)m_pSZBuffers[x].buffer;
-   }
-   delete [] (SerializeBuffers*)m_pSZBuffers;		    
 }
 
 int SoapSerializer::setSoapEnvelope(SoapEnvelope *pSoapEnvelope)
@@ -246,14 +230,11 @@
     int iStatus= AXIS_SUCCESS;
     try
     {
-    m_pOutputStream->registerReleaseBufferCallback(releaseBufferCallBack);
-
     if(m_pSoapEnvelope)
     {
         serialize("<?xml version='1.0' encoding='utf-8' ?>", NULL);
         iStatus= m_pSoapEnvelope->serialize(*this, 
             (SOAP_VERSION)m_iSoapVersion);
-        sendSerializedBuffer();
     }
     }
     catch(AxisSoapException& e)
@@ -299,8 +280,6 @@
     m_pSoapEnvelope = new SoapEnvelope();
     m_pSoapEnvelope->setSoapBody(new SoapBody());
     
-    setNextSerilizeBuffer();
-
     m_nCounter=0;
     m_NsStack.clear();
     return AXIS_SUCCESS;
@@ -366,51 +345,11 @@
         return *this;
     }
 
-    int iTmpSerBufferSize = strlen(cSerialized);
-    if((m_nFilledSize + iTmpSerBufferSize)>= m_nCurrentBufferSize) 
-    {
-        /*
-         * Send the current buffer to the transport and get
-         * another buffer to be filled
-         */
-        if (AXIS_SUCCESS == sendSerializedBuffer())
-        {
-            if (AXIS_SUCCESS == setNextSerilizeBuffer())
-            {
-                strcat((char*)m_pSZBuffers[m_nCurrentBufferIndex].buffer,
-                    cSerialized);
-                m_nFilledSize += iTmpSerBufferSize;
-            }
-        }
-    }
-    else
-    {
-        strcat((char*)m_pSZBuffers[m_nCurrentBufferIndex].buffer, cSerialized);
-        m_nFilledSize += iTmpSerBufferSize;
-    }
-    return *this;
-}
-
-int SoapSerializer::sendSerializedBuffer()
-{
-    int nStatus;
     try
     {
-    nStatus = m_pOutputStream->sendBytes((char*)
-    m_pSZBuffers[m_nCurrentBufferIndex].buffer, (void*)(&(m_pSZBuffers
-    [m_nCurrentBufferIndex].inuse)));
-    if (TRANSPORT_FINISHED == nStatus) 
-    /* transport layer has done with the buffer.So same buffer 
-     * can be re-used
-     */
-    {
-        m_pSZBuffers[m_nCurrentBufferIndex].buffer[0] = '\0'; /* put nul */
-        m_pSZBuffers[m_nCurrentBufferIndex].inuse = 0; /* not in use */
-    }
-    else if (TRANSPORT_FAILED == nStatus) 
-    {
-        return AXIS_FAIL;
-    }
+      /* send everything to transport layer, it should handle bufferization itself \
*/ +      int nStatus = m_pOutputStream->sendBytes(cSerialized, 0);
+      // FIXME: should we process nStatus somehow?
     }
     catch(AxisSoapException& e)
     {
@@ -425,49 +364,7 @@
         throw;
     }
 
-    
-    return AXIS_SUCCESS;
-}
-
-/*
- * This method sets the next buffer to be used for serialization.
- *
- */
-int SoapSerializer::setNextSerilizeBuffer()
-{
-    for (int x=0;x<m_nMaxBuffersToCreate;x++)
-    {
-        if (m_pSZBuffers[x].buffer) /* a buffer has been created */
-        {
-            if (0 == m_pSZBuffers[x].inuse) /* buffer is not being used */ 
-            {
-                m_nCurrentBufferIndex = x;
-                m_pSZBuffers[m_nCurrentBufferIndex].inuse = 1;
-                m_pSZBuffers[m_nCurrentBufferIndex].buffer[0] = '\0';
-                m_nFilledSize = 0;
-                m_nCurrentBufferSize = m_nInitialBufferSize*
-                    (1 << m_nCurrentBufferIndex);
-                return AXIS_SUCCESS;
-            }
-        }
-        else
-        /* a buffer is not yet created at this array index.
-         * So create one and use it 
-         */
-        {
-            m_nCurrentBufferIndex = x;
-            m_nCurrentBufferSize = m_nInitialBufferSize*
-                (1 << m_nCurrentBufferIndex);           
-            m_pSZBuffers[m_nCurrentBufferIndex].buffer = 
-                new char[m_nCurrentBufferSize];
-            m_pSZBuffers[m_nCurrentBufferIndex].inuse = 1;
-            m_pSZBuffers[m_nCurrentBufferIndex].buffer[0] = '\0';
-            m_nFilledSize = 0;
-            return AXIS_SUCCESS;
-        }
-    }
-    
-    return AXIS_FAIL;
+    return *this;
 }
 
 int SoapSerializer::createSoapMethod(const AxisChar* sLocalName, 
@@ -842,30 +739,6 @@
     serialize("</", pName, ">", NULL);
 }
 
-/*
- * Callback function that should be called by the transport module to release
- * a buffer passed to it by a Serializer.
- * @param 
- *        buffer - Same buffer passed to transport by calling transport's 
- *                 AXIS_MODULE_CALLBACK_SEND_MESSAGE_BYTES 
- *                 callback
- *        buffer - Same bufferid passed to transport by calling transport's 
- *                 AXIS_MODULE_CALLBACK_SEND_MESSAGE_BYTES 
- *                 callback
- *        stream - Same stream object passed to transport by calling 
- *                 transport's AXIS_MODULE_CALLBACK_SEND_MESSAGE_BYTES 
- *                 callback
- */
- 
-#ifndef USER_SERIALIZER 
-void SoapSerializer::releaseBufferCallBack(const char* buffer, const void* bufferid)
-{
-    int* pInt = (int*)bufferid;
-    *pInt = 0; /* set that the buffer is not in use */
-    char *pChar = const_cast<char*>(buffer);
-    pChar[0] = '\0'; /* set nul */ 
-}
-#endif
 
 IHeaderBlock* SoapSerializer::createHeaderBlock(AxisChar *pachLocalName, 
                                                 AxisChar *pachUri)



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic