-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcounter.c
176 lines (138 loc) · 4.51 KB
/
counter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include "signals.h"
#include "sockets.h"
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
const char* PRICE_SERVER_IP = "127.0.0.1";
const unsigned short PRICE_SERVER_PORT = 21123;
const char PULL_LISTEN_IP [] = "127.0.0.1";
const unsigned short PULL_LISTEN_PORT = 21124;
int make_getter(const char* ip, const unsigned short port) {
int getter;
struct sockaddr_in addr;
getter = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
make_addr(ip, port, &addr);
if (connect(getter, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("connect");
return -1;
}
set_blocking(getter, 0);
return getter;
}
int make_listener(const char* ip, const unsigned short port) {
int listener;
struct sockaddr_in addr;
listener = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
make_addr(ip, port, &addr);
if (bind(listener, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)) != 0) {
perror("listener failed to bind");
return -1;
}
printf("Created UDP listener listening on %s:%u\n", ip, port);
return listener;
}
int ep_init(int nsocks, ...) {
int efd = epoll_create1(0);
va_list valist;
va_start(valist, nsocks);
for (int i = 0; i < nsocks; i++) {
int fd = va_arg(valist, int);
printf("Adding %d to epoll\n", fd);
struct epoll_event event;
event.data.u64 = (uint64_t)0;
event.data.fd = fd;
event.events = EPOLLET | EPOLLIN | EPOLLOUT | EPOLLHUP;
if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event) == -1) {
perror("epoll_ctl");
close(efd);
return -1;
}
}
va_end(valist);
return efd;
}
void ep_cleanup(int efd, int nsocks, ...) {
va_list valist;
va_start(valist, nsocks);
for (int i = 0; i < nsocks; i++) {
int fd = va_arg(valist, int);
if (fd >= 0) {
printf("Removing %d from epoll\n", fd);
struct epoll_event dummy;
if (epoll_ctl(efd, EPOLL_CTL_DEL, fd, &dummy) == -1) {
fprintf(stderr, "Failure when removing %d from epoll instance", fd);
}
}
}
va_end(valist);
close(efd);
}
void count() {
int sock_tcp = -1, sock_udp = -1, efd = -1;
struct epoll_event events[4];
unsigned price;
if ((sock_tcp = make_getter(PRICE_SERVER_IP, PRICE_SERVER_PORT)) < 0) {
fprintf(stderr, "can not connect to price server\n");
goto done;
}
if ((sock_udp = make_listener(PULL_LISTEN_IP, PULL_LISTEN_PORT)) < 0) {
fprintf(stderr, "can not connect to price server\n");
goto done;
}
if ((efd = ep_init(2, sock_tcp, sock_udp)) == -1) {
fprintf(stderr, "ep_init failed");
goto done;
}
while (!shutting_down) {
int nevents = epoll_wait(efd, events, 4, -1);
if (nevents == -1) {
break;
}
printf("Got %d epoll events\n", nevents);
for (int i = 0; i < nevents; i++) {
int fd = events[i].data.fd;
if (fd == sock_tcp) {
puts("TCP");
ssize_t nrecv = recv(sock_tcp, &price, sizeof(price), 0);
if (nrecv < 0) {
perror("recv");
break;
}
if (nrecv == 0) {
printf("recv returned 0\n");
break;
}
printf("TCP received price: %u\n", price);
} else if (fd == sock_udp) {
puts("UDP");
ssize_t nrecvfrom = recvfrom(sock_udp, &price, sizeof(price), 0, 0, 0);
if (nrecvfrom < 0) {
perror("recvfrom");
break;
}
if (nrecvfrom != sizeof(price)) {
printf("recvfrom returned 0\n");
break;
}
printf("UDP received price: %u\n", price);
}
}
}
done:
ep_cleanup(efd, 2, sock_tcp, sock_udp);
close(sock_udp);
close(sock_tcp);
}
int main(int argc, char** argv) {
printf("FTL Counter\n");
if (setup_signal_handlers() != 0) {
fprintf(stderr, "Error setting up signal handlers");
return EXIT_FAILURE;
}
count();
return EXIT_SUCCESS;
}