~motumedia/mplayer2/master

« back to all changes in this revision

Viewing changes to TOOLS/netstream.c

  • Committer: Uoti Urpala
  • Author(s): wm4
  • Date: 2013-01-15 22:29:10 UTC
  • Revision ID: git-v1:a16530e63730b4887d8f647c10e4a45d446ee133
stream_netstream: Remove netstream support

This allowed to move the input stream layer across the network,
allowing the user to play anything that mplayer could play remotely.
For example, playing a DVD related on a remote server (say, with the
host name "remotehost1") could be done by starting the netstream
server (from TOOLS/netstream.c) on that remote server, and then
running:

    mplayer mpst://remotehost1/dvd://

This would open the DVD on the remote host, and transfer the raw DVD
sector reads over network. It works the same for other protocols, and
all accesses to the stream layer are marshaled over network. It's
comparable to the way the cache layer (--cache) works.

It has questionable use and most likely was barely used at all.
There's lots of potential for breakage, because it doesn't translate
the stream CTRLs to network packets. Just get rid of it.

Show diffs side-by-side

added added

removed removed

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