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