/* * Copyright (C) 2005 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // // Internet address class. // #ifdef HAVE_WINSOCK # include #else # include # include # include //# include # include #endif #include #include #include #include #include #include #include #include using namespace android; /* * =========================================================================== * InetAddress * =========================================================================== */ // lock for the next couple of functions; could tuck into InetAddress static Mutex* gGHBNLock; /* * Lock/unlock access to the hostent struct returned by gethostbyname(). */ static inline void lock_gethostbyname(void) { if (gGHBNLock == NULL) gGHBNLock = new Mutex; gGHBNLock->lock(); } static inline void unlock_gethostbyname(void) { assert(gGHBNLock != NULL); gGHBNLock->unlock(); } /* * Constructor -- just init members. This is private so that callers * are required to use getByName(). */ InetAddress::InetAddress(void) : mAddress(NULL), mLength(-1), mName(NULL) { } /* * Destructor -- free address storage. */ InetAddress::~InetAddress(void) { delete[] (char*) mAddress; delete[] mName; } /* * Copy constructor. */ InetAddress::InetAddress(const InetAddress& orig) { *this = orig; // use assignment code } /* * Assignment operator. */ InetAddress& InetAddress::operator=(const InetAddress& addr) { // handle self-assignment if (this == &addr) return *this; // copy mLength and mAddress mLength = addr.mLength; if (mLength > 0) { mAddress = new char[mLength]; memcpy(mAddress, addr.mAddress, mLength); LOG(LOG_DEBUG, "socket", "HEY: copied %d bytes in assignment operator\n", mLength); } else { mAddress = NULL; } // copy mName mName = new char[strlen(addr.mName)+1]; strcpy(mName, addr.mName); return *this; } /* * Create a new object from a name or a dotted-number IP notation. * * Returns NULL on failure. */ InetAddress* InetAddress::getByName(const char* host) { InetAddress* newAddr = NULL; struct sockaddr_in addr; struct hostent* he; DurationTimer hostTimer, lockTimer; // gethostbyname() isn't reentrant, so we need to lock things until // we can copy the data out. lockTimer.start(); lock_gethostbyname(); hostTimer.start(); he = gethostbyname(host); if (he == NULL) { LOG(LOG_WARN, "socket", "WARNING: cannot resolve host %s\n", host); unlock_gethostbyname(); return NULL; } memcpy(&addr.sin_addr, he->h_addr, he->h_length); addr.sin_family = he->h_addrtype; addr.sin_port = 0; // got it, unlock us hostTimer.stop(); he = NULL; unlock_gethostbyname(); lockTimer.stop(); if ((long) lockTimer.durationUsecs() > 100000) { long lockTime = (long) lockTimer.durationUsecs(); long hostTime = (long) hostTimer.durationUsecs(); LOG(LOG_DEBUG, "socket", "Lookup of %s took %.3fs (gethostbyname=%.3fs lock=%.3fs)\n", host, lockTime / 1000000.0, hostTime / 1000000.0, (lockTime - hostTime) / 1000000.0); } // Alloc storage and copy it over. newAddr = new InetAddress(); if (newAddr == NULL) return NULL; newAddr->mLength = sizeof(struct sockaddr_in); newAddr->mAddress = new char[sizeof(struct sockaddr_in)]; if (newAddr->mAddress == NULL) { delete newAddr; return NULL; } memcpy(newAddr->mAddress, &addr, newAddr->mLength); // Keep this for debug messages. newAddr->mName = new char[strlen(host)+1]; if (newAddr->mName == NULL) { delete newAddr; return NULL; } strcpy(newAddr->mName, host); return newAddr; } /* * =========================================================================== * InetSocketAddress * =========================================================================== */ /* * Create an address with the host wildcard (INADDR_ANY). */ bool InetSocketAddress::create(int port) { assert(mAddress == NULL); mAddress = InetAddress::getByName("0.0.0.0"); if (mAddress == NULL) return false; mPort = port; return true; } /* * Create address with host and port specified. */ bool InetSocketAddress::create(const InetAddress* addr, int port) { assert(mAddress == NULL); mAddress = new InetAddress(*addr); // make a copy if (mAddress == NULL) return false; mPort = port; return true; } /* * Create address with host and port specified. */ bool InetSocketAddress::create(const char* host, int port) { assert(mAddress == NULL); mAddress = InetAddress::getByName(host); if (mAddress == NULL) return false; mPort = port; return true; }