sdkcreationmw/sdkruntimes/wsock/src/WinsockHostResolver.cpp
changeset 0 b26acd06ea60
child 1 ac50fd48361b
equal deleted inserted replaced
-1:000000000000 0:b26acd06ea60
       
     1 /*
       
     2 * Copyright (c) 2004-2005 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: HostResolver: "
       
    20 #include "wsock.h"
       
    21 #include <in_sock.h>
       
    22 #include <utf.h>
       
    23 #include "WinsockProtocol.h"
       
    24 #include "WinsockProtocolFamily.h"
       
    25 #include "WinsockUtils.h"
       
    26 #include "WinsockHostResolver.h"
       
    27 #include "WinsockUtils.h"
       
    28 
       
    29 //
       
    30 // Structure used in getaddrinfo() call.
       
    31 //
       
    32 typedef struct _WinsockAddrInfo WinsockAddrInfo;
       
    33 struct _WinsockAddrInfo {
       
    34     int ai_flags;              // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST.
       
    35     int ai_family;             // PF_xxx.
       
    36     int ai_socktype;           // SOCK_xxx.
       
    37     int ai_protocol;           // 0 or IPPROTO_xxx for IPv4 and IPv6.
       
    38     size_t ai_addrlen;         // Length of ai_addr.
       
    39     char *ai_canonname;        // Canonical name for nodename.
       
    40     WSockAddr *ai_addr;        // Binary address.
       
    41     WinsockAddrInfo *ai_next;  // Next structure in linked list.
       
    42 };
       
    43 
       
    44 // getaddrinfo
       
    45 typedef int (WINAPI *GetAddrInfoProc)(
       
    46     const char *aNodename,
       
    47     const char *aServname,
       
    48     const WinsockAddrInfo *aHints,
       
    49     WinsockAddrInfo **aResult
       
    50 );
       
    51 
       
    52 // freeaddrinfo
       
    53 typedef void (WINAPI *FreeAddrInfoProc)(
       
    54     WinsockAddrInfo *aInfo
       
    55 );
       
    56 
       
    57 // getnameinfo
       
    58 typedef int (WINAPI *GetNameInfoProc)(
       
    59     const WSockAddr  *sa,
       
    60     int salen,
       
    61     char *host,
       
    62     int hostlen,
       
    63     char *serv,
       
    64     int servlen,
       
    65     int flags
       
    66 );
       
    67 
       
    68 static const char WinsockModule[] = "ws2_32";
       
    69 const TInt KMaxHostNameLen = 256;
       
    70 
       
    71 CWinsockHostResolver* CWinsockHostResolver::NewL(const TWinProtocolDesc* aPd)
       
    72 {
       
    73     CWinsockHostResolver* self = new(ELeave)CWinsockHostResolver(aPd);
       
    74     CleanupStack::PushL(self);
       
    75     self->ConstructL();
       
    76     CleanupStack::Pop(self);
       
    77     return self;
       
    78 }
       
    79 
       
    80 CWinsockHostResolver::CWinsockHostResolver(const TWinProtocolDesc* aProtocol):
       
    81 iProtocolDesc(aProtocol)
       
    82 {
       
    83 }
       
    84 
       
    85 CWinsockHostResolver::~CWinsockHostResolver()
       
    86 {
       
    87     delete iHostName;
       
    88 }
       
    89 
       
    90 void CWinsockHostResolver::ConstructL()
       
    91 {
       
    92     char hostname[KMaxHostNameLen];
       
    93     hostname[0] = 0;
       
    94     gethostname(hostname,N(hostname));
       
    95     TPtrC8 hostnamePtr((unsigned char*)hostname);
       
    96     iHostName = HBufC::NewL(hostnamePtr.Length()+1);
       
    97     TPtr hostNamePtr(iHostName->Des());
       
    98     hostNamePtr.Copy(hostnamePtr);
       
    99     hostNamePtr.ZeroTerminate();
       
   100     TRACE1("host name: %S",iHostName);
       
   101 }
       
   102 
       
   103 CWinsockHostResolver::TResolveErr 
       
   104 CWinsockHostResolver::Resolve6(const char* aHostName,
       
   105                                TInt aIndex, TInetAddr* aAddr)
       
   106 {
       
   107 #define NO_GET_ADDR_INFO ((GetAddrInfoProc)(-1))
       
   108 #define NO_FREE_ADDR_INFO ((FreeAddrInfoProc)(-1))
       
   109 
       
   110     static GetAddrInfoProc getAddrInfo = NULL;
       
   111     static FreeAddrInfoProc freeAddrInfo = NULL;
       
   112 
       
   113     // Initialize XP specific functions
       
   114     if (!getAddrInfo)
       
   115     {
       
   116         // We are linking with ws2_32.dll so if we are loaded, then it 
       
   117         // must be loaded too
       
   118         HMODULE hWs2 = GetModuleHandleA(WinsockModule);
       
   119         freeAddrInfo = (FreeAddrInfoProc)GetProcAddress(hWs2,"freeaddrinfo");
       
   120         if (freeAddrInfo)
       
   121         {
       
   122             TRACE1("found freeaddrinfo at 0x%08x",freeAddrInfo);
       
   123             getAddrInfo = (GetAddrInfoProc)GetProcAddress(hWs2,"getaddrinfo");
       
   124             if (getAddrInfo)
       
   125             {
       
   126                 TRACE1("found getaddrinfo at 0x%08x",getAddrInfo);
       
   127             }
       
   128             else
       
   129             {
       
   130                 TRACE("getaddrinfo is not supported");
       
   131                 getAddrInfo = NO_GET_ADDR_INFO;
       
   132             }
       
   133         }
       
   134         else
       
   135         {
       
   136             TRACE("freeaddrinfo is not supported (getaddrinfo probably too)");
       
   137             freeAddrInfo = NO_FREE_ADDR_INFO;
       
   138             getAddrInfo = NO_GET_ADDR_INFO;
       
   139         }
       
   140     }
       
   141 
       
   142     if (getAddrInfo != NO_GET_ADDR_INFO)
       
   143     {
       
   144         WinsockAddrInfo hints;
       
   145         WinsockAddrInfo *addr = NULL;
       
   146         Mem::FillZ(&hints,sizeof(hints));
       
   147         hints.ai_family = AF_INET6;
       
   148         hints.ai_socktype = SOCK_STREAM;
       
   149 
       
   150         int err = getAddrInfo(aHostName, NULL, &hints, &addr);
       
   151         if (!err && addr)
       
   152         {
       
   153             int index = 0;
       
   154             TResolveErr status = EResolveNoMore;
       
   155             WinsockAddrInfo *ai = addr;
       
   156             while (index < aIndex && ai) ai = ai->ai_next, index++;
       
   157             if (ai) {
       
   158                 WinsockUtils::ToInetAddr(aAddr, ai->ai_addr);
       
   159                 status = EResolveOK;
       
   160             }
       
   161             freeAddrInfo(addr);
       
   162             return status;
       
   163         }
       
   164         else
       
   165         {
       
   166             TRACE1("getAddrInfo error %d",WSAGetLastError());
       
   167         }
       
   168     }
       
   169     return EResolveFailed;
       
   170 }
       
   171 
       
   172 TInt CWinsockHostResolver::Resolve(const char* aHostName, 
       
   173                                    TInt aIndex, 
       
   174                                    TInetAddr* aAddr)
       
   175 {
       
   176     if (iProtocolDesc->iAddrFamily == KAfInet6)
       
   177     {
       
   178         TResolveErr err = Resolve6(aHostName, aIndex, aAddr);
       
   179         switch (err) {
       
   180         case EResolveOK:        return KErrNone;
       
   181         case EResolveNoMore:    return KErrNotFound;
       
   182         case EResolveFailed:    break;
       
   183         }
       
   184     }
       
   185 
       
   186     /* If addrFamily is KAfInet or CallGetAddrInfo failed */
       
   187     struct hostent * host = gethostbyname(aHostName);
       
   188     if (host && host->h_length == 4)
       
   189     {
       
   190         TInt n = 0;
       
   191         while (host->h_addr_list[n]) n++;
       
   192         if (aIndex < n)
       
   193         {
       
   194             struct in_addr in;
       
   195             Mem::Copy(&in, host->h_addr_list[aIndex], host->h_length);
       
   196             if (iProtocolDesc->iAddrFamily == KAfInet6)
       
   197             {
       
   198                 aAddr->SetV4MappedAddress(ntohl(in.s_addr));
       
   199             }
       
   200             else
       
   201             {
       
   202                 aAddr->SetAddress(ntohl(in.s_addr));
       
   203             }
       
   204             return KErrNone;
       
   205         }
       
   206     }
       
   207 
       
   208     return KErrNotFound;
       
   209 }
       
   210 
       
   211 TInt CWinsockHostResolver::GetHostNameFromAddr6(const TIp6Addr& aAddr,
       
   212                                                 THostName& aName)
       
   213 {
       
   214 #define NO_GET_NAME_INFO ((GetNameInfoProc)(-1))
       
   215 
       
   216     static GetNameInfoProc getNameInfo = NULL;
       
   217 
       
   218     // Initialize XP specific functions
       
   219     if (!getNameInfo)
       
   220     {
       
   221         // We are linking with ws2_32.dll so if we are loaded, then it 
       
   222         // must be loaded too
       
   223         HMODULE hWs2 = GetModuleHandleA(WinsockModule);
       
   224         getNameInfo = (GetNameInfoProc)GetProcAddress(hWs2,"getnameinfo");
       
   225         if (getNameInfo)
       
   226         {
       
   227             TRACE1("found getNameInfo at 0x%08x",getNameInfo);
       
   228         }
       
   229         else
       
   230         {
       
   231             TRACE("getNameInfo is not supported");
       
   232             getNameInfo = NO_GET_NAME_INFO;
       
   233         }
       
   234     }
       
   235 
       
   236     if (getNameInfo != NO_GET_NAME_INFO)
       
   237     {
       
   238     	char name[KMaxHostNameLen] = "";
       
   239         WSockAddr sa;
       
   240         TInetAddr inetAddr(aAddr,0);
       
   241         int len = WinsockUtils::ToSockAddr(&sa, &inetAddr);
       
   242         int err = getNameInfo(&sa, len, name, sizeof(name), NULL, 0, 0);
       
   243         if (!err && name[0])
       
   244         {
       
   245             TPtrC8 hostnamePtr((unsigned char*)name);
       
   246             aName.Copy(hostnamePtr);
       
   247             return KErrNone;
       
   248         }
       
   249         else
       
   250         {
       
   251             TRACE1("getNameInfo error %d",WSAGetLastError());
       
   252         }
       
   253     }
       
   254     return KErrNotFound;
       
   255 	
       
   256 }
       
   257 
       
   258 // Takes IPv4 address in network byte order
       
   259 TInt CWinsockHostResolver::GetHostNameFromAddr(TUint32 aAddr,THostName& aName)
       
   260 {
       
   261     struct hostent* host = gethostbyaddr((char*)&aAddr,sizeof(aAddr),AF_INET);
       
   262     if (host)
       
   263     {
       
   264         TPtrC8 hostnamePtr((unsigned char*)host->h_name);
       
   265         aName.Copy(hostnamePtr);
       
   266         return KErrNone;
       
   267     }
       
   268     return KErrNotFound;
       
   269 }
       
   270 
       
   271 // CHostResolvProvdBase
       
   272 void CWinsockHostResolver::GetByName(TNameRecord& aName)
       
   273 {
       
   274     TInt result = KErrNotFound;
       
   275     TInetAddr &addr = TInetAddr::Cast(aName.iAddr);
       
   276     TRACE2("GetByName(%S,%d)",&aName.iName,aName.iFlags);
       
   277 
       
   278     // Note that aName.iFlags is actually the index of the address 
       
   279     // to retreive. First one is zero, and so on. Sometimes we are being
       
   280     // called in a loop with aName.iFlags being incremented each time.
       
   281     // Loop terminates when we return something other than KErrNone.
       
   282     // That happens when client calls RHostResolver::Next function
       
   283 
       
   284     // First assume that it's an IP address string
       
   285     if (addr.Input(aName.iName) == KErrNone)
       
   286     {
       
   287         if (iProtocolDesc->iAddrFamily == KAfInet6 && 
       
   288             addr.Family() == KAfInet)
       
   289         {
       
   290             // Caller asked for IPv6 address
       
   291             addr.ConvertToV4Mapped();
       
   292         }
       
   293         result = ((aName.iFlags == 0) ? KErrNone : KErrNotFound);
       
   294     }
       
   295     else
       
   296     {
       
   297         // Do the name resolution
       
   298         char hostname[KMaxHostNameLen];
       
   299         TPtr8 hostnamePtr((unsigned char*)hostname, N(hostname));
       
   300         CnvUtfConverter::ConvertFromUnicodeToUtf8(hostnamePtr,aName.iName);
       
   301         hostnamePtr.ZeroTerminate();
       
   302         result = Resolve(hostname, aName.iFlags, &addr);
       
   303 #ifdef _REALLY_DEBUG
       
   304         if (result == KErrNone)
       
   305         {
       
   306             TBuf<256> buf;
       
   307             addr.OutputWithScope(buf);
       
   308             TRACE1("%S",&buf);
       
   309         }
       
   310 #endif // _REALLY_DEBUG
       
   311     }
       
   312     iNotify->QueryComplete(result);
       
   313 }
       
   314 
       
   315 void CWinsockHostResolver::GetByAddress(TNameRecord& aName)
       
   316 {
       
   317     TInt result = KErrNotFound;
       
   318     TInetAddr &addr = TInetAddr::Cast(aName.iAddr);
       
   319 
       
   320 #ifdef _REALLY_DEBUG
       
   321     TBuf<256> buf;
       
   322     addr.OutputWithScope(buf);
       
   323     TRACE2("GetByAddress(%S, %d)",&buf, aName.iFlags);
       
   324 #endif // _REALLY_DEBUG
       
   325 
       
   326     // Again, aName.iFlags is the index of the name to retreive. It can be
       
   327     // greater than zero if the client calls RHostResolver::Next. We only
       
   328     // return one, with index zero.
       
   329     if (aName.iFlags == 0)
       
   330     {
       
   331         // Everything that converts into an IPv4 address without loss of
       
   332         // information goes through gethostbyname. Note that IPv4 address
       
   333         // returned by TInetAddr::Address() is in host byte order.
       
   334         TUint32 ipv4 = htonl(addr.Address());
       
   335         result = (ipv4 ?
       
   336             GetHostNameFromAddr(ipv4, aName.iName) :
       
   337             GetHostNameFromAddr6(addr.Ip6Address(), aName.iName));
       
   338 
       
   339 #ifdef _REALLY_DEBUG
       
   340         if (result == KErrNone)
       
   341         {
       
   342             TRACE1("%S",&aName.iName);
       
   343         }
       
   344 #endif // _REALLY_DEBUG
       
   345 
       
   346     }
       
   347     iNotify->QueryComplete(result);
       
   348 }
       
   349 
       
   350 void CWinsockHostResolver::SetHostName(TDes& aNameBuf)
       
   351 {
       
   352     TRACE1("SetHostName(%S)",&aNameBuf);
       
   353     HBufC* newHostName = aNameBuf.Alloc();
       
   354     if (newHostName)
       
   355     {
       
   356         delete iHostName;
       
   357         iHostName = newHostName;
       
   358     }
       
   359 }
       
   360 
       
   361 void CWinsockHostResolver::GetHostName(TDes& aNameBuf)
       
   362 {
       
   363     TRACE("GetHostName");
       
   364     if (iHostName) aNameBuf.Copy(*iHostName);
       
   365     iNotify->QueryComplete(KErrNone);
       
   366 }
       
   367 
       
   368 // CResolverProvdBase
       
   369 void CWinsockHostResolver::CancelCurrentOperation()
       
   370 {
       
   371     // Nothing to cancel, everything is synchronous
       
   372 }