13 #define mymax(a, b) ((a) > (b) ? (a) : (b))
19 static bool dragonnet_peer_init_accepted(DragonnetPeer *p, int sock,
20 char *addr, DragonnetListener *l)
22 pthread_mutex_init(&p->mtx, NULL);
26 p->on_disconnect = l->on_disconnect;
27 p->on_recv = l->on_recv;
28 p->on_recv_type = l->on_recv_type;
33 static DragonnetPeer *dragonnet_peer_accept(int sock, char *addr,
36 DragonnetPeer *p = malloc(sizeof *p);
37 if (!dragonnet_peer_init_accepted(p, sock, addr, l)) {
38 pthread_mutex_destroy(&p->mtx);
51 DragonnetListener *dragonnet_listener_new(char *addr)
53 struct addrinfo *info = dragonnet_str2addr(addr);
57 DragonnetListener *l = malloc(sizeof *l);
59 if ((l->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol)) < 0) {
60 dragonnet_perror("socket");
67 l->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen);
69 l->on_disconnect = NULL;
71 l->on_recv_type = calloc(sizeof *l->on_recv_type, dragonnet_num_types);
74 if (setsockopt(l->sock, SOL_SOCKET, SO_REUSEADDR, (void *) &so_reuseaddr,
75 sizeof so_reuseaddr) < 0) {
76 dragonnet_perror("setsockopt");
78 dragonnet_listener_delete(l);
82 if (bind(l->sock, info->ai_addr, info->ai_addrlen) < 0) {
83 dragonnet_perror("bind");
85 dragonnet_listener_delete(l);
91 if (listen(l->sock, 10) < 0) {
92 dragonnet_perror("listen");
93 dragonnet_listener_delete(l);
100 static void *listener_main(void *g_listener)
103 pthread_setname_np(pthread_self(), "listen");
106 DragonnetListener *l = (DragonnetListener *) g_listener;
109 struct sockaddr_storage clt_addr;
110 socklen_t clt_addrlen = sizeof clt_addr;
112 struct timeval *tv = NULL;
116 FD_SET(l->sock, &set);
120 // on windows, we can't listen on the pipe, set timeout instead
121 tv = &(struct timeval) {1, 0};
123 FD_SET(l->intr[0], &set);
125 if (nfds < l->intr[0])
129 if (select(nfds + 1, &set, NULL, NULL, tv) < 0) {
130 dragonnet_perror("select");
134 if (!FD_ISSET(l->sock, &set))
137 int clt_sock = accept(l->sock, (struct sockaddr *) &clt_addr, &clt_addrlen);
139 dragonnet_perror("accept");
143 char *clt_addstr = dragonnet_addr2str((struct sockaddr *) &clt_addr, clt_addrlen);
144 DragonnetPeer *p = dragonnet_peer_accept(clt_sock, clt_addstr, l);
148 void (*on_connect)(DragonnetPeer *) = l->on_connect;
150 if (on_connect != NULL)
153 dragonnet_peer_run(p);
159 void dragonnet_listener_run(DragonnetListener *l)
164 pthread_create(&l->accept_thread, NULL, &listener_main, l);
167 void dragonnet_listener_close(DragonnetListener *l)
174 pthread_join(l->accept_thread, NULL);
180 void dragonnet_listener_delete(DragonnetListener *l)
182 free(l->on_recv_type);