src/network/socket/qnativesocketengine_win.cpp
changeset 18 2f34d5167611
parent 3 41300fa6a67c
child 37 758a864f9613
equal deleted inserted replaced
3:41300fa6a67c 18:2f34d5167611
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtNetwork module of the Qt Toolkit.
     7 ** This file is part of the QtNetwork module of the Qt Toolkit.
     8 **
     8 **
   992 
   992 
   993 qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
   993 qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
   994 {
   994 {
   995     Q_Q(QNativeSocketEngine);
   995     Q_Q(QNativeSocketEngine);
   996     qint64 ret = 0;
   996     qint64 ret = 0;
   997     // don't send more than 49152 per call to WSASendTo to avoid getting a WSAENOBUFS
   997     qint64 bytesToSend = len;
       
   998 
   998     for (;;) {
   999     for (;;) {
   999         qint64 bytesToSend = qMin<qint64>(49152, len - ret);
       
  1000         WSABUF buf;
  1000         WSABUF buf;
  1001         buf.buf = (char*)data + ret;
  1001         buf.buf = (char*)data + ret;
  1002         buf.len = bytesToSend;
  1002         buf.len = bytesToSend;
  1003         DWORD flags = 0;
  1003         DWORD flags = 0;
  1004         DWORD bytesWritten = 0;
  1004         DWORD bytesWritten = 0;
  1005 
  1005 
  1006         int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0);
  1006         int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0);
  1007 
  1007 
  1008         ret += qint64(bytesWritten);
  1008         ret += qint64(bytesWritten);
  1009 
  1009 
       
  1010         int err;
  1010         if (socketRet != SOCKET_ERROR) {
  1011         if (socketRet != SOCKET_ERROR) {
  1011             if (ret == len)
  1012             if (ret == len)
  1012                 break;
  1013                 break;
  1013             else
  1014             else
  1014                 continue;
  1015                 continue;
  1015         } else if (WSAGetLastError() == WSAEWOULDBLOCK) {
  1016         } else if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) {
  1016             break;
  1017             break;
       
  1018         } else if (err == WSAENOBUFS) {
       
  1019             // this function used to not send more than 49152 per call to WSASendTo
       
  1020             // to avoid getting a WSAENOBUFS. However this is a performance regression
       
  1021             // and we think it only appears with old windows versions. We now handle the
       
  1022             // WSAENOBUFS and hope it never appears anyway.
       
  1023             // just go on, the next loop run we will try a smaller number
  1017         } else {
  1024         } else {
  1018             int err = WSAGetLastError();
       
  1019             WS_ERROR_DEBUG(err);
  1025             WS_ERROR_DEBUG(err);
  1020             switch (err) {
  1026             switch (err) {
  1021             case WSAECONNRESET:
  1027             case WSAECONNRESET:
  1022             case WSAECONNABORTED:
  1028             case WSAECONNABORTED:
  1023                 ret = -1;
  1029                 ret = -1;
  1027             default:
  1033             default:
  1028                 break;
  1034                 break;
  1029             }
  1035             }
  1030             break;
  1036             break;
  1031         }
  1037         }
       
  1038 
       
  1039         // for next send:
       
  1040         bytesToSend = qMin<qint64>(49152, len - ret);
  1032     }
  1041     }
  1033 
  1042 
  1034 #if defined (QNATIVESOCKETENGINE_DEBUG)
  1043 #if defined (QNATIVESOCKETENGINE_DEBUG)
  1035     qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %li) == %li",
  1044     qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %li) == %li",
  1036            data, qt_prettyDebug(data, qMin((int)ret, 16), (int)ret).data(), (int)len, (int)ret);
  1045            data, qt_prettyDebug(data, qMin((int)ret, 16), (int)ret).data(), (int)len, (int)ret);
  1057         case WSAEWOULDBLOCK:
  1066         case WSAEWOULDBLOCK:
  1058             ret = -2;
  1067             ret = -2;
  1059             break;
  1068             break;
  1060         case WSAEBADF:
  1069         case WSAEBADF:
  1061         case WSAEINVAL:
  1070         case WSAEINVAL:
  1062             setError(QAbstractSocket::NetworkError, ReadErrorString);
  1071             //error string is now set in read(), not here in nativeRead()
  1063             break;
  1072             break;
  1064         case WSAECONNRESET:
  1073         case WSAECONNRESET:
  1065         case WSAECONNABORTED:
  1074         case WSAECONNABORTED:
  1066             // for tcp sockets this will be handled in QNativeSocketEngine::read
  1075             // for tcp sockets this will be handled in QNativeSocketEngine::read
  1067             ret = 0;
  1076             ret = 0;
  1188 void QNativeSocketEnginePrivate::nativeClose()
  1197 void QNativeSocketEnginePrivate::nativeClose()
  1189 {
  1198 {
  1190 #if defined (QTCPSOCKETENGINE_DEBUG)
  1199 #if defined (QTCPSOCKETENGINE_DEBUG)
  1191     qDebug("QNativeSocketEnginePrivate::nativeClose()");
  1200     qDebug("QNativeSocketEnginePrivate::nativeClose()");
  1192 #endif
  1201 #endif
  1193     linger l = {1, 0};
  1202     // We were doing a setsockopt here before with SO_DONTLINGER. (However with kind of wrong
  1194     ::setsockopt(socketDescriptor, SOL_SOCKET, SO_DONTLINGER, (char*)&l, sizeof(l));
  1203     // usage of parameters, it wants a BOOL but we used a struct and pretended it to be bool).
       
  1204     // We don't think setting this option should be done here, if a user wants it she/he can
       
  1205      // do it manually with socketDescriptor()/setSocketDescriptor();
  1195     ::closesocket(socketDescriptor);
  1206     ::closesocket(socketDescriptor);
  1196 }
  1207 }
  1197 
  1208 
  1198 QT_END_NAMESPACE
  1209 QT_END_NAMESPACE