00001
00025 #include "iothread.h"
00026 #include "hostlookup.h"
00027 #include "text.h"
00028 #include <string.h>
00029 #ifndef NDEBUG
00030 #include <stdio.h>
00031 #endif
00032 #include <assert.h>
00033 #ifndef WIN32
00034 #include <sys/socket.h>
00035 #include <arpa/inet.h>
00036 #include <netdb.h>
00037 #include <unistd.h>
00038 #endif
00039 #include <SDL.h>
00040
00046 static struct addrinfo *addrLookup = NULL;
00047
00053 static char *lookupName = NULL;
00054
00066 static int conditionCode = 0;
00067
00073 static INetAddr hostaddr;
00074
00075 char localhostName[MAX_HOST_LEN] = { 0 };
00076
00077 char localhostAddrStr[INET6_ADDRSTRLEN] = { 0 };
00078
00087 static void DoAddrLookup(void *name) {
00088 struct addrinfo hint;
00089 hint.ai_flags = AI_CANONNAME;
00090 hint.ai_family = 0;
00091 hint.ai_socktype = SOCK_DGRAM;
00092 hint.ai_protocol = 0;
00093 hint.ai_addrlen = 0;
00094 hint.ai_addr = NULL;
00095 hint.ai_canonname = NULL;
00096 hint.ai_next = NULL;
00097
00098 if (addrLookup) freeaddrinfo(addrLookup);
00099 conditionCode = getaddrinfo(name, NULL, &hint, &addrLookup);
00100 }
00101
00109 static void DoNameLookup(void *address) {
00110 SocketAddr addr;
00111 assert(lookupName != NULL);
00112 if (address == NULL) {
00113 if (hostaddr.family == AF_INET6) {
00114 addr.ipv6.sin6_family = AF_INET6;
00115 addr.ipv6.sin6_addr = hostaddr.ipv6;
00116 addr.length = sizeof(struct sockaddr_in6);
00117 }
00118 else {
00119 addr.ipv4.sin_family = AF_INET;
00120 addr.ipv4.sin_addr = hostaddr.ipv4;
00121 addr.length = sizeof(struct sockaddr_in);
00122 }
00123 address = &addr;
00124 }
00125 if ((conditionCode = getnameinfo(&(((SocketAddr*)address)->addr),
00126 ((SocketAddr*)address)->length, lookupName, MAX_HOST_LEN, 0, 0, 0)) == 0) {
00127
00128 lookupName[MAX_HOST_LEN - 1] = 0;
00129 }
00130 }
00131
00132 void StartAddrLookup(char *name) {
00133
00134 #ifndef NDEBUG
00135
00136
00137
00138
00139
00140 #endif
00141 while (conditionCode > 0) {
00142 SDL_Delay(1);
00143 }
00144 conditionCode = 1;
00145 QueueOperation(DoAddrLookup, name);
00146 }
00147
00148 #ifdef WIN32
00149 int inet_pton(int fam, char *straddr, void *addr) {
00150
00151 if (fam == AF_INET) {
00152
00153 if ((((struct in_addr*)addr)->s_addr = inet_addr(straddr)) != -1) {
00154
00155 return 1;
00156 }
00157
00158 return 0;
00159 }
00160
00161 return -1;
00162 }
00163 #endif
00164
00165 Bool StartStrNameLookup(char *addrstr, char *name) {
00166
00167 #ifndef NDEBUG
00168
00169
00170
00171
00172
00173 #endif
00174 while (conditionCode > 0) {
00175 SDL_Delay(1);
00176 }
00177
00178 conditionCode = 1;
00179
00180 if ((inet_pton(hostaddr.family = AF_INET, addrstr, &hostaddr) > 0) ||
00181 (inet_pton(hostaddr.family = AF_INET6, addrstr, &hostaddr) > 0)) {
00182
00183 lookupName = name;
00184
00185 QueueOperation(DoNameLookup, NULL);
00186
00187 return TRUE;
00188 }
00189
00190 conditionCode = 0;
00191 return FALSE;
00192 }
00193
00194 void StartNameLookup(SocketAddr *addr, char *name) {
00195
00196 #ifndef NDEBUG
00197
00198
00199
00200
00201
00202 #endif
00203 while (conditionCode > 0) {
00204 SDL_Delay(1);
00205 }
00206
00207 conditionCode = 1;
00208
00209 lookupName = name;
00210
00211 QueueOperation(DoNameLookup, addr);
00212 }
00213
00214 int LookupResult(char *name, INetAddr *addr) {
00215
00216 if (conditionCode == 1) return 0;
00217
00218 if (conditionCode != 0) {
00219
00220
00221 #ifndef NDEBUG
00222 if (addrLookup == NULL) {
00223 prnfile(stderr, strings[STRING_ERR_HOSTLOOK],
00224 gai_strerror(conditionCode));
00225 }
00226 #endif
00227 return -1;
00228 }
00229
00230 if (addrLookup == NULL) {
00231 if (addr != NULL) {
00232 if ((addr->family = hostaddr.family) == AF_INET6) {
00233 addr->ipv6 = hostaddr.ipv6;
00234 }
00235 else {
00236 addr->ipv4 = hostaddr.ipv4;
00237 }
00238 }
00239 }
00240
00241 else {
00242
00243 if (name != NULL) {
00244
00245 if (addrLookup->ai_canonname) {
00246
00247 strncpy(name, addrLookup->ai_canonname, MAX_HOST_LEN);
00248
00249 name[MAX_HOST_LEN - 1] = 0;
00250 }
00251 else {
00252
00253 name[0] = 0;
00254 }
00255 }
00256
00257 if (addr != NULL) {
00258
00259 if ((addr->family = addrLookup->ai_family) == AF_INET6) {
00260 addr->ipv6 =
00261 ((struct sockaddr_in6*)(addrLookup->ai_addr))->sin6_addr;
00262 }
00263 else {
00264 addr->ipv4 =
00265 ((struct sockaddr_in*)(addrLookup->ai_addr))->sin_addr;
00266 }
00267 }
00268
00269 freeaddrinfo(addrLookup);
00270 addrLookup = NULL;
00271 }
00272 conditionCode = 0;
00273 return 1;
00274 }
00275
00276 void DoHostnameLookup(void *ignore) {
00277 conditionCode = 1;
00278
00279 gethostname(localhostName, MAX_HOST_LEN);
00280
00281 localhostName[MAX_HOST_LEN - 1] = 0;
00282
00283 DoAddrLookup(localhostName);
00284
00285 if ((conditionCode++ == 0) && addrLookup->ai_canonname &&
00286 (strncmp("localhost", addrLookup->ai_canonname, MAX_HOST_LEN) != 0)) {
00287
00288 strncpy(localhostName, addrLookup->ai_canonname, MAX_HOST_LEN);
00289
00290 localhostName[MAX_HOST_LEN - 1] = 0;
00291
00292 if (((addrLookup->ai_family == AF_INET) &&
00293 (((struct sockaddr_in*)(addrLookup->ai_addr))->sin_addr.s_addr !=
00294 htonl(INADDR_LOOPBACK))) || ((addrLookup->ai_family == AF_INET6) &&
00295 !IN6_IS_ADDR_LOOPBACK(
00296 &(((struct sockaddr_in6*)(addrLookup->ai_addr))->sin6_addr)))) {
00297
00298 #ifdef WIN32
00299
00300 char *addrstr;
00301 if ((addrstr =
00302 inet_ntoa(((struct sockaddr_in*)(addrLookup->ai_addr))->sin_addr))
00303 != NULL) {
00304 strcpy(localhostAddrStr, addrstr);
00305 }
00306 #else
00307
00308 if (inet_ntop(addrLookup->ai_family,
00309 (addrLookup->ai_family == AF_INET) ?
00310 (void*)&((struct sockaddr_in*)(addrLookup->ai_addr))->sin_addr :
00311 (void*)&((struct sockaddr_in6*)(addrLookup->ai_addr))->sin6_addr,
00312 localhostAddrStr, sizeof(localhostAddrStr)) == NULL) {
00313
00314
00315 localhostAddrStr[0] = 0;
00316 }
00317 #endif
00318 }
00319 }
00320
00321 freeaddrinfo(addrLookup);
00322 addrLookup = NULL;
00323
00324 conditionCode = 0;
00325 }
00326