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