hashlink icon indicating copy to clipboard operation
hashlink copied to clipboard

Get peername and socketname ? ( libuv )

Open flashultra opened this issue 6 years ago • 5 comments

Is it possible to get peer address ( IPv4 or IPv6 ) and sock address via uv_tcp_getpeername or uv_tcp_getsockname ?

flashultra avatar Jan 27 '19 09:01 flashultra

C is not my strong side, but maybe something like this in uv.c ? ( for string result IP : PORT )

static  char * get_peername(uv_tcp_t *t) {
	char result[51];
	struct sockaddr_storage addr;
	memset(&addr, 0, sizeof(addr));
	int alen = 0;
	int r = uv_tcp_getpeername(&t, (struct sockaddr *)&addr, &alen);
	if (r == 0) {
		char ip[45] = { 0 };
		char portstr[5] = { 0 };
		int port = 0;
		if (addr.ss_family == AF_INET) {
			struct sockaddr_in *addr_i4 = (struct sockaddr_in *) &addr;
			uv_ip4_name(&addr_i4, ip, sizeof ip);
			port = addr_i4->sin_port;
		}
		else if (addr.ss_family == AF_INET6) {
			struct sockaddr_in6 *addr_i6 = (struct sockaddr_in6 *) &addr;
			uv_ip6_name(&addr_i6, ip, sizeof ip);
			port = addr_i6->sin6_port;
		}
		itoa(port, portstr, 10);
		strcat(result, ip);
		strcat(result, ":");
		strcat(result, portstr);
	}
	return result;
}

flashultra avatar Jan 27 '19 19:01 flashultra

I tried to return struct

#define _ADDR  _OBJ(_BYTES _I32)
DEFINE_PRIM(_ADDR, get_peername, _TCP );

typedef struct {
	char *ip;
	int *port;
} addr_data ;

HL_PRIM addr_data HL_NAME(get_peername)(uv_tcp_t *t) {
	char ip[45] = { 0 };
	int port = 0;
	struct sockaddr_storage addr;
	memset(&addr, 0, sizeof(addr));
	int alen = 0;
	int r = uv_tcp_getpeername(&t, (struct sockaddr *)&addr, &alen);
	if (r == 0) {
		if (addr.ss_family == AF_INET) {
			struct sockaddr_in *addr_i4 = (struct sockaddr_in *) &addr;
			uv_ip4_name(&addr_i4, ip, sizeof ip);
			port = addr_i4->sin_port;
		}
		else if (addr.ss_family == AF_INET6) {
			struct sockaddr_in6 *addr_i6 = (struct sockaddr_in6 *) &addr;
			uv_ip6_name(&addr_i6, ip, sizeof ip);
			port = addr_i6->sin6_port;
		}
	}
	addr_data d = { .ip =  &ip ,.port = &port };
	return d;
}

and add in Tcp.hx

	public function peerName() {
		var name = get_peername(handle);
		return name;
	}

	static function get_peername( h: HandleData ) : Addr {
		return null;
	}

but when try to get perrname I've got : Uncaught exception: Access violation

flashultra avatar Jan 29 '19 19:01 flashultra

You can't return structs from C to Haxe. You need to use pointers for output parameters:

C:

bool get_peer_name( tcp, intip, intport) { ... }

Haxe: var ip = 0, port = 0; get_peer_name(tcp, ip, port); return { ip : ip, port: port };

function get_peer_name( tcp : uv_tcp, ip : hl.Ref<Int>, port : hl.Ref<Int> ) { return false; }

On Tue, Jan 29, 2019 at 8:24 PM flashultra [email protected] wrote:

I tried to return struct

#define _ADDR _OBJ(_BYTES _I32) DEFINE_PRIM(_ADDR, get_peername, _TCP ); typedef struct { char *ip; int *port; } addr_data ;

HL_PRIM addr_data HL_NAME(get_peername)(uv_tcp_t *t) { char ip[45] = { 0 }; int port = 0; struct sockaddr_storage addr; memset(&addr, 0, sizeof(addr)); int alen = 0; int r = uv_tcp_getpeername(&t, (struct sockaddr *)&addr, &alen); if (r == 0) { if (addr.ss_family == AF_INET) { struct sockaddr_in *addr_i4 = (struct sockaddr_in *) &addr; uv_ip4_name(&addr_i4, ip, sizeof ip); port = addr_i4->sin_port; } else if (addr.ss_family == AF_INET6) { struct sockaddr_in6 *addr_i6 = (struct sockaddr_in6 *) &addr; uv_ip6_name(&addr_i6, ip, sizeof ip); port = addr_i6->sin6_port; } } addr_data d = { .ip = &ip ,.port = &port }; return d; }

and add in Tcp.hx

public function peerName() { var name = get_peername(handle); return name; }

static function get_peername( h: HandleData ) : Addr { return null; }

but when try to get perrname I've got : Uncaught exception: Access violation

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/HaxeFoundation/hashlink/issues/226#issuecomment-458672829, or mute the thread https://github.com/notifications/unsubscribe-auth/AA-bwJMFvGyY-EoksLKfetjOg1_CPKATks5vIJ_ogaJpZM4aUodY .

ncannasse avatar Jan 31 '19 11:01 ncannasse

I change code according your advice , but now get for IP empty string and for port 0 . On separate project ( only C with libuv ) I've got correct result with same C code. Here is what I use :

C: ( uv.c )

DEFINE_PRIM(_BOOL, get_peername, _TCP _REF(_STRING) _REF(_I32) );

HL_PRIM bool HL_NAME(get_peername)(uv_tcp_t *t, char *ip, int *port) {
	struct sockaddr_storage addr = { 0 };
	int alen = sizeof(addr);
	int r = uv_tcp_getpeername(t, (struct sockaddr *)&addr, &alen);
	if (r == 0) {
		if (addr.ss_family == AF_INET) {
			char ip_str[INET_ADDRSTRLEN];
			struct sockaddr_in *addr_i4 = (struct sockaddr_in *) &addr;
			uv_ip4_name(addr_i4, ip_str, sizeof(ip_str));
			*port = ntohs(addr_i4->sin_port);
			strcpy(ip, ip_str);
		}
		else if (addr.ss_family == AF_INET6) {
			char ip_str[INET6_ADDRSTRLEN];
			struct sockaddr_in6 *addr_i6 = (struct sockaddr_in6 *) &addr;
			uv_ip6_name(addr_i6, ip_str, sizeof(ip_str));
			*port = ntohs(addr_i6->sin6_port);
			strcpy(ip, ip_str);
		}
	}

	return (r == 0);
}

Haxe : ( hl.uv.Tcp )


	public function peerName() {
		var ip  = "";
		var port = 0;
		var r = get_peername(handle,ip,port);
		return { ip : ip, port: port };
	}
	static function get_peername( h: HandleData, ip:hl.Ref<String>, port:hl.Ref<Int> ) : Bool {
		return false;
	}

flashultra avatar Feb 01 '19 20:02 flashultra

I also tried to use char **ip , but result was the same . Here is changed C code:

HL_PRIM bool HL_NAME(get_peername)(uv_tcp_t *t, char **ip, int *port) {
	struct sockaddr_storage addr = { 0 };
	int alen = sizeof(addr);
	int r = uv_tcp_getpeername(t, (struct sockaddr *)&addr, &alen);
	if (r == 0) {
		if (addr.ss_family == AF_INET) {
			char ip_str[INET_ADDRSTRLEN];
			struct sockaddr_in *addr_i4 = (struct sockaddr_in *) &addr;
			uv_ip4_name(addr_i4, ip_str, sizeof(ip_str));
			*port = ntohs(addr_i4->sin_port);
			*ip = malloc(sizeof(ip_str));
			strcpy(*ip, ip_str);
		}
		else if (addr.ss_family == AF_INET6) {
			char ip_str[INET6_ADDRSTRLEN];
			struct sockaddr_in6 *addr_i6 = (struct sockaddr_in6 *) &addr;
			uv_ip6_name(addr_i6, ip_str, sizeof(ip_str));
			*port = ntohs(addr_i6->sin6_port);
			*ip = malloc(sizeof(ip_str));
			strcpy(*ip, ip_str);
		}
	}

	return (r == 0);
}

Ignoring ip and changing it to hl.Ref<Int> return same result. If client use IP v6 ( 128 bits number ) it's not possibel to save as int / float and for that reason IP is return as string

flashultra avatar Feb 03 '19 09:02 flashultra