]> git.sesse.net Git - jam/blob - jam.c
Start parsing options.
[jam] / jam.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <getopt.h>
4 #include <unistd.h>
5 #include <pthread.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8
9 const static struct option longopts[] = {
10         { "destination-file", required_argument, NULL, 'd' },
11         { NULL, 0, NULL, 0 }
12 };
13
14 void read_destination_list(char *filename)
15 {
16         
17 }
18
19 void parse_options(int argc, char **argv)
20 {
21         int option_index = 0;
22
23         for ( ;; ) {
24                 int c = getopt_long(argc, argv, "d:", longopts, &option_index); 
25                 switch (c) {
26                 case 'd':
27                         read_destination_list(optarg);
28                         break;
29                 case -1:
30                         return;       // end of argument list
31                 default:
32                         fprintf(stderr, "Invalid option\n");
33                         exit(1);
34                 }
35         }
36 }
37
38 void *receiver_worker(void *arg)
39 {
40         int sock = (int)arg;
41         char buf[65536];
42
43         printf("Received worker for socket %u\n", sock);
44
45         for ( ;; ) {
46                 int ret = read(sock, buf, 65536);
47                 if (ret == 0)
48                         break;
49
50                 // FIXME: update stats here
51         }
52
53         printf("Socket %u done\n", sock);
54         
55         if (close(sock) == -1) {
56                 perror("close()");
57                 exit(1);
58         }
59
60         pthread_exit(0);
61 }
62
63 int get_server_socket(unsigned short port)
64 {
65         int server_sock;
66         struct sockaddr_in sin;
67         unsigned one = 1;
68
69         server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
70         if (server_sock == -1) {
71                 perror("socket()");
72                 exit(1);
73         }
74
75         if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
76                 perror("setsocket(SO_REUSEADDR)");
77                 exit(1);
78         }
79
80         sin.sin_family = AF_INET;
81         sin.sin_port = htons(port);
82         sin.sin_addr.s_addr = INADDR_ANY;
83
84         if (bind(server_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1) {
85                 perror("bind()");
86                 exit(1);
87         }
88
89         if (listen(server_sock, 255) == -1) {
90                 perror("listen()");
91                 exit(1);
92         }
93
94         return server_sock;
95 }
96
97 int main(int argc, char **argv)
98 {
99         int server_sock;
100
101         parse_options(argc, argv);
102         server_sock = get_server_socket(2007);
103
104         // FIXME: fire off sender workers here
105
106         /*
107          * Listen for incoming connections, spawning off one receiver
108          * thread for each (which will just gobble up the data until
109          * we're done).
110          */
111         for ( ;; ) {
112                 struct sockaddr_in addr;
113                 socklen_t addr_len = sizeof(addr);
114                 pthread_t thread;
115                 pthread_attr_t attr;
116
117                 int sock = accept(server_sock, (struct sockaddr *)&addr, &addr_len);
118                 if (sock == -1) {
119                         perror("accept()");
120                         exit(1);
121                 }
122
123                 // FIXME: these do not really set errno
124                 if (pthread_attr_init(&attr) != 0) {
125                         perror("pthread_attr_init()");
126                         exit(1);
127                 }
128
129                 if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 65536 + 0x4000) != 0) {
130                         perror("pthread_attr_setstacksize");
131                         exit(1);
132                 }
133
134                 if (pthread_create(&thread, &attr, receiver_worker, (void *)sock) != 0) {
135                         perror("pthread_create()");
136                         exit(1);
137                 }
138         }
139
140         exit(0);
141 }