]> git.lizzy.rs Git - dragonnet.git/blob - recv_thread.c
Add wildcard receive hook
[dragonnet.git] / recv_thread.c
1 #include <assert.h>
2 #include <dragonnet/peer.h>
3 #include <dragonnet/recv.h>
4 #include <dragonnet/recv_thread.h>
5 #include <dragontype/number.h>
6 #include <pthread.h>
7 #include <stdbool.h>
8 #include <stdio.h>
9 #include <unistd.h>
10
11 void *dragonnet_peer_recv_thread(void *g_peer)
12 {
13         DragonnetPeer *p = (DragonnetPeer *) g_peer;
14
15         pthread_rwlock_wrlock(&p->mu);
16         assert(p->state == DRAGONNET_PEER_CREATED);
17         p->state++;
18         pthread_rwlock_unlock(&p->mu);
19
20         while (true) {
21                 u16 type_id;
22
23                 // Copy socket fd so that shutdown doesn't block
24                 pthread_rwlock_rdlock(&p->mu);
25                 int sock = p->sock;
26                 pthread_rwlock_unlock(&p->mu);
27
28                 ssize_t len = recv(sock, &type_id, sizeof type_id, MSG_WAITALL);
29                 if (len < 0) {
30                         perror("recv");
31                         dragonnet_peer_delete(p);
32                         return NULL;
33                 }
34
35                 // Connection closed
36                 if (len == 0) {
37                         pthread_rwlock_wrlock(&p->mu);
38
39                         close(p->sock);
40                         p->sock = -1;
41                         p->state++;
42
43                         pthread_rwlock_unlock(&p->mu);
44                         return NULL;
45                 }
46
47                 type_id = be16toh(type_id);
48                 DragonnetType type = dragonnet_types[type_id];
49                 u8 buf[type.siz];
50                 type.deserialize(p, buf);
51
52                 pthread_rwlock_rdlock(&p->mu);
53                 bool (*on_recv)(struct dragonnet_peer *, u16, void *) = p->on_recv;
54                 void (*on_recv_type)(DragonnetPeer *, void *) = p->on_recv_type[type_id];
55                 pthread_rwlock_unlock(&p->mu);
56
57                 if (on_recv != NULL && !on_recv(p, type, buf))
58                         on_recv_type = NULL;
59
60                 if (on_recv_type != NULL)
61                         on_recv_type(p, buf);
62         }
63 }