[Client-dev] Re: [Common-dev] CR: sock option for enabling read buffer reallocation to save memory

[Client-dev] Re: [Common-dev] CR: sock option for enabling read buffer reallocation to save memory

Aaron Colwell acolwell at real.com
Thu Aug 5 09:48:51 PDT 2004


The current Symbian networking code reads the data into a large buffer and
then copies the data into a buffer of the appropriate size. It just sounds
to me like Liam is just adding this code to the new socket API as well. 

The copy saves us A LOT of memory (100k or more). We were having problems 
running out of memory on the phone because the core was allocating 2-4k 
buffers for packets and not resizing them. This wastes a ton of memory 
when the stream has small packets. In my opinion this memcpy() is critical 
for low memory playback. If we want to remove memcpy()s we should look 
elsewhere.

Aaron

On Thu, Aug 05, 2004 at 09:25:46AM -0700, Greg Wright wrote:
> I am very concerned about, what appears to be, a memcpy for every single 
> packet we receive.
> Some platforms are both memory sensitive and memcpy sensitive (ARM 
> devices). each
> memcpy we do on an ARM really hurts our performance numbers. We did a 
> lot of work a
> while back to just remove 2 memcpy's per packet to get content to play 
> on a phone that
> would not otherwise.
> 
> It there no way to fix the size of the UDP read buffer to something 
> closer to the
> known packet size and not have to do the memcpy? How much memory does
> the memcpy save us? Are we talking megs, 100Ks, 10Ks? Is this memory 
> usage much
> higher then the old networking or is it a optimization over the current 
> networking memory
> usage? Is it safe to do something like reduce the read buffer size to 2K 
> when we see a 1.4K UDP
> packet come in? I know our image file formats can generate big packets 
> (18K packets are not
> uncommon) so those mixed with video packets (1.5K at most) would be 
> problematic I guess. Is the
> read buffer size on a per connection basis?
> 
> Generally I would like to see some solution that does not require any 
> additional
> memcpys. Packet memcpys are death.
> 
> --greg.
> 
> 
> 
> 
> Liam Murray wrote:
> 
> >(NOTE: this updates the previous CR that I sent and that no one has 
> >responded to yet.)
> >
> >Summary:
> >
> >Adds socket option that lets socket user control re-allocation of read 
> >buffer in order to reduce memory consumption.
> >
> >Details:
> >
> >With UDP reads we allocate a default UDP read buffer of 64K. After we 
> >read the buffer and are able to determine the actual size of the 
> >datagram we update the size of the buffer. This does not free unused 
> >memory from the buffer. Therefore each datagram held in the 
> >application buffers is using 64K even if the actual datagram is very 
> >small. This can add up to a lot of memory usage. (Similar occurs with 
> >tcp reads in cases where the net buffer has less than the maximum 
> >segment size.)
> >
> >One solution to avoid the memory overhead is to copy the buffer to a 
> >precisely sized buffer once the true size is known. Another solution 
> >is to use ioctlsocket with FIONREAD to determine the pending datagram 
> >size. This was discussed earlier and there are some uncertainties to 
> >doing this. For now the ioctlsocket approach is not considered.
> >
> >This change adds adds support for a socket option 
> >(HX_SOCKOPT_RCVBUF_FLAG) that enables the user to specify one of the 
> >following flags.
> >
> >typedef enum
> >{
> >    HX_SOCK_RCVBUF_SIZE_DEFAULT,
> >    HX_SOCK_RCVBUF_SIZE_COPY,
> >} HXSockRcvBufFlag;
> >
> >If HX_SOCK_RCVBUF_SIZE_DEFAULT (the default) is set the behavior 
> >remains the same. If HX_SOCK_RCVBUF_SIZE_COPY is set,  each read 
> >buffer allocated by the IHXSocket implementation is reallocated 
> >(copied) to a precisely sized buffer after the actual size is known.
> >
> >Some clients are particularly sensitive to memory usage and the cost 
> >of an extra copy is worth the memory we can save by doing the copy.
> >
> >There is some room for optimization. For example, a temporary buffer 
> >(or vector of buffers) sized to the max read size (max UDP or max 
> >segment) can be allocated once and reused for each read as long as we 
> >always allocate a new buffer and copy to it.
> >
> >Branch: HEAD
> >
> >Builds/functionality verified: Windows client
> >
> >
> >Liam
> >
> >
> >Index: hxnet.h
> >===================================================================
> >RCS file: /cvsroot/common/include/hxnet.h,v
> >retrieving revision 1.22
> >diff -u -w -r1.22 hxnet.h
> >--- hxnet.h     30 Jul 2004 20:53:56 -0000      1.22
> >+++ hxnet.h     5 Aug 2004 01:13:01 -0000
> >@@ -439,6 +439,12 @@
> >     HX_SOCKBUF_TIMESTAMPED      // IHXTimeStampedBuffer
> > } HXSockBufType;
> >
> >+typedef enum
> >+{
> >+    HX_SOCK_RCVBUF_SIZE_DEFAULT,    // avoids copy
> >+    HX_SOCK_RCVBUF_SIZE_COPY,       // conserves memory; results in a 
> >copy
> >+} HXSockRcvBufFlag;
> >+
> > /* Socket options for IHXSocket::GetOption() and 
> >IHXSocket::SetOption() */
> > /* XXXTDM: Separate these like the real getsockopt/setsockopt? */
> > typedef enum {
> >@@ -497,6 +503,7 @@
> >     HX_SOCKOPT_BUFFER_TYPE,
> >     HX_SOCKOPT_APP_SNDBUF,
> >     HX_SOCKOPT_APP_RCVBUF,
> >+    HX_SOCKOPT_RCVBUF_FLAG,
> >
> >     HX_SOCKOPT_LAST
> > } HXSockOpt;
> >
> >
> >Index: hxsockutil.cpp
> >===================================================================
> >RCS file: /cvsroot/common/netio/hxsockutil.cpp,v
> >retrieving revision 1.12
> >diff -u -w -r1.12 hxsockutil.cpp
> >--- hxsockutil.cpp      30 Jul 2004 19:58:18 -0000      1.12
> >+++ hxsockutil.cpp      5 Aug 2004 01:09:28 -0000
> >@@ -42,6 +42,7 @@
> > #include "safestring.h"
> > #include "debug.h"
> > #include "hxassert.h"
> >+#include "netbyte.h"
> > #include "hxheap.h"
> > #include "hxsockutil.h"
> >
> >@@ -254,7 +255,9 @@
> >
> > }
> >
> >-HX_RESULT HXSockUtil::SetAddr(IHXSockAddr* pAddr /*modified*/, const 
> >char* pAddrString, UINT16 port)
> >+HX_RESULT HXSockUtil::SetAddr(IHXSockAddr* pAddr /*modified*/,
> >+                              const char* pAddrString,
> >+                              UINT16 port)
> > {
> >     HX_ASSERT(pAddr);
> >     HX_ASSERT(pAddrString);
> >@@ -275,15 +278,15 @@
> >
> > HX_RESULT HXSockUtil::SetAddr(IHXSockAddr* pAddr /*modified*/,
> >                                 short family,
> >-                                const void* pAddrData /*net-order 
> >octets/hextets*/,
> >-                                UINT16 port)
> >+                                const void* pAddrData /*net order 
> >octets/hextets*/,
> >+                                UINT16 port /*net order*/)
> > {
> >     HX_ASSERT(pAddrData);
> >
> >     char szAddr[HX_ADDRSTRLEN]; // big enough for ipv6 and ipv4
> >     hx_inet_ntop(family, pAddrData, szAddr, HX_ADDRSTRLEN);
> >
> >-    return SetAddr(pAddr, szAddr, port);
> >+    return SetAddr(pAddr, szAddr, WToHost(port));
> > }
> >
> >
> >
> >Index: platform/posix/sockimp.cpp
> >===================================================================
> >RCS file: /cvsroot/common/netio/platform/posix/sockimp.cpp,v
> >retrieving revision 1.37
> >diff -u -w -r1.37 sockimp.cpp
> >--- platform/posix/sockimp.cpp  30 Jul 2004 20:32:57 -0000      1.37
> >+++ platform/posix/sockimp.cpp  5 Aug 2004 01:09:28 -0000
> >@@ -1005,6 +1005,7 @@
> >     m_type(HX_SOCK_TYPE_NONE),
> >     m_proto(HX_SOCK_PROTO_NONE),
> >     m_bufType(HX_SOCKBUF_DEFAULT),
> >+    m_rcvBufFlag(HX_SOCK_RCVBUF_SIZE_DEFAULT),
> >     m_sock(HX_SOCK_NONE),
> > #if defined(MISSING_DUALSOCKET)
> >     m_pSock4(NULL),
> >@@ -1034,7 +1035,6 @@
> >     }
> >     HX_ASSERT(m_punkContext != NULL);
> >     HX_ASSERT(m_pCCF != NULL);
> >-    HX_ASSERT(m_pScheduler != NULL);
> > }
> >
> > CHXSocket::CHXSocket(CHXNetServices* pNetSvc, IUnknown* punkContext,
> >@@ -1077,7 +1077,6 @@
> >     }
> >     HX_ASSERT(m_punkContext != NULL);
> >     HX_ASSERT(m_pCCF != NULL);
> >-    HX_ASSERT(m_pScheduler != NULL);
> > }
> >
> > CHXSocket::~CHXSocket(void)
> >@@ -1141,28 +1140,32 @@
> >         break;
> >     case HX_SOCK_STATE_CONNECTING:
> >         HX_ASSERT(uEvent & HX_SOCK_EVENT_WRITE);
> >-        m_sock.state = HX_SOCK_STATE_NORMAL; //XXXTDM: What if 
> >connect fails?
> >-
> >-        if (m_uSelectedEventMask & HX_SOCK_EVENT_CONNECT)
> >+        if (uEvent & HX_SOCK_EVENT_WRITE)
> >         {
> >             UINT32 err = 0;
> >-            HX_RESULT status;
> >             hx_getsockopt(&m_sock, HX_SOCKOPT_SOCKERR, &err);
> >-            status = ErrorToStatus(err);
> >+            HX_RESULT status = ErrorToStatus(err);
> >+
> >+            // NB: we shouldn't send a close event unless the 
> >connection is successful
> >+            m_sock.state = HX_SOCK_STATE_NORMAL;
> >+
> >             if (m_uSelectedEventMask & HX_SOCK_EVENT_CONNECT)
> >             {
> >                 m_pResponse->EventPending(HX_SOCK_EVENT_CONNECT, 
> >status);
> >             }
> >-        }
> >-        //XXXTDM: Pass up write event on failed connect?
> >-        if (m_uSelectedEventMask & HX_SOCK_EVENT_WRITE)
> >-        {
> >+
> >             HX_ASSERT(m_bIsResponseWriteEventPending);
> >             m_bIsResponseWriteEventPending = FALSE;
> >+
> >+            // only send the write event if the connection was 
> >successfully established
> >+            if (HXR_OK == status && m_uSelectedEventMask & 
> >HX_SOCK_EVENT_WRITE)
> >+            {
> >             m_pResponse->EventPending(HX_SOCK_EVENT_WRITE, HXR_OK);
> >         }
> >+        }
> >         break;
> >     case HX_SOCK_STATE_LISTENING:
> >+        HX_ASSERT(uEvent & HX_SOCK_EVENT_READ);
> >         if (uEvent & HX_SOCK_EVENT_READ)
> >         {
> >             m_uPendingEventMask = HX_SOCK_EVENT_ACCEPT;
> >@@ -1743,6 +1746,7 @@
> > #endif
> >     if (name == HX_SOCKOPT_IDLETIMEOUT)
> >     {
> >+        HX_ASSERT(m_pScheduler);
> >         if (m_pScheduler == NULL)
> >         {
> >             return HXR_FAIL;
> >@@ -1759,12 +1763,17 @@
> >         }
> >         return HXR_OK;
> >     }
> >-    if (name == HX_SOCKOPT_BUFFER_TYPE)
> >+    else if (name == HX_SOCKOPT_BUFFER_TYPE)
> >     {
> >         m_bufType = (HXSockBufType)val;
> >         return HXR_OK;
> >     }
> >-    if (name == HX_SOCKOPT_APP_SNDBUF)
> >+    else if (name == HX_SOCKOPT_RCVBUF_FLAG)
> >+    {
> >+        m_rcvBufFlag = (HXSockRcvBufFlag)val;
> >+        return HXR_OK;
> >+    }
> >+    else if (name == HX_SOCKOPT_APP_SNDBUF)
> >     {
> >         if (m_pSendBuffer)
> >         {
> >@@ -1773,6 +1782,7 @@
> >         return HXR_OK;
> >     }
> >
> >+
> >     if (hx_setsockopt(&m_sock, name, val) != 0)
> >     {
> >         return ErrorToStatus(hx_lastsockerr());
> >@@ -2003,6 +2013,7 @@
> >     return HXR_UNEXPECTED;
> > }
> >
> >+
> > HX_RESULT
> > CHXSocket::GetNativeAddr(IHXSockAddr* pAddr, sockaddr_in6* psa6,
> >                         sockaddr** ppsa, size_t* psalen)
> >@@ -2025,6 +2036,48 @@
> > }
> >
> > HX_RESULT
> >+CHXSocket::SetReadBufferSize(IHXBuffer** ppBuf /*modified*/, UINT32 
> >cbRead)
> >+{
> >+    HX_ASSERT(ppBuf && *ppBuf);
> >+    HX_ASSERT(cbRead != 0);
> >+
> >+    HX_RESULT hxr = HXR_OK;
> >+
> >+    //XXXLCM If we get rid of the following line and 'copy' is 
> >specified we can allocate
> >+    //       one temp buffer into which we read and avoid some extra 
> >allocations.
> >+    if (cbRead != (*ppBuf)->GetSize())
> >+    {
> >+        HX_ASSERT(cbRead < (*ppBuf)->GetSize());
> >+        if (HX_SOCK_RCVBUF_SIZE_COPY == m_rcvBufFlag)
> >+        {
> >+            // allocate a new buffer so buffer does not waste unused 
> >memory space
> >+            IHXBuffer* pResizedBuf = 0;
> >+            hxr = CreateReadBuffer(&pResizedBuf);
> >+            if (HXR_OK == hxr)
> >+            {
> >+                hxr = pResizedBuf->Set((*ppBuf)->GetBuffer(), cbRead);
> >+                if (HXR_OK == hxr)
> >+                {
> >+                    HX_RELEASE(*ppBuf);
> >+                    *ppBuf = pResizedBuf;
> >+                    (*ppBuf)->AddRef();
> >+                }
> >+                HX_RELEASE(pResizedBuf);
> >+            }
> >+        }
> >+        else
> >+        {
> >+            HX_ASSERT(HX_SOCK_RCVBUF_SIZE_DEFAULT == m_rcvBufFlag);
> >+            // just re-specify the size and avoid a copy
> >+            hxr = (*ppBuf)->SetSize(cbRead);
> >+        }
> >+    }
> >+
> >+    return hxr;
> >+}
> >+
> >+
> >+HX_RESULT
> > CHXSocket::CreateReadBuffer(IHXBuffer** ppBuf)
> > {
> >     HX_RESULT hxr = HXR_OK;
> >@@ -2116,7 +2169,7 @@
> >         n = hx_readfrom(&m_sock, (*ppBuf)->GetBuffer(), m_mss, psa, 
> >salen, bPeek);
> >         if (n > 0)
> >         {
> >-            (*ppBuf)->SetSize(n);
> >+            hxr = SetReadBufferSize(ppBuf, n);
> >         }
> >         else if (n == 0)
> >         {
> >@@ -2247,7 +2300,11 @@
> >         }
> >         else if (vec[n].get_len() < ppBufVec[n]->GetSize())
> >         {
> >-            ppBufVec[n]->SetSize(vec[n].get_len());
> >+            hxr = SetReadBufferSize(&ppBufVec[n], vec[n].get_len());
> >+            if (FAILED(hxr))
> >+            {
> >+                return hxr;
> >+            }
> >         }
> >     }
> >     return HXR_OK;
> >@@ -2767,7 +2824,7 @@
> >     Close();
> > }
> >
> >-void
> >+HX_RESULT
> > CHXNetServices::Init(IUnknown* punkContext)
> > {
> >     m_punkContext = punkContext;
> >@@ -2775,10 +2832,12 @@
> >
> >     //XXXLCM this loads then unloads the winsock dll (undesireable)
> >     HXNetDrvLoader loader;
> >-    if(HXR_OK == loader.EnsureLoaded())
> >+    HX_RESULT hr = loader.EnsureLoaded();
> >+    if (HXR_OK == hr)
> >     {
> >         m_bIN6 = hx_netdrv_familyavail(HX_SOCK_FAMILY_IN6);
> >     }
> >+    return hr;
> > }
> >
> > void
> >Index: platform/win/hxsocketselector.cpp
> >===================================================================
> >RCS file: /cvsroot/common/netio/platform/win/hxsocketselector.cpp,v
> >retrieving revision 1.6
> >diff -u -w -r1.6 hxsocketselector.cpp
> >--- platform/win/hxsocketselector.cpp   30 Jul 2004 22:57:10 
> >-0000      1.6
> >+++ platform/win/hxsocketselector.cpp   5 Aug 2004 01:09:28 -0000
> >@@ -229,12 +229,6 @@
> >     wsaMask |= TranlateMaskValue(eventMask, HX_SOCK_EVENT_WRITE,      
> >FD_WRITE);
> >     wsaMask |= TranlateMaskValue(eventMask, HX_SOCK_EVENT_CLOSE,      
> >FD_CLOSE);
> >
> >-    if(!m_wsaEventSemantics)
> >-    {
> >-        // we only will report HX_SOCK_EVENT_READ and 
> >HX_SOCK_EVENT_WRITE as on UNIX
> >-        wsaMask &= ~FD_CONNECT;
> >-    }
> >-
> >     // register to receive async socket event notifications
> >     int res = WSAAsyncSelect(fd, m_pMsgSink->GetSinkHandle(), 
> >HXMSG_SOCKETSELECT, wsaMask);
> >     if( SOCKET_ERROR != res )
> >@@ -412,7 +406,7 @@
> >
> > }
> >
> >-UINT32 HXSocketSelector::TranslateWSAAsyncSelectEvent(UINT16 wsaEvent)
> >+UINT32 TranslateWSAAsyncSelectEvent(bool wsaEventSemantics, UINT16 
> >wsaEvent, UINT16 err)
> > {
> >     UINT32 hxEvent = HX_SOCK_EVENT_NONE;
> >     switch (wsaEvent)
> >@@ -446,11 +440,15 @@
> >         // applications you do not need to handle this; you just wait
> >         // for the write event.
> >         //
> >-        HX_ASSERT(m_wsaEventSemantics);
> >-        if (m_wsaEventSemantics)
> >+        if (wsaEventSemantics)
> >         {
> >             hxEvent = HX_SOCK_EVENT_CONNECT;
> >         }
> >+        else if(err != 0)
> >+        {
> >+            // pass write event along with error code
> >+            hxEvent = HX_SOCK_EVENT_WRITE;
> >+        }
> >        break;
> >
> >     case FD_CLOSE:
> >@@ -458,7 +456,7 @@
> >         // Indicates that stream socket has transitioned to 
> >close-pending
> >         // state (either gracefully or abortively) from connected state
> >         //
> >-        if(m_wsaEventSemantics)
> >+        if(wsaEventSemantics)
> >         {
> >             hxEvent = HX_SOCK_EVENT_CLOSE;
> >         }
> >@@ -478,7 +476,7 @@
> >         //
> >         // Helix synthesizes HX_SOCK_EVENT_ACCEPT based on 
> >HX_SOCK_EVENT_READ
> >         //
> >-        if(m_wsaEventSemantics)
> >+        if(wsaEventSemantics)
> >         {
> >             hxEvent = HX_SOCK_EVENT_ACCEPT;
> >         }
> >@@ -525,13 +523,16 @@
> >
> >     if(pHandler)
> >     {
> >-        UINT32 hxEvent = TranslateWSAAsyncSelectEvent(event);
> >+        UINT32 hxEvent = 
> >TranslateWSAAsyncSelectEvent(m_wsaEventSemantics, event, err);
> >         HX_RESULT hxResult = TranslateWSAAsyncSelectError(err);
> >
> >         DPRINTF(D_SOCKETSELECT, ("HXSocketSelector::OnAsyncSelect(): 
> >%s:%s translated as %s(= %u) for handler [%p]\n",
> >             GetWSAEventString(event), GetWSAErrorString(err), 
> >GetSockEventString(hxEvent), hxEvent, pHandler));
> >
> >+        if (HX_SOCK_EVENT_NONE != hxEvent)
> >+        {
> >         pHandler->OnSelectEvent(hxEvent, hxResult);
> >+        }
> >     }
> >     else
> >     {
> >Index: platform/win/hxwinsocklib.cpp
> >===================================================================
> >RCS file: /cvsroot/common/netio/platform/win/hxwinsocklib.cpp,v
> >retrieving revision 1.6
> >diff -u -w -r1.6 hxwinsocklib.cpp
> >--- platform/win/hxwinsocklib.cpp       27 Jul 2004 01:22:10 
> >-0000      1.6
> >+++ platform/win/hxwinsocklib.cpp       5 Aug 2004 01:09:28 -0000
> >@@ -44,7 +44,7 @@
> >
> > #define D_WINSOCK D_INFO //XXXLCM
> >
> >-
> >+#include "hxheap.h"
> > #ifdef _DEBUG
> > #undef HX_THIS_FILE
> > static const char HX_THIS_FILE[] = __FILE__;
> >Index: pub/hxsockutil.h
> >===================================================================
> >RCS file: /cvsroot/common/netio/pub/hxsockutil.h,v
> >retrieving revision 1.9
> >diff -u -w -r1.9 hxsockutil.h
> >--- pub/hxsockutil.h    30 Jul 2004 19:58:45 -0000      1.9
> >+++ pub/hxsockutil.h    5 Aug 2004 01:09:28 -0000
> >@@ -12,7 +12,9 @@
> >
> > struct HXSockUtil // namespace
> > {
> >-    static HX_RESULT SetAddr(IHXSockAddr* pAddr /*modified*/, const 
> >char* pAddrString, UINT16 port);
> >+    static HX_RESULT SetAddr(IHXSockAddr* pAddr /*modified*/,
> >+                             const char* pAddrString,
> >+                             UINT16 port = 0);
> >
> >     static HX_RESULT SetAddr(IHXSockAddr* pAddr /*modified*/,
> >                                     short family,
> >Index: pub/platform/posix/sockimp.h
> >===================================================================
> >RCS file: /cvsroot/common/netio/pub/platform/posix/sockimp.h,v
> >retrieving revision 1.23
> >diff -u -w -r1.23 sockimp.h
> >--- pub/platform/posix/sockimp.h        30 Jul 2004 00:32:32 
> >-0000      1.23
> >+++ pub/platform/posix/sockimp.h        5 Aug 2004 01:09:28 -0000
> >@@ -302,6 +302,7 @@
> >                             sockaddr** ppsa, size_t* psalen);
> >     HX_RESULT ErrorToStatus(int err);
> >     HX_RESULT CreateReadBuffer(IHXBuffer** ppBuf);
> >+    HX_RESULT SetReadBufferSize(IHXBuffer** ppBuf /*modified*/, 
> >UINT32 cbRead);
> >     HX_RESULT DoRead(IHXBuffer** ppBuf, IHXSockAddr** ppAddr = NULL,
> >                             BOOL bPeek = FALSE);
> >     HX_RESULT DoWrite(IHXBuffer* pBuf,
> >@@ -336,6 +337,7 @@
> >     HXSockType                  m_type;
> >     HXSockProtocol              m_proto;
> >     HXSockBufType               m_bufType;
> >+    HXSockRcvBufFlag            m_rcvBufFlag;
> >     HX_SOCK                     m_sock;
> > #if defined(MISSING_DUALSOCKET)
> >     CHXSocket*                  m_pSock4;
> >@@ -441,7 +443,7 @@
> >     virtual ~CHXNetServices(void);
> >
> > public:
> >-    virtual void Init(IUnknown* punkContext);
> >+    virtual HX_RESULT Init(IUnknown* punkContext);
> >     virtual void Close(void);
> >
> >     // This is used by CHXSocket::Accept().
> >Index: pub/platform/win/hxsocketselector.h
> >===================================================================
> >RCS file: /cvsroot/common/netio/pub/platform/win/hxsocketselector.h,v
> >retrieving revision 1.5
> >diff -u -w -r1.5 hxsocketselector.h
> >--- pub/platform/win/hxsocketselector.h 30 Jul 2004 22:57:30 
> >-0000      1.5
> >+++ pub/platform/win/hxsocketselector.h 5 Aug 2004 01:09:28 -0000
> >@@ -81,7 +81,6 @@
> >     HXSocketSelector();
> >     virtual ~HXSocketSelector();
> >     static HX_RESULT CreateSelector(HXSocketSelector*& pSelector);
> >-    UINT32 TranslateWSAAsyncSelectEvent(UINT16 wsaEvent);
> >
> >     // HXRefCounted
> >     void FinalRelease();
> >
> >
> >At 11:44 AM 8/4/2004, Liam Murray wrote:
> >
> >>Summary:
> >>
> >>Fixes case where connect failure is not passed on via 
> >>HX_SOCK_EVENT_CONNECT. I ran into this because there was a 
> >>byte-ordering issue with a port that occurred when a resolved address 
> >>was translated to an IHXSockAddr in the client resolver.
> >>
> >>Details:
> >>
> >>1) Byte-ordering fix for HXSockUtil::SetAddr().
> >>
> >>2) Fix in sockimp to better handle connect failure. When a connect 
> >>fails a write event is passed to OnEvent(). If an error is associated 
> >>with the event the connect event is forwarded to IHXSocketResponse 
> >>with the error code and no write event is subsequently sent. The 
> >>first write event is only sent if the connection is successful. (This 
> >>is how WSA event semantics works. Please verify this makes sense for 
> >>us to follow.) Also note that a close event should not be sent unless 
> >>a connection was successfully established for a socket. (Again, this 
> >>corresponds with WSA semantics.)
> >>
> >>3) When the windows client gets an FD_CONNECT along with a failure 
> >>code from WSAAsyncSelect, it is passed on as a write event to 
> >>CHXSocket::OnEvent(). Otherwise the connect is passed on upon 
> >>receiving the first write event.
> >>
> >>4) Removed
> >>
> >>HX_ASSERT(m_pScheduler != NULL);
> >>
> >>from constructors and put assert where scheduler is actually used in 
> >>call to SetSockOpt(). This prevents asserts in unit tests that use a 
> >>mini context which doesn't expose the scheduler, but still allows us 
> >>to assert when the scheduler is actually used.
> >>
> >>5) Changed CHXSocket::Init() so it returns an HX_RESULT. This is 
> >>particularly helpful for the client derivations because they 
> >>initialize/allocate resources during initialization.
> >>
> >>Branch: HEAD
> >>
> >>Builds, platforms verified: Windows client
> >>
> >>Liam
> >>
> >>
> >>
> >>
> >>_______________________________________________
> >>Common-dev mailing list
> >>Common-dev at lists.helixcommunity.org
> >>http://lists.helixcommunity.org/mailman/listinfo/common-dev
> >
> >
> >
> >_______________________________________________
> >Common-dev mailing list
> >Common-dev at lists.helixcommunity.org
> >http://lists.helixcommunity.org/mailman/listinfo/common-dev
> >
> 
> 
> _______________________________________________
> Client-dev mailing list
> Client-dev at lists.helixcommunity.org
> http://lists.helixcommunity.org/mailman/listinfo/client-dev
> 



More information about the Common-dev mailing list
 

Site Map   |   Terms of Use   |   Privacy Policy   |   Contact Us

Copyright © 1995-2007 RealNetworks, Inc. All rights reserved. RealNetworks and Helix are trademarks of RealNetworks.
All other trademarks or registered trademarks are the property of their respective holders.