Mercurial > mplayer.hg
annotate TOOLS/netstream.c @ 27319:09cf111f68b8
Revert to previous dependency checking behavior.
Take included header files into account when generating dependency files.
This has problems when header files are removed or renamed, but does not
silently miscompile files.
author | diego |
---|---|
date | Sat, 26 Jul 2008 18:36:48 +0000 |
parents | 8825552ee585 |
children | 5a30f5bc23a0 |
rev | line source |
---|---|
22855 | 1 /* |
26743
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
2 * Copyright (C) Alban Bedel - 04/2003 |
22855 | 3 * |
26743
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
4 * This file is part of MPlayer. |
22855 | 5 * |
26743
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
6 * MPlayer is free software; you can redistribute it and/or modify |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
7 * it under the terms of the GNU General Public License as published by |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
8 * the Free Software Foundation; either version 2 of the License, or |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
9 * (at your option) any later version. |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
10 * |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
11 * MPlayer is distributed in the hope that it will be useful, |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
14 * GNU General Public License for more details. |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
15 * |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
16 * You should have received a copy of the GNU General Public License along |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
0f42fb42843c
Use standard license headers with standard formatting.
diego
parents:
26575
diff
changeset
|
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
22855 | 19 */ |
20 | |
21 #include <stdlib.h> | |
22 #include <stdio.h> | |
23 #include <unistd.h> | |
24 #include <inttypes.h> | |
25 #include <errno.h> | |
26 #include <signal.h> | |
27 #include <sys/types.h> | |
28 | |
29 #include "config.h" | |
30 | |
31 #ifndef HAVE_WINSOCK2 | |
32 #include <sys/socket.h> | |
33 #include <netinet/in.h> | |
34 #include <arpa/inet.h> | |
35 #else | |
36 #include <winsock2.h> | |
37 #include <ws2tcpip.h> | |
38 #endif | |
39 | |
40 #include "stream/stream.h" | |
41 #include "libmpdemux/demuxer.h" | |
42 #include "mp_msg.h" | |
43 #include "libavutil/common.h" | |
44 #include "mpbswap.h" | |
45 | |
46 /// Netstream packets def and some helpers | |
47 #include "stream/netstream.h" | |
48 | |
26963
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
49 // linking hacks |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
50 char *info_name; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
51 char *info_artist; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
52 char *info_genre; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
53 char *info_subject; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
54 char *info_copyright; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
55 char *info_sourceform; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
56 char *info_comment; |
22855 | 57 |
26963
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
58 char* out_filename = NULL; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
59 char* force_fourcc=NULL; |
8825552ee585
Fix the linking of TOOLS/netstream and TOOLS/vivodump.
diego
parents:
26743
diff
changeset
|
60 char* passtmpfile="divx2pass.log"; |
22855 | 61 |
62 #ifdef __MINGW32__ | |
63 #define usleep sleep | |
64 void strsep() {}; | |
65 #endif | |
66 | |
67 static unsigned short int port = 10000; | |
68 | |
69 typedef struct client_st client_t; | |
70 struct client_st { | |
71 int fd; | |
72 stream_t* stream; | |
73 client_t* next; | |
74 client_t* prev; | |
75 }; | |
76 | |
77 static int write_error(int fd,char* msg) { | |
78 int len = strlen(msg) + 1; | |
79 return write_packet(fd,NET_STREAM_ERROR,msg,len); | |
80 } | |
81 | |
82 static int net_stream_open(client_t* cl,char* url) { | |
83 int file_format=DEMUXER_TYPE_UNKNOWN; | |
84 mp_net_stream_opened_t ret; | |
85 | |
86 if(cl->stream) { | |
87 if(!write_error(cl->fd,"A stream is currently opened\n")) | |
88 return 0; | |
89 return 1; | |
90 } | |
91 | |
92 mp_msg(MSGT_NETST,MSGL_V,"Open stream %s\n",url); | |
93 cl->stream = open_stream(url,NULL,&file_format); | |
94 if(!cl->stream) { | |
95 if(!write_error(cl->fd,"Open failed\n")) | |
96 return 0; | |
97 return 1; | |
98 } | |
99 stream_reset(cl->stream); | |
100 stream_seek(cl->stream,cl->stream->start_pos); | |
101 ret.file_format = file_format; | |
102 ret.flags = cl->stream->flags; | |
103 ret.sector_size = cl->stream->sector_size; | |
104 ret.start_pos = cl->stream->start_pos; | |
105 ret.end_pos = cl->stream->end_pos; | |
106 net_stream_opened_2_me(&ret); | |
107 | |
108 if(!write_packet(cl->fd,NET_STREAM_OK,(char*)&ret,sizeof(mp_net_stream_opened_t))) | |
109 return 0; | |
110 return 1; | |
111 } | |
112 | |
113 static int net_stream_fill_buffer(client_t* cl,uint16_t max_len) { | |
114 int r; | |
115 mp_net_stream_packet_t *pack; | |
116 | |
117 if(!cl->stream) { | |
118 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
119 return 0; | |
120 return 1; | |
121 } | |
122 if(max_len == 0) { | |
24595 | 123 if(!write_error(cl->fd,"Fill buffer called with 0 length\n")) |
22855 | 124 return 0; |
125 return 1; | |
126 } | |
127 pack = malloc(max_len + sizeof(mp_net_stream_packet_t)); | |
128 pack->cmd = NET_STREAM_OK; | |
129 r = stream_read(cl->stream,pack->data,max_len); | |
130 pack->len = le2me_16(r + sizeof(mp_net_stream_packet_t)); | |
131 if(!net_write(cl->fd,(char*)pack,le2me_16(pack->len))) { | |
132 free(pack); | |
133 return 0; | |
134 } | |
135 free(pack); | |
136 return 1; | |
137 } | |
138 | |
139 static int net_stream_seek(client_t* cl, uint64_t pos) { | |
140 | |
141 if(!cl->stream) { | |
142 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
143 return 0; | |
144 return 1; | |
145 } | |
146 | |
147 if(!stream_seek(cl->stream,(off_t)pos)) { | |
148 if(!write_error(cl->fd,"Seek failed\n")) | |
149 return 0; | |
150 return 1; | |
151 } | |
152 if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) | |
153 return 0; | |
154 return 1; | |
155 } | |
156 | |
157 static int net_stream_reset(client_t* cl) { | |
158 if(!cl->stream) { | |
159 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
160 return 0; | |
161 return 1; | |
162 } | |
163 stream_reset(cl->stream); | |
164 if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) | |
165 return 0; | |
166 return 1; | |
167 } | |
168 | |
169 static int net_stream_close(client_t* cl) { | |
170 if(!cl->stream) { | |
171 if(!write_error(cl->fd,"No stream is currently opened\n")) | |
172 return 0; | |
173 return 1; | |
174 } | |
175 | |
176 free_stream(cl->stream); | |
177 cl->stream = NULL; | |
178 | |
179 if(!write_packet(cl->fd,NET_STREAM_OK,NULL,0)) | |
180 return 0; | |
181 return 1; | |
182 } | |
183 | |
26575
1ca484e74f18
Mark all functions that are only used within the file as static.
diego
parents:
25310
diff
changeset
|
184 static int handle_client(client_t* cl,mp_net_stream_packet_t* pack) { |
22855 | 185 |
186 if(!pack) | |
187 return 0; | |
188 | |
189 switch(pack->cmd) { | |
190 case NET_STREAM_OPEN: | |
191 if(((char*)pack)[pack->len-1] != '\0') { | |
192 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid open packet\n"); | |
193 return 0; | |
194 } | |
195 return net_stream_open(cl,pack->data); | |
196 case NET_STREAM_FILL_BUFFER: | |
197 if(pack->len != sizeof(mp_net_stream_packet_t) + 2) { | |
198 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); | |
199 return 0; | |
200 } | |
201 return net_stream_fill_buffer(cl,le2me_16(*((uint16_t*)pack->data))); | |
202 case NET_STREAM_SEEK: | |
203 if(pack->len != sizeof(mp_net_stream_packet_t) + 8) { | |
204 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); | |
205 return 0; | |
206 } | |
207 return net_stream_seek(cl,le2me_64(*((uint64_t*)pack->data))); | |
208 case NET_STREAM_RESET: | |
209 return net_stream_reset(cl); | |
210 case NET_STREAM_CLOSE: | |
211 if(pack->len != sizeof(mp_net_stream_packet_t)){ | |
212 mp_msg(MSGT_NETST,MSGL_WARN,"Got invalid fill buffer packet\n"); | |
213 return 0; | |
214 } | |
215 return net_stream_close(cl); | |
216 default: | |
217 mp_msg(MSGT_NETST,MSGL_WARN,"Got unknown command %d\n",pack->cmd); | |
218 if(!write_error(cl->fd,"Unknown command\n")) | |
219 return 0; | |
220 } | |
221 return 0; | |
222 } | |
223 | |
224 static client_t* add_client(client_t *head,int fd) { | |
225 client_t *new = calloc(1,sizeof(client_t)); | |
226 new->fd = fd; | |
227 if(!head) return new; | |
228 new->next = head; | |
229 head->prev = new; | |
230 return new; | |
231 } | |
232 | |
233 static int make_fd_set(fd_set* fds, client_t** _cl, int listen) { | |
234 int max_fd = listen; | |
235 client_t *cl = *_cl; | |
236 FD_ZERO(fds); | |
237 FD_SET(listen,fds); | |
238 while(cl) { | |
239 // Remove this client | |
240 if(cl->fd < 0) { | |
241 client_t* f = cl; | |
242 if(cl->prev) cl->prev->next = cl->next; | |
243 if(cl->next) cl->next->prev = cl->prev; | |
244 if(cl->stream) free_stream(cl->stream); | |
245 if(!cl->prev) // Remove the head | |
246 *_cl = cl->next; | |
247 cl = cl->next; | |
248 free(f); | |
249 continue; | |
250 } | |
251 FD_SET(cl->fd,fds); | |
252 if(cl->fd > max_fd) max_fd = cl->fd; | |
253 cl = cl->next; | |
254 } | |
255 return max_fd+1; | |
256 } | |
257 | |
258 /// Hack to 'cleanly' exit | |
259 static int run_server = 1; | |
260 | |
261 void exit_sig(int sig) { | |
262 static int count = 0; | |
263 sig++; // gcc warning | |
264 count++; | |
265 if(count==3) exit(1); | |
266 if(count > 3) | |
267 #ifdef __MINGW32__ | |
268 WSACleanup(); | |
269 #else | |
270 kill(getpid(),SIGKILL); | |
271 #endif | |
272 run_server = 0; | |
273 } | |
274 | |
275 static int main_loop(int listen_fd) { | |
276 client_t *clients = NULL,*iter; | |
277 fd_set fds; | |
278 | |
279 signal(SIGTERM,exit_sig); // kill | |
280 #ifndef __MINGW32__ | |
281 signal(SIGHUP,exit_sig); // kill -HUP / xterm closed | |
282 signal(SIGINT,exit_sig); // Interrupt from keyboard | |
283 signal(SIGQUIT,exit_sig); // Quit from keyboard | |
284 #endif | |
285 | |
286 while(run_server) { | |
287 int sel_n = make_fd_set(&fds,&clients,listen_fd); | |
288 int n = select(sel_n,&fds,NULL,NULL,NULL); | |
289 if(n < 0) { | |
290 if(errno == EINTR) | |
291 continue; | |
292 mp_msg(MSGT_NETST,MSGL_FATAL,"Select error: %s\n",strerror(errno)); | |
293 return 1; | |
294 } | |
295 // New connection | |
296 if(FD_ISSET(listen_fd,&fds)) { | |
297 struct sockaddr_in addr; | |
298 socklen_t slen = sizeof(struct sockaddr_in); | |
299 int client_fd = accept(listen_fd,(struct sockaddr*)&addr,&slen); | |
300 if(client_fd < 0) { | |
301 mp_msg(MSGT_NETST,MSGL_ERR,"accept failed: %s\n",strerror(errno)); | |
302 continue; | |
303 } | |
304 mp_msg(MSGT_NETST,MSGL_V,"New client from %s\n",inet_ntoa(addr.sin_addr)); | |
305 clients = add_client(clients,client_fd); | |
306 if(n == 1) continue; | |
307 } | |
308 // Look for the clients | |
309 for(iter = clients ; iter ; iter = iter->next) { | |
310 mp_net_stream_packet_t* pack; | |
311 if(!FD_ISSET(iter->fd,&fds)) continue; | |
312 pack = read_packet(iter->fd); | |
313 if(!pack) { | |
314 close(iter->fd); | |
315 iter->fd = -1; | |
316 continue; | |
317 } | |
318 if(!handle_client(iter,pack)) { | |
319 close(iter->fd); | |
320 iter->fd = -1; | |
321 } | |
322 free(pack); | |
323 } | |
324 } | |
325 mp_msg(MSGT_NETST,MSGL_INFO,"Exit ....\n"); | |
326 close(listen_fd); | |
327 #ifdef __MINGW32__ | |
328 WSACleanup(); | |
329 #endif | |
330 while(clients) { | |
331 client_t* f = clients; | |
332 if(f->stream) free_stream(f->stream); | |
333 if(f->fd > 0) close(f->fd); | |
334 free(f); | |
335 clients = clients->next; | |
336 } | |
337 return 0; | |
338 } | |
339 | |
25310
e3c5cd98d59a
Remove unused parameters from main(), fixes the warnings:
diego
parents:
24595
diff
changeset
|
340 int main(void) { |
22855 | 341 int listen_fd; |
342 struct sockaddr_in addr; | |
343 | |
344 mp_msg_init(); | |
345 // mp_msg_set_level(verbose+MSGL_STATUS); | |
346 | |
347 #ifdef __MINGW32__ | |
348 WSADATA wsaData; | |
349 WSAStartup(MAKEWORD(1,1), &wsaData); | |
350 #endif | |
351 listen_fd = socket(AF_INET, SOCK_STREAM, 0); | |
352 if(listen_fd < 0) { | |
353 mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to create listen_fd: %s\n",strerror(errno)); | |
354 return -1; | |
355 } | |
356 memset(&addr,0,sizeof(struct sockaddr)); | |
357 addr.sin_addr.s_addr = INADDR_ANY; | |
358 addr.sin_port = htons(port); | |
359 addr.sin_family = AF_INET; | |
360 if(bind(listen_fd,(struct sockaddr*)&addr,sizeof(struct sockaddr))) { | |
361 mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to bind listen socket: %s\n",strerror(errno)); | |
362 return -1; | |
363 } | |
364 | |
365 | |
366 if(listen(listen_fd,1)) { | |
367 mp_msg(MSGT_NETST,MSGL_FATAL,"Failed to turn the socket in listen state: %s\n",strerror(errno)); | |
368 return -1; | |
369 } | |
370 return main_loop(listen_fd); | |
371 } |