2 #include <dragonnet/peer.h>
3 #include <dragonnet/recv.h>
4 #include <dragonnet/recv_thread.h>
9 static bool dragonnet_peer_init(DragonnetPeer *p, char *addr)
11 pthread_rwlock_init(&p->mu, NULL);
12 pthread_rwlock_wrlock(&p->mu);
14 p->sock = socket(AF_INET6, SOCK_STREAM, 0);
15 p->raddr = dragonnet_addr_parse_str(addr);
16 p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types);
18 struct sockaddr_in6 sock_addr = dragonnet_addr_sock(p->raddr);
19 if (connect(p->sock, (const struct sockaddr *) &sock_addr,
20 sizeof sock_addr) < 0) {
25 struct sockaddr_in6 sock_name;
26 socklen_t sock_namelen = sizeof sock_name;
28 if (getsockname(p->sock, (struct sockaddr *) &sock_name, &sock_namelen) < 0) {
29 perror("getsockname");
33 p->laddr = dragonnet_addr_parse_sock(sock_name);
35 pthread_rwlock_unlock(&p->mu);
39 DragonnetPeer *dragonnet_connect(char *addr)
41 DragonnetPeer *p = malloc(sizeof *p);
42 if (!dragonnet_peer_init(p, addr)) {
43 dragonnet_peer_delete(p);
50 void dragonnet_peer_set_recv_hook(DragonnetPeer *p, u16 type_id,
51 void (*on_recv)(struct dragonnet_peer *, void *))
53 pthread_rwlock_rdlock(&p->mu);
54 DragonnetPeerState state = p->state;
55 pthread_rwlock_unlock(&p->mu);
57 if (state >= DRAGONNET_PEER_ACTIVE)
60 pthread_rwlock_wrlock(&p->mu);
61 p->on_recv_type[type_id] = on_recv;
62 pthread_rwlock_unlock(&p->mu);
65 void dragonnet_peer_run(DragonnetPeer *p)
67 pthread_rwlock_wrlock(&p->mu);
68 pthread_create(&p->recv_thread, NULL, &dragonnet_peer_recv_thread, p);
69 pthread_rwlock_unlock(&p->mu);
71 while (p->state < DRAGONNET_PEER_ACTIVE);
74 void dragonnet_peer_close(DragonnetPeer *p)
76 pthread_rwlock_wrlock(&p->mu);
78 pthread_t recv_thread = p->recv_thread;
79 if (p->state == DRAGONNET_PEER_ACTIVE)
80 shutdown(p->sock, SHUT_RDWR);
82 pthread_rwlock_unlock(&p->mu);
84 pthread_cancel(recv_thread);
85 pthread_join(recv_thread, NULL);
88 void dragonnet_peer_delete(DragonnetPeer *p)
90 pthread_rwlock_destroy(&p->mu);