hashlink
hashlink copied to clipboard
Get peername and socketname ? ( libuv )
Is it possible to get peer address ( IPv4 or IPv6 ) and sock address via uv_tcp_getpeername or uv_tcp_getsockname ?
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;
}
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 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 .
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;
}
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