streamers / streamer.c @ 3730fda0
History | View | Annotate | Download (7.49 KB)
1 | 89e893e2 | Luca | /*
|
---|---|---|---|
2 | 8fed7779 | CsabaKiraly | * Copyright (c) 2010 Luca Abeni
|
3 | * Copyright (c) 2010 Csaba Kiraly
|
||
4 | 89e893e2 | Luca | *
|
5 | 8fed7779 | CsabaKiraly | * This is free software; see gpl-3.0.txt
|
6 | 89e893e2 | Luca | */
|
7 | #include <stdlib.h> |
||
8 | #include <stdint.h> |
||
9 | #include <stdio.h> |
||
10 | 46c24e94 | Csaba Kiraly | #include <stdbool.h> |
11 | 89e893e2 | Luca | #include <string.h> |
12 | #include <getopt.h> |
||
13 | 5dcfffbc | CsabaKiraly | #include <signal.h> |
14 | e28a1487 | CsabaKiraly | #include <grapes_msg_types.h> |
15 | 89e893e2 | Luca | #include <net_helper.h> |
16 | |||
17 | 95e6fe96 | CsabaKiraly | #ifdef WIN32
|
18 | #include <winsock2.h> |
||
19 | #endif
|
||
20 | |||
21 | 89e893e2 | Luca | #include "net_helpers.h" |
22 | #include "loop.h" |
||
23 | f0bb64e2 | Csaba Kiraly | #include "output.h" |
24 | 581339c4 | Csaba Kiraly | #include "channel.h" |
25 | f088e50e | MarcoBiazzini | #include "topology.h" |
26 | a8a31ce0 | Csaba Kiraly | #include "measures.h" |
27 | 89e893e2 | Luca | |
28 | 7c21b5b1 | CsabaKiraly | const char *peername = NULL; |
29 | |||
30 | 613263e9 | Csaba Kiraly | static const char *my_iface = NULL; |
31 | 89e893e2 | Luca | static int port = 6666; |
32 | static int srv_port; |
||
33 | 0f23522a | Luca | static const char *srv_ip = ""; |
34 | 66f50156 | Csaba Kiraly | static int period = 40; |
35 | static int chunks_per_second = 25; |
||
36 | 6d0c8116 | GiuseppeTropea | #ifdef HTTPIO
|
37 | //input-http.c needs this in order to accomplish the -m multiple send_chunk()
|
||
38 | 66f84460 | CsabaKiraly | int multiply = 3; |
39 | 6d0c8116 | GiuseppeTropea | #else
|
40 | 66f84460 | CsabaKiraly | static int multiply = 3; |
41 | 6d0c8116 | GiuseppeTropea | #endif
|
42 | 789d6502 | Csaba Kiraly | static int buff_size = 50; |
43 | 66f84460 | CsabaKiraly | static int outbuff_size = 50; |
44 | adb2a9b2 | CsabaKiraly | static const char *fname = "/dev/stdin"; |
45 | 463000a4 | CsabaKiraly | static const char *output_config; |
46 | 46c24e94 | Csaba Kiraly | static bool loop_input = false; |
47 | 193622ac | CsabaKiraly | static const char *net_helper_config = ""; |
48 | 5f72f6b3 | Csaba Kiraly | static const char *topo_config = ""; |
49 | 33d23b91 | MarcoBiazzini | unsigned char msgTypes[] = {MSG_TYPE_CHUNK,MSG_TYPE_SIGNALLING}; |
50 | 1cd06c26 | CsabaKiraly | bool chunk_log = false; |
51 | 89e893e2 | Luca | |
52 | 20663df3 | Csaba Kiraly | extern int NEIGHBORHOOD_TARGET_SIZE; |
53 | 3730fda0 | Csaba Kiraly | extern uint64_t CB_SIZE_TIME;
|
54 | 20663df3 | Csaba Kiraly | |
55 | 75b2b975 | Csaba Kiraly | extern struct timeval print_tdiff; |
56 | extern struct timeval tstartdiff; |
||
57 | |||
58 | 43c2d7d6 | CsabaKiraly | static void print_usage(int argc, char *argv[]) |
59 | a02fc4cf | MarcoMellia | { |
60 | fprintf (stderr, |
||
61 | 60784aa1 | CsabaKiraly | "Usage:%s [options]\n"
|
62 | a02fc4cf | MarcoMellia | "\n"
|
63 | "Peer options\n"
|
||
64 | "\t[-p port]: port of the remote peer to connect at during bootstrap.\n"
|
||
65 | "\t Usually it is the source peer port.\n"
|
||
66 | "\t[-i IP]: IP address of the remote peer to connect at during bootstrap.\n"
|
||
67 | "\t Usually it is the source peer IP\n"
|
||
68 | "\t[-C name]: set the channel name to use on the repository.\n"
|
||
69 | "\t All peers should use the same channel name.\n"
|
||
70 | "\n"
|
||
71 | "\t[-b size]: set the peer Chunk Buffer size.\n"
|
||
72 | "\t This is also the chunk trading window size.\n"
|
||
73 | "\t[-o size]: set the Output Buffer size.\n"
|
||
74 | "\t[-c chunks]: set the number of chunks a peer can send per seconds.\n"
|
||
75 | "\t it controls the upload capacity of peer as well.\n"
|
||
76 | 20663df3 | Csaba Kiraly | "\t[-M peers]: neighbourhood target size.\n"
|
77 | 5f72f6b3 | Csaba Kiraly | "\t[-t config]: topology config.\n"
|
78 | a02fc4cf | MarcoMellia | "\t[-P port]: local UDP port to be used by the peer.\n"
|
79 | 60784aa1 | CsabaKiraly | "\t[-I iface]: local netwok interface to be used by the peer.\n"
|
80 | a02fc4cf | MarcoMellia | "\t Useful if the host has several interfaces/addresses.\n"
|
81 | 7c21b5b1 | CsabaKiraly | "\t[-N name]: set the name of the peer.\n"
|
82 | "\t This name will be used when publishing in the repository.\n"
|
||
83 | 193622ac | CsabaKiraly | "\t[-n options]: pass configuration options to the net-helper\n"
|
84 | 1cd06c26 | CsabaKiraly | "\t[--chunk_log]: print a chunk level log on stderr\n"
|
85 | 60784aa1 | CsabaKiraly | "\t[-F config]: configure the output module\n"
|
86 | a02fc4cf | MarcoMellia | "\n"
|
87 | "Special Source Peer options\n"
|
||
88 | "\t[-m chunks]: set the number of copies the source injects in the overlay.\n"
|
||
89 | "\t[-f filename]: name of the video stream file to transmit.\n"
|
||
90 | 8977e724 | CsabaKiraly | "\t[-l]: loop the video stream.\n"
|
91 | a02fc4cf | MarcoMellia | "\n"
|
92 | 60784aa1 | CsabaKiraly | "NOTE: by deafult the peer will dump the received video on STDOUT in raw format\n"
|
93 | a02fc4cf | MarcoMellia | " it can be played by your favourite player simply using a pipe\n"
|
94 | 60784aa1 | CsabaKiraly | " e.g., | cvlc /dev/stdin\n"
|
95 | a02fc4cf | MarcoMellia | "\n"
|
96 | "Examples:\n"
|
||
97 | "\n"
|
||
98 | "Start a source peer on port 6600:\n"
|
||
99 | "\n"
|
||
100 | 60784aa1 | CsabaKiraly | "%s -l -f foreman.mpg -P 6600\n"
|
101 | a02fc4cf | MarcoMellia | "\n"
|
102 | "Start a peer connecting to the previous source, and using videolan as player:\n"
|
||
103 | "\n"
|
||
104 | 60784aa1 | CsabaKiraly | "%s -i <sourceIP> -p <sourcePort> | cvlc /dev/stdin\n"
|
105 | "=======================================================\n", argv[0], argv[0], argv[0] |
||
106 | a02fc4cf | MarcoMellia | ); |
107 | } |
||
108 | |||
109 | |||
110 | |||
111 | 89e893e2 | Luca | static void cmdline_parse(int argc, char *argv[]) |
112 | { |
||
113 | int o;
|
||
114 | |||
115 | 4aaa8891 | MatteoSammarco | int option_index = 0; |
116 | static struct option long_options[] = { |
||
117 | e63b7606 | MatteoSammarco | {"chunk_log", no_argument, 0, 0}, |
118 | 75b2b975 | Csaba Kiraly | {"measure_start", required_argument, 0, 0}, |
119 | {"measure_every", required_argument, 0, 0}, |
||
120 | 3730fda0 | Csaba Kiraly | {"playout_limit", required_argument, 0, 0}, |
121 | e63b7606 | MatteoSammarco | {0, 0, 0, 0} |
122 | 4aaa8891 | MatteoSammarco | }; |
123 | |||
124 | 5f72f6b3 | Csaba Kiraly | while ((o = getopt_long (argc, argv, "b:o:c:p:i:P:I:f:F:m:lC:N:n:M:t:",long_options, &option_index)) != -1) { //use this function to manage long options |
125 | 89e893e2 | Luca | switch(o) {
|
126 | 4aaa8891 | MatteoSammarco | case 0: //for long options |
127 | 1cd06c26 | CsabaKiraly | if( strcmp( "chunk_log", long_options[option_index].name ) == 0 ) { chunk_log = true; } |
128 | 75b2b975 | Csaba Kiraly | if( strcmp( "measure_start", long_options[option_index].name ) == 0 ) { tstartdiff.tv_sec = atoi(optarg); } |
129 | if( strcmp( "measure_every", long_options[option_index].name ) == 0 ) { print_tdiff.tv_sec = atoi(optarg); } |
||
130 | 3730fda0 | Csaba Kiraly | if( strcmp( "playout_limit", long_options[option_index].name ) == 0 ) { CB_SIZE_TIME = atoi(optarg); } |
131 | 1cd06c26 | CsabaKiraly | break;
|
132 | 90f3a290 | CsabaKiraly | case 'b': |
133 | 0a40460a | Luca | buff_size = atoi(optarg); |
134 | break;
|
||
135 | 90f3a290 | CsabaKiraly | case 'o': |
136 | f0bb64e2 | Csaba Kiraly | outbuff_size = atoi(optarg); |
137 | break;
|
||
138 | 90f3a290 | CsabaKiraly | case 'c': |
139 | 0a40460a | Luca | chunks_per_second = atoi(optarg); |
140 | break;
|
||
141 | 90f3a290 | CsabaKiraly | case 'm': |
142 | 59b7cfc6 | Csaba Kiraly | multiply = atoi(optarg); |
143 | break;
|
||
144 | 90f3a290 | CsabaKiraly | case 'p': |
145 | 89e893e2 | Luca | srv_port = atoi(optarg); |
146 | break;
|
||
147 | 90f3a290 | CsabaKiraly | case 'i': |
148 | 89e893e2 | Luca | srv_ip = strdup(optarg); |
149 | break;
|
||
150 | 90f3a290 | CsabaKiraly | case 'P': |
151 | 89e893e2 | Luca | port = atoi(optarg); |
152 | break;
|
||
153 | 90f3a290 | CsabaKiraly | case 'I': |
154 | 568bd1bd | Luca Abeni | my_iface = strdup(optarg); |
155 | 89e893e2 | Luca | break;
|
156 | 90f3a290 | CsabaKiraly | case 'f': |
157 | e37511b1 | Luca Abeni | fname = strdup(optarg); |
158 | break;
|
||
159 | 463000a4 | CsabaKiraly | case 'F': |
160 | output_config = strdup(optarg); |
||
161 | break;
|
||
162 | 90f3a290 | CsabaKiraly | case 'l': |
163 | 46c24e94 | Csaba Kiraly | loop_input = true;
|
164 | break;
|
||
165 | 90f3a290 | CsabaKiraly | case 'C': |
166 | 581339c4 | Csaba Kiraly | channel_set_name(optarg); |
167 | 8253c8ea | CsabaKiraly | break;
|
168 | 193622ac | CsabaKiraly | case 'n': |
169 | net_helper_config = strdup(optarg); |
||
170 | 581339c4 | Csaba Kiraly | break;
|
171 | 7c21b5b1 | CsabaKiraly | case 'N': |
172 | peername = strdup(optarg); |
||
173 | break;
|
||
174 | 20663df3 | Csaba Kiraly | case 'M': |
175 | NEIGHBORHOOD_TARGET_SIZE = atoi(optarg); |
||
176 | break;
|
||
177 | 5f72f6b3 | Csaba Kiraly | case 't': |
178 | topo_config = strdup(optarg); |
||
179 | break;
|
||
180 | 89e893e2 | Luca | default:
|
181 | fprintf(stderr, "Error: unknown option %c\n", o);
|
||
182 | 43c2d7d6 | CsabaKiraly | print_usage(argc, argv); |
183 | 89e893e2 | Luca | |
184 | exit(-1);
|
||
185 | } |
||
186 | } |
||
187 | 581339c4 | Csaba Kiraly | |
188 | if (!channel_get_name()) {
|
||
189 | channel_set_name("generic");
|
||
190 | } |
||
191 | 37b749c8 | CsabaKiraly | |
192 | if (argc <= 1) { |
||
193 | print_usage(argc, argv); |
||
194 | fprintf(stderr, "Trying to start a source with default parameters, reading from %s\n", fname);
|
||
195 | } |
||
196 | 89e893e2 | Luca | } |
197 | |||
198 | 7a673aa5 | Csaba Kiraly | static void init_rand(const char * s) |
199 | { |
||
200 | long i, l, x;
|
||
201 | struct timeval t;
|
||
202 | |||
203 | gettimeofday(&t, NULL);
|
||
204 | |||
205 | x = 1;
|
||
206 | l = strlen(s); |
||
207 | for (i = 0; i < l; i++) { |
||
208 | x *= s[i]; |
||
209 | } |
||
210 | |||
211 | srand(t.tv_usec * t.tv_sec * x); |
||
212 | } |
||
213 | |||
214 | 89e893e2 | Luca | static struct nodeID *init(void) |
215 | { |
||
216 | bdd19faf | Csaba Kiraly | int i;
|
217 | 89e893e2 | Luca | struct nodeID *myID;
|
218 | 613263e9 | Csaba Kiraly | char *my_addr;
|
219 | |||
220 | if (my_iface) {
|
||
221 | my_addr = iface_addr(my_iface); |
||
222 | } else {
|
||
223 | 371a4639 | Csaba Kiraly | my_addr = default_ip_addr(); |
224 | 613263e9 | Csaba Kiraly | } |
225 | 89e893e2 | Luca | |
226 | f858e682 | Luca Abeni | if (my_addr == NULL) { |
227 | fprintf(stderr, "Cannot find network interface %s\n", my_iface);
|
||
228 | |||
229 | return NULL; |
||
230 | } |
||
231 | 33d23b91 | MarcoBiazzini | for (i=0;i<2;i++) |
232 | bdd19faf | Csaba Kiraly | bind_msg_type(msgTypes[i]); |
233 | 193622ac | CsabaKiraly | myID = net_helper_init(my_addr, port, net_helper_config); |
234 | 4136911a | Luca Abeni | if (myID == NULL) { |
235 | 89e893e2 | Luca | fprintf(stderr, "Error creating my socket (%s:%d)!\n", my_addr, port);
|
236 | 568bd1bd | Luca Abeni | free(my_addr); |
237 | 4136911a | Luca Abeni | |
238 | e63ea799 | Luca | return NULL; |
239 | 89e893e2 | Luca | } |
240 | 568bd1bd | Luca Abeni | free(my_addr); |
241 | 5331023a | CsabaKiraly | fprintf(stderr, "My network ID is: %s\n", node_addr(myID));
|
242 | 7a673aa5 | Csaba Kiraly | |
243 | init_rand(node_addr(myID)); |
||
244 | |||
245 | 5f72f6b3 | Csaba Kiraly | topologyInit(myID, topo_config); |
246 | 89e893e2 | Luca | |
247 | return myID;
|
||
248 | } |
||
249 | |||
250 | 5dcfffbc | CsabaKiraly | void leave(int sig) { |
251 | a8a31ce0 | Csaba Kiraly | end_measures(); |
252 | 5dcfffbc | CsabaKiraly | exit(sig); |
253 | } |
||
254 | 89e893e2 | Luca | |
255 | int main(int argc, char *argv[]) |
||
256 | { |
||
257 | struct nodeID *my_sock;
|
||
258 | |||
259 | 5dcfffbc | CsabaKiraly | (void) signal(SIGTERM,leave);
|
260 | |||
261 | 89e893e2 | Luca | cmdline_parse(argc, argv); |
262 | |||
263 | my_sock = init(); |
||
264 | e63ea799 | Luca | if (my_sock == NULL) { |
265 | return -1; |
||
266 | } |
||
267 | 89e893e2 | Luca | if (srv_port != 0) { |
268 | 74a5d4ae | CsabaKiraly | struct nodeID *srv;
|
269 | 89e893e2 | Luca | |
270 | 463000a4 | CsabaKiraly | output_init(outbuff_size, output_config); |
271 | |||
272 | 4136911a | Luca Abeni | srv = create_node(srv_ip, srv_port); |
273 | 0f23522a | Luca | if (srv == NULL) { |
274 | fprintf(stderr, "Cannot resolve remote address %s:%d\n", srv_ip, srv_port);
|
||
275 | |||
276 | return -1; |
||
277 | } |
||
278 | f088e50e | MarcoBiazzini | topoAddNeighbour(srv, NULL, 0); |
279 | 89e893e2 | Luca | |
280 | 0a40460a | Luca | loop(my_sock, 1000000 / chunks_per_second, buff_size);
|
281 | 98c28f0f | CsabaKiraly | } else {
|
282 | source_loop(fname, my_sock, period * 1000, multiply, loop_input);
|
||
283 | 89e893e2 | Luca | } |
284 | return 0; |
||
285 | } |