Changeset 160


Ignore:
Timestamp:
Sep 5, 2009, 2:57:17 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

network: Ported QHostInfo and QNetworkInterface to OS/2.

Location:
trunk/src/network
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/network/kernel/kernel.pri

    r2 r160  
    2323unix:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
    2424win32:SOURCES += kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp
     25os2:SOURCES += kernel/qhostinfo_os2.cpp kernel/qnetworkinterface_os2.cpp
    2526
    2627mac:LIBS+= -framework SystemConfiguration
  • TabularUnified trunk/src/network/kernel/qhostinfo_os2.cpp

    r158 r160  
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    44** Contact: Qt Software Information (qt-info@nokia.com)
     5**
     6** Copyright (C) 2009 netlabs.org. OS/2 parts.
    57**
    68** This file is part of the QtNetwork module of the Qt Toolkit.
     
    4446static const int RESOLVER_TIMEOUT = 2000;
    4547
     48#include "qt_os2.h"
    4649#include "qplatformdefs.h"
    4750
     
    5255#include <qurl.h>
    5356#include <qfile.h>
    54 #include <private/qmutexpool_p.h>
    5557
    5658extern "C" {
     
    6163}
    6264
    63 #if defined (QT_NO_GETADDRINFO)
    6465#include <qmutex.h>
    6566QT_BEGIN_NAMESPACE
    6667Q_GLOBAL_STATIC(QMutex, getHostByNameMutex)
    6768QT_END_NAMESPACE
    68 #endif
    6969
    7070QT_BEGIN_NAMESPACE
     
    7575#endif
    7676
    77 // HP-UXi has a bug in getaddrinfo(3) that makes it thread-unsafe
    78 // with this flag. So disable it in that platform.
    79 #if defined(AI_ADDRCONFIG) && !defined(Q_OS_HPUX)
    80 #  define Q_ADDRCONFIG          AI_ADDRCONFIG
    81 #endif
    82 
    83 typedef struct __res_state *res_state_ptr;
    84 
    85 typedef int (*res_init_proto)(void);
    86 static res_init_proto local_res_init = 0;
    87 typedef int (*res_ninit_proto)(res_state_ptr);
    88 static res_ninit_proto local_res_ninit = 0;
    89 typedef void (*res_nclose_proto)(res_state_ptr);
    90 static res_nclose_proto local_res_nclose = 0;
    91 static res_state_ptr local_res = 0;
    92 
    93 static void resolveLibrary()
    94 {
    95 #ifndef QT_NO_LIBRARY
    96     QLibrary lib(QLatin1String("resolv"));
    97     if (!lib.load())
    98         return;
    99 
    100     local_res_init = res_init_proto(lib.resolve("__res_init"));
    101     if (!local_res_init)
    102         local_res_init = res_init_proto(lib.resolve("res_init"));
    103 
    104     local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit"));
    105     if (!local_res_ninit)
    106         local_res_ninit = res_ninit_proto(lib.resolve("res_ninit"));
    107 
    108     if (!local_res_ninit) {
    109         // if we can't get a thread-safe context, we have to use the global _res state
    110         local_res = res_state_ptr(lib.resolve("_res"));
    111     } else {
    112         local_res_nclose = res_nclose_proto(lib.resolve("res_nclose"));
    113         if (!local_res_nclose)
    114             local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose"));
    115         if (!local_res_nclose)
    116             local_res_ninit = 0;
    117     }
    118 #endif
    119 }
    120 
    12177QHostInfo QHostInfoAgent::fromName(const QString &hostName)
    12278{
     
    12985#endif
    13086
    131     // Load res_init on demand.
    132     static volatile bool triedResolve = false;
    133     if (!triedResolve) {
    134 #ifndef QT_NO_THREAD
    135         QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init));
    136 #endif
    137         if (!triedResolve) {
    138             resolveLibrary();
    139             triedResolve = true;
    140         }
    141     }
    142 
    143     // If res_init is available, poll it.
    144     if (local_res_init)
    145         local_res_init();
    146 
    14787    QHostAddress address;
    14888    if (address.setAddress(hostName)) {
    14989        // Reverse lookup
    150 // Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead.
    151 #if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN)
    152         sockaddr_in sa4;
    153 #ifndef QT_NO_IPV6
    154         sockaddr_in6 sa6;
    155 #endif
    156         sockaddr *sa = 0;
    157         QT_SOCKLEN_T saSize = 0;
    158         if (address.protocol() == QAbstractSocket::IPv4Protocol) {
    159             sa = (sockaddr *)&sa4;
    160             saSize = sizeof(sa4);
    161             memset(&sa4, 0, sizeof(sa4));
    162             sa4.sin_family = AF_INET;
    163             sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
    164         }
    165 #ifndef QT_NO_IPV6
    166         else {
    167             sa = (sockaddr *)&sa6;
    168             saSize = sizeof(sa6);
    169             memset(&sa6, 0, sizeof(sa6));
    170             sa6.sin6_family = AF_INET6;
    171             memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr));
    172         }
    173 #endif
    174 
    175         char hbuf[NI_MAXHOST];
    176         if (!sa || getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) != 0) {
    177             results.setError(QHostInfo::HostNotFound);
    178             results.setErrorString(tr("Host not found"));
    179             return results;
    180         }
    181         results.setHostName(QString::fromLatin1(hbuf));
    182 #else
    18390        in_addr_t inetaddr = inet_addr(hostName.toLatin1().constData());
    18491        struct hostent *ent = gethostbyaddr((const char *)&inetaddr, sizeof(inetaddr), AF_INET);
     
    18996        }
    19097        results.setHostName(QString::fromLatin1(ent->h_name));
    191 #endif
    192     }
    193 
    194 #if !defined (QT_NO_GETADDRINFO)
    195     // Call getaddrinfo, and place all IPv4 addresses at the start and
    196     // the IPv6 addresses at the end of the address list in results.
    197     addrinfo *res = 0;
    198     struct addrinfo hints;
    199     memset(&hints, 0, sizeof(hints));
    200     hints.ai_family = PF_UNSPEC;
    201 #ifdef Q_ADDRCONFIG
    202     hints.ai_flags = Q_ADDRCONFIG;
    203 #endif
    204 
    205     int result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res);
    206 # ifdef Q_ADDRCONFIG
    207     if (result == EAI_BADFLAGS) {
    208         // if the lookup failed with AI_ADDRCONFIG set, try again without it
    209         hints.ai_flags = 0;
    210         result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res);
    211     }
    212 # endif
    213 
    214     if (result == 0) {
    215         addrinfo *node = res;
    216         QList<QHostAddress> addresses;
    217         while (node) {
    218             if (node->ai_family == AF_INET) {
    219                 QHostAddress addr;
    220                 addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr));
    221                 if (!addresses.contains(addr))
    222                     addresses.append(addr);
    223             }
    224 #ifndef QT_NO_IPV6
    225             else if (node->ai_family == AF_INET6) {
    226                 QHostAddress addr;
    227                 addr.setAddress(((sockaddr_in6 *) node->ai_addr)->sin6_addr.s6_addr);
    228                 if (!addresses.contains(addr))
    229                     addresses.append(addr);
    230             }
    231 #endif
    232             node = node->ai_next;
    233         }
    234         if (addresses.isEmpty() && node == 0) {
    235             // Reached the end of the list, but no addresses were found; this
    236             // means the list contains one or more unknown address types.
    237             results.setError(QHostInfo::UnknownError);
    238             results.setErrorString(tr("Unknown address type"));
    239         }
    240 
    241         results.setAddresses(addresses);
    242         freeaddrinfo(res);
    243     } else if (result == EAI_NONAME
    244                || result ==  EAI_FAIL
    245 #ifdef EAI_NODATA
    246                // EAI_NODATA is deprecated in RFC 3493
    247                || result == EAI_NODATA
    248 #endif
    249                ) {
    250         results.setError(QHostInfo::HostNotFound);
    251         results.setErrorString(tr("Host not found"));
    252     } else {
    253         results.setError(QHostInfo::UnknownError);
    254         results.setErrorString(QString::fromLocal8Bit(gai_strerror(result)));
    255     }
    256 
    257 #else
     98    }
     99
    258100    // Fall back to gethostbyname for platforms that don't define
    259101    // getaddrinfo. gethostbyname does not support IPv6, and it's not
     
    285127        results.setErrorString(tr("Unknown error"));
    286128    }
    287 #endif //  !defined (QT_NO_GETADDRINFO)
    288129
    289130#if defined(QHOSTINFO_DEBUG)
     
    317158QString QHostInfo::localDomainName()
    318159{
    319     resolveLibrary();
    320     if (local_res_ninit) {
    321         // using thread-safe version
    322         res_state_ptr state = res_state_ptr(qMalloc(sizeof(*state)));
    323         memset(state, 0, sizeof(*state));
    324         local_res_ninit(state);
    325         QString domainName = QUrl::fromAce(state->defdname);
    326         if (domainName.isEmpty())
    327             domainName = QUrl::fromAce(state->dnsrch[0]);
    328         local_res_nclose(state);
    329         qFree(state);
    330 
    331         return domainName;
    332     }
    333 
    334     if (local_res_init && local_res) {
    335         // using thread-unsafe version
    336 
    337 #if defined(QT_NO_GETADDRINFO)
    338         // We have to call res_init to be sure that _res was initialized
    339         // So, for systems without getaddrinfo (which is thread-safe), we lock the mutex too
     160    // We have to call res_init to be sure that _res was initialized
     161    // So, for systems without getaddrinfo (which is thread-safe), we lock the mutex too
     162    {
    340163        QMutexLocker locker(::getHostByNameMutex());
    341 #endif
    342         local_res_init();
    343         QString domainName = QUrl::fromAce(local_res->defdname);
    344         if (domainName.isEmpty())
    345             domainName = QUrl::fromAce(local_res->dnsrch[0]);
    346         return domainName;
     164        if ((_res.options & RES_INIT) || res_init() == 0) {
     165            QString domainName = QUrl::fromAce(_res.defdname);
     166            if (domainName.isEmpty())
     167                domainName = QUrl::fromAce(_res.dnsrch[0]);
     168            return domainName;
     169        }
    347170    }
    348171
    349172    // nothing worked, try doing it by ourselves:
    350173    QFile resolvconf;
    351 #if defined(_PATH_RESCONF)
    352     resolvconf.setFileName(QFile::decodeName(_PATH_RESCONF));
    353 #else
    354     resolvconf.setFileName(QLatin1String("/etc/resolv.conf"));
    355 #endif
     174    QByteArray etc = qgetenv("ETC");
     175    if (etc.isEmpty()) {
     176        etc = "x:\\MPTN\\ETC";
     177        ULONG boot = 0;
     178        DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)boot, sizeof(boot));
     179        etc[0] = (char)(boot + 'A' - 1);
     180    }
     181    // currently, resolv takes precedence over resolv2 assuming that resolv
     182    // is created for PPP connections and therefore should override resolv2
     183    // which is created for permanent LAN connections.
     184    resolvconf.setFileName(QFile::decodeName(etc) + QLatin1String("\\resolv"));
     185    if (!resolvconf.exists())
     186        resolvconf.setFileName(QFile::decodeName(etc)+ QLatin1String("\\resolv2"));
     187
    356188    if (!resolvconf.open(QIODevice::ReadOnly))
    357189        return QString();       // failure
  • TabularUnified trunk/src/network/kernel/qnetworkinterface_os2.cpp

    r158 r160  
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    44** Contact: Qt Software Information (qt-info@nokia.com)
     5**
     6** Copyright (C) 2009 netlabs.org. OS/2 parts.
    57**
    68** This file is part of the QtNetwork module of the Qt Toolkit.
     
    4749#ifndef QT_NO_NETWORKINTERFACE
    4850
    49 #define IP_MULTICAST    // make AIX happy and define IFF_MULTICAST
    50 
    5151#include <sys/types.h>
    5252#include <sys/socket.h>
    5353
    54 #ifdef Q_OS_SOLARIS
    55 # include <sys/sockio.h>
    56 #endif
     54#include <sys/sockio.h>
    5755#include <net/if.h>
    58 
    59 #ifndef QT_NO_GETIFADDRS
    60 # include <ifaddrs.h>
    61 #endif
    62 
    63 #ifdef QT_LINUXBASE
    64 #  include <arpa/inet.h>
    65 #  ifndef SIOCGIFBRDADDR
    66 #    define SIOCGIFBRDADDR 0x8919
    67 #  endif
    68 #endif // QT_LINUXBASE
    6956
    7057#include <qplatformdefs.h>
     
    8067    if (sa->sa_family == AF_INET)
    8168        address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr));
    82 #ifndef QT_NO_IPV6
    83     else if (sa->sa_family == AF_INET6)
    84         address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr);
    85 #endif
    8669    return address;
    8770
     
    10588}
    10689
    107 #ifdef QT_NO_GETIFADDRS
    108 // getifaddrs not available
    109 
    11090static const int STORAGEBUFFER_GROWTH = 256;
    11191
     
    11393{
    11494    QSet<QByteArray> result;
    115 #ifdef QT_NO_IPV6IFNAME
    11695    QByteArray storageBuffer;
    11796    struct ifconf interfaceList;
     
    148127
    149128    return result;
    150 #else
    151     Q_UNUSED(socket);
    152 
    153     // use if_nameindex
    154     struct if_nameindex *interfaceList = ::if_nameindex();
    155     for (struct if_nameindex *ptr = interfaceList; ptr && ptr->if_name; ++ptr)
    156         result << ptr->if_name;
    157 
    158     if_freenameindex(interfaceList);
    159     return result;
    160 #endif
    161129}
    162130
     
    167135    int ifindex = 0;
    168136
    169 #ifndef QT_NO_IPV6IFNAME
    170     // Get the interface index
    171     ifindex = if_nametoindex(req.ifr_name);
    172 
    173     // find the interface data
    174     QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
    175     for ( ; if_it != interfaces.end(); ++if_it)
    176         if ((*if_it)->index == ifindex) {
    177             // existing interface
    178             iface = *if_it;
    179             break;
    180         }
    181 #else
    182137    // Search by name
    183138    QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
     
    188143            break;
    189144        }
    190 #endif
    191145
    192146    if (!iface) {
     
    274228}
    275229
    276 #else
    277 // use getifaddrs
    278 
    279 // platform-specific defs:
    280 # ifdef Q_OS_LINUX
    281 QT_BEGIN_INCLUDE_NAMESPACE
    282 #  include <features.h>
    283 QT_END_INCLUDE_NAMESPACE
    284 # endif
    285 
    286 # if defined(Q_OS_LINUX) &&  __GLIBC__ - 0 >= 2 && __GLIBC_MINOR__ - 0 >= 1
    287 #  include <netpacket/packet.h>
    288 
    289 static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
    290 {
    291     QList<QNetworkInterfacePrivate *> interfaces;
    292 
    293     for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
    294         if ( !ptr->ifa_addr )
    295             continue;
    296 
    297         // Get the interface index
    298         int ifindex = if_nametoindex(ptr->ifa_name);
    299 
    300         // on Linux we use AF_PACKET and sockaddr_ll to obtain hHwAddress
    301         QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
    302         for ( ; if_it != interfaces.end(); ++if_it)
    303             if ((*if_it)->index == ifindex) {
    304                 // this one has been added already
    305                 if ( ptr->ifa_addr->sa_family == AF_PACKET
    306                         && (*if_it)->hardwareAddress.isEmpty()) {
    307                     sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
    308                     (*if_it)->hardwareAddress = (*if_it)->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
    309                 }
    310                 break;
    311             }
    312         if ( if_it != interfaces.end() )
    313             continue;
    314        
    315         QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
    316         interfaces << iface;
    317         iface->index = ifindex;
    318         iface->name = QString::fromLatin1(ptr->ifa_name);
    319         iface->flags = convertFlags(ptr->ifa_flags);
    320 
    321         if ( ptr->ifa_addr->sa_family == AF_PACKET ) {
    322             sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
    323             iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
    324         }
    325     }
    326 
    327     return interfaces;
    328 }
    329 
    330 # elif defined(Q_OS_BSD4)
    331 QT_BEGIN_INCLUDE_NAMESPACE
    332 #  include <net/if_dl.h>
    333 QT_END_INCLUDE_NAMESPACE
    334 
    335 static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
    336 {
    337     QList<QNetworkInterfacePrivate *> interfaces;
    338 
    339     // on NetBSD we use AF_LINK and sockaddr_dl
    340     // scan the list for that family
    341     for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next)
    342         if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_LINK) {
    343             QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
    344             interfaces << iface;
    345 
    346             sockaddr_dl *sdl = (sockaddr_dl *)ptr->ifa_addr;
    347             iface->index = sdl->sdl_index;
    348             iface->name = QString::fromLatin1(ptr->ifa_name);
    349             iface->flags = convertFlags(ptr->ifa_flags);
    350             iface->hardwareAddress = iface->makeHwAddress(sdl->sdl_alen, (uchar*)LLADDR(sdl));
    351         }
    352 
    353     return interfaces;
    354 }
    355 
    356 # else  // Generic version
    357 
    358 static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
    359 {
    360     QList<QNetworkInterfacePrivate *> interfaces;
    361 
    362     // make sure there's one entry for each interface
    363     for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
    364         // Get the interface index
    365         int ifindex = if_nametoindex(ptr->ifa_name);
    366 
    367         QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
    368         for ( ; if_it != interfaces.end(); ++if_it)
    369             if ((*if_it)->index == ifindex)
    370                 // this one has been added already
    371                 break;
    372 
    373         if (if_it == interfaces.end()) {
    374             // none found, create
    375             QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
    376             interfaces << iface;
    377 
    378             iface->index = ifindex;
    379             iface->name = QString::fromLatin1(ptr->ifa_name);
    380             iface->flags = convertFlags(ptr->ifa_flags);
    381         }
    382     }
    383 
    384     return interfaces;
    385 }
    386 
    387 # endif
    388 
    389 
    390 static QList<QNetworkInterfacePrivate *> interfaceListing()
    391 {
    392     QList<QNetworkInterfacePrivate *> interfaces;
    393 
    394     int socket;
    395     if ((socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1)
    396         return interfaces;      // error
    397 
    398     ifaddrs *interfaceListing;
    399     if (getifaddrs(&interfaceListing) == -1) {
    400         // error
    401         ::close(socket);
    402         return interfaces;
    403     }
    404 
    405     interfaces = createInterfaces(interfaceListing);
    406     for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
    407         // Get the interface index
    408         int ifindex = if_nametoindex(ptr->ifa_name);
    409         QNetworkInterfacePrivate *iface = 0;
    410         QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
    411         for ( ; if_it != interfaces.end(); ++if_it)
    412             if ((*if_it)->index == ifindex) {
    413                 // found this interface already
    414                 iface = *if_it;
    415                 break;
    416             }
    417         if (!iface) {
    418             // skip all non-IP interfaces
    419             continue;
    420         }
    421 
    422         QNetworkAddressEntry entry;
    423         entry.setIp(addressFromSockaddr(ptr->ifa_addr));
    424         if (entry.ip().isNull())
    425             // could not parse the address
    426             continue;
    427 
    428         entry.setNetmask(addressFromSockaddr(ptr->ifa_netmask));
    429         if (iface->flags & QNetworkInterface::CanBroadcast)
    430             entry.setBroadcast(addressFromSockaddr(ptr->ifa_broadaddr));
    431 
    432         iface->addressEntries << entry;
    433     }
    434 
    435     freeifaddrs(interfaceListing);
    436     ::close(socket);
    437     return interfaces;
    438 }
    439 #endif
    440 
    441230QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
    442231{
  • TabularUnified trunk/src/network/network.pro

    r2 r160  
    22
    33TARGET   = QtNetwork
     4
     5os2:TARGET_SHORT = QtNet
     6
    47QPRO_PWD = $$PWD
    58DEFINES += QT_BUILD_NETWORK_LIB QT_NO_USING_NAMESPACE
Note: See TracChangeset for help on using the changeset viewer.