/[cvs]/wurmi/streamer.c
ViewVC logotype

Contents of /wurmi/streamer.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6 - (show annotations)
Mon Sep 10 13:00:55 2007 UTC (11 years, 3 months ago) by riso
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +4 -1 lines
File MIME type: text/plain
Running now  :-)
:

1 #include <stdio.h>
2 #include <signal.h>
3 #include <errno.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <arpa/inet.h>
8 #include <netdb.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sys/select.h>
12
13 //#define dbg(x...) fprintf(stderr, x)
14 #define dbg(x...)
15
16
17 struct client {
18 int fd;
19 int ptr;
20 };
21
22 struct vector {
23 int n, size, alloc;
24 void *data;
25 struct client *C;
26 };
27
28 static inline int max(int a, int b) {
29 return (a>b)? a:b;
30 }
31
32 void InitVector(struct vector *v, int size) {
33 v->size = size;
34 v->n = 0;
35 v->alloc = 1024;
36 v->data = malloc(v->alloc*v->size);
37 v->C = (struct client *)v->data;
38 }
39
40 void GrowVector(struct vector *v) {
41 if (v->n >= v->alloc) {
42 v->alloc = (v->n/1024 +1)*1024;
43 v->data = realloc(v->data, v->alloc*v->size);
44 v->C = (struct client *)v->data;
45 }
46 }
47
48 void FreeVector(struct vector *v) {
49 free(v->data);
50 v->alloc = v->n = 0;
51 }
52
53 void Usage() {
54 fprintf(stderr, "Usage: streamer master-port client-port [-single]\n");
55 exit(0);
56 }
57
58 int StartServer(int port) {
59 int fd, opt;
60 struct sockaddr_in saddr;
61
62 if (-1 == (fd = socket(PF_INET, SOCK_STREAM, 0))) {
63 fprintf(stderr, "Cannot open socket\n");
64 return -1;
65 }
66
67 saddr.sin_family = AF_INET;
68 saddr.sin_port = htons(port);
69 saddr.sin_addr.s_addr = INADDR_ANY;
70
71 opt = 1;
72 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
73 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr))) {
74 perror("Cannot bind socket");
75 close(fd);
76 return -1;
77 }
78
79 if (listen(fd, 5)) {
80 fprintf(stderr, "Cannot listen socket\n");
81 close(fd);
82 return -1;
83 }
84
85 return fd;
86 }
87
88 void DoSession(int master_fd, int client_fd) {
89 static const int buflen = 65536;
90
91 struct vector data, clients;
92 fd_set rset, wset;
93 int i, maxfd, len;
94
95 InitVector(&data, 1);
96 InitVector(&clients, sizeof(struct client));
97
98 dbg("Starting session\n");
99
100 while(1) {
101 FD_ZERO(&rset);
102 FD_ZERO(&wset);
103 FD_SET(master_fd, &rset);
104 FD_SET(client_fd, &rset);
105 maxfd = max(master_fd, client_fd);
106 for (i=0; i<clients.n; i++)
107 if (clients.C[i].ptr < data.n) {
108 FD_SET(clients.C[i].fd, &wset);
109 maxfd = max(maxfd, clients.C[i].fd);
110 }
111
112 dbg("selecting\n");
113 select(maxfd+1, &rset, &wset, NULL, NULL);
114 dbg("done\n");
115
116 if (FD_ISSET(client_fd, &rset)) {
117 i = accept(client_fd, NULL, NULL);
118 if (i != -1) {
119 clients.C[clients.n].fd = i;
120 clients.C[clients.n].ptr = 0;
121 clients.n++;
122 GrowVector(&clients);
123 }
124 }
125
126 for (i=0; i<clients.n; i++)
127 if (FD_ISSET(clients.C[i].fd, &wset) && clients.C[i].ptr < data.n) {
128 len = write(clients.C[i].fd, data.data+clients.C[i].ptr, data.n-clients.C[i].ptr);
129 if (len > 0) clients.C[i].ptr += len;
130 if (len == EPIPE) {
131 close(clients.C[i].fd);
132 clients.C[i] = clients.C[--clients.n];
133 i--;
134 }
135 }
136
137 if (FD_ISSET(master_fd, &rset)) {
138 dbg("reading...\n");
139 data.n += buflen;
140 GrowVector(&data);
141 len = read(master_fd, data.data+data.n-buflen, buflen);
142 if (len < 0) data.n = data.n-buflen;
143 else data.n = data.n-buflen+len;
144 if (len == 0) break; // EOF from master
145 }
146 }
147
148 for (i=0; i<clients.n; i++) {
149 close(clients.C[i].fd);
150 }
151 FreeVector(&clients);
152 FreeVector(&data);
153 close(master_fd);
154 }
155
156 int main(int argc, char **argv) {
157 int master_port, client_port;
158 int master_fd, client_fd, fd;
159 struct sockaddr_in saddr;
160 unsigned len;
161 struct hostent *hent;
162 char **i;
163 int OneShot = 0;
164
165 if (argc<=2) Usage();
166 if (sscanf(argv[1], "%d", &master_port) != 1) Usage();
167 if (sscanf(argv[2], "%d", &client_port) != 1) Usage();
168 if (argc>3) OneShot=1;
169
170 signal(SIGPIPE,SIG_IGN);
171 master_fd = StartServer(master_port);
172 client_fd = StartServer(client_port);
173
174 hent = gethostbyname("localhost");
175
176 fprintf(stderr,"Starting streamer: master port=%d, client port=%d\n",master_port,client_port);
177
178 while(1) {
179 len = sizeof(saddr);
180 if (-1 == (fd = accept(master_fd, (struct sockaddr *)&saddr, &len)) ) continue;
181 for (i = hent->h_addr_list; *i; i++) // check if the connection is from localhost
182 if (*(u_int32_t *)(*i) == saddr.sin_addr.s_addr) break;
183 if (*i) DoSession(fd, client_fd);
184 else {
185 dbg("Connection refused to %x\n",saddr.sin_addr.s_addr);
186 close(fd);
187 }
188 if (OneShot) break;
189 }
190
191 fprintf(stderr,"Exiting streamer: master port=%d, client port=%d\n",master_port,client_port);
192
193 return 0;
194 }

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.26