]> git.lizzy.rs Git - dragonnet.git/blob - peer.c
Use dragontype numbers instead of stdint everywhere
[dragonnet.git] / peer.c
1 #include <assert.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #include "peer.h"
7 #include "recv_thread.h"
8
9 const struct timeval dragonnet_timeout = {
10         .tv_sec = 30,
11         .tv_usec = 0
12 };
13
14 static bool dragonnet_peer_init(DragonnetPeer *p, char *addr)
15 {
16         pthread_rwlock_init(&p->mu, NULL);
17         pthread_rwlock_wrlock(&p->mu);
18
19         p->sock = socket(AF_INET6, SOCK_STREAM, 0);
20         p->raddr = dragonnet_addr_parse_str(addr);
21
22         if (setsockopt(p->sock, SOL_SOCKET, SO_RCVTIMEO, &dragonnet_timeout,
23                         sizeof dragonnet_timeout) < 0) {
24                 perror("setsockopt");
25                 return false;
26         }
27
28         if (setsockopt(p->sock, SOL_SOCKET, SO_SNDTIMEO, &dragonnet_timeout,
29                         sizeof dragonnet_timeout) < 0) {
30                 perror("setsockopt");
31                 return false;
32         }
33
34         struct sockaddr_in6 sock_addr = dragonnet_addr_sock(p->raddr);
35         if (connect(p->sock, (const struct sockaddr *) &sock_addr,
36                         sizeof sock_addr) < 0) {
37                 perror("connect");
38                 return false;
39         }
40
41         struct sockaddr_in6 sock_name;
42         socklen_t sock_namelen = sizeof sock_name;
43
44         if (getsockname(p->sock, (struct sockaddr *) &sock_name, &sock_namelen) < 0) {
45                 perror("getsockname");
46                 return false;
47         }
48
49         p->laddr = dragonnet_addr_parse_sock(sock_name);
50
51         pthread_rwlock_unlock(&p->mu);
52         return true;
53 }
54
55 DragonnetPeer *dragonnet_connect(char *addr)
56 {
57         DragonnetPeer *p = malloc(sizeof *p);
58         if (!dragonnet_peer_init(p, addr)) {
59                 dragonnet_peer_delete(p);
60                 return NULL;
61         }
62
63         return p;
64 }
65
66 void dragonnet_peer_run(DragonnetPeer *p)
67 {
68         pthread_t recv_thread;
69         pthread_create(&recv_thread, NULL, &dragonnet_peer_recv_thread, p);
70         pthread_join(recv_thread, NULL);
71 }
72
73 void dragonnet_peer_close(DragonnetPeer *p)
74 {
75         pthread_rwlock_wrlock(&p->mu);
76
77         if (p->state == DRAGONNET_PEER_ACTIVE) {
78                 shutdown(p->sock, SHUT_RDWR);
79                 p->state++;
80         }
81
82         pthread_rwlock_unlock(&p->mu);
83 }
84
85 void dragonnet_peer_delete(DragonnetPeer *p)
86 {
87         pthread_rwlock_destroy(&p->mu);
88         free(p);
89 }