]> git.sesse.net Git - cubemap/blob - cubemap.cpp
98db848152a380b9a279f4ac29e57ceedcf0a8d0
[cubemap] / cubemap.cpp
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdint.h>
4 #include <assert.h>
5 #include <arpa/inet.h>
6 #include <curl/curl.h>
7 #include <sys/socket.h>
8 #include <pthread.h>
9 #include <sys/types.h>
10 #include <sys/ioctl.h>
11 #include <sys/epoll.h>
12 #include <errno.h>
13 #include <vector>
14 #include <string>
15 #include <map>
16
17 #include "metacube.h"
18 #include "server.h"
19 #include "input.h"
20
21 #define NUM_SERVERS 4
22 #define STREAM_ID "stream"
23 #define STREAM_URL "http://gruessi.zrh.sesse.net:4013/"
24 #define PORT 9094
25
26 using namespace std;
27
28 Server *servers = NULL;
29
30 int create_server_socket(int port)
31 {
32         int server_sock = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
33         if (server_sock == -1) {
34                 perror("socket");
35                 exit(1);
36         }
37
38         // We want dual-stack sockets. (Sorry, OpenBSD and Windows XP...)
39         int zero = 0;
40         if (setsockopt(server_sock, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) == -1) {
41                 perror("setsockopt(IPV6_V6ONLY)");
42                 exit(1);
43         }
44
45         sockaddr_in6 addr;
46         memset(&addr, 0, sizeof(addr));
47         addr.sin6_family = AF_INET6;
48         addr.sin6_port = htons(port);
49
50         if (bind(server_sock, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) == -1) {
51                 perror("bind");
52                 exit(1);
53         }
54
55         if (listen(server_sock, 128) == -1) {
56                 perror("listen");
57                 exit(1);
58         }
59
60         return server_sock;
61 }
62
63 void *acceptor_thread_run(void *arg)
64 {
65         int server_sock = int(intptr_t(arg));
66         int num_accepted = 0;
67         for ( ;; ) {
68                 sockaddr_in6 addr;
69                 socklen_t addrlen = sizeof(addr);
70
71                 // Get a new socket.
72                 int sock = accept(server_sock, reinterpret_cast<sockaddr *>(&addr), &addrlen);
73                 if (sock == -1 && errno == EINTR) {
74                         continue;
75                 }
76                 if (sock == -1) {
77                         perror("accept");
78                         exit(1);
79                 }
80
81                 // Set the socket as nonblocking.
82                 int one = 1;
83                 if (ioctl(sock, FIONBIO, &one) == -1) {
84                         perror("FIONBIO");
85                         exit(1);
86                 }
87
88                 // Pick a server, round-robin, and hand over the socket to it.
89                 servers[num_accepted % NUM_SERVERS].add_client(sock);
90                 ++num_accepted; 
91         }
92 }
93
94 int main(int argc, char **argv)
95 {
96         servers = new Server[NUM_SERVERS];
97         for (int i = 0; i < NUM_SERVERS; ++i) {
98                 servers[i].add_stream(STREAM_ID);
99                 servers[i].run();
100         }
101
102         int server_sock = create_server_socket(PORT);
103
104         pthread_t acceptor_thread;
105         pthread_create(&acceptor_thread, NULL, acceptor_thread_run, reinterpret_cast<void *>(server_sock));
106
107         Input input(STREAM_ID);
108         input.run(STREAM_URL);
109 }