-#include <asprintf/asprintf.h>
#include <dragonnet/addr.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-DragonnetAddr dragonnet_addr_parse_str(char *str)
+struct addrinfo *dragonnet_str2addr(const char *str)
{
- DragonnetAddr addr = {0};
-
- size_t colon_i = 0;
- for (ssize_t i = strlen(str)-1; i >= 0; --i) {
- if (str[i] == ':') {
- colon_i = i;
- break;
- }
+ const char *port = str + strlen(str) - 1;
+ while (port >= str && *port != ':')
+ port--;
+ port++;
+
+ const char *host_begin = str;
+ if (*host_begin == '[')
+ host_begin++;
+
+ const char *host_end = port - 2;
+ if (host_end >= str && *host_end == ']')
+ host_end--;
+
+ ssize_t host_len = host_end - host_begin + 1;
+ if (host_len < 0)
+ host_len = 0;
+
+ char host[host_len + 1];
+ host[host_len] = '\0';
+ memcpy(host, host_begin, host_len);
+
+ struct addrinfo *result, hints = {0};
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ int err;
+ if ((err = getaddrinfo(host, port, &hints, &result))) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
+ return NULL;
}
- size_t ip_addr_i = 0, port_i = 0;
- for (size_t i = 0; i < strlen(str); ++i) {
- if (i < colon_i && str[i] != '[' && str[i] != ']')
- addr.ip[ip_addr_i++] = str[i];
- else if (i > colon_i)
- addr.port[port_i++] = str[i];
- }
-
- return addr;
-}
-
-char *dragonnet_addr_str(DragonnetAddr addr)
-{
- char *ptr;
- asprintf(&ptr, "[%s]:%s", addr.ip, addr.port);
- return ptr;
+ return result;
}
-DragonnetAddr dragonnet_addr_parse_sock(struct sockaddr_in6 ai_addr)
+char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len)
{
- DragonnetAddr addr = {0};
- sprintf(addr.port, "%d", ntohs(ai_addr.sin6_port));
- inet_ntop(AF_INET6, &ai_addr.sin6_addr, addr.ip, INET6_ADDRSTRLEN);
+ char host[NI_MAXHOST], port[NI_MAXSERV];
- return addr;
-}
-
-struct sockaddr_in6 dragonnet_addr_sock(DragonnetAddr addr)
-{
- struct sockaddr_in6 ai_addr = {0};
- ai_addr.sin6_family = AF_INET6;
- ai_addr.sin6_flowinfo = 0;
- ai_addr.sin6_port = htons(atoi(addr.port));
- inet_pton(AF_INET6, addr.ip, &ai_addr.sin6_addr);
+ int err;
+ if ((err = getnameinfo(addr, addr_len, host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICSERV))) {
+ fprintf(stderr, "getnameinfo: %s\n", gai_strerror(err));
+ return NULL;
+ }
- return ai_addr;
+ char str[1 + strlen(host) + 1 + 1 + strlen(port) + 1];
+ sprintf(str, "[%s]:%s", host, port);
+ return strdup(str);
}
#ifndef _DRAGONNET_ADDR_H_
#define _DRAGONNET_ADDR_H_
-#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
-typedef struct {
- char ip[INET6_ADDRSTRLEN];
- char port[6];
-} DragonnetAddr;
-
-DragonnetAddr dragonnet_addr_parse_str(char *addr);
-char *dragonnet_addr_str(DragonnetAddr addr);
-
-DragonnetAddr dragonnet_addr_parse_sock(struct sockaddr_in6 ai_addr);
-struct sockaddr_in6 dragonnet_addr_sock(DragonnetAddr addr);
+struct addrinfo *dragonnet_str2addr(const char *str);
+char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len);
#endif
#define _GNU_SOURCE
#include <assert.h>
+#include <dragonnet/addr.h>
#include <dragonnet/listen.h>
#include <dragonnet/recv.h>
#include <errno.h>
// ----
static bool dragonnet_peer_init_accepted(DragonnetPeer *p, int sock,
- struct sockaddr_in6 addr, DragonnetListener *l)
+ char *addr, DragonnetListener *l)
{
pthread_mutex_init(&p->mtx, NULL);
p->sock = sock;
- p->laddr = l->laddr;
- p->raddr = dragonnet_addr_parse_sock(addr);
+ p->address = addr;
p->on_disconnect = l->on_disconnect;
p->on_recv = l->on_recv;
p->on_recv_type = l->on_recv_type;
return true;
}
-static DragonnetPeer *dragonnet_peer_accept(int sock, struct sockaddr_in6 addr,
+static DragonnetPeer *dragonnet_peer_accept(int sock, char *addr,
DragonnetListener *l)
{
DragonnetPeer *p = malloc(sizeof *p);
if (!dragonnet_peer_init_accepted(p, sock, addr, l)) {
pthread_mutex_destroy(&p->mtx);
free(p);
+ free(addr);
return NULL;
}
DragonnetListener *dragonnet_listener_new(char *addr)
{
+ struct addrinfo *info = dragonnet_str2addr(addr);
+ if (!info)
+ return NULL;
+
DragonnetListener *l = malloc(sizeof *l);
l->active = true;
- l->sock = socket(AF_INET6, SOCK_STREAM, 0);
+ l->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
+ l->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen);
l->on_connect = NULL;
l->on_disconnect = NULL;
l->on_recv = NULL;
if (setsockopt(l->sock, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr,
sizeof so_reuseaddr) < 0) {
perror("setsockopt");
+ freeaddrinfo(info);
dragonnet_listener_delete(l);
return NULL;
}
- l->laddr = dragonnet_addr_parse_str(addr);
- struct sockaddr_in6 ai_addr = dragonnet_addr_sock(l->laddr);
-
- if (bind(l->sock, (const struct sockaddr *) &ai_addr, sizeof ai_addr) < 0) {
+ if (bind(l->sock, info->ai_addr, info->ai_addrlen) < 0) {
perror("bind");
+ freeaddrinfo(info);
dragonnet_listener_delete(l);
return NULL;
}
+ freeaddrinfo(info);
+
if (listen(l->sock, 10) < 0) {
perror("listen");
dragonnet_listener_delete(l);
DragonnetListener *l = (DragonnetListener *) g_listener;
while (l->active) {
- struct sockaddr_in6 clt_addr;
- socklen_t clt_addrlen = sizeof clt_addr;
+ struct sockaddr_storage clt_addr;
+ socklen_t clt_addrlen;
int clt_sock = accept(l->sock, (struct sockaddr *) &clt_addr, &clt_addrlen);
if (clt_sock < 0) {
continue;
}
- DragonnetPeer *p = dragonnet_peer_accept(clt_sock, clt_addr, l);
+ char *clt_addstr = dragonnet_addr2str((struct sockaddr *) &clt_addr, clt_addrlen);
+ DragonnetPeer *p = dragonnet_peer_accept(clt_sock, clt_addstr, l);
if (p == NULL)
continue;
void dragonnet_listener_delete(DragonnetListener *l)
{
free(l->on_recv_type);
+ free(l->address);
free(l);
}
typedef struct {
int sock;
- DragonnetAddr laddr;
+ char *address;
+
pthread_t accept_thread;
bool active;
#include <assert.h>
+#include <dragonnet/addr.h>
#include <dragonnet/peer.h>
#include <dragonnet/recv.h>
#include <dragonnet/recv_thread.h>
{
pthread_mutex_init(&p->mtx, NULL);
- p->sock = socket(AF_INET6, SOCK_STREAM, 0);
- p->raddr = dragonnet_addr_parse_str(addr);
- p->on_disconnect = NULL;
- p->on_recv = NULL;
- p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types);
+ struct addrinfo *info = dragonnet_str2addr(addr);
+ if (!info)
+ return false;
+
+ p->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
+ p->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen);
- struct sockaddr_in6 sock_addr = dragonnet_addr_sock(p->raddr);
- if (connect(p->sock, (const struct sockaddr *) &sock_addr,
- sizeof sock_addr) < 0) {
+ if (connect(p->sock, info->ai_addr, info->ai_addrlen) < 0) {
+ freeaddrinfo(info);
perror("connect");
return false;
}
- struct sockaddr_in6 sock_name;
- socklen_t sock_namelen = sizeof sock_name;
+ freeaddrinfo(info);
- if (getsockname(p->sock, (struct sockaddr *) &sock_name, &sock_namelen) < 0) {
- perror("getsockname");
- return false;
- }
+ p->on_disconnect = NULL;
+ p->on_recv = NULL;
+ p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types); // fixme: memory leak
- p->laddr = dragonnet_addr_parse_sock(sock_name);
return true;
}
#ifndef _DRAGONNET_PEER_H_
#define _DRAGONNET_PEER_H_
-#include <dragonnet/addr.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct dragonnet_peer {
int sock;
- DragonnetAddr laddr, raddr;
+ char *address;
+
pthread_t recv_thread;
pthread_mutex_t mtx;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
bool dragonnet_recv_raw(DragonnetPeer *p, void *buf, size_t n)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
void *dragonnet_peer_recv_thread(void *g_peer)
p->on_disconnect(p);
close(p->sock);
+ free(p->address);
pthread_mutex_destroy(&p->mtx);
free(p);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
bool dragonnet_send_raw(DragonnetPeer *p, bool submit, const void *buf, size_t n)
{