Merge pull request #7271 from Faless/ipv6_cleanup
Fixes and improvementes for IPv6 implementation.
This commit is contained in:
commit
0b2771bd65
|
@ -842,7 +842,7 @@ bool test_29() {
|
|||
IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
|
||||
OS::get_singleton()->print("ip0 is %ls\n", String(ip0).c_str());
|
||||
|
||||
IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, IP_Address::TYPE_IPV6);
|
||||
IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, true);
|
||||
OS::get_singleton()->print("ip6 is %ls\n", String(ip).c_str());
|
||||
|
||||
IP_Address ip2("fe80::52e5:49ff:fe93:1baf");
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
#include "http_client.h"
|
||||
#include "io/stream_peer_ssl.h"
|
||||
|
||||
VARIANT_ENUM_CAST(IP_Address::AddrType);
|
||||
void HTTPClient::set_ip_type(IP::Type p_type) {
|
||||
ip_type = p_type;
|
||||
}
|
||||
|
||||
Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host, IP_Address::AddrType p_addr_type){
|
||||
Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_verify_host){
|
||||
|
||||
close();
|
||||
tcp_connection->set_ip_type(ip_type);
|
||||
conn_port=p_port;
|
||||
conn_host=p_host;
|
||||
|
||||
|
@ -63,7 +66,7 @@ Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_ve
|
|||
status=STATUS_CONNECTING;
|
||||
} else {
|
||||
//is hostname
|
||||
resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, p_addr_type);
|
||||
resolving=IP::get_singleton()->resolve_hostname_queue_item(conn_host, ip_type);
|
||||
status=STATUS_RESOLVING;
|
||||
|
||||
}
|
||||
|
@ -636,7 +639,8 @@ Error HTTPClient::_get_http_data(uint8_t* p_buffer, int p_bytes,int &r_received)
|
|||
|
||||
void HTTPClient::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true),DEFVAL(IP_Address::TYPE_ANY));
|
||||
ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPClient::set_ip_type);
|
||||
ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true));
|
||||
ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection);
|
||||
ObjectTypeDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection);
|
||||
ObjectTypeDB::bind_method(_MD("request_raw","method","url","headers","body"),&HTTPClient::request_raw);
|
||||
|
@ -762,6 +766,7 @@ String HTTPClient::query_string_from_dict(const Dictionary& p_dict) {
|
|||
|
||||
HTTPClient::HTTPClient(){
|
||||
|
||||
ip_type = IP::TYPE_ANY;
|
||||
tcp_connection = StreamPeerTCP::create_ref();
|
||||
resolving = IP::RESOLVER_INVALID_ID;
|
||||
status=STATUS_DISCONNECTED;
|
||||
|
|
|
@ -132,6 +132,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
IP::Type ip_type;
|
||||
Status status;
|
||||
IP::ResolverID resolving;
|
||||
int conn_port;
|
||||
|
@ -164,8 +165,9 @@ private:
|
|||
public:
|
||||
|
||||
|
||||
void set_ip_type(IP::Type p_type);
|
||||
//Error connect_and_get(const String& p_url,bool p_verify_host=true); //connects to a full url and perform request
|
||||
Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true, IP_Address::AddrType p_addr_type = IP_Address::TYPE_ANY);
|
||||
Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true);
|
||||
|
||||
void set_connection(const Ref<StreamPeer>& p_connection);
|
||||
Ref<StreamPeer> get_connection() const;
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "hash_map.h"
|
||||
|
||||
VARIANT_ENUM_CAST(IP::ResolverStatus);
|
||||
VARIANT_ENUM_CAST(IP_Address::AddrType);
|
||||
|
||||
/************* RESOLVER ******************/
|
||||
|
||||
|
@ -44,12 +43,12 @@ struct _IP_ResolverPrivate {
|
|||
volatile IP::ResolverStatus status;
|
||||
IP_Address response;
|
||||
String hostname;
|
||||
IP_Address::AddrType type;
|
||||
IP::Type type;
|
||||
|
||||
void clear() {
|
||||
status = IP::RESOLVER_STATUS_NONE;
|
||||
response = IP_Address();
|
||||
type = IP_Address::TYPE_NONE;
|
||||
type = IP::TYPE_NONE;
|
||||
hostname="";
|
||||
};
|
||||
|
||||
|
@ -83,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;
|
||||
|
@ -108,25 +107,28 @@ struct _IP_ResolverPrivate {
|
|||
|
||||
HashMap<String, IP_Address> cache;
|
||||
|
||||
static String get_cache_key(String p_hostname, IP::Type p_type) {
|
||||
return itos(p_type) + p_hostname;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
IP_Address IP::resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) {
|
||||
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)
|
||||
return resolver->cache[p_hostname];
|
||||
// requested type is different from type in cache. continue resolution, if successful it'll overwrite cache
|
||||
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
|
||||
if (resolver->cache.has(key))
|
||||
return resolver->cache[key];
|
||||
|
||||
IP_Address res = _resolve_hostname(p_hostname, p_type);
|
||||
resolver->cache[p_hostname]=res;
|
||||
resolver->cache[key]=res;
|
||||
return res;
|
||||
|
||||
}
|
||||
IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type) {
|
||||
IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP::Type p_type) {
|
||||
|
||||
GLOBAL_LOCK_FUNCTION;
|
||||
|
||||
|
@ -137,10 +139,11 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String& p_hostname, IP_Addr
|
|||
return id;
|
||||
}
|
||||
|
||||
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
|
||||
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) {
|
||||
resolver->queue[id].response=resolver->cache[p_hostname];
|
||||
if (resolver->cache.has(key)) {
|
||||
resolver->queue[id].response=resolver->cache[key];
|
||||
resolver->queue[id].status=IP::RESOLVER_STATUS_DONE;
|
||||
} else {
|
||||
resolver->queue[id].response=IP_Address();
|
||||
|
@ -194,7 +197,10 @@ void IP::clear_cache(const String &p_hostname) {
|
|||
if (p_hostname.empty()) {
|
||||
resolver->cache.clear();
|
||||
} else {
|
||||
resolver->cache.erase(p_hostname);
|
||||
resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_NONE));
|
||||
resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_IPV4));
|
||||
resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_IPV6));
|
||||
resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_ANY));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -212,8 +218,8 @@ Array IP::_get_local_addresses() const {
|
|||
|
||||
void IP::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("resolve_hostname","host","ip_type"),&IP::resolve_hostname,DEFVAL(IP_Address::TYPE_ANY));
|
||||
ObjectTypeDB::bind_method(_MD("resolve_hostname_queue_item","host","ip_type"),&IP::resolve_hostname_queue_item,DEFVAL(IP_Address::TYPE_ANY));
|
||||
ObjectTypeDB::bind_method(_MD("resolve_hostname","host","ip_type"),&IP::resolve_hostname,DEFVAL(IP::TYPE_ANY));
|
||||
ObjectTypeDB::bind_method(_MD("resolve_hostname_queue_item","host","ip_type"),&IP::resolve_hostname_queue_item,DEFVAL(IP::TYPE_ANY));
|
||||
ObjectTypeDB::bind_method(_MD("get_resolve_item_status","id"),&IP::get_resolve_item_status);
|
||||
ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address);
|
||||
ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item);
|
||||
|
@ -228,6 +234,10 @@ void IP::_bind_methods() {
|
|||
BIND_CONSTANT( RESOLVER_MAX_QUERIES );
|
||||
BIND_CONSTANT( RESOLVER_INVALID_ID );
|
||||
|
||||
BIND_CONSTANT( TYPE_NONE );
|
||||
BIND_CONSTANT( TYPE_IPV4 );
|
||||
BIND_CONSTANT( TYPE_IPV6 );
|
||||
BIND_CONSTANT( TYPE_ANY );
|
||||
}
|
||||
|
||||
|
||||
|
|
18
core/io/ip.h
18
core/io/ip.h
|
@ -48,12 +48,12 @@ public:
|
|||
RESOLVER_STATUS_ERROR,
|
||||
};
|
||||
|
||||
enum AddressType {
|
||||
enum Type {
|
||||
|
||||
ADDRESS_IPV4 = 1,
|
||||
ADDRESS_IPV6 = 2,
|
||||
|
||||
ADDRESS_ANY = 3,
|
||||
TYPE_NONE = 0,
|
||||
TYPE_IPV4 = 1,
|
||||
TYPE_IPV6 = 2,
|
||||
TYPE_ANY = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -73,7 +73,7 @@ protected:
|
|||
static IP*singleton;
|
||||
static void _bind_methods();
|
||||
|
||||
virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY)=0;
|
||||
virtual IP_Address _resolve_hostname(const String& p_hostname, Type p_type = TYPE_ANY)=0;
|
||||
Array _get_local_addresses() const;
|
||||
|
||||
static IP* (*_create)();
|
||||
|
@ -81,9 +81,9 @@ public:
|
|||
|
||||
|
||||
|
||||
IP_Address resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY);
|
||||
IP_Address resolve_hostname(const String& p_hostname, Type p_type = TYPE_ANY);
|
||||
// async resolver hostname
|
||||
ResolverID resolve_hostname_queue_item(const String& p_hostname, IP_Address::AddrType p_type = IP_Address::TYPE_ANY);
|
||||
ResolverID resolve_hostname_queue_item(const String& p_hostname, Type p_type = TYPE_ANY);
|
||||
ResolverStatus get_resolve_item_status(ResolverID p_id) const;
|
||||
IP_Address get_resolve_item_address(ResolverID p_id) const;
|
||||
virtual void get_local_addresses(List<IP_Address> *r_addresses) const=0;
|
||||
|
@ -101,4 +101,6 @@ public:
|
|||
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(IP::Type);
|
||||
|
||||
#endif // IP_H
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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(); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -31,20 +31,18 @@
|
|||
|
||||
PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL;
|
||||
|
||||
VARIANT_ENUM_CAST(IP_Address::AddrType);
|
||||
|
||||
String PacketPeerUDP::_get_packet_ip() const {
|
||||
|
||||
return get_packet_address();
|
||||
}
|
||||
|
||||
Error PacketPeerUDP::_set_send_address(const String& p_address,int p_port,IP_Address::AddrType p_type) {
|
||||
Error PacketPeerUDP::_set_send_address(const String& p_address, int p_port) {
|
||||
|
||||
IP_Address ip;
|
||||
if (p_address.is_valid_ip_address()) {
|
||||
ip=p_address;
|
||||
} else {
|
||||
ip=IP::get_singleton()->resolve_hostname(p_address, p_type);
|
||||
ip=IP::get_singleton()->resolve_hostname(p_address, ip_type);
|
||||
if (ip==IP_Address())
|
||||
return ERR_CANT_RESOLVE;
|
||||
}
|
||||
|
@ -53,16 +51,22 @@ Error PacketPeerUDP::_set_send_address(const String& p_address,int p_port,IP_Add
|
|||
return OK;
|
||||
}
|
||||
|
||||
void PacketPeerUDP::set_ip_type(IP::Type p_type) {
|
||||
close();
|
||||
ip_type = p_type;
|
||||
}
|
||||
|
||||
void PacketPeerUDP::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("listen:Error","port","ip_type", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(IP_Address::TYPE_ANY),DEFVAL(65536));
|
||||
ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&PacketPeerUDP::set_ip_type);
|
||||
ObjectTypeDB::bind_method(_MD("listen:Error","port", "recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536));
|
||||
ObjectTypeDB::bind_method(_MD("close"),&PacketPeerUDP::close);
|
||||
ObjectTypeDB::bind_method(_MD("wait:Error"),&PacketPeerUDP::wait);
|
||||
ObjectTypeDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening);
|
||||
ObjectTypeDB::bind_method(_MD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip);
|
||||
//ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address);
|
||||
ObjectTypeDB::bind_method(_MD("get_packet_port"),&PacketPeerUDP::get_packet_port);
|
||||
ObjectTypeDB::bind_method(_MD("set_send_address","host","port","ip_type"),&PacketPeerUDP::_set_send_address,DEFVAL(IP_Address::TYPE_ANY));
|
||||
ObjectTypeDB::bind_method(_MD("set_send_address","host","port"),&PacketPeerUDP::_set_send_address);
|
||||
|
||||
|
||||
}
|
||||
|
@ -83,4 +87,5 @@ PacketPeerUDP* PacketPeerUDP::create() {
|
|||
|
||||
PacketPeerUDP::PacketPeerUDP()
|
||||
{
|
||||
ip_type = IP::TYPE_ANY;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define PACKET_PEER_UDP_H
|
||||
|
||||
|
||||
#include "io/ip.h"
|
||||
#include "io/packet_peer.h"
|
||||
|
||||
class PacketPeerUDP : public PacketPeer {
|
||||
|
@ -37,16 +38,19 @@ class PacketPeerUDP : public PacketPeer {
|
|||
|
||||
protected:
|
||||
|
||||
IP::Type ip_type;
|
||||
|
||||
static PacketPeerUDP* (*_create)();
|
||||
static void _bind_methods();
|
||||
|
||||
String _get_packet_ip() const;
|
||||
|
||||
virtual Error _set_send_address(const String& p_address,int p_port, IP_Address::AddrType p_address_type = IP_Address::TYPE_ANY);
|
||||
virtual Error _set_send_address(const String& p_address,int p_port);
|
||||
|
||||
public:
|
||||
|
||||
virtual Error listen(int p_port, IP_Address::AddrType p_address_type = IP_Address::TYPE_ANY, int p_recv_buffer_size=65536)=0;
|
||||
virtual void set_ip_type(IP::Type p_type);
|
||||
virtual Error listen(int p_port, int p_recv_buffer_size=65536)=0;
|
||||
virtual void close()=0;
|
||||
virtual Error wait()=0;
|
||||
virtual bool is_listening() const=0;
|
||||
|
|
|
@ -30,15 +30,13 @@
|
|||
|
||||
StreamPeerTCP* (*StreamPeerTCP::_create)()=NULL;
|
||||
|
||||
VARIANT_ENUM_CAST(IP_Address::AddrType);
|
||||
|
||||
Error StreamPeerTCP::_connect(const String& p_address,int p_port,IP_Address::AddrType p_type) {
|
||||
Error StreamPeerTCP::_connect(const String& p_address,int p_port) {
|
||||
|
||||
IP_Address ip;
|
||||
if (p_address.is_valid_ip_address()) {
|
||||
ip=p_address;
|
||||
} else {
|
||||
ip=IP::get_singleton()->resolve_hostname(p_address, p_type);
|
||||
ip=IP::get_singleton()->resolve_hostname(p_address, ip_type);
|
||||
if (ip==IP_Address())
|
||||
return ERR_CANT_RESOLVE;
|
||||
}
|
||||
|
@ -47,9 +45,15 @@ Error StreamPeerTCP::_connect(const String& p_address,int p_port,IP_Address::Add
|
|||
return OK;
|
||||
}
|
||||
|
||||
void StreamPeerTCP::set_ip_type(IP::Type p_type) {
|
||||
disconnect();
|
||||
ip_type = p_type;
|
||||
}
|
||||
|
||||
void StreamPeerTCP::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("connect","host","port","ip_type"),&StreamPeerTCP::_connect,DEFVAL(IP_Address::TYPE_ANY));
|
||||
ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&StreamPeerTCP::set_ip_type);
|
||||
ObjectTypeDB::bind_method(_MD("connect","host","port"),&StreamPeerTCP::_connect);
|
||||
ObjectTypeDB::bind_method(_MD("is_connected"),&StreamPeerTCP::is_connected);
|
||||
ObjectTypeDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status);
|
||||
ObjectTypeDB::bind_method(_MD("get_connected_host"),&StreamPeerTCP::get_connected_host);
|
||||
|
@ -79,6 +83,7 @@ StreamPeerTCP* StreamPeerTCP::create() {
|
|||
|
||||
StreamPeerTCP::StreamPeerTCP() {
|
||||
|
||||
ip_type = IP::TYPE_ANY;
|
||||
}
|
||||
|
||||
StreamPeerTCP::~StreamPeerTCP() {
|
||||
|
|
|
@ -51,12 +51,15 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
virtual Error _connect(const String& p_address, int p_port, IP_Address::AddrType p_type = IP_Address::TYPE_ANY);
|
||||
IP::Type ip_type;
|
||||
|
||||
virtual Error _connect(const String& p_address, int p_port);
|
||||
static StreamPeerTCP* (*_create)();
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
|
||||
virtual void set_ip_type(IP::Type p_type);
|
||||
virtual Error connect(const IP_Address& p_host, uint16_t p_port)=0;
|
||||
|
||||
//read/write from streampeer
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
|
||||
TCP_Server* (*TCP_Server::_create)()=NULL;
|
||||
|
||||
VARIANT_ENUM_CAST(IP_Address::AddrType);
|
||||
|
||||
Ref<TCP_Server> TCP_Server::create_ref() {
|
||||
|
||||
if (!_create)
|
||||
|
@ -46,19 +44,25 @@ TCP_Server* TCP_Server::create() {
|
|||
return _create();
|
||||
}
|
||||
|
||||
Error TCP_Server::_listen(uint16_t p_port, IP_Address::AddrType p_type, DVector<String> p_accepted_hosts) {
|
||||
Error TCP_Server::_listen(uint16_t p_port, DVector<String> p_accepted_hosts) {
|
||||
|
||||
List<String> hosts;
|
||||
for(int i=0;i<p_accepted_hosts.size();i++)
|
||||
hosts.push_back(p_accepted_hosts.get(i));
|
||||
|
||||
return listen(p_port,p_type, hosts.size()?&hosts:NULL);
|
||||
return listen(p_port, hosts.size()?&hosts:NULL);
|
||||
|
||||
}
|
||||
|
||||
void TCP_Server::set_ip_type(IP::Type p_type) {
|
||||
stop();
|
||||
ip_type = p_type;
|
||||
}
|
||||
|
||||
void TCP_Server::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("listen","port","ip_type", "accepted_hosts"),&TCP_Server::_listen,DEFVAL(IP_Address::TYPE_ANY),DEFVAL(DVector<String>()));
|
||||
ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&TCP_Server::set_ip_type);
|
||||
ObjectTypeDB::bind_method(_MD("listen","port","accepted_hosts"),&TCP_Server::_listen,DEFVAL(DVector<String>()));
|
||||
ObjectTypeDB::bind_method(_MD("is_connection_available"),&TCP_Server::is_connection_available);
|
||||
ObjectTypeDB::bind_method(_MD("take_connection"),&TCP_Server::take_connection);
|
||||
ObjectTypeDB::bind_method(_MD("stop"),&TCP_Server::stop);
|
||||
|
@ -68,4 +72,5 @@ void TCP_Server::_bind_methods() {
|
|||
|
||||
TCP_Server::TCP_Server()
|
||||
{
|
||||
ip_type = IP::TYPE_ANY;
|
||||
}
|
||||
|
|
|
@ -38,14 +38,17 @@ class TCP_Server : public Reference {
|
|||
OBJ_TYPE( TCP_Server, Reference );
|
||||
protected:
|
||||
|
||||
IP::Type ip_type;
|
||||
|
||||
static TCP_Server* (*_create)();
|
||||
|
||||
//bind helper
|
||||
Error _listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_ANY ,DVector<String> p_accepted_hosts=DVector<String>());
|
||||
Error _listen(uint16_t p_port, DVector<String> p_accepted_hosts=DVector<String>());
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type = IP_Address::TYPE_ANY, const List<String> *p_accepted_hosts=NULL)=0;
|
||||
virtual void set_ip_type(IP::Type p_type);
|
||||
virtual Error listen(uint16_t p_port, const List<String> *p_accepted_hosts=NULL)=0;
|
||||
virtual bool is_connection_available() const=0;
|
||||
virtual Ref<StreamPeerTCP> take_connection()=0;
|
||||
|
||||
|
|
|
@ -1825,10 +1825,6 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
|
|||
_VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_BILINEAR",Image::INTERPOLATE_BILINEAR);
|
||||
_VariantCall::add_constant(Variant::IMAGE,"INTERPOLATE_CUBIC",Image::INTERPOLATE_CUBIC);
|
||||
|
||||
_VariantCall::add_constant(Variant::INT, "IP_TYPE_NONE", IP_Address::TYPE_NONE);
|
||||
_VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV4", IP_Address::TYPE_IPV4);
|
||||
_VariantCall::add_constant(Variant::INT, "IP_TYPE_IPV6", IP_Address::TYPE_IPV6);
|
||||
_VariantCall::add_constant(Variant::INT, "IP_TYPE_ANY", IP_Address::TYPE_ANY);
|
||||
}
|
||||
|
||||
void unregister_variant_methods() {
|
||||
|
|
|
@ -16089,7 +16089,7 @@
|
|||
</return>
|
||||
<argument index="0" name="host" type="String">
|
||||
</argument>
|
||||
<argument index="1" name="ip_type" type="int" default="int.IP_TYPE_ANY">
|
||||
<argument index="1" name="ip_type" type="int" default="IP.TYPE_ANY">
|
||||
</argument>
|
||||
<description>
|
||||
Resolve a given hostname, blocking. Resolved hostname is returned as an IPv4 or IPv6 depending on "ip_type".
|
||||
|
@ -16100,7 +16100,7 @@
|
|||
</return>
|
||||
<argument index="0" name="host" type="String">
|
||||
</argument>
|
||||
<argument index="1" name="ip_type" type="int" default="int.IP_TYPE_ANY">
|
||||
<argument index="1" name="ip_type" type="int" default="IP.TYPE_ANY">
|
||||
</argument>
|
||||
<description>
|
||||
Create a queue item for resolving a given hostname to an IPv4 or IPv6 depending on "ip_type". The queue ID is returned, or RESOLVER_INVALID_ID on error.
|
||||
|
@ -25382,15 +25382,10 @@
|
|||
</return>
|
||||
<argument index="0" name="port" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="ip_type" type="int" default="int.IP_TYPE_ANY">
|
||||
</argument>
|
||||
<argument index="2" name="recv_buf_size" type="int" default="65536">
|
||||
<argument index="1" name="recv_buf_size" type="int" default="65536">
|
||||
</argument>
|
||||
<description>
|
||||
Make this [PacketPeerUDP] listen on the "port" using protocol "ip_type" and a buffer size "recv_buf_size". Listens on all available adresses.
|
||||
IP_TYPE_IPV4 = IPv4 only
|
||||
IP_TYPE_IPV6 = IPv6 only
|
||||
IP_TYPE_ANY = Dual stack (supports both IPv6 and IPv4 connections).
|
||||
Make this [PacketPeerUDP] listen on the "port" with a buffer size "recv_buf_size". Listens on all available addresses.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_send_address">
|
||||
|
@ -25400,10 +25395,8 @@
|
|||
</argument>
|
||||
<argument index="1" name="port" type="int">
|
||||
</argument>
|
||||
<argument index="2" name="ip_type" type="int" default="int.IP_TYPE_ANY">
|
||||
</argument>
|
||||
<description>
|
||||
Set the destination address and port for sending packets and variables, a hostname will be resolved using "ip_type" (v4/v6/any) if valid.
|
||||
Set the destination address and port for sending packets and variables, a hostname will be resolved using if valid.
|
||||
</description>
|
||||
</method>
|
||||
<method name="wait">
|
||||
|
@ -39227,10 +39220,8 @@
|
|||
</argument>
|
||||
<argument index="1" name="port" type="int">
|
||||
</argument>
|
||||
<argument index="2" name="ip_type" type="int" default="int.IP_TYPE_ANY">
|
||||
</argument>
|
||||
<description>
|
||||
Connect to the specified host:port pair. A hostname will be resolved using "ip_type" (v4/v6/any) if valid. Returns [OK] on success or [FAILED] on failure.
|
||||
Connect to the specified host:port pair. A hostname will be resolved if valid. Returns [OK] on success or [FAILED] on failure.
|
||||
</description>
|
||||
</method>
|
||||
<method name="disconnect">
|
||||
|
@ -40553,15 +40544,10 @@
|
|||
</return>
|
||||
<argument index="0" name="port" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="ip_type" type="int" default="int.IP_TYPE_ANY">
|
||||
</argument>
|
||||
<argument index="2" name="accepted_hosts" type="StringArray" default="StringArray([])">
|
||||
<argument index="1" name="accepted_hosts" type="StringArray" default="StringArray([])">
|
||||
</argument>
|
||||
<description>
|
||||
Listen on a port using protocol "ip_type", alternatively give a white-list of accepted hosts.
|
||||
IP_TYPE_IPV4 = IPv4 only
|
||||
IP_TYPE_IPV6 = IPv6 only
|
||||
IP_TYPE_ANY = Dual stack (supports both IPv6 and IPv4 connections).
|
||||
Listen on a port using protocol, alternatively give a white-list of accepted hosts.
|
||||
</description>
|
||||
</method>
|
||||
<method name="stop">
|
||||
|
|
|
@ -37,9 +37,6 @@
|
|||
#ifndef AI_ADDRCONFIG
|
||||
#define AI_ADDRCONFIG 0x00000400
|
||||
#endif
|
||||
#ifndef AI_V4MAPPED
|
||||
#define AI_V4MAPPED 0x00000800
|
||||
#endif
|
||||
#ifdef UWP_ENABLED
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
|
@ -75,32 +72,29 @@ static IP_Address _sockaddr2ip(struct sockaddr* p_addr) {
|
|||
IP_Address ip;
|
||||
if (p_addr->sa_family == AF_INET) {
|
||||
struct sockaddr_in* addr = (struct sockaddr_in*)p_addr;
|
||||
ip.field32[0] = *((unsigned long*)&addr->sin_addr);
|
||||
ip.type = IP_Address::TYPE_IPV4;
|
||||
ip.set_ipv4((uint8_t *)&(addr->sin_addr));
|
||||
} else {
|
||||
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr;
|
||||
for (int i=0; i<16; i++)
|
||||
ip.field8[i] = addr6->sin6_addr.s6_addr[i];
|
||||
ip.type = IP_Address::TYPE_IPV6;
|
||||
ip.set_ipv6(addr6->sin6_addr.s6_addr);
|
||||
};
|
||||
|
||||
return ip;
|
||||
};
|
||||
|
||||
IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type) {
|
||||
IP_Address IP_Unix::_resolve_hostname(const String& p_hostname, Type p_type) {
|
||||
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* result;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
if (p_type == IP_Address::TYPE_IPV4) {
|
||||
if (p_type == TYPE_IPV4) {
|
||||
hints.ai_family = AF_INET;
|
||||
} else if (p_type == IP_Address::TYPE_IPV6) {
|
||||
} else if (p_type == TYPE_IPV6) {
|
||||
hints.ai_family = AF_INET6;
|
||||
hints.ai_flags = 0;
|
||||
} else {
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
};
|
||||
|
||||
int s = getaddrinfo(p_hostname.utf8().get_data(), NULL, &hints, &result);
|
||||
|
@ -184,15 +178,12 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
|
|||
|
||||
SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
|
||||
|
||||
ip.field32[0] = *((unsigned long*)&ipv4->sin_addr);
|
||||
ip.type = IP_Address::TYPE_IPV4;
|
||||
ip.set_ipv4((uint8_t *)&(ipv4->sin_addr));
|
||||
} else { // ipv6
|
||||
|
||||
SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);
|
||||
for (int i=0; i<16; i++) {
|
||||
ip.field8[i] = ipv6->sin6_addr.s6_addr[i];
|
||||
};
|
||||
ip.type = IP_Address::TYPE_IPV6;
|
||||
|
||||
ip.set_ipv6(ipv6->sin6_addr.s6_addr);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
class IP_Unix : public IP {
|
||||
OBJ_TYPE(IP_Unix, IP);
|
||||
|
||||
virtual IP_Address _resolve_hostname(const String& p_hostname, IP_Address::AddrType p_type);
|
||||
virtual IP_Address _resolve_hostname(const String& p_hostname, IP::Type p_type);
|
||||
|
||||
static IP* _create_unix();
|
||||
public:
|
||||
|
|
|
@ -76,12 +76,14 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size
|
|||
uint32_t size;
|
||||
uint8_t type;
|
||||
rb.read(&type, 1, true);
|
||||
if (type == IP_Address::TYPE_IPV4) {
|
||||
rb.read((uint8_t*)&packet_ip.field8,4,true);
|
||||
packet_ip.type = IP_Address::TYPE_IPV4;
|
||||
if (type == IP::TYPE_IPV4) {
|
||||
uint8_t ip[4];
|
||||
rb.read(ip,4,true);
|
||||
packet_ip.set_ipv4(ip);
|
||||
} else {
|
||||
rb.read((uint8_t*)&packet_ip.field8,16,true);
|
||||
packet_ip.type = IP_Address::TYPE_IPV6;
|
||||
uint8_t ipv6[16];
|
||||
rb.read(ipv6,16,true);
|
||||
packet_ip.set_ipv6(ipv6);
|
||||
};
|
||||
rb.read((uint8_t*)&packet_port,4,true);
|
||||
rb.read((uint8_t*)&size,4,true);
|
||||
|
@ -94,12 +96,12 @@ Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size
|
|||
}
|
||||
Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){
|
||||
|
||||
ERR_FAIL_COND_V(peer_addr.type == IP_Address::TYPE_NONE, ERR_UNCONFIGURED);
|
||||
ERR_FAIL_COND_V(peer_addr == IP_Address(), ERR_UNCONFIGURED);
|
||||
|
||||
int sock = _get_socket(peer_addr.type);
|
||||
int sock = _get_socket();
|
||||
ERR_FAIL_COND_V( sock == -1, FAILED );
|
||||
struct sockaddr_storage addr;
|
||||
size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port);
|
||||
size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, ip_type);
|
||||
|
||||
errno = 0;
|
||||
int err;
|
||||
|
@ -119,24 +121,16 @@ int PacketPeerUDPPosix::get_max_packet_size() const{
|
|||
return 512; // uhm maybe not
|
||||
}
|
||||
|
||||
Error PacketPeerUDPPosix::listen(int p_port, IP_Address::AddrType p_type, int p_recv_buffer_size) {
|
||||
Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size) {
|
||||
|
||||
close();
|
||||
int sock = _get_socket(p_type);
|
||||
int sock = _get_socket();
|
||||
|
||||
if (sock == -1 )
|
||||
return ERR_CANT_CREATE;
|
||||
|
||||
if(p_type == IP_Address::TYPE_IPV6) {
|
||||
// Use IPv6 only socket
|
||||
int yes = 1;
|
||||
if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&yes, sizeof(yes)) != 0) {
|
||||
WARN_PRINT("Unable to unset IPv4 address mapping over IPv6");
|
||||
}
|
||||
}
|
||||
|
||||
sockaddr_storage addr = {0};
|
||||
size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, NULL);
|
||||
size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL);
|
||||
|
||||
if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) {
|
||||
close();
|
||||
|
@ -171,7 +165,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) {
|
|||
uint32_t port = 0;
|
||||
|
||||
if (from.ss_family == AF_INET) {
|
||||
uint8_t type = (uint8_t)IP_Address::TYPE_IPV4;
|
||||
uint8_t type = (uint8_t)IP::TYPE_IPV4;
|
||||
rb.write(&type, 1);
|
||||
struct sockaddr_in* sin_from = (struct sockaddr_in*)&from;
|
||||
rb.write((uint8_t*)&sin_from->sin_addr, 4);
|
||||
|
@ -179,7 +173,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) {
|
|||
|
||||
} else if (from.ss_family == AF_INET6) {
|
||||
|
||||
uint8_t type = (uint8_t)IP_Address::TYPE_IPV6;
|
||||
uint8_t type = (uint8_t)IP::TYPE_IPV6;
|
||||
rb.write(&type, 1);
|
||||
|
||||
struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from;
|
||||
|
@ -189,7 +183,7 @@ Error PacketPeerUDPPosix::_poll(bool p_wait) {
|
|||
|
||||
} else {
|
||||
// WARN_PRINT("Ignoring packet with unknown address family");
|
||||
uint8_t type = (uint8_t)IP_Address::TYPE_NONE;
|
||||
uint8_t type = (uint8_t)IP::TYPE_NONE;
|
||||
rb.write(&type, 1);
|
||||
};
|
||||
|
||||
|
@ -225,12 +219,12 @@ int PacketPeerUDPPosix::get_packet_port() const{
|
|||
return packet_port;
|
||||
}
|
||||
|
||||
int PacketPeerUDPPosix::_get_socket(IP_Address::AddrType p_type) {
|
||||
int PacketPeerUDPPosix::_get_socket() {
|
||||
|
||||
if (sockfd != -1)
|
||||
return sockfd;
|
||||
|
||||
sockfd = _socket_create(p_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||
sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
@ -259,6 +253,7 @@ PacketPeerUDPPosix::PacketPeerUDPPosix() {
|
|||
packet_port=0;
|
||||
queue_count=0;
|
||||
peer_port=0;
|
||||
ip_type = IP::TYPE_ANY;
|
||||
}
|
||||
|
||||
PacketPeerUDPPosix::~PacketPeerUDPPosix() {
|
||||
|
|
|
@ -52,7 +52,7 @@ class PacketPeerUDPPosix : public PacketPeerUDP {
|
|||
IP_Address peer_addr;
|
||||
int peer_port;
|
||||
|
||||
_FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type);
|
||||
_FORCE_INLINE_ int _get_socket();
|
||||
|
||||
static PacketPeerUDP* _create();
|
||||
virtual Error _poll(bool p_block);
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
|
||||
virtual int get_max_packet_size() const;
|
||||
|
||||
virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536);
|
||||
virtual Error listen(int p_port, int p_recv_buffer_size=65536);
|
||||
virtual void close();
|
||||
virtual Error wait();
|
||||
virtual bool is_listening() const;
|
||||
|
|
|
@ -16,31 +16,42 @@
|
|||
|
||||
// helpers for sockaddr -> IP_Address and back, should work for posix and winsock. All implementations should use this
|
||||
|
||||
static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port) {
|
||||
static size_t _set_sockaddr(struct sockaddr_storage* p_addr, const IP_Address& p_ip, int p_port, IP::Type p_sock_type = IP::TYPE_ANY) {
|
||||
|
||||
memset(p_addr, 0, sizeof(struct sockaddr_storage));
|
||||
if (p_ip.type == IP_Address::TYPE_IPV6) {
|
||||
|
||||
ERR_FAIL_COND_V(p_ip==IP_Address(),0);
|
||||
|
||||
// IPv6 socket
|
||||
if (p_sock_type == IP::TYPE_IPV6 || p_sock_type == IP::TYPE_ANY) {
|
||||
|
||||
// IPv6 only socket with IPv4 address
|
||||
ERR_FAIL_COND_V(p_sock_type == IP::TYPE_IPV6 && p_ip.is_ipv4(),0);
|
||||
|
||||
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr;
|
||||
addr6->sin6_family = AF_INET6;
|
||||
addr6->sin6_port = htons(p_port);
|
||||
copymem(&addr6->sin6_addr.s6_addr, p_ip.field8, 16);
|
||||
copymem(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16);
|
||||
return sizeof(sockaddr_in6);
|
||||
|
||||
} else {
|
||||
} else { // IPv4 socket
|
||||
|
||||
// IPv4 socket with IPv6 address
|
||||
ERR_FAIL_COND_V(!p_ip.is_ipv4(),0);
|
||||
|
||||
uint32_t ipv4 = *((uint32_t *)p_ip.get_ipv4());
|
||||
struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr;
|
||||
addr4->sin_family = AF_INET; // host byte order
|
||||
addr4->sin_family = AF_INET;
|
||||
addr4->sin_port = htons(p_port); // short, network byte order
|
||||
addr4->sin_addr = *((struct in_addr*)&p_ip.field32[0]);
|
||||
copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 16);
|
||||
return sizeof(sockaddr_in);
|
||||
};
|
||||
};
|
||||
|
||||
static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP_Address::AddrType p_address_type, const List<String> *p_accepted_hosts) {
|
||||
static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port, IP::Type p_sock_type, const List<String> *p_accepted_hosts) {
|
||||
|
||||
memset(p_addr, 0, sizeof(struct sockaddr_storage));
|
||||
if (p_address_type == IP_Address::TYPE_IPV4) {
|
||||
if (p_sock_type == IP::TYPE_IPV4) {
|
||||
struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr;
|
||||
addr4->sin_family = AF_INET;
|
||||
addr4->sin_port = htons(p_port);
|
||||
|
@ -56,20 +67,20 @@ static size_t _set_listen_sockaddr(struct sockaddr_storage* p_addr, int p_port,
|
|||
};
|
||||
};
|
||||
|
||||
static int _socket_create(IP_Address::AddrType p_type, int type, int protocol) {
|
||||
static int _socket_create(IP::Type p_type, int type, int protocol) {
|
||||
|
||||
ERR_FAIL_COND_V(p_type > IP_Address::TYPE_ANY || p_type < IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(p_type > IP::TYPE_ANY || p_type < IP::TYPE_NONE, ERR_INVALID_PARAMETER);
|
||||
|
||||
int family = p_type == IP_Address::TYPE_IPV4 ? AF_INET : AF_INET6;
|
||||
int family = p_type == IP::TYPE_IPV4 ? AF_INET : AF_INET6;
|
||||
int sockfd = socket(family, type, protocol);
|
||||
|
||||
ERR_FAIL_COND_V( sockfd == -1, -1 );
|
||||
|
||||
if(family == AF_INET6) {
|
||||
// Ensure IPv4 over IPv6 is enabled
|
||||
int no = 0;
|
||||
if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&no, sizeof(no)) != 0) {
|
||||
WARN_PRINT("Unable to set IPv4 address mapping over IPv6");
|
||||
// Select IPv4 over IPv6 mapping
|
||||
int opt = p_type != IP::TYPE_ANY;
|
||||
if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&opt, sizeof(opt)) != 0) {
|
||||
WARN_PRINT("Unable to set/unset IPv4 address mapping over IPv6");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,19 +91,16 @@ static int _socket_create(IP_Address::AddrType p_type, int type, int protocol) {
|
|||
static void _set_ip_addr_port(IP_Address& r_ip, int& r_port, struct sockaddr_storage* p_addr) {
|
||||
|
||||
if (p_addr->ss_family == AF_INET) {
|
||||
r_ip.type = IP_Address::TYPE_IPV4;
|
||||
|
||||
struct sockaddr_in* addr4 = (struct sockaddr_in*)p_addr;
|
||||
r_ip.field32[0] = (uint32_t)addr4->sin_addr.s_addr;
|
||||
r_ip.set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr));
|
||||
|
||||
r_port = ntohs(addr4->sin_port);
|
||||
|
||||
} else if (p_addr->ss_family == AF_INET6) {
|
||||
|
||||
r_ip.type = IP_Address::TYPE_IPV6;
|
||||
|
||||
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)p_addr;
|
||||
copymem(&addr6->sin6_addr.s6_addr, r_ip.field8, 16);
|
||||
r_ip.set_ipv6(addr6->sin6_addr.s6_addr);
|
||||
|
||||
r_port = ntohs(addr6->sin6_port);
|
||||
};
|
||||
|
|
|
@ -98,7 +98,7 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
|
|||
};
|
||||
|
||||
struct sockaddr_storage their_addr;
|
||||
size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port);
|
||||
size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, ip_type);
|
||||
|
||||
if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1) {
|
||||
|
||||
|
@ -107,7 +107,12 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
|
|||
return OK;
|
||||
};
|
||||
|
||||
return OK;
|
||||
if (errno == EINPROGRESS || errno == EALREADY) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
status = STATUS_ERROR;
|
||||
return ERR_CONNECTION_ERROR;
|
||||
} else {
|
||||
|
||||
status = STATUS_CONNECTED;
|
||||
|
@ -117,8 +122,9 @@ Error StreamPeerTCPPosix::_poll_connection(bool p_block) const {
|
|||
return OK;
|
||||
};
|
||||
|
||||
void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port) {
|
||||
void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) {
|
||||
|
||||
ip_type = p_ip_type;
|
||||
sockfd = p_sockfd;
|
||||
#ifndef NO_FCNTL
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
|
@ -135,9 +141,9 @@ void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port)
|
|||
|
||||
Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) {
|
||||
|
||||
ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER);
|
||||
|
||||
sockfd = _socket_create(p_host.type, SOCK_STREAM, IPPROTO_TCP);
|
||||
sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sockfd == -1) {
|
||||
ERR_PRINT("Socket creation failed!");
|
||||
disconnect();
|
||||
|
@ -153,7 +159,7 @@ Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) {
|
|||
#endif
|
||||
|
||||
struct sockaddr_storage their_addr;
|
||||
size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port);
|
||||
size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, ip_type);
|
||||
|
||||
errno = 0;
|
||||
if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == -1 && errno != EINPROGRESS) {
|
||||
|
@ -387,6 +393,7 @@ StreamPeerTCPPosix::StreamPeerTCPPosix() {
|
|||
sockfd = -1;
|
||||
status = STATUS_NONE;
|
||||
peer_port = 0;
|
||||
ip_type = IP::TYPE_ANY;
|
||||
};
|
||||
|
||||
StreamPeerTCPPosix::~StreamPeerTCPPosix() {
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
|
||||
virtual int get_available_bytes() const;
|
||||
|
||||
void set_socket(int p_sockfd, IP_Address p_host, int p_port);
|
||||
void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type);
|
||||
|
||||
virtual IP_Address get_connected_host() const;
|
||||
virtual uint16_t get_connected_port() const;
|
||||
|
|
|
@ -68,20 +68,13 @@ void TCPServerPosix::make_default() {
|
|||
TCP_Server::_create = TCPServerPosix::_create;
|
||||
};
|
||||
|
||||
Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const List<String> *p_accepted_hosts) {
|
||||
Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
|
||||
|
||||
int sockfd;
|
||||
sockfd = _socket_create(p_type, SOCK_STREAM, IPPROTO_TCP);
|
||||
sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
ERR_FAIL_COND_V(sockfd == -1, FAILED);
|
||||
|
||||
if(p_type == IP_Address::TYPE_IPV6) {
|
||||
// Use IPv6 only socket
|
||||
int yes = 1;
|
||||
if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&yes, sizeof(yes)) != 0) {
|
||||
WARN_PRINT("Unable to unset IPv4 address mapping over IPv6");
|
||||
}
|
||||
}
|
||||
#ifndef NO_FCNTL
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
#else
|
||||
|
@ -95,7 +88,7 @@ Error TCPServerPosix::listen(uint16_t p_port, IP_Address::AddrType p_type, const
|
|||
}
|
||||
|
||||
struct sockaddr_storage addr;
|
||||
size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, p_accepted_hosts);
|
||||
size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, p_accepted_hosts);
|
||||
|
||||
// automatically fill with my IP TODO: use p_accepted_hosts
|
||||
|
||||
|
@ -164,7 +157,7 @@ Ref<StreamPeerTCP> TCPServerPosix::take_connection() {
|
|||
int port;
|
||||
_set_ip_addr_port(ip, port, &their_addr);
|
||||
|
||||
conn->set_socket(fd, ip, port);
|
||||
conn->set_socket(fd, ip, port, ip_type);
|
||||
|
||||
return conn;
|
||||
};
|
||||
|
@ -183,6 +176,7 @@ void TCPServerPosix::stop() {
|
|||
TCPServerPosix::TCPServerPosix() {
|
||||
|
||||
listen_sockfd = -1;
|
||||
ip_type = IP::TYPE_ANY;
|
||||
};
|
||||
|
||||
TCPServerPosix::~TCPServerPosix() {
|
||||
|
|
|
@ -40,7 +40,7 @@ class TCPServerPosix : public TCP_Server {
|
|||
|
||||
public:
|
||||
|
||||
virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type, const List<String> *p_accepted_hosts=NULL);
|
||||
virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
|
||||
virtual bool is_connection_available() const;
|
||||
virtual Ref<StreamPeerTCP> take_connection();
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int
|
|||
Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port, int p_in_bandwidth, int p_out_bandwidth){
|
||||
|
||||
ERR_FAIL_COND_V(active,ERR_ALREADY_IN_USE);
|
||||
ERR_FAIL_COND_V(p_ip.type != IP_Address::TYPE_IPV4, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(!p_ip.is_ipv4(), ERR_INVALID_PARAMETER);
|
||||
|
||||
host = enet_host_create (NULL /* create a client host */,
|
||||
1 /* only allow 1 outgoing connection */,
|
||||
|
@ -91,7 +91,7 @@ Error NetworkedMultiplayerENet::create_client(const IP_Address& p_ip, int p_port
|
|||
_setup_compressor();
|
||||
|
||||
ENetAddress address;
|
||||
address.host=p_ip.field32[0];
|
||||
address.host=*((uint32_t *)p_ip.get_ipv4());
|
||||
address.port=p_port;
|
||||
|
||||
//enet_address_set_host (& address, "localhost");
|
||||
|
@ -150,8 +150,7 @@ void NetworkedMultiplayerENet::poll(){
|
|||
}
|
||||
|
||||
IP_Address ip;
|
||||
ip.type = IP_Address::TYPE_IPV4;
|
||||
ip.field32[0]=event.peer -> address.host;
|
||||
ip.set_ipv4((uint8_t *)&(event.peer -> address.host));
|
||||
|
||||
int *new_id = memnew( int );
|
||||
*new_id = event.data;
|
||||
|
@ -685,6 +684,6 @@ NetworkedMultiplayerENet::~NetworkedMultiplayerENet(){
|
|||
// sets IP for ENet to bind when using create_server
|
||||
// if no IP is set, then ENet bind to ENET_HOST_ANY
|
||||
void NetworkedMultiplayerENet::set_bind_ip(const IP_Address& p_ip){
|
||||
ERR_FAIL_COND(p_ip.type != IP_Address::TYPE_IPV4);
|
||||
bind_ip=p_ip.field32[0];
|
||||
ERR_FAIL_COND(!p_ip.is_ipv4());
|
||||
bind_ip=*(uint32_t *)p_ip.get_ipv4();
|
||||
}
|
||||
|
|
|
@ -53,12 +53,14 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si
|
|||
uint32_t size;
|
||||
uint8_t type;
|
||||
rb.read(&type, 1, true);
|
||||
if (type == IP_Address::TYPE_IPV4) {
|
||||
rb.read((uint8_t*)&packet_ip.field8,4,true);
|
||||
packet_ip.type = IP_Address::TYPE_IPV4;
|
||||
if (type == IP::TYPE_IPV4) {
|
||||
uint8_t ip[4];
|
||||
rb.read(ip,4,true);
|
||||
packet_ip.set_ipv4(ip);
|
||||
} else {
|
||||
rb.read((uint8_t*)&packet_ip.field8,16,true);
|
||||
packet_ip.type = IP_Address::TYPE_IPV6;
|
||||
uint8_t ip[16];
|
||||
rb.read(ip,16,true);
|
||||
packet_ip.set_ipv6(ip);
|
||||
};
|
||||
rb.read((uint8_t*)&packet_port,4,true);
|
||||
rb.read((uint8_t*)&size,4,true);
|
||||
|
@ -71,10 +73,10 @@ Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_si
|
|||
}
|
||||
Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){
|
||||
|
||||
int sock = _get_socket(peer_addr.type);
|
||||
int sock = _get_socket();
|
||||
ERR_FAIL_COND_V( sock == -1, FAILED );
|
||||
struct sockaddr_storage addr;
|
||||
size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port);
|
||||
size_t addr_size = _set_sockaddr(&addr, peer_addr, peer_port, ip_type);
|
||||
|
||||
_set_blocking(true);
|
||||
|
||||
|
@ -112,23 +114,15 @@ void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) {
|
|||
};
|
||||
}
|
||||
|
||||
Error PacketPeerUDPWinsock::listen(int p_port, IP_Address::AddrType p_type, int p_recv_buffer_size) {
|
||||
Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size) {
|
||||
|
||||
close();
|
||||
int sock = _get_socket(p_type);
|
||||
int sock = _get_socket();
|
||||
if (sock == -1 )
|
||||
return ERR_CANT_CREATE;
|
||||
|
||||
if(p_type == IP_Address::TYPE_IPV6) {
|
||||
// Use IPv6 only socket
|
||||
int yes = 1;
|
||||
if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&yes, sizeof(yes)) != 0) {
|
||||
WARN_PRINT("Unable to unset IPv4 address mapping over IPv6");
|
||||
}
|
||||
}
|
||||
|
||||
struct sockaddr_storage addr = {0};
|
||||
size_t addr_size = _set_listen_sockaddr(&addr, p_port, p_type, NULL);
|
||||
size_t addr_size = _set_listen_sockaddr(&addr, p_port, ip_type, NULL);
|
||||
|
||||
if (bind(sock, (struct sockaddr*)&addr, addr_size) == -1 ) {
|
||||
close();
|
||||
|
@ -170,7 +164,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) {
|
|||
uint32_t port = 0;
|
||||
|
||||
if (from.ss_family == AF_INET) {
|
||||
uint8_t type = (uint8_t)IP_Address::TYPE_IPV4;
|
||||
uint8_t type = (uint8_t)IP::TYPE_IPV4;
|
||||
rb.write(&type, 1);
|
||||
struct sockaddr_in* sin_from = (struct sockaddr_in*)&from;
|
||||
rb.write((uint8_t*)&sin_from->sin_addr, 4);
|
||||
|
@ -178,7 +172,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) {
|
|||
|
||||
} else if (from.ss_family == AF_INET6) {
|
||||
|
||||
uint8_t type = (uint8_t)IP_Address::TYPE_IPV6;
|
||||
uint8_t type = (uint8_t)IP::TYPE_IPV6;
|
||||
rb.write(&type, 1);
|
||||
|
||||
struct sockaddr_in6* s6_from = (struct sockaddr_in6*)&from;
|
||||
|
@ -188,7 +182,7 @@ Error PacketPeerUDPWinsock::_poll(bool p_wait) {
|
|||
|
||||
} else {
|
||||
// WARN_PRINT("Ignoring packet with unknown address family");
|
||||
uint8_t type = (uint8_t)IP_Address::TYPE_NONE;
|
||||
uint8_t type = (uint8_t)IP::TYPE_NONE;
|
||||
rb.write(&type, 1);
|
||||
};
|
||||
|
||||
|
@ -242,12 +236,12 @@ int PacketPeerUDPWinsock::get_packet_port() const{
|
|||
return packet_port;
|
||||
}
|
||||
|
||||
int PacketPeerUDPWinsock::_get_socket(IP_Address::AddrType p_type) {
|
||||
int PacketPeerUDPWinsock::_get_socket() {
|
||||
|
||||
if (sockfd != -1)
|
||||
return sockfd;
|
||||
|
||||
sockfd = _socket_create(p_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||
sockfd = _socket_create(ip_type, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
@ -277,6 +271,7 @@ PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
|
|||
packet_port=0;
|
||||
queue_count=0;
|
||||
peer_port=0;
|
||||
ip_type = IP::TYPE_ANY;
|
||||
}
|
||||
|
||||
PacketPeerUDPWinsock::~PacketPeerUDPWinsock() {
|
||||
|
|
|
@ -50,7 +50,7 @@ class PacketPeerUDPWinsock : public PacketPeerUDP {
|
|||
IP_Address peer_addr;
|
||||
int peer_port;
|
||||
|
||||
_FORCE_INLINE_ int _get_socket(IP_Address::AddrType p_type);
|
||||
_FORCE_INLINE_ int _get_socket();
|
||||
|
||||
static PacketPeerUDP* _create();
|
||||
|
||||
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
virtual int get_max_packet_size() const;
|
||||
|
||||
virtual Error listen(int p_port, IP_Address::AddrType p_address_type, int p_recv_buffer_size=65536);
|
||||
virtual Error listen(int p_port, int p_recv_buffer_size=65536);
|
||||
virtual void close();
|
||||
virtual Error wait();
|
||||
virtual bool is_listening() const;
|
||||
|
|
|
@ -88,7 +88,7 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const {
|
|||
};
|
||||
|
||||
struct sockaddr_storage their_addr;
|
||||
size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port);
|
||||
size_t addr_size = _set_sockaddr(&their_addr, peer_host, peer_port, ip_type);
|
||||
|
||||
if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) {
|
||||
|
||||
|
@ -98,7 +98,12 @@ Error StreamPeerWinsock::_poll_connection(bool p_block) const {
|
|||
return OK;
|
||||
};
|
||||
|
||||
return OK;
|
||||
if (errno == WSAEINPROGRESS || errno == WSAEALREADY) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
status = STATUS_ERROR;
|
||||
return ERR_CONNECTION_ERROR;
|
||||
} else {
|
||||
|
||||
status = STATUS_CONNECTED;
|
||||
|
@ -284,8 +289,9 @@ void StreamPeerWinsock::disconnect() {
|
|||
peer_port = 0;
|
||||
};
|
||||
|
||||
void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port) {
|
||||
void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type) {
|
||||
|
||||
ip_type = p_ip_type;
|
||||
sockfd = p_sockfd;
|
||||
status = STATUS_CONNECTING;
|
||||
peer_host = p_host;
|
||||
|
@ -294,9 +300,9 @@ void StreamPeerWinsock::set_socket(int p_sockfd, IP_Address p_host, int p_port)
|
|||
|
||||
Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) {
|
||||
|
||||
ERR_FAIL_COND_V( p_host.type == IP_Address::TYPE_NONE, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V( p_host == IP_Address(), ERR_INVALID_PARAMETER);
|
||||
|
||||
sockfd = _socket_create(p_host.type, SOCK_STREAM, IPPROTO_TCP);
|
||||
sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sockfd == INVALID_SOCKET) {
|
||||
ERR_PRINT("Socket creation failed!");
|
||||
disconnect();
|
||||
|
@ -312,7 +318,7 @@ Error StreamPeerWinsock::connect(const IP_Address& p_host, uint16_t p_port) {
|
|||
};
|
||||
|
||||
struct sockaddr_storage their_addr;
|
||||
size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port);
|
||||
size_t addr_size = _set_sockaddr(&their_addr, p_host, p_port, ip_type);
|
||||
|
||||
if (::connect(sockfd, (struct sockaddr *)&their_addr,addr_size) == SOCKET_ERROR) {
|
||||
|
||||
|
@ -362,6 +368,7 @@ StreamPeerWinsock::StreamPeerWinsock() {
|
|||
sockfd = INVALID_SOCKET;
|
||||
status = STATUS_NONE;
|
||||
peer_port = 0;
|
||||
ip_type = IP::TYPE_ANY;
|
||||
};
|
||||
|
||||
StreamPeerWinsock::~StreamPeerWinsock() {
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
virtual int get_available_bytes() const;
|
||||
|
||||
void set_socket(int p_sockfd, IP_Address p_host, int p_port);
|
||||
void set_socket(int p_sockfd, IP_Address p_host, int p_port, IP::Type p_ip_type);
|
||||
|
||||
virtual IP_Address get_connected_host() const;
|
||||
virtual uint16_t get_connected_port() const;
|
||||
|
|
|
@ -63,20 +63,12 @@ void TCPServerWinsock::cleanup() {
|
|||
};
|
||||
|
||||
|
||||
Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,const List<String> *p_accepted_hosts) {
|
||||
Error TCPServerWinsock::listen(uint16_t p_port,const List<String> *p_accepted_hosts) {
|
||||
|
||||
int sockfd;
|
||||
sockfd = _socket_create(p_type, SOCK_STREAM, IPPROTO_TCP);
|
||||
sockfd = _socket_create(ip_type, SOCK_STREAM, IPPROTO_TCP);
|
||||
ERR_FAIL_COND_V(sockfd == INVALID_SOCKET, FAILED);
|
||||
|
||||
if(p_type == IP_Address::TYPE_IPV6) {
|
||||
// Use IPv6 only socket
|
||||
int yes = 1;
|
||||
if(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&yes, sizeof(yes)) != 0) {
|
||||
WARN_PRINT("Unable to unset IPv4 address mapping over IPv6");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long par = 1;
|
||||
if (ioctlsocket(sockfd, FIONBIO, &par)) {
|
||||
perror("setting non-block mode");
|
||||
|
@ -85,7 +77,7 @@ Error TCPServerWinsock::listen(uint16_t p_port, IP_Address::AddrType p_type,cons
|
|||
};
|
||||
|
||||
struct sockaddr_storage my_addr;
|
||||
size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, p_type, p_accepted_hosts);
|
||||
size_t addr_size = _set_listen_sockaddr(&my_addr, p_port, ip_type, p_accepted_hosts);
|
||||
|
||||
int reuse=1;
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
|
||||
|
@ -158,7 +150,7 @@ Ref<StreamPeerTCP> TCPServerWinsock::take_connection() {
|
|||
int port;
|
||||
_set_ip_addr_port(ip, port, &their_addr);
|
||||
|
||||
conn->set_socket(fd, ip, port);
|
||||
conn->set_socket(fd, ip, port, ip_type);
|
||||
|
||||
return conn;
|
||||
};
|
||||
|
@ -176,6 +168,7 @@ void TCPServerWinsock::stop() {
|
|||
TCPServerWinsock::TCPServerWinsock() {
|
||||
|
||||
listen_sockfd = INVALID_SOCKET;
|
||||
ip_type = IP::TYPE_ANY;
|
||||
};
|
||||
|
||||
TCPServerWinsock::~TCPServerWinsock() {
|
||||
|
|
|
@ -39,7 +39,7 @@ class TCPServerWinsock : public TCP_Server {
|
|||
|
||||
public:
|
||||
|
||||
virtual Error listen(uint16_t p_port, IP_Address::AddrType p_type,const List<String> *p_accepted_hosts=NULL);
|
||||
virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL);
|
||||
virtual bool is_connection_available() const;
|
||||
virtual Ref<StreamPeerTCP> take_connection();
|
||||
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
/*************************************************************************/
|
||||
#include "http_request.h"
|
||||
|
||||
void HTTPRequest::set_ip_type(IP::Type p_type) {
|
||||
client->set_ip_type(p_type);
|
||||
}
|
||||
|
||||
void HTTPRequest::_redirect_request(const String& p_new_url) {
|
||||
|
||||
|
||||
|
@ -535,6 +539,7 @@ int HTTPRequest::get_body_size() const{
|
|||
|
||||
void HTTPRequest::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_ip_type","ip_type"),&HTTPRequest::set_ip_type);
|
||||
ObjectTypeDB::bind_method(_MD("request","url","custom_headers","ssl_validate_domain","method","request_data"),&HTTPRequest::request,DEFVAL(StringArray()),DEFVAL(true),DEFVAL(HTTPClient::METHOD_GET),DEFVAL(String()));
|
||||
ObjectTypeDB::bind_method(_MD("cancel_request"),&HTTPRequest::cancel_request);
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ protected:
|
|||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_ip_type(IP::Type p_type);
|
||||
Error request(const String& p_url, const Vector<String>& p_custom_headers=Vector<String>(), bool p_ssl_validate_domain=true, HTTPClient::Method p_method=HTTPClient::METHOD_GET, const String& p_request_data=""); //connects to a full url and perform request
|
||||
void cancel_request();
|
||||
HTTPClient::Status get_http_client_status() const;
|
||||
|
|
Loading…
Reference in New Issue