sdkcreationmw/sdkruntimes/wsock/src/WinsockServProvider.cpp
changeset 0 b26acd06ea60
child 1 ac50fd48361b
equal deleted inserted replaced
-1:000000000000 0:b26acd06ea60
       
     1 /*
       
     2 * Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #define TRACE_PREFIX "WSOCK: ServProvider: "
       
    20 #include <es_mbuf.h>
       
    21 #include "wsock.h"
       
    22 #include "WinsockProtocol.h"
       
    23 #include "WinsockProtocolFamily.h"
       
    24 #include "WinsockServProvider.h"
       
    25 #include "WinsockUtils.h"
       
    26 
       
    27 #define KMaxInetAddrBufSize 64
       
    28 
       
    29 // CWinsockServProvider::CWriteData
       
    30 class CWinsockServProvider::CWriteData : public CBase
       
    31 {
       
    32 public:
       
    33     TDblQueLink iLink;
       
    34     TSockAddr* iAddr;
       
    35     HBufC8* iData;
       
    36 public:
       
    37     static CWriteData* New(const TDesC8& aData, TSockAddr* aAddr);
       
    38     ~CWriteData();
       
    39 };
       
    40 
       
    41 // CWinsockServProvider::CWriteRequest
       
    42 class CWinsockServProvider::CWriteRequest : public CActive
       
    43 {
       
    44 private:
       
    45     CWinsockServProvider* iProvider;
       
    46     RTimer iTimer;
       
    47     TBool iTimerCreated;
       
    48     TBool iTimerActive;
       
    49 public:
       
    50     CWriteRequest(CWinsockServProvider* aProvider);
       
    51     ~CWriteRequest();
       
    52     void Submit(TInt aDelay = 0);
       
    53 
       
    54     // CActive
       
    55     virtual void DoCancel();
       
    56     virtual void RunL();
       
    57 };
       
    58 
       
    59 // CWinsockServProvider::CSelectRequest
       
    60 class CWinsockServProvider::CSelectRequest : public CActive,
       
    61                                              public MSelectRequest
       
    62 {
       
    63 private:
       
    64     CWinsockServProvider* iProvider;
       
    65     RThread iServerThread;
       
    66     TInt iSelectMask;
       
    67 public:
       
    68     static CSelectRequest* NewLC(CWinsockServProvider* aProvider);
       
    69     virtual ~CSelectRequest();
       
    70     void SubmitL();
       
    71 
       
    72     // CActive
       
    73     virtual void DoCancel();
       
    74     virtual void RunL();
       
    75 
       
    76     // MSelectRequest
       
    77     virtual TUint Socket();
       
    78     virtual TInt SelectMask();
       
    79     virtual void SelectComplete(TInt aSelectMask);
       
    80 
       
    81 private:
       
    82     CSelectRequest(CWinsockServProvider* aProvider);
       
    83     void ConstructL();
       
    84 };
       
    85 
       
    86 // CWinsockServProvider::CNewDataNotifier
       
    87 class CWinsockServProvider::CNewDataNotifier : public CActive
       
    88 {
       
    89 private:
       
    90     CWinsockServProvider* iProvider;
       
    91 public:
       
    92     CNewDataNotifier(CWinsockServProvider* aProvider);
       
    93     void Submit();
       
    94 
       
    95     // CActive
       
    96     virtual void DoCancel();
       
    97     virtual void RunL();
       
    98 };
       
    99 
       
   100 // CWinsockServProvider
       
   101 #define SUPER CServProviderBase
       
   102 CWinsockServProvider* CWinsockServProvider::NewL(CWinsockProtocol* aProtocol)
       
   103 {
       
   104     return new(ELeave)CWinsockServProvider(aProtocol);
       
   105 }
       
   106 
       
   107 CWinsockServProvider* CWinsockServProvider::FromSocket(CWinsockProtocol* aPro,
       
   108                                                        TInt aSocket,
       
   109                                                        TInt aFamily)
       
   110 {
       
   111     ASSERT(aFamily != 0);
       
   112     ASSERT(aSocket != INVALID_SOCKET);
       
   113     CWinsockServProvider* self = new CWinsockServProvider(aPro);
       
   114     if (self) {
       
   115         self->iWinSocket = aSocket;
       
   116         self->iFamily = aFamily;
       
   117         self->iFlags |= (EFlagConnect | EFlagNeedSelect);
       
   118         // Select will be called from SetNotify. Otherwise, under some rare
       
   119         // circumstances select may complete and NewDataCheck is invoked
       
   120         // before SetNotify has been invoked and therefore iSocket is still
       
   121         // NULL.
       
   122     }
       
   123     return self;
       
   124 }
       
   125 
       
   126 CWinsockServProvider::CWinsockServProvider(CWinsockProtocol* aProtocol) :
       
   127 iProtocol(aProtocol),
       
   128 iWinSocket(INVALID_SOCKET),
       
   129 iWriteQ(_FOFF(CWriteData,iLink)),
       
   130 iTcpSendWinSize(8192),
       
   131 iTcpRecvWinSize(8192),
       
   132 iTcpMaxSegSize(1460),
       
   133 iUdpRecvBuf(8192)
       
   134 {
       
   135     WTRACE("created");
       
   136 }
       
   137 
       
   138 CWinsockServProvider::~CWinsockServProvider()
       
   139 {
       
   140     iProtocol->SetReadPending(this, EFalse);
       
   141     if (iWrite)
       
   142     {
       
   143         iWrite->Cancel();
       
   144         delete iWrite;
       
   145     }
       
   146     if (iNewData)
       
   147     {
       
   148         iNewData->Cancel();
       
   149         delete iNewData;
       
   150     }
       
   151     if (iSelect)
       
   152     {
       
   153         CWinsockSelectThread::Static()->Cancel(iSelect);
       
   154         iSelect->Cancel();
       
   155     }
       
   156     if (iAdapterInfo)
       
   157     {
       
   158         User::Free(iAdapterInfo);
       
   159     }
       
   160     if (iWinSocket != INVALID_SOCKET)
       
   161     {
       
   162         closesocket(iWinSocket);
       
   163     }
       
   164 #ifdef V1_5_PRT_INTERFACE
       
   165     if (iDataBuf)
       
   166     {
       
   167         delete iDataBuf;
       
   168     }
       
   169 #endif
       
   170     WTRACE("destroyed");
       
   171 }
       
   172 
       
   173 // Returns the socket, or creates one using default address family.
       
   174 TInt CWinsockServProvider::Socket() const
       
   175 {
       
   176     CWinsockServProvider* This = (CWinsockServProvider*)this;
       
   177     return This->Socket(Family());
       
   178 }
       
   179 
       
   180 // Returns the socket, creating one if necessary. Note that the requested
       
   181 // address family may not match the protocol family given to us in the
       
   182 // constructor. That's because some Symbian code (such as HTTP protocol
       
   183 // framework) may, for example, create an IPv4 socket and then connect
       
   184 // it to an IPv6 address. Also note that once we have created the Windows
       
   185 // socket we can't change its address family.
       
   186 TInt CWinsockServProvider::Socket(TUint aFamily)
       
   187 {
       
   188     if (iWinSocket == INVALID_SOCKET)
       
   189     {
       
   190         if (!aFamily) aFamily = Family();
       
   191         TInt af = (aFamily == KAfInet6) ? AF_INET6 : AF_INET;
       
   192         TInt type = iProtocol->ProtocolDesc()->iWinSockType;
       
   193         TInt protocol = iProtocol->ProtocolDesc()->iWinProtocol;
       
   194         iWinSocket = socket(af, type, protocol);
       
   195         if (iWinSocket == INVALID_SOCKET)
       
   196         {
       
   197             WTRACE4("socket(%d,%d,%d) failed, err %d",af, type, protocol,
       
   198             WSAGetLastError());
       
   199         }
       
   200         else
       
   201         {
       
   202             // Remember the actual address family
       
   203             iFamily = aFamily;
       
   204             WTRACE2("created %s %S socket", (af == AF_INET6) ?
       
   205                 _S("IPv6") : _S("IPv4"), &iProtocol->ProtocolDesc()->iName);
       
   206 
       
   207             // Connection-less sockets immediately start accepting
       
   208             // incoming datagrams
       
   209             if (iProtocol->IsDatagramProtocol())
       
   210             {
       
   211                 Select();
       
   212             }
       
   213         }
       
   214     }
       
   215     else
       
   216     {
       
   217         // This ASSERT means that we have already created the Windows socket
       
   218         // and then we were asked to connect or bind it to the address with
       
   219         // a different address family. That's bad.
       
   220         ASSERT(!aFamily || aFamily == iFamily);
       
   221     }
       
   222     return iWinSocket;
       
   223 }
       
   224 
       
   225 // Returns address family of this socket in Symbian format,
       
   226 // i.e. KAfInet or KAfInet6
       
   227 TUint CWinsockServProvider::Family() const
       
   228 {
       
   229     if (iFamily)
       
   230     {
       
   231         // The socket has already been created
       
   232         return iFamily;
       
   233     }
       
   234     else if (iRemAddr.Family())
       
   235     {
       
   236         // Assume the same address family as in remote address. That makes
       
   237         // URLs like http://[fe80::a00:20ff:fef9:bf8]/ work in the browser.
       
   238         // In that case we get the following sequence of calls:
       
   239         //    SetRemName -> AutoBind -> ActiveOpen
       
   240         // This allows us to create the socket of the right type in AutoBind.
       
   241         return iRemAddr.Family();
       
   242     }
       
   243     else
       
   244     {
       
   245         // With no additional information, assume the address family from
       
   246         // the protocol object.
       
   247         return iProtocol->ProtocolDesc()->iAddrFamily;
       
   248     }
       
   249 }
       
   250 
       
   251 // CServProviderBase
       
   252 void CWinsockServProvider::Start()
       
   253 {
       
   254     WTRACE("Start()");
       
   255 }
       
   256 
       
   257 void CWinsockServProvider::SetNotify(MSocketNotify* aSocket)
       
   258 {
       
   259     WTRACE1("SetNotify(%08X)",aSocket);
       
   260     SUPER::SetNotify(aSocket);
       
   261     if (iFlags & EFlagNeedSelect)
       
   262     {
       
   263         iFlags &= ~EFlagNeedSelect;
       
   264         Select();
       
   265     }
       
   266 }
       
   267 
       
   268 typedef int (WSAAPI *GetSockNameProc)(
       
   269     SOCKET s,
       
   270     struct sockaddr* name,
       
   271     int* namelen
       
   272 );
       
   273 
       
   274 static void GetSockName(SOCKET sock, TSockAddr& aAddr,
       
   275                         GetSockNameProc aFunction,
       
   276                         const TText* DEBUG_ONLY(aFunctionName))
       
   277 {
       
   278     WSockAddr sa;
       
   279     int namelen = SOCKADDR_SIZE;
       
   280     int err = aFunction(sock, &sa.Address, &namelen);
       
   281     if (!err)
       
   282     {
       
   283         WinsockUtils::ToInetAddr(&aAddr,&sa);
       
   284     }
       
   285     else
       
   286     {
       
   287         TRACE2("%s failed, error %d\n",aFunctionName,err);
       
   288     }
       
   289 }
       
   290 
       
   291 void CWinsockServProvider::LocalName(TSockAddr& aAddr) const
       
   292 {
       
   293     if (Socket() == INVALID_SOCKET)
       
   294     {
       
   295         WTRACE("LocalName() - no socket");
       
   296     }
       
   297     else
       
   298     {
       
   299         GetSockName(iWinSocket,aAddr,getsockname,_S("getsockname"));
       
   300     }
       
   301 }
       
   302 
       
   303 // Wrapper around WinsockUtils::ToSockAddr which attempts to convert
       
   304 // the address into the form compatible with the address family of
       
   305 // this socket.
       
   306 int CWinsockServProvider::ToSockAddr(union _WSockAddr* aToAddr,
       
   307                                      const TSockAddr* aFromAddr)
       
   308 {
       
   309     if (Family() == KAfInet6 && aFromAddr->Family() == KAfInet)
       
   310     {
       
   311         // Convert IPv4 address to IPv4-mapped IPv6 address.
       
   312         TInetAddr ipv6(*aFromAddr);
       
   313         ipv6.ConvertToV4Mapped();
       
   314         ASSERT(ipv6.Family() == KAfInet6);
       
   315         return WinsockUtils::ToSockAddr(aToAddr, &ipv6);
       
   316     }
       
   317 
       
   318     if (Family() == KAfInet && aFromAddr->Family() == KAfInet6)
       
   319     {
       
   320         TInetAddr& ipv6 = TInetAddr::Cast(aFromAddr);
       
   321         if (ipv6.IsV4Mapped() || ipv6.IsV4Compat())
       
   322         {
       
   323             // Convert IPv4 compatible IPv6 address to IPv4
       
   324             TInetAddr ipv4(ipv6);
       
   325             ipv4.ConvertToV4();
       
   326             return WinsockUtils::ToSockAddr(aToAddr, &ipv4);
       
   327         }
       
   328     }
       
   329 
       
   330     // Do the default conversion
       
   331     return WinsockUtils::ToSockAddr(aToAddr, aFromAddr);
       
   332 }
       
   333 
       
   334 TInt CWinsockServProvider::SetLocalName(TSockAddr& aAddr)
       
   335 {
       
   336 #ifdef _REALLY_DEBUG
       
   337     TBuf<KMaxInetAddrBufSize> buf;
       
   338     TInetAddr::Cast(aAddr).OutputWithScope(buf);
       
   339     if (buf.Length() == 0) buf.Append('*');
       
   340     WTRACE2("SetLocalName(%S,%d)",&buf,aAddr.Port());
       
   341 #endif // _REALLY_DEBUG
       
   342 
       
   343     if (Socket(aAddr.Family()) == INVALID_SOCKET)
       
   344     {
       
   345         WTRACE("SetLocalName - no socket");
       
   346         iFlags |= EFlagError;
       
   347         return KErrNotSupported;
       
   348     }
       
   349 
       
   350     // Bind new socket to the specified address
       
   351     WSockAddr sa;
       
   352     int len = ToSockAddr(&sa, &aAddr);
       
   353     int err = bind(iWinSocket, &sa.Address, len);
       
   354     if (err)
       
   355     {
       
   356         WTRACE1("bind failed, err %d",WSAGetLastError());
       
   357         return KErrArgument;
       
   358     }
       
   359     else
       
   360     {
       
   361 #ifdef _REALLY_DEBUG
       
   362         TInetAddr localAddr;
       
   363         GetSockName(iWinSocket,localAddr,getsockname,_S("getsockname"));
       
   364         localAddr.OutputWithScope(buf);
       
   365         WTRACE2("bound to %S port %d",&buf,localAddr.Port());
       
   366 #endif // _REALLY_DEBUG
       
   367 
       
   368         return KErrNone;
       
   369     }
       
   370 }
       
   371 
       
   372 void CWinsockServProvider::RemName(TSockAddr& aAddr) const
       
   373 {
       
   374     if (iFlags & EFlagConnect)
       
   375     {
       
   376         GetSockName(iWinSocket,aAddr,getpeername,_S("getpeername"));
       
   377     }
       
   378     else
       
   379     {
       
   380         aAddr = iRemAddr;
       
   381     }
       
   382 }
       
   383 
       
   384 TInt CWinsockServProvider::SetRemName(TSockAddr& aAddr)
       
   385 {
       
   386     iRemAddr = TInetAddr::Cast(aAddr);
       
   387 
       
   388 #ifdef _REALLY_DEBUG
       
   389     TBuf<KMaxInetAddrBufSize> buf;
       
   390     iRemAddr.OutputWithScope(buf);
       
   391     WTRACE2("SetRemName(%S,%d)",&buf,iRemAddr.Port());
       
   392 #endif // _REALLY_DEBUG
       
   393 
       
   394     if (iProtocol->IsDatagramProtocol())
       
   395     {
       
   396         // application called connect() on datagram-socket. Propagate call to
       
   397         // Winsock. (In case of stream-socket, connect() appears to happen
       
   398         // ActiveOpen()-call, but that is not called in case of udp-socket.)
       
   399         Connect();
       
   400     }
       
   401     return KErrNone;
       
   402 }
       
   403 
       
   404 void CWinsockServProvider::Ioctl(TUint DEBUG_ONLY(aLevel),
       
   405                                  TUint DEBUG_ONLY(aName),
       
   406                                  TDes8* /*anOption*/)
       
   407 {
       
   408     WTRACE2("Ioctl(%d,%08X)",aLevel,aName);
       
   409 }
       
   410 
       
   411 void CWinsockServProvider::CancelIoctl(TUint DEBUG_ONLY(aLevel),
       
   412                                        TUint DEBUG_ONLY(aName))
       
   413 {
       
   414     WTRACE2("CancelIoctl(%d,%08X)",aLevel,aName);
       
   415 }
       
   416 
       
   417 TInt CWinsockServProvider::SetOption(TUint aLevel, TUint aName,
       
   418                                      const TDesC8& aOption)
       
   419 {
       
   420     switch (aLevel)
       
   421     {
       
   422     case KSOLSocket:
       
   423         WTRACE1("SetOption(KSOLSocket,%08X)",aName);
       
   424         return KErrNone;
       
   425 
       
   426     case KSolInetIfCtrl:
       
   427         switch (aName)
       
   428         {
       
   429         case KSoInetEnumInterfaces:
       
   430             WTRACE("SetOption(KSoInetEnumInterfaces)");
       
   431             if (iAdapterInfo)
       
   432             {
       
   433                 User::Free(iAdapterInfo);
       
   434                 iAdapterInfo = NULL;
       
   435             }
       
   436             iAdapterInfo = iProtocol->GetAdapterInfo();
       
   437             iNextAdapter = iAdapterInfo;
       
   438             iLastAdapter = NULL;
       
   439             return KErrNone;
       
   440         default:
       
   441             WTRACE1("SetOption(KSolInetIfCtrl,%08X)",aName);
       
   442             break;
       
   443         }
       
   444 
       
   445     case KSOLProvider:
       
   446         switch (aName)
       
   447         {
       
   448         case KSoConnectionInfo:
       
   449             iConnectionInfo = *((TSoIfConnectionInfo*)aOption.Ptr());
       
   450             WTRACE2("SetOption(KSoConnectionInfo) IAP %d, network %d",
       
   451                    iConnectionInfo.iIAPId, iConnectionInfo.iNetworkId);
       
   452             return KErrNone;
       
   453         default:
       
   454             WTRACE1("SetOption(KSOLProvider,%08X) - UNSUPPORTED",aName);
       
   455             break;
       
   456         }
       
   457         break;
       
   458 
       
   459     case KSolInetIp:
       
   460         switch (aName)
       
   461         {
       
   462         case KSoIpTTL:
       
   463             WTRACE1("SetOption(KSoIpTTL) %d",*((int*)aOption.Ptr()));
       
   464             if (!setsockopt(Socket(), IPPROTO_IP, IP_TTL,
       
   465                 (char*)aOption.Ptr(), aOption.Length()))
       
   466             {
       
   467                 return KErrNone;
       
   468             }
       
   469             WTRACE1("setsockopt(IP_TTL) error %d",WSAGetLastError());
       
   470             break;
       
   471         case KSoReuseAddr:
       
   472             WTRACE1("SetOption(KSoReuseAddr) %d",*((int*)aOption.Ptr()));
       
   473             if (!setsockopt(Socket(), SOL_SOCKET, SO_REUSEADDR,
       
   474                 (char*)aOption.Ptr(), aOption.Length()))
       
   475             {
       
   476                 return KErrNone;
       
   477             }
       
   478             WTRACE1("setsockopt(SO_REUSEADDR) error %d",WSAGetLastError());
       
   479             break;
       
   480         default:
       
   481             WTRACE1("SetOption(KSolInetIp,%08X)",aName);
       
   482             break;
       
   483         }
       
   484         break;
       
   485 
       
   486     case KSolInetTcp:
       
   487         if (iProtocol->ProtocolDesc()->iProtocol == KProtocolInetTcp) {
       
   488             switch (aName)
       
   489             {
       
   490             case KSoTcpSendWinSize:
       
   491                 WTRACE("SetOption(KSoTcpSendWinSize)");
       
   492                 if (iFlags & EFlagConnect) return KErrLocked;
       
   493                 if (aOption.Length() != sizeof(TInt)) return KErrArgument;
       
   494                 iTcpSendWinSize = *((TInt*)aOption.Ptr());
       
   495                 return KErrNone;
       
   496             case KSoTcpRecvWinSize:
       
   497                 WTRACE("SetOption(KSoTcpSendWinSize)");
       
   498                 if (iFlags & EFlagConnect) return KErrLocked;
       
   499                 if (aOption.Length() != sizeof(TInt)) return KErrArgument;
       
   500                 iTcpRecvWinSize = *((TInt*)aOption.Ptr());
       
   501                 return KErrNone;
       
   502             case KSoTcpMaxSegSize:
       
   503                 WTRACE("SetOption(KSoTcpMaxSegSize)");
       
   504                 if (iFlags & EFlagConnect) return KErrLocked;
       
   505                 if (aOption.Length() != sizeof(TInt)) return KErrArgument;
       
   506                 iTcpMaxSegSize = *((TInt*)aOption.Ptr());
       
   507                 return KErrNone;
       
   508             case KSoTcpNoDelay:
       
   509                 WTRACE1("SetOption(KSoTcpNoDelay) %d",*((TInt*)aOption.Ptr()));
       
   510                 if (!setsockopt(Socket(), IPPROTO_TCP, TCP_NODELAY,
       
   511                     (char*)aOption.Ptr(),aOption.Length())) return KErrNone;
       
   512                 WTRACE1("setsockopt(TCP_NODELAY) error %d",WSAGetLastError());
       
   513                 break;
       
   514             case KSoTcpKeepAlive:
       
   515                 WTRACE1("SetOption(KSoTcpKeepAlive) %d",*((TInt*)aOption.Ptr()));
       
   516                 if (!setsockopt(Socket(), SOL_SOCKET, SO_KEEPALIVE,
       
   517                     (char*)aOption.Ptr(),aOption.Length())) return KErrNone;
       
   518                 WTRACE1("setsockopt(SO_KEEPALIVE) error %d",WSAGetLastError());
       
   519                 break;
       
   520             default:
       
   521                 WTRACE1("SetOption(KSolInetTcp,%08X) - UNSUPPORTED",aName);
       
   522                 break;
       
   523             }
       
   524         } else {
       
   525             WTRACE1("SetOption(KSolInetTcp,%08X) - not a TCP socket!",aName);
       
   526         }
       
   527         break;
       
   528 
       
   529     case KSolInetUdp:
       
   530         if (iProtocol->ProtocolDesc()->iProtocol == KProtocolInetUdp) {
       
   531             switch (aName)
       
   532             {
       
   533             case KSoUdpReceiveICMPError:
       
   534                 WTRACE("SetOption(KSoUdpReceiveICMPError)");
       
   535                 if (aOption.Length() != sizeof(TInt)) return KErrArgument;
       
   536                 iUdpReceiveICMPError = *((TInt*)aOption.Ptr());
       
   537                 return KErrNone;
       
   538             case KSoUdpRecvBuf:
       
   539                 WTRACE("SetOption(KSoUdpRecvBuf)");
       
   540                 if (aOption.Length() != sizeof(TInt)) return KErrArgument;
       
   541                 iUdpRecvBuf = *((TInt*)aOption.Ptr());
       
   542                 return KErrNone;
       
   543             case KSoUdpSynchronousSend:
       
   544                 WTRACE("SetOption(KSoUdpSynchronousSend)");
       
   545                 if (aOption.Length() != sizeof(TInt)) return KErrArgument;
       
   546                 iUdpSynchronousSend = *((TInt*)aOption.Ptr());
       
   547                 return KErrNone;
       
   548             default:
       
   549                 WTRACE1("SetOption(KSolInetUdp,%08X) - UNSUPPORTED",aName);
       
   550                 break;
       
   551             }
       
   552         } else {
       
   553             WTRACE1("SetOption(KSolInetUdp,%08X) - not a UDP socket!",aName);
       
   554         }
       
   555         break;
       
   556 
       
   557     default:
       
   558         WTRACE2("SetOption(%d,%08X) - UNSUPPORTED",aLevel,aName);
       
   559         break;
       
   560     }
       
   561     return KErrNotSupported;
       
   562 }
       
   563 
       
   564 TInt CWinsockServProvider::GetOption(TUint aLevel, TUint aName,
       
   565                                      TDes8& aOption) const
       
   566 {
       
   567     TInt len;
       
   568     switch (aLevel)
       
   569     {
       
   570     case KSOLSocket:
       
   571         switch (aName)
       
   572         {
       
   573         // This one used by SIP code:
       
   574         case KSOReadBytesPending:
       
   575             if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   576             aOption.SetLength(sizeof(TInt));
       
   577             if (!ioctlsocket(Socket(), FIONREAD, (u_long*)aOption.Ptr()))
       
   578             {
       
   579                 WTRACE1("GetOption(KSOReadBytesPending) %d",
       
   580                     *((TInt*)aOption.Ptr()));
       
   581                 return KErrNone;
       
   582             }
       
   583             WTRACE1("GetOption(KSOReadBytesPending) - ioctl(FIONREAD) err %d",
       
   584                 WSAGetLastError());
       
   585             break;
       
   586 
       
   587         case KSORecvBuf:
       
   588         case KSOSendBuf:
       
   589             WTRACE1("GetOption(KSOLSocket,%08X)",aName);
       
   590             if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   591             aOption.SetLength(sizeof(TInt));
       
   592             *((TInt*)aOption.Ptr()) = KSocketDefaultBufferSize;
       
   593             return KErrNone;
       
   594 
       
   595         default:
       
   596             WTRACE1("GetOption(KSOLSocket,%08X) - UNSUPPORTED",aName);
       
   597             break;
       
   598         }
       
   599         break;
       
   600 
       
   601     case KSolInetIfCtrl:
       
   602         switch (aName)
       
   603         {
       
   604         case KSoInetNextInterface:
       
   605             WTRACE("GetOption(KSoInetNextInterface)");
       
   606             iLastAdapter = iNextAdapter;
       
   607             if (iLastAdapter)
       
   608             {
       
   609                 iNextAdapter = iLastAdapter->Next;
       
   610 
       
   611                 // Copy interface information into the output buffer
       
   612                 TSoInetInterfaceInfo *opt;
       
   613                 aOption.SetLength(sizeof(*opt));
       
   614                 opt = (TSoInetInterfaceInfo*)aOption.Ptr();
       
   615                 opt->iName.Copy(TPtrC8(iLastAdapter->AdapterName));
       
   616                 const WinsockIpAddrString*adr = iLastAdapter->CurrentIpAddress;
       
   617                 if (!adr) adr = &iLastAdapter->IpAddressList;
       
   618                 TUint ip = inet_addr((char*)adr->IpAddress.String);
       
   619                 TUint mask = inet_addr((char*)adr->IpMask.String);
       
   620                 opt->iAddress.SetAddress(ntohl(ip));
       
   621                 opt->iNetMask.SetAddress(ntohl(mask));
       
   622                 opt->iState = EIfUp;
       
   623                 opt->iMtu = 1500;
       
   624                 opt->iSpeedMetric = 10000;
       
   625                 opt->iFeatures = 0;
       
   626                 return KErrNone;
       
   627             }
       
   628             else
       
   629             {
       
   630                 return KErrNotFound;
       
   631             }
       
   632         default:
       
   633             WTRACE1("GetOption(KSolInetIfCtrl,%08X)",aName);
       
   634             break;
       
   635         }
       
   636         break;
       
   637 
       
   638     case KSolInetIfQuery:
       
   639         switch (aName)
       
   640         {
       
   641         case KSoInetIfQueryByName:
       
   642             WTRACE("GetOption(KSoInetIfQueryByName)");
       
   643             if (!iAdapterInfo)
       
   644             {
       
   645                 iAdapterInfo = iProtocol->GetAdapterInfo();
       
   646             }
       
   647             if (iAdapterInfo)
       
   648             {
       
   649                 TSoInetIfQuery* query = (TSoInetIfQuery*)aOption.Ptr();
       
   650                 WinsockIpAdapterInfo* adapter = iAdapterInfo;
       
   651                 while (adapter)
       
   652                 {
       
   653                     TUint len = User::StringLength(adapter->AdapterName);
       
   654                     HBufC* buf = HBufC::New(len);
       
   655                     if (buf)
       
   656                     {
       
   657                         TPtr16 ptr(buf->Des());
       
   658                         ptr.Copy(TPtrC8(adapter->AdapterName));
       
   659                         if (ptr.Compare(query->iName) == 0)
       
   660                         {
       
   661                             query->iIndex = adapter->Index;
       
   662                             query->iZone[0] = adapter->Index;
       
   663                             query->iZone[1] = iConnectionInfo.iIAPId;
       
   664                             query->iZone[15] = iConnectionInfo.iNetworkId;
       
   665                             for (TInt i=2; i<15; i++) query->iZone[i] = 0;
       
   666                             query->iIsUp = ETrue;
       
   667                             delete buf;
       
   668                             return KErrNone;
       
   669                         }
       
   670                         delete buf;
       
   671                     }
       
   672                     adapter = adapter->Next;
       
   673                 }
       
   674             }
       
   675             return KErrNotFound;
       
   676         default:
       
   677             WTRACE1("GetOption(KSolInetIfQuery,%08X)",aName);
       
   678             break;
       
   679         }
       
   680         break;
       
   681 
       
   682     case KSolInetIp:
       
   683         switch (aName)
       
   684         {
       
   685         case KSoIpTTL:
       
   686             WTRACE("GetOption(KSoIpTTL)");
       
   687             if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   688             aOption.SetLength(len = sizeof(TInt));
       
   689             if (!getsockopt(Socket(), IPPROTO_IP, IP_TTL,
       
   690                 (char*)aOption.Ptr(), &len))
       
   691             {
       
   692                 aOption.SetLength(len);
       
   693                 return KErrNone;
       
   694             }
       
   695             WTRACE1("getsockopt(IP_TTL) error %d",WSAGetLastError());
       
   696             break;
       
   697         case KSoReuseAddr:
       
   698             WTRACE("GetOption(KSoReuseAddr)");
       
   699             if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   700             aOption.SetLength(len = sizeof(TInt));
       
   701             if (!getsockopt(Socket(), SOL_SOCKET, SO_REUSEADDR,
       
   702                 (char*)aOption.Ptr(), &len))
       
   703             {
       
   704                 return KErrNone;
       
   705             }
       
   706             WTRACE1("getsockopt(SO_REUSEADDR) error %d",WSAGetLastError());
       
   707             break;
       
   708         default:
       
   709             WTRACE1("SetOption(KSolInetIp,%08X)",aName);
       
   710             break;
       
   711         }
       
   712         break;
       
   713 
       
   714     case KSolInetTcp:
       
   715         if (iProtocol->ProtocolDesc()->iProtocol == KProtocolInetTcp) {
       
   716             switch (aName)
       
   717             {
       
   718             case KSoTcpSendWinSize:
       
   719                 WTRACE("GetOption(KSoTcpSendWinSize)");
       
   720                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   721                 aOption.SetLength(sizeof(TInt));
       
   722                 *((TInt*)aOption.Ptr()) = iTcpSendWinSize;
       
   723                 return KErrNone;
       
   724             case KSoTcpRecvWinSize:
       
   725                 WTRACE("GetOption(KSoTcpSendWinSize)");
       
   726                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   727                 aOption.SetLength(sizeof(TInt));
       
   728                 *((TInt*)aOption.Ptr()) = iTcpRecvWinSize;
       
   729                 return KErrNone;
       
   730             case KSoTcpMaxSegSize:
       
   731                 WTRACE("GetOption(KSoTcpMaxSegSize)");
       
   732                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   733                 aOption.SetLength(sizeof(TInt));
       
   734                 *((TInt*)aOption.Ptr()) = iTcpMaxSegSize;
       
   735                 return KErrNone;
       
   736             case KSoTcpNoDelay:
       
   737                 WTRACE("GetOption(KSoTcpNoDelay)");
       
   738                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   739                 aOption.SetLength(len = sizeof(TInt));
       
   740                 if (!getsockopt(Socket(), IPPROTO_TCP, TCP_NODELAY,
       
   741                     (char*)aOption.Ptr(),&len))
       
   742                 {
       
   743                     aOption.SetLength(len);
       
   744                     return KErrNone;
       
   745                 }
       
   746                 WTRACE1("getsockopt(TCP_NODELAY) error %d",WSAGetLastError());
       
   747                 break;
       
   748             case KSoTcpKeepAlive:
       
   749                 WTRACE("GetOption(KSoTcpKeepAlive)");
       
   750                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   751                 aOption.SetLength(len = sizeof(TInt));
       
   752                 if (!getsockopt(Socket(), SOL_SOCKET, SO_KEEPALIVE,
       
   753                     (char*)aOption.Ptr(),&len))
       
   754                 {
       
   755                     aOption.SetLength(len);
       
   756                     return KErrNone;
       
   757                 }
       
   758                 WTRACE1("getsockopt(SO_KEEPALIVE) error %d",WSAGetLastError());
       
   759                 break;
       
   760             case KSoTcpSendBytesPending:
       
   761                 WTRACE("GetOption(KSoTcpSendBytesPending)");
       
   762                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   763                 aOption.FillZ(sizeof(TInt));
       
   764                 return KErrNone;
       
   765             // This is a useful one:
       
   766             case KSoTcpReadBytesPending:
       
   767                 WTRACE("GetOption(KSoTcpReadBytesPending)");
       
   768                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   769                 aOption.SetLength(sizeof(TInt));
       
   770                 if (!ioctlsocket(Socket(), FIONREAD, (u_long*)aOption.Ptr()))
       
   771                 {
       
   772                     WTRACE1("%d bytes in socket",*((TInt*)aOption.Ptr()));
       
   773                     return KErrNone;
       
   774                 }
       
   775                 WTRACE1("ioctl(FIONREAD) error %d",WSAGetLastError());
       
   776                 break;
       
   777             case KSoTcpListening:
       
   778                 WTRACE("GetOption(KSoTcpListening)");
       
   779                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   780                 aOption.SetLength(sizeof(TInt));
       
   781                 *((TInt*)aOption.Ptr()) = (iFlags & EFlagListen) ? 1 : 0;
       
   782                 return KErrNone;
       
   783             case KSoTcpNumSockets:
       
   784                 WTRACE("GetOption(KSoTcpNumSockets)");
       
   785                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   786                 aOption.SetLength(sizeof(TInt));
       
   787                 *((TInt*)aOption.Ptr()) = 1; 
       
   788                 return KErrNone;
       
   789             default:
       
   790                 WTRACE1("SetOption(KSolInetTcp,%08X) - UNSUPPORTED",aName);
       
   791                 break;
       
   792             }
       
   793         } else {
       
   794             WTRACE1("SetOption(KSolInetTcp,%08X) - not a TCP socket!",aName);
       
   795         }
       
   796         break;
       
   797 
       
   798     case KSolInetUdp:
       
   799         if (iProtocol->ProtocolDesc()->iProtocol == KProtocolInetUdp) {
       
   800             switch (aName)
       
   801             {
       
   802             case KSoUdpReceiveICMPError:
       
   803                 WTRACE("SetOption(KSoUdpReceiveICMPError)");
       
   804                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   805                 aOption.SetLength(sizeof(TInt));
       
   806                 *((TInt*)aOption.Ptr()) = iUdpReceiveICMPError;
       
   807                 return KErrNone;
       
   808             case KSoUdpRecvBuf:
       
   809                 WTRACE("SetOption(KSoUdpRecvBuf)");
       
   810                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   811                 aOption.SetLength(sizeof(TInt));
       
   812                 *((TInt*)aOption.Ptr()) = iUdpRecvBuf;
       
   813                 return KErrNone;
       
   814             case KSoUdpSynchronousSend:
       
   815                 WTRACE("SetOption(KSoUdpSynchronousSend)");
       
   816                 if (aOption.MaxLength() < sizeof(TInt)) return KErrArgument;
       
   817                 aOption.SetLength(sizeof(TInt));
       
   818                 *((TInt*)aOption.Ptr()) = iUdpSynchronousSend;
       
   819                 return KErrNone;
       
   820             default:
       
   821                 WTRACE1("SetOption(KSolInetUdp,%08X) - UNSUPPORTED",aName);
       
   822                 break;
       
   823             }
       
   824         } else {
       
   825             WTRACE1("SetOption(KSolInetUdp,%08X) - not a UDP socket!",aName);
       
   826         }
       
   827         break;
       
   828 
       
   829     default:
       
   830         WTRACE2("GetOption(%d,%08X) - UNSUPPORTED",aLevel,aName);
       
   831         break;
       
   832     }
       
   833     aOption.SetLength(0);
       
   834     return KErrNotSupported;
       
   835 }
       
   836 
       
   837 TBool CWinsockServProvider::Connect()
       
   838 {
       
   839     if (Socket(iRemAddr.Family()) == INVALID_SOCKET)
       
   840     {
       
   841         WTRACE("can't connect, no socket");
       
   842         iFlags |= EFlagError;
       
   843         iSocket->Error(KErrCouldNotConnect);
       
   844         return EFalse;
       
   845     }
       
   846     else
       
   847     {
       
   848         WSockAddr sa;
       
   849         int len = ToSockAddr(&sa, &iRemAddr);
       
   850         int err = connect(iWinSocket, &sa.Address, len);
       
   851         if (err)
       
   852         {
       
   853             WTRACE1("connect failed, err %d",WSAGetLastError());
       
   854             switch (WSAGetLastError())
       
   855             {
       
   856             case WSAENETUNREACH:
       
   857                 iSocket->Error(KErrNetUnreach);
       
   858                 break;
       
   859             case WSAEHOSTUNREACH:
       
   860                 iSocket->Error(KErrHostUnreach);
       
   861                 break;
       
   862             default:
       
   863                 iSocket->Error(KErrCouldNotConnect);
       
   864                 break;
       
   865             }
       
   866             iFlags |= EFlagError;
       
   867             return EFalse;
       
   868         }
       
   869         else
       
   870         {
       
   871             iFlags |= EFlagConnect;
       
   872             return ETrue;
       
   873         }
       
   874     }
       
   875 }
       
   876 
       
   877 TInt CWinsockServProvider::Listen(TInt aBacklog)
       
   878 {
       
   879     ASSERT(iProtocol->IsStreamProtocol());
       
   880     if (Socket() == INVALID_SOCKET)
       
   881     {
       
   882         WTRACE("can't listen, no socket");
       
   883         return KErrGeneral;
       
   884     }
       
   885     else
       
   886     {
       
   887         int err = listen(iWinSocket, aBacklog);
       
   888         if (err)
       
   889         {
       
   890             WTRACE1("listen failed, err %d",WSAGetLastError());
       
   891             return KErrArgument;
       
   892         }
       
   893         else
       
   894         {
       
   895             return KErrNone;
       
   896         }
       
   897     }
       
   898 }
       
   899 
       
   900 // Creates and submits a new request
       
   901 CWinsockServProvider::CSelectRequest*
       
   902 CWinsockServProvider::CreateAndSubmitNewRequestL()
       
   903 {
       
   904     CSelectRequest* request = CSelectRequest::NewLC(this);
       
   905     request->SubmitL();
       
   906     CleanupStack::Pop(request);
       
   907     return request;
       
   908 }
       
   909 
       
   910 // Schedules CWriteRequest
       
   911 TBool CWinsockServProvider::ScheduleWriteRequest(TInt aDelay)
       
   912 {
       
   913     if (!iWrite)
       
   914     {
       
   915         iWrite = new CWriteRequest(this);
       
   916         if (!iWrite)
       
   917         {
       
   918             return EFalse;
       
   919         }
       
   920     }
       
   921     iWrite->Submit(aDelay);
       
   922     return ETrue;
       
   923 }
       
   924 
       
   925 // Schedules CNewDataNotifier
       
   926 TBool CWinsockServProvider::ScheduleNewDataCheck()
       
   927 {
       
   928     if (!iNewData)
       
   929     {
       
   930         iNewData = new CNewDataNotifier(this);
       
   931         if (!iNewData)
       
   932         {
       
   933             return EFalse;
       
   934         }
       
   935     }
       
   936     iNewData->Submit();
       
   937     return ETrue;
       
   938 }
       
   939 
       
   940 TInt CWinsockServProvider::Select()
       
   941 {
       
   942     TInt err = KErrNone;
       
   943     if (!iSelect)
       
   944     {
       
   945         TRAP(err,iSelect = CreateAndSubmitNewRequestL());
       
   946     }
       
   947 
       
   948     ASSERT(iSelect || err != KErrNone);
       
   949     if (iSelect && !iSelect->IsActive())
       
   950     {
       
   951         TRAP(err, iSelect->SubmitL());
       
   952     }
       
   953     return err;
       
   954 }
       
   955 
       
   956 void CWinsockServProvider::ActiveOpen()
       
   957 {
       
   958 #ifdef _REALLY_DEBUG
       
   959     TBuf<KMaxInetAddrBufSize> buf;
       
   960     iRemAddr.OutputWithScope(buf);
       
   961     WTRACE2("ActiveOpen(%S,%d)",&buf,iRemAddr.Port());
       
   962 #endif // _REALLY_DEBUG
       
   963     ASSERT(iProtocol->IsStreamProtocol());
       
   964     if (Connect())
       
   965     {
       
   966         iSocket->ConnectComplete();
       
   967         TInt err = Select();
       
   968         if (err != KErrNone)
       
   969         {
       
   970             iFlags |= EFlagError;
       
   971             iSocket->Error(err);
       
   972         }
       
   973     }
       
   974 }
       
   975 
       
   976 void CWinsockServProvider::ActiveOpen(const TDesC8& /*aConnectionData*/)
       
   977 {
       
   978     ASSERT(FALSE);
       
   979     iSocket->Error(KErrNotSupported);
       
   980 }
       
   981 
       
   982 TInt CWinsockServProvider::PassiveOpen(TUint aQueSize)
       
   983 {
       
   984     WTRACE1("PassiveOpen(%d)",aQueSize);
       
   985     ASSERT(iProtocol->IsStreamProtocol());
       
   986     TInt err = Listen(aQueSize);
       
   987     if (err == KErrNone)
       
   988     {
       
   989         iFlags |= EFlagListen;
       
   990         err = Select();
       
   991     }
       
   992     return err;
       
   993 }
       
   994 
       
   995 TInt CWinsockServProvider::PassiveOpen(TUint aQueSize,const TDesC8& /*aData*/)
       
   996 {
       
   997     ASSERT(FALSE);
       
   998     return PassiveOpen(aQueSize);
       
   999 }
       
  1000 
       
  1001 void CWinsockServProvider::Shutdown(TCloseType anOption)
       
  1002 {
       
  1003     WTRACE1("Shutdown(%08X)",anOption);
       
  1004     int how;
       
  1005     switch (anOption)
       
  1006     {
       
  1007     default:
       
  1008     case EImmediate:
       
  1009     case ENormal: how = SD_BOTH; break;
       
  1010     case EStopInput: how = SD_RECEIVE; break;
       
  1011     case EStopOutput: how = SD_SEND; break;
       
  1012     }
       
  1013     if (iWinSocket != INVALID_SOCKET)
       
  1014     {
       
  1015         shutdown(iWinSocket, how);
       
  1016     }
       
  1017     iFlags |= EFlagShutdown;
       
  1018     if (!(iFlags & EFlagError) && anOption != EImmediate)
       
  1019     {
       
  1020         // CSocket panics if we call CanClose() after reporting an error.
       
  1021         // It also gets pretty upset if we call CanClose() from Shutdown
       
  1022         // call with EImmediate parameter.
       
  1023         iSocket->CanClose();
       
  1024     }
       
  1025 }
       
  1026 
       
  1027 void CWinsockServProvider::Shutdown(TCloseType anOption,const TDesC8& /*aData*/)
       
  1028 {
       
  1029     Shutdown(anOption);
       
  1030 }
       
  1031 
       
  1032 void CWinsockServProvider::AutoBind()
       
  1033 {
       
  1034     if (Socket() == INVALID_SOCKET)
       
  1035     {
       
  1036         WTRACE("AutoBind - no socket");
       
  1037     }
       
  1038     else
       
  1039     {
       
  1040         WTRACE("AutoBind");
       
  1041         TInetAddr bindAddr;
       
  1042         bindAddr.Init(Family());
       
  1043         WSockAddr sa;
       
  1044         int len = WinsockUtils::ToSockAddr(&sa, &bindAddr);
       
  1045         int err = bind(iWinSocket, &sa.Address, len);
       
  1046         if (err)
       
  1047         {
       
  1048             WTRACE1("bind failed, err %d",WSAGetLastError());
       
  1049             iFlags |= EFlagError;
       
  1050             iSocket->Error(err);
       
  1051         }
       
  1052     }
       
  1053 }
       
  1054 
       
  1055 // The reason for not writing the data immediately is that socket server
       
  1056 // is processing both read and write requests on the same thread. If we
       
  1057 // are writing data faster than we are reading them, eventually send
       
  1058 // will block forever. We try to give the reader a chance.
       
  1059 void CWinsockServProvider::DoWrite()
       
  1060 {
       
  1061     if (!iWriteQ.IsEmpty())
       
  1062     {
       
  1063         ASSERT(iWinSocket != INVALID_SOCKET);
       
  1064 
       
  1065         // Check if the socket is writable
       
  1066         TBool canWrite = ETrue;
       
  1067         fd_set writefs;
       
  1068         FD_ZERO(&writefs);
       
  1069         FD_SET(iWinSocket,&writefs);
       
  1070         struct timeval tv;
       
  1071         tv.tv_sec = 0;
       
  1072         tv.tv_usec = 0;
       
  1073 
       
  1074         BEGIN_WIN32();
       
  1075         int nfd = select(iWinSocket+1, NULL, &writefs, NULL, &tv);
       
  1076         END_WIN32();
       
  1077 
       
  1078         if (nfd == SOCKET_ERROR)
       
  1079         {
       
  1080             WTRACE1("select err %d",WSAGetLastError());
       
  1081             iSocket->Error(KErrWrite);
       
  1082         }
       
  1083         else
       
  1084         {
       
  1085             if (FD_ISSET(iWinSocket,&writefs))
       
  1086             {
       
  1087                 // Send exactly one block of data
       
  1088                 CWriteData* data = iWriteQ.First();
       
  1089                 data->iLink.Deque();
       
  1090                 TUint nBytes = SendNow(*data->iData, data->iAddr);
       
  1091                 if (nBytes)
       
  1092                 {
       
  1093                     WTRACE1("sent %d bytes",nBytes);
       
  1094                     iProtocol->DataSent(nBytes);
       
  1095                 }
       
  1096                 delete data;
       
  1097 
       
  1098                 // Have more data to send?
       
  1099                 if (!iWriteQ.IsEmpty())
       
  1100                 {
       
  1101                     ScheduleWriteRequest(0);
       
  1102                 }
       
  1103             }
       
  1104             else
       
  1105             {
       
  1106                 // Delay the retry to ease the CPU load and give the
       
  1107                 // reader a chance to catch up
       
  1108                 WTRACE("socket is not writable, waiting...");
       
  1109                 ScheduleWriteRequest(500000);
       
  1110             }
       
  1111         }
       
  1112     }
       
  1113 }
       
  1114 
       
  1115 TUint CWinsockServProvider::SendLater(const TDesC8& aData, TSockAddr* aAddr)
       
  1116 {
       
  1117     CWriteData* data = CWriteData::New(aData, aAddr);
       
  1118     if (data)
       
  1119     {
       
  1120         iWriteQ.AddLast(*data);
       
  1121         ScheduleWriteRequest(0);
       
  1122         return aData.Length();
       
  1123     }
       
  1124     return 0;
       
  1125 }
       
  1126 
       
  1127 TUint CWinsockServProvider::SendNow(const TDesC8& aData, TSockAddr* aAddr)
       
  1128 {
       
  1129     int nbytes;
       
  1130     const char * buf = (char*)aData.Ptr();
       
  1131     int len = aData.Length();
       
  1132     if (iFlags & EFlagConnect)
       
  1133     {
       
  1134         BEGIN_WIN32();
       
  1135         nbytes = send(iWinSocket, buf, len, 0);
       
  1136         END_WIN32();
       
  1137     }
       
  1138     else
       
  1139     {
       
  1140         ASSERT(aAddr);
       
  1141         WSockAddr to;
       
  1142         int tolen = WinsockUtils::ToSockAddr(&to, aAddr);
       
  1143 
       
  1144         BEGIN_WIN32();
       
  1145         nbytes = sendto(Socket(aAddr->Family()),buf,len,0,&to.Address,tolen);
       
  1146         END_WIN32();
       
  1147 
       
  1148         if (nbytes < len) nbytes = 0;
       
  1149     }
       
  1150     if (nbytes == SOCKET_ERROR)
       
  1151     {
       
  1152         WTRACE1("send failed, err %d",WSAGetLastError());
       
  1153         iSocket->Error(KErrWrite);
       
  1154         return 0;
       
  1155     }
       
  1156     else
       
  1157     {
       
  1158         if (nbytes < len)
       
  1159         {
       
  1160             iSocket->Error(KErrWrite);
       
  1161         }
       
  1162         return nbytes;
       
  1163     }
       
  1164 }
       
  1165 
       
  1166 TUint CWinsockServProvider::Write(const TDesC8& aData, TUint, TSockAddr* aAddr)
       
  1167 {
       
  1168     if (Socket() == INVALID_SOCKET)
       
  1169     {
       
  1170         WTRACE("Write - no socket");
       
  1171         iSocket->Error(KErrWrite);
       
  1172         return 0;
       
  1173     }
       
  1174     else
       
  1175     {
       
  1176         WTRACE1("sending %d bytes",aData.Length());
       
  1177         if (!iWriteQ.IsEmpty() || iProtocol->ReadPending())
       
  1178         {
       
  1179             // If have asynchronous writes pending, we have to send this
       
  1180             // chunk of data asynchronously too, otherwise the order of
       
  1181             // chunks will change. If there's any unread data in one of
       
  1182             // the sockets, we also want to be asynchronous to avoid
       
  1183             // starving the reading thread, which can result in filling
       
  1184             // up TCP buffer, blocking socket server thread and finally
       
  1185             // deadlock.
       
  1186             return SendLater(aData, aAddr);
       
  1187         }
       
  1188         else
       
  1189         {
       
  1190             // No read or writes pending, send it now.
       
  1191             return SendNow(aData, aAddr);
       
  1192         }
       
  1193     }
       
  1194 }
       
  1195 
       
  1196 #ifdef V1_5_PRT_INTERFACE
       
  1197 
       
  1198 TInt CWinsockServProvider::Receive(TDes8& aData, TUint aOpt, TSockAddr* aAddr)
       
  1199 {
       
  1200     ASSERT(aData.Length() > 0);
       
  1201     ASSERT(!(iFlags & (EFlagEndOfData | EFlagShutdown)));
       
  1202 
       
  1203     WSockAddr from;
       
  1204     int maxbytes = Min(aData.Length(), iDataAvailable);
       
  1205     char* buf = (char*)&aData[0];
       
  1206 
       
  1207     int retval;     // Return value from recv or recvfrom
       
  1208     int nbytes;     // How much is actually in the buffer
       
  1209 
       
  1210     ASSERT(!(aOpt & KIpHeaderIncluded));        // Option is not implemented
       
  1211     // ASSERT(!(aOpt & KSockReadContinuation)); // ignore, does not affect operation
       
  1212     int opt = ((aOpt & KSockReadPeek) ? MSG_PEEK : 0);
       
  1213 
       
  1214     if (aAddr)
       
  1215     {
       
  1216         int fromlen = SOCKADDR_SIZE;
       
  1217         retval = recvfrom(Socket(), buf, maxbytes, opt, (struct sockaddr*)
       
  1218             &from, &fromlen);
       
  1219     }
       
  1220     else
       
  1221     {
       
  1222         // No address information is required, probably a TCP socket
       
  1223         retval = recv(Socket(), buf, maxbytes, opt);
       
  1224     }
       
  1225 
       
  1226     if (retval == SOCKET_ERROR && WSAGetLastError() == WSAEMSGSIZE)
       
  1227     {
       
  1228         ASSERT( EFalse ); // should not happen anymore; whole datagram is read
       
  1229         WTRACE1("datagram truncated to %d bytes",maxbytes);
       
  1230         nbytes = maxbytes;
       
  1231     }
       
  1232     else
       
  1233     {
       
  1234         nbytes = retval;
       
  1235     }
       
  1236 
       
  1237     if (nbytes == SOCKET_ERROR)
       
  1238     {
       
  1239         WTRACE1("recv err %d",WSAGetLastError());
       
  1240         iFlags |= EFlagError;
       
  1241         aData.SetLength(0);
       
  1242         retval = (iProtocol->IsStreamProtocol()) ? KErrDisconnected : KErrGeneral;
       
  1243     }
       
  1244     else if (retval == 0)
       
  1245     {
       
  1246         // the connection has been gracefully closed
       
  1247         iFlags |= EFlagEndOfData;
       
  1248         aData.SetLength(0);
       
  1249         WTRACE("end of data");
       
  1250         ScheduleNewDataCheck();
       
  1251     }
       
  1252     else
       
  1253     {
       
  1254         if (aAddr) WinsockUtils::ToInetAddr(aAddr, &from);
       
  1255         aData.SetLength(nbytes);
       
  1256 
       
  1257         if (iProtocol->IsStreamProtocol())
       
  1258         {
       
  1259             ASSERT(iDataAvailable >= nbytes);
       
  1260             iDataAvailable -= nbytes;
       
  1261         }
       
  1262         else
       
  1263         {
       
  1264             // In case of UDP we always indicate no more than one datagram.
       
  1265             // After socket server has called our GetData function, it thinks
       
  1266             // that it has received the only available datagram and that we
       
  1267             // no longer have any data in the receive queue. We need
       
  1268             // to reset iDataAvailable to zero and start from scratch.
       
  1269             iDataAvailable = 0;
       
  1270             
       
  1271             retval = 1; // indicate, that one datagram was read
       
  1272         }
       
  1273 
       
  1274         if (iDataAvailable <= 0)
       
  1275         {
       
  1276             // Find out how much data still left
       
  1277             TUint32 size = 0;
       
  1278             int err = ioctlsocket(iWinSocket, FIONREAD, &size);
       
  1279             iProtocol->SetReadPending(this, !err && (size > 0));
       
  1280             if (err == SOCKET_ERROR)
       
  1281             {
       
  1282                 WTRACE1("ioctl(FIONREAD) err %d",WSAGetLastError());
       
  1283                 iFlags |= EFlagError;
       
  1284                 retval = KErrGeneral;
       
  1285             }
       
  1286             else
       
  1287             {
       
  1288                 TInt bytesInSocket = size;
       
  1289                 WTRACE2("%d bytes in socket, %d bytes unread",
       
  1290                     bytesInSocket, iDataAvailable);
       
  1291                 if (bytesInSocket > iDataAvailable)
       
  1292                 {
       
  1293                     // iSocket->NewData is not reentrant. If we call it from
       
  1294                     // here, it will get into an infinite loop
       
  1295                     WTRACE("scheduling new data check");
       
  1296                     ScheduleNewDataCheck();
       
  1297                 }
       
  1298                 else
       
  1299                 {
       
  1300                     // Re-submit the select request
       
  1301                     TInt err = Select();
       
  1302                     if (err != KErrNone)
       
  1303                     {
       
  1304                         iFlags |= EFlagError;
       
  1305                         retval = KErrGeneral;
       
  1306                     }
       
  1307                 }
       
  1308             }
       
  1309         }
       
  1310     }
       
  1311     return retval; // error-code, nbytes (if stream) or 1 (if dgram)
       
  1312 }
       
  1313 
       
  1314 TInt CWinsockServProvider::GetData(RMBufChain& aData, TUint aLength,
       
  1315                                    TUint aOptions, TSockAddr* aAddr)
       
  1316 {
       
  1317     if (!iDataAvailable)
       
  1318     {
       
  1319         // This should only happen for datagram protocols
       
  1320         WTRACE1("%d bytes requested, nothing is available",
       
  1321                aLength & ~KGetDataWholeDatagram);
       
  1322         ASSERT(iProtocol->IsDatagramProtocol());
       
  1323         return KErrNotReady;
       
  1324     }
       
  1325     else if (Socket() == INVALID_SOCKET)
       
  1326     {
       
  1327         WTRACE("GetData - no socket");
       
  1328         return KErrGeneral;
       
  1329     }
       
  1330     else
       
  1331     {
       
  1332         WTRACE2("%d bytes requested, %d bytes unread", 
       
  1333                (aLength & ~KGetDataWholeDatagram), iDataAvailable);
       
  1334 
       
  1335         if (aLength & KGetDataWholeDatagram)
       
  1336         {
       
  1337             // we're asked to read the whole dgram, even if client wants less
       
  1338             aLength &= ~KGetDataWholeDatagram;
       
  1339             aLength = Max(aLength, iDataAvailable);
       
  1340         }
       
  1341         
       
  1342         // alloc buffer
       
  1343         TInt extraNeeded = aLength - aData.Length();
       
  1344         if (extraNeeded > 0)
       
  1345         {
       
  1346             TRAPD(err, aData.AppendL(extraNeeded));
       
  1347             if (err != KErrNone)
       
  1348             {
       
  1349                 return KErrNoMBufs;
       
  1350             }
       
  1351         }
       
  1352 
       
  1353         // the new GetData-inteface with RMBufChain-param (i.e. v1.5 PRT inter-
       
  1354         // face) is somewhat problematic from Winsock's point of view.
       
  1355         // RMBufChain is essentially a linked list of buffers. But especially
       
  1356         // when UDP-datagram bigger than the a single buffer is being read,
       
  1357         // the windows-socket recvfrom-operation has to be done in a single
       
  1358         // operation - otherwise datagram gets truncated.
       
  1359         // Therefore we have to have a local buffer where to read the data - 
       
  1360         // and then copy it into RMBufChain.
       
  1361         //
       
  1362         // reference: \src\common\generic\comms-infras\documentation\
       
  1363         // Comms Framework Migration Guide for NIFs and v1.5 PRTs.doc
       
  1364         //
       
  1365         // The code below is more or less copied from 
       
  1366         // \src\common\generic\comms-infras\esock\ssock\SS_PROT.CPP
       
  1367 
       
  1368         if(!iDataBuf)
       
  1369         {
       
  1370             iDataBuf = HBufC8::New(aLength);
       
  1371             if(!iDataBuf)
       
  1372             {
       
  1373                 return KErrNoMemory;
       
  1374             }
       
  1375         }
       
  1376         else if(iDataBuf->Size() < TInt(aLength))
       
  1377         {
       
  1378             // We need extra room for data. As ReAlloc returns NULL if fails, 
       
  1379             // we need to temporary save the previous storage in order to 
       
  1380             // clear it in the case of ReAlloc failure.
       
  1381             HBufC8* aTempPtr = iDataBuf;
       
  1382             iDataBuf = iDataBuf->ReAlloc(aLength);
       
  1383             if(!iDataBuf)
       
  1384             {
       
  1385                 delete aTempPtr;
       
  1386                 return KErrNoMemory;
       
  1387             }
       
  1388         }
       
  1389         TPtr8 des = iDataBuf->Des();
       
  1390         des.SetLength(aLength);
       
  1391 
       
  1392         TInt retval = Receive( des, aOptions, aAddr );
       
  1393 
       
  1394         TInt bytesReceived = des.Length();
       
  1395         aData.CopyIn(des);
       
  1396 
       
  1397         if(des.Length() < TInt(aLength))
       
  1398         {
       
  1399             aData.TrimEnd(des.Length());
       
  1400         }
       
  1401         WTRACE2("received %d bytes, %d bytes left", bytesReceived, iDataAvailable);
       
  1402         if (bytesReceived > 0)
       
  1403         {
       
  1404             iProtocol->DataReceived(bytesReceived);
       
  1405         }
       
  1406 
       
  1407         return retval;
       
  1408     }
       
  1409 }
       
  1410 
       
  1411 #else // PRT v1.0 interface
       
  1412 
       
  1413 void CWinsockServProvider::Receive(TDes8& aDesc, TUint aOpt, TSockAddr* aAddr)
       
  1414 {
       
  1415     ASSERT(aDesc.Length() > 0);
       
  1416     ASSERT(!(iFlags & (EFlagEndOfData | EFlagShutdown)));
       
  1417 
       
  1418     WSockAddr from;
       
  1419     int maxbytes = Min(aDesc.Length(), iDataAvailable);
       
  1420     char* buf = (char*)&aDesc[0];
       
  1421 
       
  1422     int retval;     // Return value from recv or recvfrom
       
  1423     int nbytes;     // How much is actually in the buffer
       
  1424 
       
  1425     ASSERT(!(aOpt & KIpHeaderIncluded));            // Option is not implemented
       
  1426     ASSERT(!(aOpt & KSockReadContinuation));        // Option is not implemented
       
  1427     int opt = ((aOpt & KSockReadPeek) ? MSG_PEEK : 0);
       
  1428 
       
  1429     if (aAddr)
       
  1430     {
       
  1431         int fromlen = SOCKADDR_SIZE;
       
  1432         retval = recvfrom(Socket(), buf, maxbytes, opt, (struct sockaddr*)
       
  1433             &from, &fromlen);
       
  1434     }
       
  1435     else
       
  1436     {
       
  1437         // No address information is required, probably a TCP socket
       
  1438         retval = recv(Socket(), buf, maxbytes, opt);
       
  1439     }
       
  1440 
       
  1441     // How to handle truncated datagrams?
       
  1442     if (retval == SOCKET_ERROR && WSAGetLastError() == WSAEMSGSIZE)
       
  1443     {
       
  1444         WTRACE1("datagram truncated to %d bytes",maxbytes);
       
  1445         nbytes = maxbytes;
       
  1446     }
       
  1447     else
       
  1448     {
       
  1449         nbytes = retval;
       
  1450     }
       
  1451 
       
  1452     if (nbytes == SOCKET_ERROR)
       
  1453     {
       
  1454         WTRACE1("recv err %d",WSAGetLastError());
       
  1455         iFlags |= EFlagError;
       
  1456         aDesc.SetLength(0);
       
  1457         if (iProtocol->IsStreamProtocol())
       
  1458         {
       
  1459             iSocket->Error(KErrDisconnected);
       
  1460         }
       
  1461         else
       
  1462         {
       
  1463             iSocket->Error(KErrGeneral);
       
  1464         }
       
  1465     }
       
  1466     else if (retval == 0)
       
  1467     {
       
  1468         // the connection has been gracefully closed
       
  1469         iFlags |= EFlagEndOfData;
       
  1470         aDesc.SetLength(0);
       
  1471         WTRACE("end of data");
       
  1472         ScheduleNewDataCheck();
       
  1473     }
       
  1474     else
       
  1475     {
       
  1476         if (aAddr) WinsockUtils::ToInetAddr(aAddr, &from);
       
  1477         aDesc.SetLength(nbytes);
       
  1478 
       
  1479         if (iProtocol->IsStreamProtocol())
       
  1480         {
       
  1481             ASSERT(iDataAvailable >= nbytes);
       
  1482             iDataAvailable -= nbytes;
       
  1483         }
       
  1484         else
       
  1485         {
       
  1486             // In case of UDP we always indicate no more than one datagram.
       
  1487             // After socket server has called our GetData function, it thinks
       
  1488             // that it has received the only available datagram and that we
       
  1489             // no longer have any data in the receive queue. Also, datagram
       
  1490             // may have been truncated and in that case we don't really know
       
  1491             // how much data are still sitting in the receive queue. We need
       
  1492             // to reset iDataAvailable to zero and start from scratch.
       
  1493             iDataAvailable = 0;
       
  1494         }
       
  1495         if (iDataAvailable <= 0)
       
  1496         {
       
  1497             // Find out how much data still left
       
  1498             TUint32 size = 0;
       
  1499             int err = ioctlsocket(iWinSocket, FIONREAD, &size);
       
  1500             iProtocol->SetReadPending(this, !err && (size > 0));
       
  1501             if (err == SOCKET_ERROR)
       
  1502             {
       
  1503                 WTRACE1("ioctl(FIONREAD) err %d",WSAGetLastError());
       
  1504                 iFlags |= EFlagError;
       
  1505                 iSocket->Error(KErrGeneral);
       
  1506             }
       
  1507             else
       
  1508             {
       
  1509                 TInt bytesInSocket = size;
       
  1510                 WTRACE2("%d bytes in socket, %d bytes unread",
       
  1511                     bytesInSocket, iDataAvailable);
       
  1512                 if (bytesInSocket > iDataAvailable)
       
  1513                 {
       
  1514                     // iSocket->NewData is not reentrant. If we call it from
       
  1515                     // here, it will get into an infinite loop
       
  1516                     WTRACE("scheduling new data check");
       
  1517                     ScheduleNewDataCheck();
       
  1518                 }
       
  1519                 else
       
  1520                 {
       
  1521                     // Re-submit the select request
       
  1522                     TInt err = Select();
       
  1523                     if (err != KErrNone)
       
  1524                     {
       
  1525                         iFlags |= EFlagError;
       
  1526                         iSocket->Error(KErrGeneral);
       
  1527                     }
       
  1528                 }
       
  1529             }
       
  1530         }
       
  1531     }
       
  1532 }
       
  1533 
       
  1534 void CWinsockServProvider::GetData(TDes8& aDesc, TUint aOptions, TSockAddr* aAddr)
       
  1535 {
       
  1536     if (Socket() == INVALID_SOCKET)
       
  1537     {
       
  1538         WTRACE("GetData - no socket");
       
  1539         iSocket->Error(KErrGeneral);
       
  1540     }
       
  1541     else
       
  1542     {
       
  1543         WTRACE2("%d bytes requested, %d bytes unread",
       
  1544                aDesc.Length(),iDataAvailable);
       
  1545         if (!iDataAvailable)
       
  1546         {
       
  1547             aDesc.SetLength(0);
       
  1548         }
       
  1549         else
       
  1550         {
       
  1551             Receive(aDesc, aOptions, aAddr);
       
  1552             TInt bytesReceived = aDesc.Length();
       
  1553             WTRACE2("received %d bytes, %d bytes left",
       
  1554                    bytesReceived, iDataAvailable);
       
  1555             if (bytesReceived > 0)
       
  1556             {
       
  1557                 iProtocol->DataReceived(bytesReceived);
       
  1558             }
       
  1559         }
       
  1560     }
       
  1561 }
       
  1562 
       
  1563 TInt CWinsockServProvider::GetData(RMBufChain& aData, TUint aLength,
       
  1564                                    TUint aOptions, TSockAddr* anAddr)
       
  1565 {
       
  1566     if (!iDataAvailable)
       
  1567     {
       
  1568         // This should only happen for datagram protocols
       
  1569         WTRACE1("%d bytes requested, nothing is available",
       
  1570                aLength & ~KGetDataWholeDatagram);
       
  1571         ASSERT(iProtocol->IsDatagramProtocol());
       
  1572         return KErrNotReady;
       
  1573     }
       
  1574 
       
  1575     // The base class never returns an error
       
  1576     TInt ret = SUPER::GetData(aData, aLength, aOptions, anAddr);
       
  1577     if (iFlags & EFlagError)
       
  1578     {
       
  1579         if (iProtocol->IsDatagramProtocol())
       
  1580         {
       
  1581             return KErrGeneral;
       
  1582         }
       
  1583         else
       
  1584         {
       
  1585             return KErrDisconnected;
       
  1586         }
       
  1587     }
       
  1588     else
       
  1589     {
       
  1590         return ret;
       
  1591     }
       
  1592 }
       
  1593 
       
  1594 #endif // V1_5_PRT_INTERFACE
       
  1595 
       
  1596 // upcall from CSelectRequest invoked in the context of the thread
       
  1597 // submitted the request
       
  1598 void CWinsockServProvider::SelectComplete(TInt aMask)
       
  1599 {
       
  1600     if (aMask & ESelectError)
       
  1601     {
       
  1602         if (!(iFlags & EFlagError))
       
  1603         {
       
  1604             iFlags |= EFlagError;
       
  1605             iSocket->Error(KErrDisconnected);
       
  1606         }
       
  1607     }
       
  1608     else if (!(iFlags & EFlagError) && (aMask & ESelectRead))
       
  1609     {
       
  1610         if (iFlags & EFlagListen)
       
  1611         {
       
  1612             // Accept new connection
       
  1613             WSockAddr addr;
       
  1614             int addrlen = SOCKADDR_SIZE;
       
  1615             SOCKET sock = accept(iWinSocket,&addr.Address,&addrlen);
       
  1616             if (sock == INVALID_SOCKET)
       
  1617             {
       
  1618                 // ignore this error
       
  1619                 WTRACE1("accept failed, err %d",WSAGetLastError());
       
  1620             }
       
  1621             else
       
  1622             {
       
  1623                 WTRACE("accepted incoming connection");
       
  1624                 CWinsockServProvider* newSock = CWinsockServProvider::
       
  1625                     FromSocket(iProtocol, sock, iFamily);
       
  1626                 if (newSock)
       
  1627                 {
       
  1628                     iSocket->ConnectComplete(*newSock);
       
  1629                 }
       
  1630             }
       
  1631 
       
  1632             // Re-submit the request
       
  1633             TInt err = Select();
       
  1634             if (err != KErrNone)
       
  1635             {
       
  1636                 iFlags |= EFlagError;
       
  1637                 iSocket->Error(KErrCouldNotConnect);
       
  1638             }
       
  1639         }
       
  1640         else
       
  1641         {
       
  1642             NewDataCheck();
       
  1643         }
       
  1644     }
       
  1645 }
       
  1646 
       
  1647 // Upcall from CNewDataNotifier. Also invoked from SelectComplete
       
  1648 void CWinsockServProvider::NewDataCheck()
       
  1649 {
       
  1650     if (iFlags & EFlagShutdown)
       
  1651     {
       
  1652         return;
       
  1653     }
       
  1654 
       
  1655     if (iFlags & EFlagEndOfData)
       
  1656     {
       
  1657         if (!(iFlags & EFlagDisconnected))
       
  1658         {
       
  1659             WTRACE("indicating end of data");
       
  1660             iSocket->NewData(KNewDataEndofData);
       
  1661         }
       
  1662         return;
       
  1663     }
       
  1664 
       
  1665     TUint32 size = 0;
       
  1666     ASSERT(iWinSocket != INVALID_SOCKET);
       
  1667     int err = ioctlsocket(iWinSocket, FIONREAD, &size);
       
  1668     iProtocol->SetReadPending(this, !err && (size > 0));
       
  1669     if (err == SOCKET_ERROR)
       
  1670     {
       
  1671         WTRACE1("ioctl(FIONREAD) err %d",WSAGetLastError());
       
  1672         iFlags |= EFlagError;
       
  1673         iSocket->Error(KErrGeneral);
       
  1674     }
       
  1675     else
       
  1676     {
       
  1677         TInt bytesInSocket = size;
       
  1678         WTRACE2("%d bytes in socket, %d bytes unread",
       
  1679             bytesInSocket, iDataAvailable);
       
  1680         if (bytesInSocket > iDataAvailable)
       
  1681         {
       
  1682             // Report more data
       
  1683             TInt newData = bytesInSocket - iDataAvailable;
       
  1684             iDataAvailable = bytesInSocket;
       
  1685             if (iProtocol->IsStreamProtocol())
       
  1686             {
       
  1687                 WTRACE1("indicating %d bytes",newData);
       
  1688                 iSocket->NewData(newData);
       
  1689             }
       
  1690             else
       
  1691             {
       
  1692                 WTRACE("indicating (at least) 1 datagram");
       
  1693                 iSocket->NewData(1);
       
  1694             }
       
  1695         }
       
  1696         else if (iProtocol->IsStreamProtocol())
       
  1697         {
       
  1698             // For connection-oriented sockets, readability may indicate that
       
  1699             // a request to close the socket has been received from the peer.
       
  1700             // If the connection was closed gracefully, and all data was
       
  1701             // received, then a recv will return immediately with zero bytes
       
  1702             // read. If the connection was reset, then a recv will complete
       
  1703             // immediately with an error code
       
  1704             if (!bytesInSocket && !iDataAvailable)
       
  1705             {
       
  1706                 BEGIN_WIN32();
       
  1707                 char buf;
       
  1708                 int ret = recv(iWinSocket, &buf, 1, 0);
       
  1709                 END_WIN32();
       
  1710 
       
  1711                 if (ret == 0)
       
  1712                 {
       
  1713                     iFlags |= EFlagEndOfData;
       
  1714                     WTRACE("end of data, I guess");
       
  1715                     iSocket->NewData(KNewDataEndofData);
       
  1716                 }
       
  1717                 else if (ret == SOCKET_ERROR)
       
  1718                 {
       
  1719                     WTRACE1("recv err %d",WSAGetLastError());
       
  1720                     iFlags |= EFlagError;
       
  1721                     iSocket->Error(KErrDisconnected);
       
  1722                 }
       
  1723                 else
       
  1724                 {
       
  1725                     // This means that we were wrong about the connection
       
  1726                     // being either reset or close. Too bad...
       
  1727                     WTRACE("oops... didn't expect any data");
       
  1728                     ASSERT(FALSE);
       
  1729                     iFlags |= EFlagError;
       
  1730                     iSocket->Error(KErrGeneral);
       
  1731                 }
       
  1732             }
       
  1733         }
       
  1734     }
       
  1735 }
       
  1736 
       
  1737 // CWinsockServProvider::CSelectRequest
       
  1738 CWinsockServProvider::CSelectRequest*
       
  1739 CWinsockServProvider::CSelectRequest::NewLC(CWinsockServProvider* aProvider)
       
  1740 {
       
  1741     CSelectRequest* self = new(ELeave)CSelectRequest(aProvider);
       
  1742     CleanupStack::PushL(self);
       
  1743     self->ConstructL();
       
  1744     return self;
       
  1745 }
       
  1746 
       
  1747 CWinsockServProvider::CSelectRequest::CSelectRequest(CWinsockServProvider* aP) :
       
  1748 CActive(EPriorityStandard), iProvider(aP)
       
  1749 {
       
  1750     CActiveScheduler::Add(this);
       
  1751 }
       
  1752 
       
  1753 CWinsockServProvider::CSelectRequest::~CSelectRequest()
       
  1754 {
       
  1755     iServerThread.Close();
       
  1756 }
       
  1757 
       
  1758 void CWinsockServProvider::CSelectRequest::ConstructL()
       
  1759 {
       
  1760     LEAVE_IF_ERROR(iServerThread.Open(RThread().Id()));
       
  1761 }
       
  1762 
       
  1763 void CWinsockServProvider::CSelectRequest::SubmitL()
       
  1764 {
       
  1765     if (!IsActive())
       
  1766     {
       
  1767         iStatus = KRequestPending;
       
  1768         SetActive();
       
  1769     }
       
  1770     LEAVE_IF_ERROR(CWinsockSelectThread::StaticL().Submit(this));
       
  1771 }
       
  1772 
       
  1773 TUint CWinsockServProvider::CSelectRequest::Socket()
       
  1774 {
       
  1775     ASSERT(iProvider->iWinSocket != INVALID_SOCKET);
       
  1776     return iProvider->iWinSocket;
       
  1777 }
       
  1778 
       
  1779 TInt CWinsockServProvider::CSelectRequest::SelectMask()
       
  1780 {
       
  1781     return (ESelectRead|ESelectError);
       
  1782 }
       
  1783 
       
  1784 void CWinsockServProvider::CSelectRequest::SelectComplete(TInt aSelectMask)
       
  1785 {
       
  1786     iSelectMask = aSelectMask;
       
  1787     TRequestStatus *status = (&iStatus);
       
  1788     iServerThread.RequestComplete(status, KErrNone);
       
  1789 }
       
  1790 
       
  1791 void CWinsockServProvider::CSelectRequest::DoCancel()
       
  1792 {
       
  1793     TRequestStatus *status = (&iStatus);
       
  1794     User::RequestComplete(status, KErrCancel);
       
  1795 }
       
  1796 
       
  1797 void CWinsockServProvider::CSelectRequest::RunL()
       
  1798 {
       
  1799     iProvider->SelectComplete(iSelectMask);
       
  1800 }
       
  1801 
       
  1802 // CWinsockServProvider::CWriteData
       
  1803 CWinsockServProvider::CWriteData*
       
  1804 CWinsockServProvider::CWriteData::New(const TDesC8& aData, TSockAddr* aAddr)
       
  1805 {
       
  1806     CWriteData* data = new(CWriteData);
       
  1807     if (data)
       
  1808     {
       
  1809         data->iData = aData.Alloc();
       
  1810         if (data->iData)
       
  1811         {
       
  1812             if (aAddr)
       
  1813             {
       
  1814                 data->iAddr = new(TSockAddr);
       
  1815                 if (data->iAddr) (*data->iAddr) = *aAddr;
       
  1816             }
       
  1817             if (!aAddr || data->iAddr)
       
  1818             {
       
  1819                 return data;
       
  1820             }
       
  1821         }
       
  1822         delete data;
       
  1823     }
       
  1824     return NULL;
       
  1825 }
       
  1826 
       
  1827 CWinsockServProvider::CWriteData::~CWriteData()
       
  1828 {
       
  1829     delete iAddr;
       
  1830     delete iData;
       
  1831 }
       
  1832 
       
  1833 // CWinsockServProvider::CWriteRequest
       
  1834 CWinsockServProvider::CWriteRequest::CWriteRequest(CWinsockServProvider* aP) :
       
  1835 CActive(EPriorityStandard), iProvider(aP)
       
  1836 {
       
  1837     CActiveScheduler::Add(this);
       
  1838 }
       
  1839 
       
  1840 CWinsockServProvider::CWriteRequest::~CWriteRequest()
       
  1841 {
       
  1842     Cancel();
       
  1843     if (iTimerCreated)
       
  1844     {
       
  1845         iTimer.Close();
       
  1846     }
       
  1847 }
       
  1848 
       
  1849 void CWinsockServProvider::CWriteRequest::Submit(TInt aDelay)
       
  1850 {
       
  1851     if (aDelay)
       
  1852     {
       
  1853         if (!iTimerCreated)
       
  1854         {
       
  1855             // Create timer first time we need a delay
       
  1856             TInt err = iTimer.CreateLocal();
       
  1857             if (err == KErrNone) iTimerCreated = ETrue;
       
  1858         }
       
  1859         if (iTimerCreated)
       
  1860         {
       
  1861             Cancel();
       
  1862             SetActive();
       
  1863             iTimer.After(iStatus, aDelay);
       
  1864             iTimerActive = ETrue;
       
  1865             return;
       
  1866         }
       
  1867     }
       
  1868     if (!IsActive())
       
  1869     {
       
  1870         // Complete request immediately
       
  1871         SetActive();
       
  1872         TRequestStatus *status = (&iStatus);
       
  1873         User::RequestComplete(status, KErrCancel);
       
  1874     }
       
  1875 }
       
  1876 
       
  1877 void CWinsockServProvider::CWriteRequest::DoCancel()
       
  1878 {
       
  1879     TRequestStatus *status = (&iStatus);
       
  1880     if (iTimerActive)
       
  1881     {
       
  1882         iTimerActive = EFalse;
       
  1883         iTimer.Cancel();
       
  1884     }
       
  1885     else
       
  1886     {
       
  1887         User::RequestComplete(status, KErrCancel);
       
  1888     }
       
  1889 }
       
  1890 
       
  1891 void CWinsockServProvider::CWriteRequest::RunL()
       
  1892 {
       
  1893     iTimerActive = EFalse;
       
  1894     iProvider->DoWrite();
       
  1895 }
       
  1896 
       
  1897 // CWinsockServProvider::CNewDataNotifier
       
  1898 CWinsockServProvider::CNewDataNotifier::CNewDataNotifier(CWinsockServProvider* aP) :
       
  1899 CActive(EPriorityStandard), iProvider(aP)
       
  1900 {
       
  1901     CActiveScheduler::Add(this);
       
  1902 }
       
  1903 
       
  1904 void CWinsockServProvider::CNewDataNotifier::Submit()
       
  1905 {
       
  1906     if (!IsActive())
       
  1907     {
       
  1908         SetActive();
       
  1909         TRequestStatus *status = (&iStatus);
       
  1910         User::RequestComplete(status, KErrCancel);
       
  1911     }
       
  1912 }
       
  1913 
       
  1914 void CWinsockServProvider::CNewDataNotifier::DoCancel()
       
  1915 {
       
  1916     TRequestStatus *status = (&iStatus);
       
  1917     User::RequestComplete(status, KErrCancel);
       
  1918 }
       
  1919 
       
  1920 void CWinsockServProvider::CNewDataNotifier::RunL()
       
  1921 {
       
  1922     iProvider->NewDataCheck();
       
  1923 }
       
  1924 
       
  1925 /**
       
  1926  * Local Variables:
       
  1927  * c-basic-offset: 4
       
  1928  * indent-tabs-mode: nil
       
  1929  * End:
       
  1930  */