summaryrefslogtreecommitdiff
path: root/core/io
diff options
context:
space:
mode:
Diffstat (limited to 'core/io')
-rw-r--r--core/io/ip.cpp9
-rw-r--r--core/io/ip_address.cpp82
-rw-r--r--core/io/ip_address.h21
3 files changed, 65 insertions, 47 deletions
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 00835c26d5..113be976ac 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -82,7 +82,7 @@ struct _IP_ResolverPrivate {
continue;
queue[i].response=IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type);
- if (queue[i].response.type==IP_Address::TYPE_NONE)
+ if (queue[i].response==IP_Address())
queue[i].status=IP::RESOLVER_STATUS_ERROR;
else
queue[i].status=IP::RESOLVER_STATUS_DONE;
@@ -116,7 +116,8 @@ IP_Address IP::resolve_hostname(const String& p_hostname, IP::Type p_type) {
GLOBAL_LOCK_FUNCTION;
if (resolver->cache.has(p_hostname))
- if (resolver->cache[p_hostname].type & p_type != 0)
+ if ((resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV6) ||
+ (!resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV4))
return resolver->cache[p_hostname];
// requested type is different from type in cache. continue resolution, if successful it'll overwrite cache
@@ -138,7 +139,9 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP::Typ
resolver->queue[id].hostname=p_hostname;
resolver->queue[id].type = p_type;
- if (resolver->cache.has(p_hostname) && (resolver->cache[p_hostname].type & p_type) != 0) {
+ if (resolver->cache.has(p_hostname) &&
+ ((resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV6) ||
+ (!resolver->cache[p_hostname].is_ipv4() && p_type != IP::TYPE_IPV4))) {
resolver->queue[id].response=resolver->cache[p_hostname];
resolver->queue[id].status=IP::RESOLVER_STATUS_DONE;
} else {
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index 9887cd132b..7df5fe79ec 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -38,21 +38,18 @@ IP_Address::operator Variant() const {
IP_Address::operator String() const {
- if (type == TYPE_NONE)
- return "0.0.0.0";
- if (type == TYPE_IPV4)
- return itos(field8[0])+"."+itos(field8[1])+"."+itos(field8[2])+"."+itos(field8[3]);
- else {
- String ret;
- for (int i=0; i<8; i++) {
- if (i > 0)
- ret = ret + ":";
- uint16_t num = (field8[i*2] << 8) + field8[i*2+1];
- ret = ret + String::num_int64(num, 16);
- };
-
- return ret;
+ if(is_ipv4())
+ // IPv4 address mapped to IPv6
+ return itos(field8[12])+"."+itos(field8[13])+"."+itos(field8[14])+"."+itos(field8[15]);
+ String ret;
+ for (int i=0; i<8; i++) {
+ if (i > 0)
+ ret = ret + ":";
+ uint16_t num = (field8[i*2] << 8) + field8[i*2+1];
+ ret = ret + String::num_int64(num, 16);
};
+
+ return ret;
}
static void _parse_hex(const String& p_string, int p_start, uint8_t* p_dst) {
@@ -176,17 +173,41 @@ void IP_Address::clear() {
memset(&field8[0], 0, sizeof(field8));
};
+bool IP_Address::is_ipv4() const{
+ return (field32[0]==0 && field32[1]==0 && field16[4]==0 && field16[5]==0xffff);
+}
+
+const uint8_t *IP_Address::get_ipv4() const{
+ ERR_FAIL_COND_V(!is_ipv4(),0);
+ return &(field8[12]);
+}
+
+void IP_Address::set_ipv4(const uint8_t *p_ip) {
+ clear();
+ field16[5]=0xffff;
+ field32[3]=*((const uint32_t *)p_ip);
+}
+
+const uint8_t *IP_Address::get_ipv6() const{
+ return field8;
+}
+
+void IP_Address::set_ipv6(const uint8_t *p_buf) {
+ clear();
+ for (int i=0; i<16; i++)
+ field8[i] = p_buf[i];
+}
+
IP_Address::IP_Address(const String& p_string) {
clear();
if (p_string.find(":") >= 0) {
_parse_ipv6(p_string);
- type = TYPE_IPV6;
} else {
-
- _parse_ipv4(p_string, 0, &field8[0]);
- type = TYPE_IPV4;
+ // Mapped to IPv6
+ field16[5] = 0xffff;
+ _parse_ipv4(p_string, 0, &field8[12]);
};
}
@@ -198,25 +219,22 @@ _FORCE_INLINE_ static void _32_to_buf(uint8_t* p_dst, uint32_t p_n) {
p_dst[3] = (p_n >> 0) & 0xff;
};
-IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, IP_Address::AddrType p_type) {
+IP_Address::IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6) {
- type = p_type;
- memset(&field8[0], 0, sizeof(field8));
- if (p_type == TYPE_IPV4) {
- field8[0]=p_a;
- field8[1]=p_b;
- field8[2]=p_c;
- field8[3]=p_d;
- } else if (type == TYPE_IPV6) {
+ clear();
+ if (!is_v6) {
+ // Mapped to IPv6
+ field16[5]=0xffff;
+ field8[12]=p_a;
+ field8[13]=p_b;
+ field8[14]=p_c;
+ field8[15]=p_d;
+ } else {
_32_to_buf(&field8[0], p_a);
_32_to_buf(&field8[4], p_b);
_32_to_buf(&field8[8], p_c);
_32_to_buf(&field8[12], p_d);
- } else {
- type = TYPE_NONE;
- ERR_EXPLAIN("Invalid type specified for IP_Address (use TYPE_IPV4 or TYPE_IPV6");
- ERR_FAIL();
- };
+ }
}
diff --git a/core/io/ip_address.h b/core/io/ip_address.h
index fe13d70611..b7c1649547 100644
--- a/core/io/ip_address.h
+++ b/core/io/ip_address.h
@@ -33,16 +33,7 @@
struct IP_Address {
-public:
- enum AddrType {
- TYPE_NONE = 0,
- TYPE_IPV4 = 1,
- TYPE_IPV6 = 2,
-
- TYPE_ANY = 3,
- };
-
- AddrType type;
+private:
union {
uint8_t field8[16];
@@ -70,11 +61,17 @@ public:
}
void clear();
+ bool is_ipv4() const;
+ const uint8_t *get_ipv4() const;
+ void set_ipv4(const uint8_t *p_ip);
+
+ const uint8_t *get_ipv6() const;
+ void set_ipv6(const uint8_t *buf);
operator String() const;
IP_Address(const String& p_string);
- IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, AddrType p_type=TYPE_IPV4);
- IP_Address() { clear(); type=TYPE_NONE; }
+ IP_Address(uint32_t p_a,uint32_t p_b,uint32_t p_c,uint32_t p_d, bool is_v6=false);
+ IP_Address() { clear(); }
};