diff options
Diffstat (limited to 'libs/utils/InetAddress.cpp')
-rw-r--r-- | libs/utils/InetAddress.cpp | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/libs/utils/InetAddress.cpp b/libs/utils/InetAddress.cpp new file mode 100644 index 000000000000..39a0a6839a53 --- /dev/null +++ b/libs/utils/InetAddress.cpp @@ -0,0 +1,236 @@ +/* + * 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 <winsock2.h> +#else +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +//# include <arpa/inet.h> +# include <netdb.h> +#endif + +#include <utils/inet_address.h> +#include <utils/threads.h> +#include <utils/Log.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +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; +} + |