+#else
+int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
+{
+ lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
+ int i, port, namelen, d1, d2, d3, d4;
+ struct hostent *hostentry;
+ unsigned char *a;
+ const char *colon;
+ char name[128];
+#ifdef STANDALONETEST
+ char string2[128];
+#endif
+ if (!address || !string || !*string)
+ return 0;
+ memset(address, 0, sizeof(*address));
+ address->addresstype = LHNETADDRESSTYPE_NONE;
+ port = 0;
+ colon = strrchr(string, ':');
+ if (colon && (colon == strchr(string, ':') || (string[0] == '[' && colon - string > 0 && colon[-1] == ']')))
+ // EITHER: colon is the ONLY colon OR: colon comes after [...] delimited IPv6 address
+ // fixes misparsing of IPv6 addresses without port
+ {
+ port = atoi(colon + 1);
+ }
+ else
+ colon = string + strlen(string);
+ if (port == 0)
+ port = defaultport;
+ namelen = colon - string;
+ if (namelen > 127)
+ namelen = 127;
+ if (string[0] == '[' && namelen > 0 && string[namelen-1] == ']') // ipv6
+ {
+ string++;
+ namelen -= 2;
+ }
+ memcpy(name, string, namelen);
+ name[namelen] = 0;
+ // handle loopback
+ if (!strcmp(name, "local"))
+ {
+ address->addresstype = LHNETADDRESSTYPE_LOOP;
+ address->port = port;
+ return 1;
+ }
+ // try to parse as dotted decimal ipv4 address first
+ // note this supports partial ip addresses
+ d1 = d2 = d3 = d4 = 0;
+#if _MSC_VER >= 1400
+#define sscanf sscanf_s
+#endif
+ if (sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) >= 1 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
+ {
+ // parsed a valid ipv4 address
+ address->addresstype = LHNETADDRESSTYPE_INET4;
+ address->port = port;
+ address->addr.in.sin_family = AF_INET;
+ address->addr.in.sin_port = htons((unsigned short)port);
+ a = (unsigned char *)&address->addr.in.sin_addr;
+ a[0] = d1;
+ a[1] = d2;
+ a[2] = d3;
+ a[3] = d4;
+#ifdef STANDALONETEST
+ LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
+ printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
+#endif
+ return 1;
+ }
+ for (i = 0;i < MAX_NAMECACHE;i++)
+ if (!strcmp(namecache[i].name, name))
+ break;
+#ifdef STANDALONETEST
+ if (i < MAX_NAMECACHE)
+#else
+ if (i < MAX_NAMECACHE && realtime < namecache[i].expirationtime)
+#endif
+ {
+ *address = namecache[i].address;
+ address->port = port;
+ if (address->addresstype == LHNETADDRESSTYPE_INET6)
+ {
+#ifndef NOSUPPORTIPV6
+ address->addr.in6.sin6_port = htons((unsigned short)port);
+ return 1;
+#endif
+ }
+ else if (address->addresstype == LHNETADDRESSTYPE_INET4)
+ {
+ address->addr.in.sin_port = htons((unsigned short)port);
+ return 1;
+ }
+ return 0;
+ }
+ // try gethostbyname (handles dns and other ip formats)
+ hostentry = gethostbyname(name);
+ if (hostentry)
+ {
+ if (hostentry->h_addrtype == AF_INET6)
+ {
+#ifndef NOSUPPORTIPV6
+ // great it worked
+ address->addresstype = LHNETADDRESSTYPE_INET6;
+ address->port = port;
+ address->addr.in6.sin6_family = hostentry->h_addrtype;
+ address->addr.in6.sin6_port = htons((unsigned short)port);
+ memcpy(&address->addr.in6.sin6_addr, hostentry->h_addr_list[0], sizeof(address->addr.in6.sin6_addr));
+ for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
+ namecache[namecacheposition].name[i] = name[i];
+ namecache[namecacheposition].name[i] = 0;
+#ifndef STANDALONETEST
+ namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
+#endif
+ namecache[namecacheposition].address = *address;
+ namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
+#ifdef STANDALONETEST
+ LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
+ printf("gethostbyname(\"%s\") returned ipv6 address %s\n", string, string2);
+#endif
+ return 1;
+#endif
+ }
+ else if (hostentry->h_addrtype == AF_INET)
+ {
+ // great it worked
+ address->addresstype = LHNETADDRESSTYPE_INET4;
+ address->port = port;
+ address->addr.in.sin_family = hostentry->h_addrtype;
+ address->addr.in.sin_port = htons((unsigned short)port);
+ memcpy(&address->addr.in.sin_addr, hostentry->h_addr_list[0], sizeof(address->addr.in.sin_addr));
+ for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
+ namecache[namecacheposition].name[i] = name[i];
+ namecache[namecacheposition].name[i] = 0;
+#ifndef STANDALONETEST
+ namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
+#endif
+ namecache[namecacheposition].address = *address;
+ namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
+#ifdef STANDALONETEST
+ LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
+ printf("gethostbyname(\"%s\") returned ipv4 address %s\n", string, string2);
+#endif
+ return 1;
+ }
+ }
+#ifdef STANDALONETEST
+ printf("gethostbyname failed on address \"%s\"\n", name);
+#endif
+ for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
+ namecache[namecacheposition].name[i] = name[i];
+ namecache[namecacheposition].name[i] = 0;
+#ifndef STANDALONETEST
+ namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
+#endif
+ namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
+ namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
+ return 0;
+}
+#endif