blob: 39a0a6839a53d71be39e030d818ed6f0547774aa [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2005 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//
18// Internet address class.
19//
20#ifdef HAVE_WINSOCK
21# include <winsock2.h>
22#else
23# include <sys/types.h>
24# include <sys/socket.h>
25# include <netinet/in.h>
26//# include <arpa/inet.h>
27# include <netdb.h>
28#endif
29
30#include <utils/inet_address.h>
31#include <utils/threads.h>
32#include <utils/Log.h>
33
34#include <errno.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <assert.h>
39
40using namespace android;
41
42
43/*
44 * ===========================================================================
45 * InetAddress
46 * ===========================================================================
47 */
48
49// lock for the next couple of functions; could tuck into InetAddress
50static Mutex* gGHBNLock;
51
52/*
53 * Lock/unlock access to the hostent struct returned by gethostbyname().
54 */
55static inline void lock_gethostbyname(void)
56{
57 if (gGHBNLock == NULL)
58 gGHBNLock = new Mutex;
59 gGHBNLock->lock();
60}
61static inline void unlock_gethostbyname(void)
62{
63 assert(gGHBNLock != NULL);
64 gGHBNLock->unlock();
65}
66
67
68/*
69 * Constructor -- just init members. This is private so that callers
70 * are required to use getByName().
71 */
72InetAddress::InetAddress(void)
73 : mAddress(NULL), mLength(-1), mName(NULL)
74{
75}
76
77/*
78 * Destructor -- free address storage.
79 */
80InetAddress::~InetAddress(void)
81{
82 delete[] (char*) mAddress;
83 delete[] mName;
84}
85
86/*
87 * Copy constructor.
88 */
89InetAddress::InetAddress(const InetAddress& orig)
90{
91 *this = orig; // use assignment code
92}
93
94/*
95 * Assignment operator.
96 */
97InetAddress& InetAddress::operator=(const InetAddress& addr)
98{
99 // handle self-assignment
100 if (this == &addr)
101 return *this;
102 // copy mLength and mAddress
103 mLength = addr.mLength;
104 if (mLength > 0) {
105 mAddress = new char[mLength];
106 memcpy(mAddress, addr.mAddress, mLength);
107 LOG(LOG_DEBUG, "socket",
108 "HEY: copied %d bytes in assignment operator\n", mLength);
109 } else {
110 mAddress = NULL;
111 }
112 // copy mName
113 mName = new char[strlen(addr.mName)+1];
114 strcpy(mName, addr.mName);
115
116 return *this;
117}
118
119/*
120 * Create a new object from a name or a dotted-number IP notation.
121 *
122 * Returns NULL on failure.
123 */
124InetAddress*
125InetAddress::getByName(const char* host)
126{
127 InetAddress* newAddr = NULL;
128 struct sockaddr_in addr;
129 struct hostent* he;
130 DurationTimer hostTimer, lockTimer;
131
132 // gethostbyname() isn't reentrant, so we need to lock things until
133 // we can copy the data out.
134 lockTimer.start();
135 lock_gethostbyname();
136 hostTimer.start();
137
138 he = gethostbyname(host);
139 if (he == NULL) {
140 LOG(LOG_WARN, "socket", "WARNING: cannot resolve host %s\n", host);
141 unlock_gethostbyname();
142 return NULL;
143 }
144
145 memcpy(&addr.sin_addr, he->h_addr, he->h_length);
146 addr.sin_family = he->h_addrtype;
147 addr.sin_port = 0;
148
149 // got it, unlock us
150 hostTimer.stop();
151 he = NULL;
152 unlock_gethostbyname();
153
154 lockTimer.stop();
155 if ((long) lockTimer.durationUsecs() > 100000) {
156 long lockTime = (long) lockTimer.durationUsecs();
157 long hostTime = (long) hostTimer.durationUsecs();
158 LOG(LOG_DEBUG, "socket",
159 "Lookup of %s took %.3fs (gethostbyname=%.3fs lock=%.3fs)\n",
160 host, lockTime / 1000000.0, hostTime / 1000000.0,
161 (lockTime - hostTime) / 1000000.0);
162 }
163
164 // Alloc storage and copy it over.
165 newAddr = new InetAddress();
166 if (newAddr == NULL)
167 return NULL;
168
169 newAddr->mLength = sizeof(struct sockaddr_in);
170 newAddr->mAddress = new char[sizeof(struct sockaddr_in)];
171 if (newAddr->mAddress == NULL) {
172 delete newAddr;
173 return NULL;
174 }
175 memcpy(newAddr->mAddress, &addr, newAddr->mLength);
176
177 // Keep this for debug messages.
178 newAddr->mName = new char[strlen(host)+1];
179 if (newAddr->mName == NULL) {
180 delete newAddr;
181 return NULL;
182 }
183 strcpy(newAddr->mName, host);
184
185 return newAddr;
186}
187
188
189/*
190 * ===========================================================================
191 * InetSocketAddress
192 * ===========================================================================
193 */
194
195/*
196 * Create an address with the host wildcard (INADDR_ANY).
197 */
198bool InetSocketAddress::create(int port)
199{
200 assert(mAddress == NULL);
201
202 mAddress = InetAddress::getByName("0.0.0.0");
203 if (mAddress == NULL)
204 return false;
205 mPort = port;
206 return true;
207}
208
209/*
210 * Create address with host and port specified.
211 */
212bool InetSocketAddress::create(const InetAddress* addr, int port)
213{
214 assert(mAddress == NULL);
215
216 mAddress = new InetAddress(*addr); // make a copy
217 if (mAddress == NULL)
218 return false;
219 mPort = port;
220 return true;
221}
222
223/*
224 * Create address with host and port specified.
225 */
226bool InetSocketAddress::create(const char* host, int port)
227{
228 assert(mAddress == NULL);
229
230 mAddress = InetAddress::getByName(host);
231 if (mAddress == NULL)
232 return false;
233 mPort = port;
234 return true;
235}
236