]> git.sesse.net Git - jam/blob - jam.c
Start parsing the destination list.
[jam] / jam.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <getopt.h>
5 #include <netdb.h>
6 #include <unistd.h>
7 #include <pthread.h>
8 #include <sys/socket.h>
9 #include <netinet/in.h>
10
11 unsigned short port = 2007;
12 struct in_addr *destinations = NULL;
13 unsigned num_destinations = 0;
14 unsigned room_destinations = 0;
15
16 const static struct option longopts[] = {
17         { "destination-file", required_argument, NULL, 'd' },
18         { "port", required_argument, NULL, 'p' },
19         { NULL, 0, NULL, 0 }
20 };
21
22 void read_destination_list(char *filename)
23 {
24         char buf[256];
25         FILE *in = fopen(filename, "r");
26         if (in == NULL) {
27                 perror(filename);
28                 exit(1);
29         }
30
31         for ( ;; ) {
32                 char *ptr;
33                 struct in_addr addr;
34                 struct hostent *he;
35
36                 if (fgets(buf, 256, in) == NULL)
37                         break;
38
39                 ptr = strchr(buf, '\n');
40                 if (ptr != NULL)
41                         *ptr = 0;
42
43                 ptr = strchr(buf, '\r');
44                 if (ptr != NULL)
45                         *ptr = 0;
46                 
47                 ptr = buf + strspn(buf, " \t");
48
49                 if (ptr[0] == '#' || ptr[0] == 0)
50                         continue;
51
52                 he = gethostbyname(ptr);
53                 if (he == NULL) {
54                         perror(ptr);
55                         exit(1);
56                 }
57
58                 // just pick the first for now
59                 memcpy(&addr.s_addr, he->h_addr_list[0], sizeof(addr.s_addr));
60
61                 // FIXME: store here
62         }
63
64         fclose(in);
65 }
66
67 void parse_options(int argc, char **argv)
68 {
69         int option_index = 0;
70
71         for ( ;; ) {
72                 int c = getopt_long(argc, argv, "d:p:", longopts, &option_index); 
73                 switch (c) {
74                 case 'd':
75                         read_destination_list(optarg);
76                         break;
77                 case 'p':
78                         port = atoi(optarg);
79                         break;
80                 case -1:
81                         return;       // end of argument list
82                 default:
83                         fprintf(stderr, "Invalid option\n");
84                         exit(1);
85                 }
86         }
87 }
88
89 void *receiver_worker(void *arg)
90 {
91         int sock = (int)arg;
92         char buf[65536];
93
94         printf("Received worker for socket %u\n", sock);
95
96         for ( ;; ) {
97                 int ret = read(sock, buf, 65536);
98                 if (ret == 0)
99                         break;
100
101                 // FIXME: update stats here
102         }
103
104         printf("Socket %u done\n", sock);
105         
106         if (close(sock) == -1) {
107                 perror("close()");
108                 exit(1);
109         }
110
111         pthread_exit(0);
112 }
113
114 int get_server_socket(unsigned short port)
115 {
116         int server_sock;
117         struct sockaddr_in sin;
118         unsigned one = 1;
119
120         server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
121         if (server_sock == -1) {
122                 perror("socket()");
123                 exit(1);
124         }
125
126         if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
127                 perror("setsocket(SO_REUSEADDR)");
128                 exit(1);
129         }
130
131         sin.sin_family = AF_INET;
132         sin.sin_port = htons(port);
133         sin.sin_addr.s_addr = INADDR_ANY;
134
135         if (bind(server_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) {
136                 perror("bind()");
137                 exit(1);
138         }
139
140         if (listen(server_sock, 255) == -1) {
141                 perror("listen()");
142                 exit(1);
143         }
144
145         return server_sock;
146 }
147
148 int main(int argc, char **argv)
149 {
150         int server_sock;
151
152         parse_options(argc, argv);
153         server_sock = get_server_socket(port);
154
155         // FIXME: fire off sender workers here
156
157         /*
158          * Listen for incoming connections, spawning off one receiver
159          * thread for each (which will just gobble up the data until
160          * we're done).
161          */
162         for ( ;; ) {
163                 struct sockaddr_in addr;
164                 socklen_t addr_len = sizeof(addr);
165                 pthread_t thread;
166                 pthread_attr_t attr;
167
168                 int sock = accept(server_sock, (struct sockaddr *)&addr, &addr_len);
169                 if (sock == -1) {
170                         perror("accept()");
171                         exit(1);
172                 }
173
174                 // FIXME: these do not really set errno
175                 if (pthread_attr_init(&attr) != 0) {
176                         perror("pthread_attr_init()");
177                         exit(1);
178                 }
179
180                 if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 65536 + 0x4000) != 0) {
181                         perror("pthread_attr_setstacksize");
182                         exit(1);
183                 }
184
185                 if (pthread_create(&thread, &attr, receiver_worker, (void *)sock) != 0) {
186                         perror("pthread_create()");
187                         exit(1);
188                 }
189         }
190
191         exit(0);
192 }