winlin

merge from wenjie, fix the pause bug of jw/flower which actually send closeStream to pause.

要显示太多修改。

为保证性能只显示 6 of 6+ 个文件。

1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013-2014 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#include <srs_core_client.hpp>  
25 -  
26 -#include <arpa/inet.h>  
27 -#include <stdlib.h>  
28 -  
29 -using namespace std;  
30 -  
31 -#include <srs_core_error.hpp>  
32 -#include <srs_core_log.hpp>  
33 -#include <srs_core_rtmp.hpp>  
34 -#include <srs_core_protocol.hpp>  
35 -#include <srs_core_autofree.hpp>  
36 -#include <srs_core_source.hpp>  
37 -#include <srs_core_server.hpp>  
38 -#include <srs_core_pithy_print.hpp>  
39 -#include <srs_core_config.hpp>  
40 -#include <srs_core_refer.hpp>  
41 -#include <srs_core_hls.hpp>  
42 -#include <srs_core_http.hpp>  
43 -#include <srs_core_bandwidth.hpp>  
44 -  
45 -SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd)  
46 - : SrsConnection(srs_server, client_stfd)  
47 -{  
48 - ip = NULL;  
49 - req = new SrsRequest();  
50 - res = new SrsResponse();  
51 - rtmp = new SrsRtmp(client_stfd);  
52 - refer = new SrsRefer();  
53 -#ifdef SRS_HTTP  
54 - http_hooks = new SrsHttpHooks();  
55 -#endif  
56 - bandwidth = new SrsBandwidth();  
57 -  
58 - config->subscribe(this);  
59 -}  
60 -  
61 -SrsClient::~SrsClient()  
62 -{  
63 - config->unsubscribe(this);  
64 -  
65 - srs_freepa(ip);  
66 - srs_freep(req);  
67 - srs_freep(res);  
68 - srs_freep(rtmp);  
69 - srs_freep(refer);  
70 -#ifdef SRS_HTTP  
71 - srs_freep(http_hooks);  
72 -#endif  
73 - srs_freep(bandwidth);  
74 -}  
75 -  
76 -// TODO: return detail message when error for client.  
77 -int SrsClient::do_cycle()  
78 -{  
79 - int ret = ERROR_SUCCESS;  
80 -  
81 - if ((ret = get_peer_ip()) != ERROR_SUCCESS) {  
82 - srs_error("get peer ip failed. ret=%d", ret);  
83 - return ret;  
84 - }  
85 - srs_trace("get peer ip success. ip=%s, send_to=%"PRId64", recv_to=%"PRId64"",  
86 - ip, SRS_SEND_TIMEOUT_US, SRS_RECV_TIMEOUT_US);  
87 -  
88 - rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US);  
89 - rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US);  
90 -  
91 - if ((ret = rtmp->handshake()) != ERROR_SUCCESS) {  
92 - srs_error("rtmp handshake failed. ret=%d", ret);  
93 - return ret;  
94 - }  
95 - srs_verbose("rtmp handshake success");  
96 -  
97 - if ((ret = rtmp->connect_app(req)) != ERROR_SUCCESS) {  
98 - srs_error("rtmp connect vhost/app failed. ret=%d", ret);  
99 - return ret;  
100 - }  
101 - srs_verbose("rtmp connect app success");  
102 -  
103 - if ((ret = check_vhost()) != ERROR_SUCCESS) {  
104 - srs_error("check vhost failed. ret=%d", ret);  
105 - return ret;  
106 - }  
107 - srs_verbose("check vhost success.");  
108 -  
109 - srs_trace("rtmp connect app success. "  
110 - "tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s",  
111 - req->tcUrl.c_str(), req->pageUrl.c_str(), req->swfUrl.c_str(),  
112 - req->schema.c_str(), req->vhost.c_str(), req->port.c_str(),  
113 - req->app.c_str());  
114 -  
115 - ret = service_cycle();  
116 - on_close();  
117 -  
118 - return ret;  
119 -}  
120 -  
121 -int SrsClient::on_reload_vhost_removed(string vhost)  
122 -{  
123 - int ret = ERROR_SUCCESS;  
124 -  
125 - if (req->vhost != vhost) {  
126 - return ret;  
127 - }  
128 -  
129 - // if the vhost connected is removed, disconnect the client.  
130 - srs_trace("vhost %s removed/disabled, close client url=%s",  
131 - vhost.c_str(), req->get_stream_url().c_str());  
132 -  
133 - srs_close_stfd(stfd);  
134 -  
135 - return ret;  
136 -}  
137 -  
138 -int SrsClient::service_cycle()  
139 -{  
140 - int ret = ERROR_SUCCESS;  
141 -  
142 - if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) {  
143 - srs_error("set window acknowledgement size failed. ret=%d", ret);  
144 - return ret;  
145 - }  
146 - srs_verbose("set window acknowledgement size success");  
147 -  
148 - if ((ret = rtmp->set_peer_bandwidth(2.5 * 1000 * 1000, 2)) != ERROR_SUCCESS) {  
149 - srs_error("set peer bandwidth failed. ret=%d", ret);  
150 - return ret;  
151 - }  
152 - srs_verbose("set peer bandwidth success");  
153 -  
154 - // do bandwidth test if connect to the vhost which is for bandwidth check.  
155 - if (config->get_bw_check_enabled(req->vhost)) {  
156 - return bandwidth->bandwidth_test(req, stfd, rtmp);  
157 - }  
158 -  
159 - if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) {  
160 - srs_error("response connect app failed. ret=%d", ret);  
161 - return ret;  
162 - }  
163 - srs_verbose("response connect app success");  
164 -  
165 - if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) {  
166 - srs_error("on_bw_done failed. ret=%d", ret);  
167 - return ret;  
168 - }  
169 - srs_verbose("on_bw_done success");  
170 -  
171 - SrsClientType type;  
172 - if ((ret = rtmp->identify_client(res->stream_id, type, req->stream)) != ERROR_SUCCESS) {  
173 - srs_error("identify client failed. ret=%d", ret);  
174 - return ret;  
175 - }  
176 - req->strip();  
177 - srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str());  
178 -  
179 - int chunk_size = config->get_chunk_size(req->vhost);  
180 - if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) {  
181 - srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret);  
182 - return ret;  
183 - }  
184 - srs_trace("set chunk_size=%d success", chunk_size);  
185 -  
186 - // find a source to publish.  
187 - SrsSource* source = SrsSource::find(req);  
188 - srs_assert(source != NULL);  
189 -  
190 - // check publish available.  
191 - if (type != SrsClientPlay && !source->can_publish()) {  
192 - ret = ERROR_SYSTEM_STREAM_BUSY;  
193 - srs_warn("stream %s is already publishing. ret=%d",  
194 - req->get_stream_url().c_str(), ret);  
195 - // to delay request  
196 - st_usleep(SRS_STREAM_BUSY_SLEEP_US);  
197 - return ret;  
198 - }  
199 -  
200 - bool enabled_cache = config->get_gop_cache(req->vhost);  
201 - srs_info("source found, url=%s, enabled_cache=%d", req->get_stream_url().c_str(), enabled_cache);  
202 - source->set_cache(enabled_cache);  
203 -  
204 - switch (type) {  
205 - case SrsClientPlay: {  
206 - srs_verbose("start to play stream %s.", req->stream.c_str());  
207 -  
208 - if ((ret = rtmp->start_play(res->stream_id)) != ERROR_SUCCESS) {  
209 - srs_error("start to play stream failed. ret=%d", ret);  
210 - return ret;  
211 - }  
212 - if ((ret = on_play()) != ERROR_SUCCESS) {  
213 - srs_error("http hook on_play failed. ret=%d", ret);  
214 - return ret;  
215 - }  
216 - srs_info("start to play stream %s success", req->stream.c_str());  
217 - ret = playing(source);  
218 - on_stop();  
219 - return ret;  
220 - }  
221 - case SrsClientFMLEPublish: {  
222 - srs_verbose("FMLE start to publish stream %s.", req->stream.c_str());  
223 -  
224 - if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) {  
225 - srs_error("start to publish stream failed. ret=%d", ret);  
226 - return ret;  
227 - }  
228 - if ((ret = on_publish()) != ERROR_SUCCESS) {  
229 - srs_error("http hook on_publish failed. ret=%d", ret);  
230 - return ret;  
231 - }  
232 - srs_info("start to publish stream %s success", req->stream.c_str());  
233 - ret = publish(source, true);  
234 - source->on_unpublish();  
235 - on_unpublish();  
236 - return ret;  
237 - }  
238 - case SrsClientFlashPublish: {  
239 - srs_verbose("flash start to publish stream %s.", req->stream.c_str());  
240 -  
241 - if ((ret = rtmp->start_flash_publish(res->stream_id)) != ERROR_SUCCESS) {  
242 - srs_error("flash start to publish stream failed. ret=%d", ret);  
243 - return ret;  
244 - }  
245 - if ((ret = on_publish()) != ERROR_SUCCESS) {  
246 - srs_error("http hook on_publish failed. ret=%d", ret);  
247 - return ret;  
248 - }  
249 - srs_info("flash start to publish stream %s success", req->stream.c_str());  
250 - ret = publish(source, false);  
251 - source->on_unpublish();  
252 - on_unpublish();  
253 - return ret;  
254 - }  
255 - default: {  
256 - ret = ERROR_SYSTEM_CLIENT_INVALID;  
257 - srs_info("invalid client type=%d. ret=%d", type, ret);  
258 - return ret;  
259 - }  
260 - }  
261 -  
262 - return ret;  
263 -}  
264 -  
265 -int SrsClient::check_vhost()  
266 -{  
267 - int ret = ERROR_SUCCESS;  
268 -  
269 - srs_assert(req != NULL);  
270 -  
271 - SrsConfDirective* vhost = config->get_vhost(req->vhost);  
272 - if (vhost == NULL) {  
273 - ret = ERROR_RTMP_VHOST_NOT_FOUND;  
274 - srs_error("vhost %s not found. ret=%d", req->vhost.c_str(), ret);  
275 - return ret;  
276 - }  
277 -  
278 - if (!config->get_vhost_enabled(req->vhost)) {  
279 - ret = ERROR_RTMP_VHOST_NOT_FOUND;  
280 - srs_error("vhost %s disabled. ret=%d", req->vhost.c_str(), ret);  
281 - return ret;  
282 - }  
283 -  
284 - if (req->vhost != vhost->arg0()) {  
285 - srs_trace("vhost change from %s to %s", req->vhost.c_str(), vhost->arg0().c_str());  
286 - req->vhost = vhost->arg0();  
287 - }  
288 -  
289 - if ((ret = refer->check(req->pageUrl, config->get_refer(req->vhost))) != ERROR_SUCCESS) {  
290 - srs_error("check refer failed. ret=%d", ret);  
291 - return ret;  
292 - }  
293 - srs_verbose("check refer success.");  
294 -  
295 - if ((ret = on_connect()) != ERROR_SUCCESS) {  
296 - return ret;  
297 - }  
298 -  
299 - return ret;  
300 -}  
301 -  
302 -int SrsClient::playing(SrsSource* source)  
303 -{  
304 - int ret = ERROR_SUCCESS;  
305 -  
306 - if ((ret = refer->check(req->pageUrl, config->get_refer_play(req->vhost))) != ERROR_SUCCESS) {  
307 - srs_error("check play_refer failed. ret=%d", ret);  
308 - return ret;  
309 - }  
310 - srs_verbose("check play_refer success.");  
311 -  
312 - SrsConsumer* consumer = NULL;  
313 - if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) {  
314 - srs_error("create consumer failed. ret=%d", ret);  
315 - return ret;  
316 - }  
317 -  
318 - srs_assert(consumer != NULL);  
319 - SrsAutoFree(SrsConsumer, consumer, false);  
320 - srs_verbose("consumer created success.");  
321 -  
322 - rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_US);  
323 -  
324 - SrsPithyPrint pithy_print(SRS_STAGE_PLAY_USER);  
325 -  
326 - while (true) {  
327 - pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);  
328 -  
329 - // switch to other st-threads.  
330 - st_usleep(0);  
331 -  
332 - // read from client.  
333 - int ctl_msg_ret = ERROR_SUCCESS;  
334 - if (true) {  
335 - SrsCommonMessage* msg = NULL;  
336 - ctl_msg_ret = ret = rtmp->recv_message(&msg);  
337 -  
338 - srs_verbose("play loop recv message. ret=%d", ret);  
339 - if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {  
340 - srs_error("recv client control message failed. ret=%d", ret);  
341 - return ret;  
342 - }  
343 - if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) {  
344 - srs_error("process play control message failed. ret=%d", ret);  
345 - return ret;  
346 - }  
347 - }  
348 -  
349 - // get messages from consumer.  
350 - SrsSharedPtrMessage** msgs = NULL;  
351 - int count = 0;  
352 - if ((ret = consumer->get_packets(0, msgs, count)) != ERROR_SUCCESS) {  
353 - srs_error("get messages from consumer failed. ret=%d", ret);  
354 - return ret;  
355 - }  
356 -  
357 - // reportable  
358 - if (pithy_print.can_print()) {  
359 - srs_trace("-> time=%"PRId64", cmr=%d, msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",  
360 - pithy_print.get_age(), ctl_msg_ret, count, rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps());  
361 - }  
362 -  
363 - if (count <= 0) {  
364 - srs_verbose("no packets in queue.");  
365 - continue;  
366 - }  
367 - SrsAutoFree(SrsSharedPtrMessage*, msgs, true);  
368 -  
369 - // sendout messages  
370 - for (int i = 0; i < count; i++) {  
371 - SrsSharedPtrMessage* msg = msgs[i];  
372 -  
373 - // the send_message will free the msg,  
374 - // so set the msgs[i] to NULL.  
375 - msgs[i] = NULL;  
376 -  
377 - if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {  
378 - srs_error("send message to client failed. ret=%d", ret);  
379 - return ret;  
380 - }  
381 - }  
382 - }  
383 -  
384 - return ret;  
385 -}  
386 -  
387 -int SrsClient::publish(SrsSource* source, bool is_fmle)  
388 -{  
389 - int ret = ERROR_SUCCESS;  
390 -  
391 - if ((ret = refer->check(req->pageUrl, config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) {  
392 - srs_error("check publish_refer failed. ret=%d", ret);  
393 - return ret;  
394 - }  
395 - srs_verbose("check publish_refer success.");  
396 -  
397 - SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);  
398 -  
399 - // notify the hls to prepare when publish start.  
400 - if ((ret = source->on_publish(req)) != ERROR_SUCCESS) {  
401 - srs_error("hls on_publish failed. ret=%d", ret);  
402 - return ret;  
403 - }  
404 - srs_verbose("hls on_publish success.");  
405 -  
406 - while (true) {  
407 - // switch to other st-threads.  
408 - st_usleep(0);  
409 -  
410 - SrsCommonMessage* msg = NULL;  
411 - if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) {  
412 - srs_error("recv identify client message failed. ret=%d", ret);  
413 - return ret;  
414 - }  
415 -  
416 - SrsAutoFree(SrsCommonMessage, msg, false);  
417 -  
418 - pithy_print.set_age(msg->header.timestamp);  
419 -  
420 - // reportable  
421 - if (pithy_print.can_print()) {  
422 - srs_trace("<- time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",  
423 - pithy_print.get_age(), rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps());  
424 - }  
425 -  
426 - if ((ret = process_publish_message(source, msg, is_fmle)) != ERROR_SUCCESS) {  
427 - srs_error("process publish message failed. ret=%d", ret);  
428 - return ret;  
429 - }  
430 - }  
431 -  
432 - return ret;  
433 -}  
434 -  
435 -int SrsClient::process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle)  
436 -{  
437 - int ret = ERROR_SUCCESS;  
438 -  
439 - // process audio packet  
440 - if (msg->header.is_audio()) {  
441 - if ((ret = source->on_audio(msg)) != ERROR_SUCCESS) {  
442 - srs_error("source process audio message failed. ret=%d", ret);  
443 - return ret;  
444 - }  
445 - }  
446 - // process video packet  
447 - if (msg->header.is_video()) {  
448 - if ((ret = source->on_video(msg)) != ERROR_SUCCESS) {  
449 - srs_error("source process video message failed. ret=%d", ret);  
450 - return ret;  
451 - }  
452 - }  
453 -  
454 - // process onMetaData  
455 - if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {  
456 - if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {  
457 - srs_error("decode onMetaData message failed. ret=%d", ret);  
458 - return ret;  
459 - }  
460 -  
461 - SrsPacket* pkt = msg->get_packet();  
462 - if (dynamic_cast<SrsOnMetaDataPacket*>(pkt)) {  
463 - SrsOnMetaDataPacket* metadata = dynamic_cast<SrsOnMetaDataPacket*>(pkt);  
464 - if ((ret = source->on_meta_data(msg, metadata)) != ERROR_SUCCESS) {  
465 - srs_error("source process onMetaData message failed. ret=%d", ret);  
466 - return ret;  
467 - }  
468 - srs_trace("process onMetaData message success.");  
469 - return ret;  
470 - }  
471 -  
472 - srs_trace("ignore AMF0/AMF3 data message.");  
473 - return ret;  
474 - }  
475 -  
476 - // process UnPublish event.  
477 - if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) {  
478 - if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {  
479 - srs_error("decode unpublish message failed. ret=%d", ret);  
480 - return ret;  
481 - }  
482 -  
483 - // flash unpublish.  
484 - if (!is_fmle) {  
485 - srs_trace("flash publish finished.");  
486 - return ret;  
487 - }  
488 -  
489 - SrsPacket* pkt = msg->get_packet();  
490 - if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {  
491 - SrsFMLEStartPacket* unpublish = dynamic_cast<SrsFMLEStartPacket*>(pkt);  
492 - return rtmp->fmle_unpublish(res->stream_id, unpublish->transaction_id);  
493 - }  
494 -  
495 - srs_trace("ignore AMF0/AMF3 command message.");  
496 - return ret;  
497 - }  
498 -  
499 - return ret;  
500 -}  
501 -  
502 -int SrsClient::get_peer_ip()  
503 -{  
504 - int ret = ERROR_SUCCESS;  
505 -  
506 - int fd = st_netfd_fileno(stfd);  
507 -  
508 - // discovery client information  
509 - sockaddr_in addr;  
510 - socklen_t addrlen = sizeof(addr);  
511 - if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) {  
512 - ret = ERROR_SOCKET_GET_PEER_NAME;  
513 - srs_error("discovery client information failed. ret=%d", ret);  
514 - return ret;  
515 - }  
516 - srs_verbose("get peer name success.");  
517 -  
518 - // ip v4 or v6  
519 - char buf[INET6_ADDRSTRLEN];  
520 - memset(buf, 0, sizeof(buf));  
521 -  
522 - if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {  
523 - ret = ERROR_SOCKET_GET_PEER_IP;  
524 - srs_error("convert client information failed. ret=%d", ret);  
525 - return ret;  
526 - }  
527 - srs_verbose("get peer ip of client ip=%s, fd=%d", buf, fd);  
528 -  
529 - ip = new char[strlen(buf) + 1];  
530 - strcpy(ip, buf);  
531 -  
532 - srs_verbose("get peer ip success. ip=%s, fd=%d", ip, fd);  
533 -  
534 - return ret;  
535 -}  
536 -  
537 -int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg)  
538 -{  
539 - int ret = ERROR_SUCCESS;  
540 -  
541 - if (!msg) {  
542 - srs_verbose("ignore all empty message.");  
543 - return ret;  
544 - }  
545 - SrsAutoFree(SrsCommonMessage, msg, false);  
546 -  
547 - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) {  
548 - srs_info("ignore all message except amf0/amf3 command.");  
549 - return ret;  
550 - }  
551 -  
552 - if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {  
553 - srs_error("decode the amf0/amf3 command packet failed. ret=%d", ret);  
554 - return ret;  
555 - }  
556 - srs_info("decode the amf0/amf3 command packet success.");  
557 -  
558 - SrsPausePacket* pause = dynamic_cast<SrsPausePacket*>(msg->get_packet());  
559 - if (!pause) {  
560 - srs_info("ignore all amf0/amf3 command except pause.");  
561 - return ret;  
562 - }  
563 -  
564 - if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) {  
565 - srs_error("rtmp process play client pause failed. ret=%d", ret);  
566 - return ret;  
567 - }  
568 -  
569 - if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) {  
570 - srs_error("consumer process play client pause failed. ret=%d", ret);  
571 - return ret;  
572 - }  
573 - srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms);  
574 -  
575 - return ret;  
576 -}  
577 -  
578 -int SrsClient::on_connect()  
579 -{  
580 - int ret = ERROR_SUCCESS;  
581 -  
582 -#ifdef SRS_HTTP  
583 - // HTTP: on_connect  
584 - SrsConfDirective* on_connect = config->get_vhost_on_connect(req->vhost);  
585 - if (!on_connect) {  
586 - srs_info("ignore the empty http callback: on_connect");  
587 - return ret;  
588 - }  
589 -  
590 - for (int i = 0; i < (int)on_connect->args.size(); i++) {  
591 - std::string url = on_connect->args.at(i);  
592 - if ((ret = http_hooks->on_connect(url, connection_id, ip, req)) != ERROR_SUCCESS) {  
593 - srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret);  
594 - return ret;  
595 - }  
596 - }  
597 -#endif  
598 -  
599 - return ret;  
600 -}  
601 -  
602 -void SrsClient::on_close()  
603 -{  
604 -#ifdef SRS_HTTP  
605 - // whatever the ret code, notify the api hooks.  
606 - // HTTP: on_close  
607 - SrsConfDirective* on_close = config->get_vhost_on_close(req->vhost);  
608 - if (!on_close) {  
609 - srs_info("ignore the empty http callback: on_close");  
610 - return;  
611 - }  
612 -  
613 - for (int i = 0; i < (int)on_close->args.size(); i++) {  
614 - std::string url = on_close->args.at(i);  
615 - http_hooks->on_close(url, connection_id, ip, req);  
616 - }  
617 -#endif  
618 -}  
619 -  
620 -int SrsClient::on_publish()  
621 -{  
622 - int ret = ERROR_SUCCESS;  
623 -  
624 -#ifdef SRS_HTTP  
625 - // HTTP: on_publish  
626 - SrsConfDirective* on_publish = config->get_vhost_on_publish(req->vhost);  
627 - if (!on_publish) {  
628 - srs_info("ignore the empty http callback: on_publish");  
629 - return ret;  
630 - }  
631 -  
632 - for (int i = 0; i < (int)on_publish->args.size(); i++) {  
633 - std::string url = on_publish->args.at(i);  
634 - if ((ret = http_hooks->on_publish(url, connection_id, ip, req)) != ERROR_SUCCESS) {  
635 - srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret);  
636 - return ret;  
637 - }  
638 - }  
639 -#endif  
640 -  
641 - return ret;  
642 -}  
643 -  
644 -void SrsClient::on_unpublish()  
645 -{  
646 -#ifdef SRS_HTTP  
647 - // whatever the ret code, notify the api hooks.  
648 - // HTTP: on_unpublish  
649 - SrsConfDirective* on_unpublish = config->get_vhost_on_unpublish(req->vhost);  
650 - if (!on_unpublish) {  
651 - srs_info("ignore the empty http callback: on_unpublish");  
652 - return;  
653 - }  
654 -  
655 - for (int i = 0; i < (int)on_unpublish->args.size(); i++) {  
656 - std::string url = on_unpublish->args.at(i);  
657 - http_hooks->on_unpublish(url, connection_id, ip, req);  
658 - }  
659 -#endif  
660 -}  
661 -  
662 -int SrsClient::on_play()  
663 -{  
664 - int ret = ERROR_SUCCESS;  
665 -  
666 -#ifdef SRS_HTTP  
667 - // HTTP: on_play  
668 - SrsConfDirective* on_play = config->get_vhost_on_play(req->vhost);  
669 - if (!on_play) {  
670 - srs_info("ignore the empty http callback: on_play");  
671 - return ret;  
672 - }  
673 -  
674 - for (int i = 0; i < (int)on_play->args.size(); i++) {  
675 - std::string url = on_play->args.at(i);  
676 - if ((ret = http_hooks->on_play(url, connection_id, ip, req)) != ERROR_SUCCESS) {  
677 - srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret);  
678 - return ret;  
679 - }  
680 - }  
681 -#endif  
682 -  
683 - return ret;  
684 -}  
685 -  
686 -void SrsClient::on_stop()  
687 -{  
688 -#ifdef SRS_HTTP  
689 - // whatever the ret code, notify the api hooks.  
690 - // HTTP: on_stop  
691 - SrsConfDirective* on_stop = config->get_vhost_on_stop(req->vhost);  
692 - if (!on_stop) {  
693 - srs_info("ignore the empty http callback: on_stop");  
694 - return;  
695 - }  
696 -  
697 - for (int i = 0; i < (int)on_stop->args.size(); i++) {  
698 - std::string url = on_stop->args.at(i);  
699 - http_hooks->on_stop(url, connection_id, ip, req);  
700 - }  
701 -#endif  
702 -}  
703 - 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_core_client.hpp>
  25 +
  26 +#include <arpa/inet.h>
  27 +#include <stdlib.h>
  28 +
  29 +using namespace std;
  30 +
  31 +#include <srs_core_error.hpp>
  32 +#include <srs_core_log.hpp>
  33 +#include <srs_core_rtmp.hpp>
  34 +#include <srs_core_protocol.hpp>
  35 +#include <srs_core_autofree.hpp>
  36 +#include <srs_core_source.hpp>
  37 +#include <srs_core_server.hpp>
  38 +#include <srs_core_pithy_print.hpp>
  39 +#include <srs_core_config.hpp>
  40 +#include <srs_core_refer.hpp>
  41 +#include <srs_core_hls.hpp>
  42 +#include <srs_core_http.hpp>
  43 +#include <srs_core_bandwidth.hpp>
  44 +
  45 +SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd)
  46 + : SrsConnection(srs_server, client_stfd)
  47 +{
  48 + ip = NULL;
  49 + req = new SrsRequest();
  50 + res = new SrsResponse();
  51 + rtmp = new SrsRtmp(client_stfd);
  52 + refer = new SrsRefer();
  53 +#ifdef SRS_HTTP
  54 + http_hooks = new SrsHttpHooks();
  55 +#endif
  56 + bandwidth = new SrsBandwidth();
  57 +
  58 + config->subscribe(this);
  59 +}
  60 +
  61 +SrsClient::~SrsClient()
  62 +{
  63 + config->unsubscribe(this);
  64 +
  65 + srs_freepa(ip);
  66 + srs_freep(req);
  67 + srs_freep(res);
  68 + srs_freep(rtmp);
  69 + srs_freep(refer);
  70 +#ifdef SRS_HTTP
  71 + srs_freep(http_hooks);
  72 +#endif
  73 + srs_freep(bandwidth);
  74 +}
  75 +
  76 +// TODO: return detail message when error for client.
  77 +int SrsClient::do_cycle()
  78 +{
  79 + int ret = ERROR_SUCCESS;
  80 +
  81 + if ((ret = get_peer_ip()) != ERROR_SUCCESS) {
  82 + srs_error("get peer ip failed. ret=%d", ret);
  83 + return ret;
  84 + }
  85 + srs_trace("get peer ip success. ip=%s, send_to=%"PRId64", recv_to=%"PRId64"",
  86 + ip, SRS_SEND_TIMEOUT_US, SRS_RECV_TIMEOUT_US);
  87 +
  88 + rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US);
  89 + rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US);
  90 +
  91 + if ((ret = rtmp->handshake()) != ERROR_SUCCESS) {
  92 + srs_error("rtmp handshake failed. ret=%d", ret);
  93 + return ret;
  94 + }
  95 + srs_verbose("rtmp handshake success");
  96 +
  97 + if ((ret = rtmp->connect_app(req)) != ERROR_SUCCESS) {
  98 + srs_error("rtmp connect vhost/app failed. ret=%d", ret);
  99 + return ret;
  100 + }
  101 + srs_verbose("rtmp connect app success");
  102 +
  103 + if ((ret = check_vhost()) != ERROR_SUCCESS) {
  104 + srs_error("check vhost failed. ret=%d", ret);
  105 + return ret;
  106 + }
  107 + srs_verbose("check vhost success.");
  108 +
  109 + srs_trace("rtmp connect app success. "
  110 + "tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s",
  111 + req->tcUrl.c_str(), req->pageUrl.c_str(), req->swfUrl.c_str(),
  112 + req->schema.c_str(), req->vhost.c_str(), req->port.c_str(),
  113 + req->app.c_str());
  114 +
  115 + ret = service_cycle();
  116 + on_close();
  117 +
  118 + return ret;
  119 +}
  120 +
  121 +int SrsClient::on_reload_vhost_removed(string vhost)
  122 +{
  123 + int ret = ERROR_SUCCESS;
  124 +
  125 + if (req->vhost != vhost) {
  126 + return ret;
  127 + }
  128 +
  129 + // if the vhost connected is removed, disconnect the client.
  130 + srs_trace("vhost %s removed/disabled, close client url=%s",
  131 + vhost.c_str(), req->get_stream_url().c_str());
  132 +
  133 + srs_close_stfd(stfd);
  134 +
  135 + return ret;
  136 +}
  137 +
  138 +int SrsClient::service_cycle()
  139 +{
  140 + int ret = ERROR_SUCCESS;
  141 +
  142 + if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) {
  143 + srs_error("set window acknowledgement size failed. ret=%d", ret);
  144 + return ret;
  145 + }
  146 + srs_verbose("set window acknowledgement size success");
  147 +
  148 + if ((ret = rtmp->set_peer_bandwidth(2.5 * 1000 * 1000, 2)) != ERROR_SUCCESS) {
  149 + srs_error("set peer bandwidth failed. ret=%d", ret);
  150 + return ret;
  151 + }
  152 + srs_verbose("set peer bandwidth success");
  153 +
  154 + // do bandwidth test if connect to the vhost which is for bandwidth check.
  155 + if (config->get_bw_check_enabled(req->vhost)) {
  156 + return bandwidth->bandwidth_test(req, stfd, rtmp);
  157 + }
  158 +
  159 + if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) {
  160 + srs_error("response connect app failed. ret=%d", ret);
  161 + return ret;
  162 + }
  163 + srs_verbose("response connect app success");
  164 +
  165 + if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) {
  166 + srs_error("on_bw_done failed. ret=%d", ret);
  167 + return ret;
  168 + }
  169 + srs_verbose("on_bw_done success");
  170 +
  171 + while (true) {
  172 + ret = stream_service_cycle();
  173 +
  174 + // stream service must terminated with error, never success.
  175 + srs_assert(ret != ERROR_SUCCESS);
  176 +
  177 + // when not system control error, fatal error, return.
  178 + if (!srs_is_system_control_error(ret)) {
  179 + srs_error("stream service cycle failed. ret=%d", ret);
  180 + return ret;
  181 + }
  182 +
  183 + // for "some" system control error,
  184 + // logical accept and retry stream service.
  185 + if (ret == ERROR_CONTROL_RTMP_CLOSE) {
  186 + // set timeout to a larger value, for user paused.
  187 + rtmp->set_recv_timeout(SRS_PAUSED_SEND_TIMEOUT_US);
  188 + rtmp->set_send_timeout(SRS_PAUSED_SEND_TIMEOUT_US);
  189 +
  190 + srs_trace("control message(close) accept, retry stream service.");
  191 + continue;
  192 + }
  193 +
  194 + // for other system control message, fatal error.
  195 + srs_error("control message(%d) reject as error. ret=%d", ret, ret);
  196 + return ret;
  197 + }
  198 +
  199 + return ret;
  200 +}
  201 +
  202 +int SrsClient::stream_service_cycle()
  203 +{
  204 + int ret = ERROR_SUCCESS;
  205 +
  206 + SrsClientType type;
  207 + if ((ret = rtmp->identify_client(res->stream_id, type, req->stream)) != ERROR_SUCCESS) {
  208 + srs_error("identify client failed. ret=%d", ret);
  209 + return ret;
  210 + }
  211 + req->strip();
  212 + srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str());
  213 +
  214 + // client is identified, set the timeout to service timeout.
  215 + rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US);
  216 + rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US);
  217 +
  218 + // set timeout to larger.
  219 + int chunk_size = config->get_chunk_size(req->vhost);
  220 + if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) {
  221 + srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret);
  222 + return ret;
  223 + }
  224 + srs_trace("set chunk_size=%d success", chunk_size);
  225 +
  226 + // find a source to publish.
  227 + SrsSource* source = SrsSource::find(req);
  228 + srs_assert(source != NULL);
  229 +
  230 + // check publish available.
  231 + if (type != SrsClientPlay && !source->can_publish()) {
  232 + ret = ERROR_SYSTEM_STREAM_BUSY;
  233 + srs_warn("stream %s is already publishing. ret=%d",
  234 + req->get_stream_url().c_str(), ret);
  235 + // to delay request
  236 + st_usleep(SRS_STREAM_BUSY_SLEEP_US);
  237 + return ret;
  238 + }
  239 +
  240 + bool enabled_cache = config->get_gop_cache(req->vhost);
  241 + srs_info("source found, url=%s, enabled_cache=%d", req->get_stream_url().c_str(), enabled_cache);
  242 + source->set_cache(enabled_cache);
  243 +
  244 + switch (type) {
  245 + case SrsClientPlay: {
  246 + srs_verbose("start to play stream %s.", req->stream.c_str());
  247 +
  248 + if ((ret = rtmp->start_play(res->stream_id)) != ERROR_SUCCESS) {
  249 + srs_error("start to play stream failed. ret=%d", ret);
  250 + return ret;
  251 + }
  252 + if ((ret = on_play()) != ERROR_SUCCESS) {
  253 + srs_error("http hook on_play failed. ret=%d", ret);
  254 + return ret;
  255 + }
  256 + srs_info("start to play stream %s success", req->stream.c_str());
  257 + ret = playing(source);
  258 + on_stop();
  259 + return ret;
  260 + }
  261 + case SrsClientFMLEPublish: {
  262 + srs_verbose("FMLE start to publish stream %s.", req->stream.c_str());
  263 +
  264 + if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) {
  265 + srs_error("start to publish stream failed. ret=%d", ret);
  266 + return ret;
  267 + }
  268 + if ((ret = on_publish()) != ERROR_SUCCESS) {
  269 + srs_error("http hook on_publish failed. ret=%d", ret);
  270 + return ret;
  271 + }
  272 + srs_info("start to publish stream %s success", req->stream.c_str());
  273 + ret = publish(source, true);
  274 + source->on_unpublish();
  275 + on_unpublish();
  276 + return ret;
  277 + }
  278 + case SrsClientFlashPublish: {
  279 + srs_verbose("flash start to publish stream %s.", req->stream.c_str());
  280 +
  281 + if ((ret = rtmp->start_flash_publish(res->stream_id)) != ERROR_SUCCESS) {
  282 + srs_error("flash start to publish stream failed. ret=%d", ret);
  283 + return ret;
  284 + }
  285 + if ((ret = on_publish()) != ERROR_SUCCESS) {
  286 + srs_error("http hook on_publish failed. ret=%d", ret);
  287 + return ret;
  288 + }
  289 + srs_info("flash start to publish stream %s success", req->stream.c_str());
  290 + ret = publish(source, false);
  291 + source->on_unpublish();
  292 + on_unpublish();
  293 + return ret;
  294 + }
  295 + default: {
  296 + ret = ERROR_SYSTEM_CLIENT_INVALID;
  297 + srs_info("invalid client type=%d. ret=%d", type, ret);
  298 + return ret;
  299 + }
  300 + }
  301 +
  302 + return ret;
  303 +}
  304 +
  305 +int SrsClient::check_vhost()
  306 +{
  307 + int ret = ERROR_SUCCESS;
  308 +
  309 + srs_assert(req != NULL);
  310 +
  311 + SrsConfDirective* vhost = config->get_vhost(req->vhost);
  312 + if (vhost == NULL) {
  313 + ret = ERROR_RTMP_VHOST_NOT_FOUND;
  314 + srs_error("vhost %s not found. ret=%d", req->vhost.c_str(), ret);
  315 + return ret;
  316 + }
  317 +
  318 + if (!config->get_vhost_enabled(req->vhost)) {
  319 + ret = ERROR_RTMP_VHOST_NOT_FOUND;
  320 + srs_error("vhost %s disabled. ret=%d", req->vhost.c_str(), ret);
  321 + return ret;
  322 + }
  323 +
  324 + if (req->vhost != vhost->arg0()) {
  325 + srs_trace("vhost change from %s to %s", req->vhost.c_str(), vhost->arg0().c_str());
  326 + req->vhost = vhost->arg0();
  327 + }
  328 +
  329 + if ((ret = refer->check(req->pageUrl, config->get_refer(req->vhost))) != ERROR_SUCCESS) {
  330 + srs_error("check refer failed. ret=%d", ret);
  331 + return ret;
  332 + }
  333 + srs_verbose("check refer success.");
  334 +
  335 + if ((ret = on_connect()) != ERROR_SUCCESS) {
  336 + return ret;
  337 + }
  338 +
  339 + return ret;
  340 +}
  341 +
  342 +int SrsClient::playing(SrsSource* source)
  343 +{
  344 + int ret = ERROR_SUCCESS;
  345 +
  346 + if ((ret = refer->check(req->pageUrl, config->get_refer_play(req->vhost))) != ERROR_SUCCESS) {
  347 + srs_error("check play_refer failed. ret=%d", ret);
  348 + return ret;
  349 + }
  350 + srs_verbose("check play_refer success.");
  351 +
  352 + SrsConsumer* consumer = NULL;
  353 + if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) {
  354 + srs_error("create consumer failed. ret=%d", ret);
  355 + return ret;
  356 + }
  357 +
  358 + srs_assert(consumer != NULL);
  359 + SrsAutoFree(SrsConsumer, consumer, false);
  360 + srs_verbose("consumer created success.");
  361 +
  362 + rtmp->set_recv_timeout(SRS_PULSE_TIMEOUT_US);
  363 +
  364 + SrsPithyPrint pithy_print(SRS_STAGE_PLAY_USER);
  365 +
  366 + while (true) {
  367 + pithy_print.elapse(SRS_PULSE_TIMEOUT_US / 1000);
  368 +
  369 + // switch to other st-threads.
  370 + st_usleep(0);
  371 +
  372 + // read from client.
  373 + int ctl_msg_ret = ERROR_SUCCESS;
  374 + if (true) {
  375 + SrsCommonMessage* msg = NULL;
  376 + ctl_msg_ret = ret = rtmp->recv_message(&msg);
  377 +
  378 + srs_verbose("play loop recv message. ret=%d", ret);
  379 + if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
  380 + srs_error("recv client control message failed. ret=%d", ret);
  381 + return ret;
  382 + }
  383 + if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) {
  384 + if (!srs_is_system_control_error(ret)) {
  385 + srs_error("process play control message failed. ret=%d", ret);
  386 + }
  387 + return ret;
  388 + }
  389 + }
  390 +
  391 + // get messages from consumer.
  392 + SrsSharedPtrMessage** msgs = NULL;
  393 + int count = 0;
  394 + if ((ret = consumer->get_packets(0, msgs, count)) != ERROR_SUCCESS) {
  395 + srs_error("get messages from consumer failed. ret=%d", ret);
  396 + return ret;
  397 + }
  398 +
  399 + // reportable
  400 + if (pithy_print.can_print()) {
  401 + srs_trace("-> time=%"PRId64", cmr=%d, msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
  402 + pithy_print.get_age(), ctl_msg_ret, count, rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps());
  403 + }
  404 +
  405 + if (count <= 0) {
  406 + srs_verbose("no packets in queue.");
  407 + continue;
  408 + }
  409 + SrsAutoFree(SrsSharedPtrMessage*, msgs, true);
  410 +
  411 + // sendout messages
  412 + for (int i = 0; i < count; i++) {
  413 + SrsSharedPtrMessage* msg = msgs[i];
  414 +
  415 + // the send_message will free the msg,
  416 + // so set the msgs[i] to NULL.
  417 + msgs[i] = NULL;
  418 +
  419 + if ((ret = rtmp->send_message(msg)) != ERROR_SUCCESS) {
  420 + srs_error("send message to client failed. ret=%d", ret);
  421 + return ret;
  422 + }
  423 + }
  424 + }
  425 +
  426 + return ret;
  427 +}
  428 +
  429 +int SrsClient::publish(SrsSource* source, bool is_fmle)
  430 +{
  431 + int ret = ERROR_SUCCESS;
  432 +
  433 + if ((ret = refer->check(req->pageUrl, config->get_refer_publish(req->vhost))) != ERROR_SUCCESS) {
  434 + srs_error("check publish_refer failed. ret=%d", ret);
  435 + return ret;
  436 + }
  437 + srs_verbose("check publish_refer success.");
  438 +
  439 + SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);
  440 +
  441 + // notify the hls to prepare when publish start.
  442 + if ((ret = source->on_publish(req)) != ERROR_SUCCESS) {
  443 + srs_error("hls on_publish failed. ret=%d", ret);
  444 + return ret;
  445 + }
  446 + srs_verbose("hls on_publish success.");
  447 +
  448 + while (true) {
  449 + // switch to other st-threads.
  450 + st_usleep(0);
  451 +
  452 + SrsCommonMessage* msg = NULL;
  453 + if ((ret = rtmp->recv_message(&msg)) != ERROR_SUCCESS) {
  454 + srs_error("recv identify client message failed. ret=%d", ret);
  455 + return ret;
  456 + }
  457 +
  458 + SrsAutoFree(SrsCommonMessage, msg, false);
  459 +
  460 + pithy_print.set_age(msg->header.timestamp);
  461 +
  462 + // reportable
  463 + if (pithy_print.can_print()) {
  464 + srs_trace("<- time=%"PRId64", obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
  465 + pithy_print.get_age(), rtmp->get_send_bytes(), rtmp->get_recv_bytes(), rtmp->get_send_kbps(), rtmp->get_recv_kbps());
  466 + }
  467 +
  468 + if ((ret = process_publish_message(source, msg, is_fmle)) != ERROR_SUCCESS) {
  469 + srs_error("process publish message failed. ret=%d", ret);
  470 + return ret;
  471 + }
  472 + }
  473 +
  474 + return ret;
  475 +}
  476 +
  477 +int SrsClient::process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle)
  478 +{
  479 + int ret = ERROR_SUCCESS;
  480 +
  481 + // process audio packet
  482 + if (msg->header.is_audio()) {
  483 + if ((ret = source->on_audio(msg)) != ERROR_SUCCESS) {
  484 + srs_error("source process audio message failed. ret=%d", ret);
  485 + return ret;
  486 + }
  487 + }
  488 + // process video packet
  489 + if (msg->header.is_video()) {
  490 + if ((ret = source->on_video(msg)) != ERROR_SUCCESS) {
  491 + srs_error("source process video message failed. ret=%d", ret);
  492 + return ret;
  493 + }
  494 + }
  495 +
  496 + // process onMetaData
  497 + if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
  498 + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {
  499 + srs_error("decode onMetaData message failed. ret=%d", ret);
  500 + return ret;
  501 + }
  502 +
  503 + SrsPacket* pkt = msg->get_packet();
  504 + if (dynamic_cast<SrsOnMetaDataPacket*>(pkt)) {
  505 + SrsOnMetaDataPacket* metadata = dynamic_cast<SrsOnMetaDataPacket*>(pkt);
  506 + if ((ret = source->on_meta_data(msg, metadata)) != ERROR_SUCCESS) {
  507 + srs_error("source process onMetaData message failed. ret=%d", ret);
  508 + return ret;
  509 + }
  510 + srs_trace("process onMetaData message success.");
  511 + return ret;
  512 + }
  513 +
  514 + srs_trace("ignore AMF0/AMF3 data message.");
  515 + return ret;
  516 + }
  517 +
  518 + // process UnPublish event.
  519 + if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) {
  520 + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {
  521 + srs_error("decode unpublish message failed. ret=%d", ret);
  522 + return ret;
  523 + }
  524 +
  525 + // flash unpublish.
  526 + if (!is_fmle) {
  527 + srs_trace("flash publish finished.");
  528 + return ret;
  529 + }
  530 +
  531 + SrsPacket* pkt = msg->get_packet();
  532 + if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {
  533 + SrsFMLEStartPacket* unpublish = dynamic_cast<SrsFMLEStartPacket*>(pkt);
  534 + return rtmp->fmle_unpublish(res->stream_id, unpublish->transaction_id);
  535 + }
  536 +
  537 + srs_trace("ignore AMF0/AMF3 command message.");
  538 + return ret;
  539 + }
  540 +
  541 + return ret;
  542 +}
  543 +
  544 +int SrsClient::get_peer_ip()
  545 +{
  546 + int ret = ERROR_SUCCESS;
  547 +
  548 + int fd = st_netfd_fileno(stfd);
  549 +
  550 + // discovery client information
  551 + sockaddr_in addr;
  552 + socklen_t addrlen = sizeof(addr);
  553 + if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) {
  554 + ret = ERROR_SOCKET_GET_PEER_NAME;
  555 + srs_error("discovery client information failed. ret=%d", ret);
  556 + return ret;
  557 + }
  558 + srs_verbose("get peer name success.");
  559 +
  560 + // ip v4 or v6
  561 + char buf[INET6_ADDRSTRLEN];
  562 + memset(buf, 0, sizeof(buf));
  563 +
  564 + if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
  565 + ret = ERROR_SOCKET_GET_PEER_IP;
  566 + srs_error("convert client information failed. ret=%d", ret);
  567 + return ret;
  568 + }
  569 + srs_verbose("get peer ip of client ip=%s, fd=%d", buf, fd);
  570 +
  571 + ip = new char[strlen(buf) + 1];
  572 + strcpy(ip, buf);
  573 +
  574 + srs_verbose("get peer ip success. ip=%s, fd=%d", ip, fd);
  575 +
  576 + return ret;
  577 +}
  578 +
  579 +int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg)
  580 +{
  581 + int ret = ERROR_SUCCESS;
  582 +
  583 + if (!msg) {
  584 + srs_verbose("ignore all empty message.");
  585 + return ret;
  586 + }
  587 + SrsAutoFree(SrsCommonMessage, msg, false);
  588 +
  589 + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) {
  590 + srs_info("ignore all message except amf0/amf3 command.");
  591 + return ret;
  592 + }
  593 +
  594 + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {
  595 + srs_error("decode the amf0/amf3 command packet failed. ret=%d", ret);
  596 + return ret;
  597 + }
  598 + srs_info("decode the amf0/amf3 command packet success.");
  599 +
  600 + SrsCloseStreamPacket* close = dynamic_cast<SrsCloseStreamPacket*>(msg->get_packet());
  601 + if (close) {
  602 + ret = ERROR_CONTROL_RTMP_CLOSE;
  603 + srs_trace("system control message: rtmp close stream. ret=%d", ret);
  604 + return ret;
  605 + }
  606 +
  607 + SrsPausePacket* pause = dynamic_cast<SrsPausePacket*>(msg->get_packet());
  608 + if (!pause) {
  609 + srs_info("ignore all amf0/amf3 command except pause.");
  610 + return ret;
  611 + }
  612 +
  613 + if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) {
  614 + srs_error("rtmp process play client pause failed. ret=%d", ret);
  615 + return ret;
  616 + }
  617 +
  618 + if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) {
  619 + srs_error("consumer process play client pause failed. ret=%d", ret);
  620 + return ret;
  621 + }
  622 + srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms);
  623 +
  624 + return ret;
  625 +}
  626 +
  627 +int SrsClient::on_connect()
  628 +{
  629 + int ret = ERROR_SUCCESS;
  630 +
  631 +#ifdef SRS_HTTP
  632 + // HTTP: on_connect
  633 + SrsConfDirective* on_connect = config->get_vhost_on_connect(req->vhost);
  634 + if (!on_connect) {
  635 + srs_info("ignore the empty http callback: on_connect");
  636 + return ret;
  637 + }
  638 +
  639 + for (int i = 0; i < (int)on_connect->args.size(); i++) {
  640 + std::string url = on_connect->args.at(i);
  641 + if ((ret = http_hooks->on_connect(url, connection_id, ip, req)) != ERROR_SUCCESS) {
  642 + srs_error("hook client on_connect failed. url=%s, ret=%d", url.c_str(), ret);
  643 + return ret;
  644 + }
  645 + }
  646 +#endif
  647 +
  648 + return ret;
  649 +}
  650 +
  651 +void SrsClient::on_close()
  652 +{
  653 +#ifdef SRS_HTTP
  654 + // whatever the ret code, notify the api hooks.
  655 + // HTTP: on_close
  656 + SrsConfDirective* on_close = config->get_vhost_on_close(req->vhost);
  657 + if (!on_close) {
  658 + srs_info("ignore the empty http callback: on_close");
  659 + return;
  660 + }
  661 +
  662 + for (int i = 0; i < (int)on_close->args.size(); i++) {
  663 + std::string url = on_close->args.at(i);
  664 + http_hooks->on_close(url, connection_id, ip, req);
  665 + }
  666 +#endif
  667 +}
  668 +
  669 +int SrsClient::on_publish()
  670 +{
  671 + int ret = ERROR_SUCCESS;
  672 +
  673 +#ifdef SRS_HTTP
  674 + // HTTP: on_publish
  675 + SrsConfDirective* on_publish = config->get_vhost_on_publish(req->vhost);
  676 + if (!on_publish) {
  677 + srs_info("ignore the empty http callback: on_publish");
  678 + return ret;
  679 + }
  680 +
  681 + for (int i = 0; i < (int)on_publish->args.size(); i++) {
  682 + std::string url = on_publish->args.at(i);
  683 + if ((ret = http_hooks->on_publish(url, connection_id, ip, req)) != ERROR_SUCCESS) {
  684 + srs_error("hook client on_publish failed. url=%s, ret=%d", url.c_str(), ret);
  685 + return ret;
  686 + }
  687 + }
  688 +#endif
  689 +
  690 + return ret;
  691 +}
  692 +
  693 +void SrsClient::on_unpublish()
  694 +{
  695 +#ifdef SRS_HTTP
  696 + // whatever the ret code, notify the api hooks.
  697 + // HTTP: on_unpublish
  698 + SrsConfDirective* on_unpublish = config->get_vhost_on_unpublish(req->vhost);
  699 + if (!on_unpublish) {
  700 + srs_info("ignore the empty http callback: on_unpublish");
  701 + return;
  702 + }
  703 +
  704 + for (int i = 0; i < (int)on_unpublish->args.size(); i++) {
  705 + std::string url = on_unpublish->args.at(i);
  706 + http_hooks->on_unpublish(url, connection_id, ip, req);
  707 + }
  708 +#endif
  709 +}
  710 +
  711 +int SrsClient::on_play()
  712 +{
  713 + int ret = ERROR_SUCCESS;
  714 +
  715 +#ifdef SRS_HTTP
  716 + // HTTP: on_play
  717 + SrsConfDirective* on_play = config->get_vhost_on_play(req->vhost);
  718 + if (!on_play) {
  719 + srs_info("ignore the empty http callback: on_play");
  720 + return ret;
  721 + }
  722 +
  723 + for (int i = 0; i < (int)on_play->args.size(); i++) {
  724 + std::string url = on_play->args.at(i);
  725 + if ((ret = http_hooks->on_play(url, connection_id, ip, req)) != ERROR_SUCCESS) {
  726 + srs_error("hook client on_play failed. url=%s, ret=%d", url.c_str(), ret);
  727 + return ret;
  728 + }
  729 + }
  730 +#endif
  731 +
  732 + return ret;
  733 +}
  734 +
  735 +void SrsClient::on_stop()
  736 +{
  737 +#ifdef SRS_HTTP
  738 + // whatever the ret code, notify the api hooks.
  739 + // HTTP: on_stop
  740 + SrsConfDirective* on_stop = config->get_vhost_on_stop(req->vhost);
  741 + if (!on_stop) {
  742 + srs_info("ignore the empty http callback: on_stop");
  743 + return;
  744 + }
  745 +
  746 + for (int i = 0; i < (int)on_stop->args.size(); i++) {
  747 + std::string url = on_stop->args.at(i);
  748 + http_hooks->on_stop(url, connection_id, ip, req);
  749 + }
  750 +#endif
  751 +}
  752 +
1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013-2014 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#ifndef SRS_CORE_CLIENT_HPP  
25 -#define SRS_CORE_CLIENT_HPP  
26 -  
27 -/*  
28 -#include <srs_core_client.hpp>  
29 -*/  
30 -  
31 -#include <srs_core.hpp>  
32 -  
33 -#include <srs_core_conn.hpp>  
34 -#include <srs_core_reload.hpp>  
35 -  
36 -class SrsRtmp;  
37 -class SrsRequest;  
38 -class SrsResponse;  
39 -class SrsSource;  
40 -class SrsRefer;  
41 -class SrsConsumer;  
42 -class SrsCommonMessage;  
43 -#ifdef SRS_HTTP  
44 -class SrsHttpHooks;  
45 -#endif  
46 -class SrsBandwidth;  
47 -  
48 -/**  
49 -* the client provides the main logic control for RTMP clients.  
50 -*/  
51 -class SrsClient : public SrsConnection, public ISrsReloadHandler  
52 -{  
53 -private:  
54 - char* ip;  
55 - SrsRequest* req;  
56 - SrsResponse* res;  
57 - SrsRtmp* rtmp;  
58 - SrsRefer* refer;  
59 -#ifdef SRS_HTTP  
60 - SrsHttpHooks* http_hooks;  
61 -#endif  
62 - SrsBandwidth* bandwidth;  
63 -public:  
64 - SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);  
65 - virtual ~SrsClient();  
66 -protected:  
67 - virtual int do_cycle();  
68 -// interface ISrsReloadHandler  
69 -public:  
70 - virtual int on_reload_vhost_removed(std::string vhost);  
71 -private:  
72 - // when valid and connected to vhost/app, service the client.  
73 - virtual int service_cycle();  
74 - virtual int check_vhost();  
75 - virtual int playing(SrsSource* source);  
76 - virtual int publish(SrsSource* source, bool is_fmle);  
77 - virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle);  
78 - virtual int get_peer_ip();  
79 - virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);  
80 -private:  
81 - virtual int on_connect();  
82 - virtual void on_close();  
83 - virtual int on_publish();  
84 - virtual void on_unpublish();  
85 - virtual int on_play();  
86 - virtual void on_stop();  
87 -};  
88 - 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_CORE_CLIENT_HPP
  25 +#define SRS_CORE_CLIENT_HPP
  26 +
  27 +/*
  28 +#include <srs_core_client.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <srs_core_conn.hpp>
  34 +#include <srs_core_reload.hpp>
  35 +
  36 +class SrsRtmp;
  37 +class SrsRequest;
  38 +class SrsResponse;
  39 +class SrsSource;
  40 +class SrsRefer;
  41 +class SrsConsumer;
  42 +class SrsCommonMessage;
  43 +#ifdef SRS_HTTP
  44 +class SrsHttpHooks;
  45 +#endif
  46 +class SrsBandwidth;
  47 +
  48 +/**
  49 +* the client provides the main logic control for RTMP clients.
  50 +*/
  51 +class SrsClient : public SrsConnection, public ISrsReloadHandler
  52 +{
  53 +private:
  54 + char* ip;
  55 + SrsRequest* req;
  56 + SrsResponse* res;
  57 + SrsRtmp* rtmp;
  58 + SrsRefer* refer;
  59 +#ifdef SRS_HTTP
  60 + SrsHttpHooks* http_hooks;
  61 +#endif
  62 + SrsBandwidth* bandwidth;
  63 +public:
  64 + SrsClient(SrsServer* srs_server, st_netfd_t client_stfd);
  65 + virtual ~SrsClient();
  66 +protected:
  67 + virtual int do_cycle();
  68 +// interface ISrsReloadHandler
  69 +public:
  70 + virtual int on_reload_vhost_removed(std::string vhost);
  71 +private:
  72 + // when valid and connected to vhost/app, service the client.
  73 + virtual int service_cycle();
  74 + // stream(play/publish) service cycle, identify client first.
  75 + virtual int stream_service_cycle();
  76 + virtual int check_vhost();
  77 + virtual int playing(SrsSource* source);
  78 + virtual int publish(SrsSource* source, bool is_fmle);
  79 + virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle);
  80 + virtual int get_peer_ip();
  81 + virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
  82 +private:
  83 + virtual int on_connect();
  84 + virtual void on_close();
  85 + virtual int on_publish();
  86 + virtual void on_unpublish();
  87 + virtual int on_play();
  88 + virtual void on_stop();
  89 +};
  90 +
89 #endif 91 #endif
1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013-2014 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#include <srs_core_error.hpp> 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_core_error.hpp>
  25 +
  26 +bool srs_is_system_control_error(int error_code)
  27 +{
  28 + return error_code == ERROR_CONTROL_RTMP_CLOSE;
  29 +}
1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013-2014 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#ifndef SRS_CORE_ERROR_HPP  
25 -#define SRS_CORE_ERROR_HPP  
26 -  
27 -/*  
28 -#include <srs_core_error.hpp>  
29 -*/  
30 -  
31 -#include <srs_core.hpp>  
32 -  
33 -#define ERROR_SUCCESS 0  
34 -  
35 -#define ERROR_ST_SET_EPOLL 100  
36 -#define ERROR_ST_INITIALIZE 101  
37 -#define ERROR_ST_OPEN_SOCKET 102  
38 -#define ERROR_ST_CREATE_LISTEN_THREAD 103  
39 -#define ERROR_ST_CREATE_CYCLE_THREAD 104  
40 -#define ERROR_ST_CONNECT 105  
41 -  
42 -#define ERROR_SOCKET_CREATE 200  
43 -#define ERROR_SOCKET_SETREUSE 201  
44 -#define ERROR_SOCKET_BIND 202  
45 -#define ERROR_SOCKET_LISTEN 203  
46 -#define ERROR_SOCKET_CLOSED 204  
47 -#define ERROR_SOCKET_GET_PEER_NAME 205  
48 -#define ERROR_SOCKET_GET_PEER_IP 206  
49 -#define ERROR_SOCKET_READ 207  
50 -#define ERROR_SOCKET_READ_FULLY 208  
51 -#define ERROR_SOCKET_WRITE 209  
52 -#define ERROR_SOCKET_WAIT 210  
53 -#define ERROR_SOCKET_TIMEOUT 211  
54 -#define ERROR_SOCKET_GET_LOCAL_IP 212  
55 -  
56 -#define ERROR_RTMP_PLAIN_REQUIRED 300  
57 -#define ERROR_RTMP_CHUNK_START 301  
58 -#define ERROR_RTMP_MSG_INVLIAD_SIZE 302  
59 -#define ERROR_RTMP_AMF0_DECODE 303  
60 -#define ERROR_RTMP_AMF0_INVALID 304  
61 -#define ERROR_RTMP_REQ_CONNECT 305  
62 -#define ERROR_RTMP_REQ_TCURL 306  
63 -#define ERROR_RTMP_MESSAGE_DECODE 307  
64 -#define ERROR_RTMP_MESSAGE_ENCODE 308  
65 -#define ERROR_RTMP_AMF0_ENCODE 309  
66 -#define ERROR_RTMP_CHUNK_SIZE 310  
67 -#define ERROR_RTMP_TRY_SIMPLE_HS 311  
68 -#define ERROR_RTMP_CH_SCHEMA 312  
69 -#define ERROR_RTMP_PACKET_SIZE 313  
70 -#define ERROR_RTMP_VHOST_NOT_FOUND 314  
71 -#define ERROR_RTMP_ACCESS_DENIED 315  
72 -#define ERROR_RTMP_HANDSHAKE 316  
73 -#define ERROR_RTMP_NO_REQUEST 317  
74 -  
75 -#define ERROR_SYSTEM_STREAM_INIT 400  
76 -#define ERROR_SYSTEM_PACKET_INVALID 401  
77 -#define ERROR_SYSTEM_CLIENT_INVALID 402  
78 -#define ERROR_SYSTEM_ASSERT_FAILED 403  
79 -#define ERROR_SYSTEM_SIZE_NEGATIVE 404  
80 -#define ERROR_SYSTEM_CONFIG_INVALID 405  
81 -#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406  
82 -#define ERROR_SYSTEM_CONFIG_BLOCK_START 407  
83 -#define ERROR_SYSTEM_CONFIG_BLOCK_END 408  
84 -#define ERROR_SYSTEM_CONFIG_EOF 409  
85 -#define ERROR_SYSTEM_STREAM_BUSY 410  
86 -#define ERROR_SYSTEM_IP_INVALID 411  
87 -#define ERROR_SYSTEM_FORWARD_LOOP 412  
88 -#define ERROR_SYSTEM_WAITPID 413  
89 -#define ERROR_SYSTEM_BANDWIDTH_KEY 414  
90 -#define ERROR_SYSTEM_BANDWIDTH_DENIED 415  
91 -  
92 -// see librtmp.  
93 -// failed when open ssl create the dh  
94 -#define ERROR_OpenSslCreateDH 500  
95 -// failed when open ssl create the Private key.  
96 -#define ERROR_OpenSslCreateP 501  
97 -// when open ssl create G.  
98 -#define ERROR_OpenSslCreateG 502  
99 -// when open ssl parse P1024  
100 -#define ERROR_OpenSslParseP1024 503  
101 -// when open ssl set G  
102 -#define ERROR_OpenSslSetG 504  
103 -// when open ssl generate DHKeys  
104 -#define ERROR_OpenSslGenerateDHKeys 505  
105 -// when open ssl share key already computed.  
106 -#define ERROR_OpenSslShareKeyComputed 506  
107 -// when open ssl get shared key size.  
108 -#define ERROR_OpenSslGetSharedKeySize 507  
109 -// when open ssl get peer public key.  
110 -#define ERROR_OpenSslGetPeerPublicKey 508  
111 -// when open ssl compute shared key.  
112 -#define ERROR_OpenSslComputeSharedKey 509  
113 -// when open ssl is invalid DH state.  
114 -#define ERROR_OpenSslInvalidDHState 510  
115 -// when open ssl copy key  
116 -#define ERROR_OpenSslCopyKey 511  
117 -// when open ssl sha256 digest key invalid size.  
118 -#define ERROR_OpenSslSha256DigestSize 512  
119 -  
120 -#define ERROR_HLS_METADATA 600  
121 -#define ERROR_HLS_DECODE_ERROR 601  
122 -#define ERROR_HLS_CREATE_DIR 602  
123 -#define ERROR_HLS_OPEN_FAILED 603  
124 -#define ERROR_HLS_WRITE_FAILED 604  
125 -#define ERROR_HLS_AAC_FRAME_LENGTH 605  
126 -#define ERROR_HLS_AVC_SAMPLE_SIZE 606  
127 -  
128 -#define ERROR_ENCODER_VCODEC 700  
129 -#define ERROR_ENCODER_OUTPUT 701  
130 -#define ERROR_ENCODER_ACHANNELS 702  
131 -#define ERROR_ENCODER_ASAMPLE_RATE 703  
132 -#define ERROR_ENCODER_ABITRATE 704  
133 -#define ERROR_ENCODER_ACODEC 705  
134 -#define ERROR_ENCODER_VPRESET 706  
135 -#define ERROR_ENCODER_VPROFILE 707  
136 -#define ERROR_ENCODER_VTHREADS 708  
137 -#define ERROR_ENCODER_VHEIGHT 709  
138 -#define ERROR_ENCODER_VWIDTH 710  
139 -#define ERROR_ENCODER_VFPS 711  
140 -#define ERROR_ENCODER_VBITRATE 712  
141 -#define ERROR_ENCODER_FORK 713  
142 -#define ERROR_ENCODER_LOOP 714  
143 -#define ERROR_ENCODER_OPEN 715  
144 -#define ERROR_ENCODER_DUP2 716  
145 -  
146 -#define ERROR_HTTP_PARSE_URI 800  
147 -#define ERROR_HTTP_DATA_INVLIAD 801  
148 -#define ERROR_HTTP_PARSE_HEADER 802  
149 - 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_CORE_ERROR_HPP
  25 +#define SRS_CORE_ERROR_HPP
  26 +
  27 +/*
  28 +#include <srs_core_error.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#define ERROR_SUCCESS 0
  34 +
  35 +#define ERROR_ST_SET_EPOLL 100
  36 +#define ERROR_ST_INITIALIZE 101
  37 +#define ERROR_ST_OPEN_SOCKET 102
  38 +#define ERROR_ST_CREATE_LISTEN_THREAD 103
  39 +#define ERROR_ST_CREATE_CYCLE_THREAD 104
  40 +#define ERROR_ST_CONNECT 105
  41 +
  42 +#define ERROR_SOCKET_CREATE 200
  43 +#define ERROR_SOCKET_SETREUSE 201
  44 +#define ERROR_SOCKET_BIND 202
  45 +#define ERROR_SOCKET_LISTEN 203
  46 +#define ERROR_SOCKET_CLOSED 204
  47 +#define ERROR_SOCKET_GET_PEER_NAME 205
  48 +#define ERROR_SOCKET_GET_PEER_IP 206
  49 +#define ERROR_SOCKET_READ 207
  50 +#define ERROR_SOCKET_READ_FULLY 208
  51 +#define ERROR_SOCKET_WRITE 209
  52 +#define ERROR_SOCKET_WAIT 210
  53 +#define ERROR_SOCKET_TIMEOUT 211
  54 +#define ERROR_SOCKET_GET_LOCAL_IP 212
  55 +
  56 +#define ERROR_RTMP_PLAIN_REQUIRED 300
  57 +#define ERROR_RTMP_CHUNK_START 301
  58 +#define ERROR_RTMP_MSG_INVLIAD_SIZE 302
  59 +#define ERROR_RTMP_AMF0_DECODE 303
  60 +#define ERROR_RTMP_AMF0_INVALID 304
  61 +#define ERROR_RTMP_REQ_CONNECT 305
  62 +#define ERROR_RTMP_REQ_TCURL 306
  63 +#define ERROR_RTMP_MESSAGE_DECODE 307
  64 +#define ERROR_RTMP_MESSAGE_ENCODE 308
  65 +#define ERROR_RTMP_AMF0_ENCODE 309
  66 +#define ERROR_RTMP_CHUNK_SIZE 310
  67 +#define ERROR_RTMP_TRY_SIMPLE_HS 311
  68 +#define ERROR_RTMP_CH_SCHEMA 312
  69 +#define ERROR_RTMP_PACKET_SIZE 313
  70 +#define ERROR_RTMP_VHOST_NOT_FOUND 314
  71 +#define ERROR_RTMP_ACCESS_DENIED 315
  72 +#define ERROR_RTMP_HANDSHAKE 316
  73 +#define ERROR_RTMP_NO_REQUEST 317
  74 +
  75 +#define ERROR_SYSTEM_STREAM_INIT 400
  76 +#define ERROR_SYSTEM_PACKET_INVALID 401
  77 +#define ERROR_SYSTEM_CLIENT_INVALID 402
  78 +#define ERROR_SYSTEM_ASSERT_FAILED 403
  79 +#define ERROR_SYSTEM_SIZE_NEGATIVE 404
  80 +#define ERROR_SYSTEM_CONFIG_INVALID 405
  81 +#define ERROR_SYSTEM_CONFIG_DIRECTIVE 406
  82 +#define ERROR_SYSTEM_CONFIG_BLOCK_START 407
  83 +#define ERROR_SYSTEM_CONFIG_BLOCK_END 408
  84 +#define ERROR_SYSTEM_CONFIG_EOF 409
  85 +#define ERROR_SYSTEM_STREAM_BUSY 410
  86 +#define ERROR_SYSTEM_IP_INVALID 411
  87 +#define ERROR_SYSTEM_FORWARD_LOOP 412
  88 +#define ERROR_SYSTEM_WAITPID 413
  89 +#define ERROR_SYSTEM_BANDWIDTH_KEY 414
  90 +#define ERROR_SYSTEM_BANDWIDTH_DENIED 415
  91 +
  92 +// see librtmp.
  93 +// failed when open ssl create the dh
  94 +#define ERROR_OpenSslCreateDH 500
  95 +// failed when open ssl create the Private key.
  96 +#define ERROR_OpenSslCreateP 501
  97 +// when open ssl create G.
  98 +#define ERROR_OpenSslCreateG 502
  99 +// when open ssl parse P1024
  100 +#define ERROR_OpenSslParseP1024 503
  101 +// when open ssl set G
  102 +#define ERROR_OpenSslSetG 504
  103 +// when open ssl generate DHKeys
  104 +#define ERROR_OpenSslGenerateDHKeys 505
  105 +// when open ssl share key already computed.
  106 +#define ERROR_OpenSslShareKeyComputed 506
  107 +// when open ssl get shared key size.
  108 +#define ERROR_OpenSslGetSharedKeySize 507
  109 +// when open ssl get peer public key.
  110 +#define ERROR_OpenSslGetPeerPublicKey 508
  111 +// when open ssl compute shared key.
  112 +#define ERROR_OpenSslComputeSharedKey 509
  113 +// when open ssl is invalid DH state.
  114 +#define ERROR_OpenSslInvalidDHState 510
  115 +// when open ssl copy key
  116 +#define ERROR_OpenSslCopyKey 511
  117 +// when open ssl sha256 digest key invalid size.
  118 +#define ERROR_OpenSslSha256DigestSize 512
  119 +
  120 +#define ERROR_HLS_METADATA 600
  121 +#define ERROR_HLS_DECODE_ERROR 601
  122 +#define ERROR_HLS_CREATE_DIR 602
  123 +#define ERROR_HLS_OPEN_FAILED 603
  124 +#define ERROR_HLS_WRITE_FAILED 604
  125 +#define ERROR_HLS_AAC_FRAME_LENGTH 605
  126 +#define ERROR_HLS_AVC_SAMPLE_SIZE 606
  127 +
  128 +#define ERROR_ENCODER_VCODEC 700
  129 +#define ERROR_ENCODER_OUTPUT 701
  130 +#define ERROR_ENCODER_ACHANNELS 702
  131 +#define ERROR_ENCODER_ASAMPLE_RATE 703
  132 +#define ERROR_ENCODER_ABITRATE 704
  133 +#define ERROR_ENCODER_ACODEC 705
  134 +#define ERROR_ENCODER_VPRESET 706
  135 +#define ERROR_ENCODER_VPROFILE 707
  136 +#define ERROR_ENCODER_VTHREADS 708
  137 +#define ERROR_ENCODER_VHEIGHT 709
  138 +#define ERROR_ENCODER_VWIDTH 710
  139 +#define ERROR_ENCODER_VFPS 711
  140 +#define ERROR_ENCODER_VBITRATE 712
  141 +#define ERROR_ENCODER_FORK 713
  142 +#define ERROR_ENCODER_LOOP 714
  143 +#define ERROR_ENCODER_OPEN 715
  144 +#define ERROR_ENCODER_DUP2 716
  145 +
  146 +#define ERROR_HTTP_PARSE_URI 800
  147 +#define ERROR_HTTP_DATA_INVLIAD 801
  148 +#define ERROR_HTTP_PARSE_HEADER 802
  149 +
  150 +// system control message,
  151 +// not an error, but special control logic.
  152 +// sys ctl: rtmp close stream, support replay.
  153 +#define ERROR_CONTROL_RTMP_CLOSE 900
  154 +
  155 +/**
  156 +* whether the error code is an system control error.
  157 +*/
  158 +extern bool srs_is_system_control_error(int error_code);
  159 +
150 #endif 160 #endif
@@ -196,6 +196,7 @@ messages. @@ -196,6 +196,7 @@ messages.
196 */ 196 */
197 #define RTMP_AMF0_COMMAND_CONNECT "connect" 197 #define RTMP_AMF0_COMMAND_CONNECT "connect"
198 #define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" 198 #define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream"
  199 +#define RTMP_AMF0_COMMAND_CLOSE_STREAM "closeStream"
199 #define RTMP_AMF0_COMMAND_PLAY "play" 200 #define RTMP_AMF0_COMMAND_PLAY "play"
200 #define RTMP_AMF0_COMMAND_PAUSE "pause" 201 #define RTMP_AMF0_COMMAND_PAUSE "pause"
201 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" 202 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone"
@@ -1363,6 +1364,10 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) @@ -1363,6 +1364,10 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol)
1363 srs_info("decode the AMF0/AMF3 band width check message."); 1364 srs_info("decode the AMF0/AMF3 band width check message.");
1364 packet = new SrsBandwidthPacket(); 1365 packet = new SrsBandwidthPacket();
1365 return packet->decode(stream); 1366 return packet->decode(stream);
  1367 + } else if (command == RTMP_AMF0_COMMAND_CLOSE_STREAM) {
  1368 + srs_info("decode the AMF0/AMF3 closeStream message.");
  1369 + packet = new SrsCloseStreamPacket();
  1370 + return packet->decode(stream);
1366 } 1371 }
1367 1372
1368 // default packet to drop message. 1373 // default packet to drop message.
@@ -2064,6 +2069,41 @@ int SrsCreateStreamResPacket::encode_packet(SrsStream* stream) @@ -2064,6 +2069,41 @@ int SrsCreateStreamResPacket::encode_packet(SrsStream* stream)
2064 return ret; 2069 return ret;
2065 } 2070 }
2066 2071
  2072 +SrsCloseStreamPacket::SrsCloseStreamPacket()
  2073 +{
  2074 + command_name = RTMP_AMF0_COMMAND_CLOSE_STREAM;
  2075 + transaction_id = 0;
  2076 + command_object = new SrsAmf0Null();
  2077 +}
  2078 +
  2079 +SrsCloseStreamPacket::~SrsCloseStreamPacket()
  2080 +{
  2081 + srs_freep(command_object);
  2082 +}
  2083 +
  2084 +int SrsCloseStreamPacket::decode(SrsStream* stream)
  2085 +{
  2086 + int ret = ERROR_SUCCESS;
  2087 +
  2088 + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
  2089 + srs_error("amf0 decode closeStream command_name failed. ret=%d", ret);
  2090 + return ret;
  2091 + }
  2092 +
  2093 + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) {
  2094 + srs_error("amf0 decode closeStream transaction_id failed. ret=%d", ret);
  2095 + return ret;
  2096 + }
  2097 +
  2098 + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
  2099 + srs_error("amf0 decode closeStream command_object failed. ret=%d", ret);
  2100 + return ret;
  2101 + }
  2102 + srs_info("amf0 decode closeStream packet success");
  2103 +
  2104 + return ret;
  2105 +}
  2106 +
2067 SrsFMLEStartPacket::SrsFMLEStartPacket() 2107 SrsFMLEStartPacket::SrsFMLEStartPacket()
2068 { 2108 {
2069 command_name = RTMP_AMF0_COMMAND_CREATE_STREAM; 2109 command_name = RTMP_AMF0_COMMAND_CREATE_STREAM;
1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013-2014 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#ifndef SRS_CORE_PROTOCOL_HPP  
25 -#define SRS_CORE_PROTOCOL_HPP  
26 -  
27 -/*  
28 -#include <srs_core_protocol.hpp>  
29 -*/  
30 -  
31 -#include <srs_core.hpp>  
32 -  
33 -#include <map>  
34 -#include <string>  
35 -  
36 -#include <srs_core_log.hpp>  
37 -#include <srs_core_error.hpp>  
38 -  
39 -// the following is the timeout for rtmp protocol,  
40 -// to avoid death connection.  
41 -  
42 -// when got a messae header, there must be some data,  
43 -// increase recv timeout to got an entire message.  
44 -#define SRS_MIN_RECV_TIMEOUT_US 60*1000*1000L  
45 -  
46 -// the timeout to wait for client control message,  
47 -// if timeout, we generally ignore and send the data to client,  
48 -// generally, it's the pulse time for data seding.  
49 -#define SRS_PULSE_TIMEOUT_US 200*1000L  
50 -  
51 -// the timeout to wait client data,  
52 -// if timeout, close the connection.  
53 -#define SRS_SEND_TIMEOUT_US 30*1000*1000L  
54 -  
55 -// the timeout to send data to client,  
56 -// if timeout, close the connection.  
57 -#define SRS_RECV_TIMEOUT_US 30*1000*1000L  
58 -  
59 -// when stream is busy, for example, streaming is already  
60 -// publishing, when a new client to request to publish,  
61 -// sleep a while and close the connection.  
62 -#define SRS_STREAM_BUSY_SLEEP_US 3*1000*1000L  
63 -  
64 -// when error, forwarder sleep for a while and retry.  
65 -#define SRS_FORWARDER_SLEEP_US 3*1000*1000L  
66 -  
67 -// when error, encoder sleep for a while and retry.  
68 -#define SRS_ENCODER_SLEEP_US 3*1000*1000L  
69 -  
70 -class SrsSocket;  
71 -class SrsBuffer;  
72 -class SrsPacket;  
73 -class SrsStream;  
74 -class SrsCommonMessage;  
75 -class SrsChunkStream;  
76 -class SrsAmf0Object;  
77 -class SrsAmf0Null;  
78 -class SrsAmf0Undefined;  
79 -class ISrsMessage;  
80 -  
81 -// convert class name to string.  
82 -#define CLASS_NAME_STRING(className) #className  
83 -  
84 -/**  
85 -* max rtmp header size:  
86 -* 1bytes basic header,  
87 -* 11bytes message header,  
88 -* 4bytes timestamp header,  
89 -* that is, 1+11+4=16bytes.  
90 -*/  
91 -#define RTMP_MAX_FMT0_HEADER_SIZE 16  
92 -/**  
93 -* max rtmp header size:  
94 -* 1bytes basic header,  
95 -* 4bytes timestamp header,  
96 -* that is, 1+4=5bytes.  
97 -*/  
98 -#define RTMP_MAX_FMT3_HEADER_SIZE 5  
99 -  
100 -/**  
101 -* the protocol provides the rtmp-message-protocol services,  
102 -* to recv RTMP message from RTMP chunk stream,  
103 -* and to send out RTMP message over RTMP chunk stream.  
104 -*/  
105 -class SrsProtocol  
106 -{  
107 -private:  
108 - struct AckWindowSize  
109 - {  
110 - int ack_window_size;  
111 - int64_t acked_size;  
112 -  
113 - AckWindowSize();  
114 - };  
115 -// peer in/out  
116 -private:  
117 - st_netfd_t stfd;  
118 - SrsSocket* skt;  
119 - char* pp;  
120 - /**  
121 - * requests sent out, used to build the response.  
122 - * key: transactionId  
123 - * value: the request command name  
124 - */  
125 - std::map<double, std::string> requests;  
126 -// peer in  
127 -private:  
128 - std::map<int, SrsChunkStream*> chunk_streams;  
129 - SrsBuffer* buffer;  
130 - int32_t in_chunk_size;  
131 - AckWindowSize in_ack_size;  
132 -// peer out  
133 -private:  
134 - char out_header_fmt0[RTMP_MAX_FMT0_HEADER_SIZE];  
135 - char out_header_fmt3[RTMP_MAX_FMT3_HEADER_SIZE];  
136 - int32_t out_chunk_size;  
137 -public:  
138 - SrsProtocol(st_netfd_t client_stfd);  
139 - virtual ~SrsProtocol();  
140 -public:  
141 - std::string get_request_name(double transcationId);  
142 - /**  
143 - * set the timeout in us.  
144 - * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT.  
145 - */  
146 - virtual void set_recv_timeout(int64_t timeout_us);  
147 - virtual int64_t get_recv_timeout();  
148 - virtual void set_send_timeout(int64_t timeout_us);  
149 - virtual int64_t get_send_timeout();  
150 - virtual int64_t get_recv_bytes();  
151 - virtual int64_t get_send_bytes();  
152 - virtual int get_recv_kbps();  
153 - virtual int get_send_kbps();  
154 - /**  
155 - * recv a message with raw/undecoded payload from peer.  
156 - * the payload is not decoded, use srs_rtmp_expect_message<T> if requires  
157 - * specifies message.  
158 - * @pmsg, user must free it. NULL if not success.  
159 - * @remark, only when success, user can use and must free the pmsg.  
160 - */  
161 - virtual int recv_message(SrsCommonMessage** pmsg);  
162 - /**  
163 - * send out message with encoded payload to peer.  
164 - * use the message encode method to encode to payload,  
165 - * then sendout over socket.  
166 - * @msg this method will free it whatever return value.  
167 - */  
168 - virtual int send_message(ISrsMessage* msg);  
169 -private:  
170 - /**  
171 - * when recv message, update the context.  
172 - */  
173 - virtual int on_recv_message(SrsCommonMessage* msg);  
174 - virtual int response_acknowledgement_message();  
175 - virtual int response_ping_message(int32_t timestamp);  
176 - /**  
177 - * when message sentout, update the context.  
178 - */  
179 - virtual int on_send_message(ISrsMessage* msg);  
180 - /**  
181 - * try to recv interlaced message from peer,  
182 - * return error if error occur and nerver set the pmsg,  
183 - * return success and pmsg set to NULL if no entire message got,  
184 - * return success and pmsg set to entire message if got one.  
185 - */  
186 - virtual int recv_interlaced_message(SrsCommonMessage** pmsg);  
187 - /**  
188 - * read the chunk basic header(fmt, cid) from chunk stream.  
189 - * user can discovery a SrsChunkStream by cid.  
190 - * @bh_size return the chunk basic header size, to remove the used bytes when finished.  
191 - */  
192 - virtual int read_basic_header(char& fmt, int& cid, int& bh_size);  
193 - /**  
194 - * read the chunk message header(timestamp, payload_length, message_type, stream_id)  
195 - * from chunk stream and save to SrsChunkStream.  
196 - * @mh_size return the chunk message header size, to remove the used bytes when finished.  
197 - */  
198 - virtual int read_message_header(SrsChunkStream* chunk, char fmt, int bh_size, int& mh_size);  
199 - /**  
200 - * read the chunk payload, remove the used bytes in buffer,  
201 - * if got entire message, set the pmsg.  
202 - * @payload_size read size in this roundtrip, generally a chunk size or left message size.  
203 - */  
204 - virtual int read_message_payload(SrsChunkStream* chunk, int bh_size, int mh_size, int& payload_size, SrsCommonMessage** pmsg);  
205 -};  
206 -  
207 -/**  
208 -* 4.1. Message Header  
209 -*/  
210 -struct SrsMessageHeader  
211 -{  
212 - /**  
213 - * One byte field to represent the message type. A range of type IDs  
214 - * (1-7) are reserved for protocol control messages.  
215 - */  
216 - int8_t message_type;  
217 - /**  
218 - * Three-byte field that represents the size of the payload in bytes.  
219 - * It is set in big-endian format.  
220 - */  
221 - int32_t payload_length;  
222 - /**  
223 - * Three-byte field that contains a timestamp delta of the message.  
224 - * The 4 bytes are packed in the big-endian order.  
225 - * @remark, only used for decoding message from chunk stream.  
226 - */  
227 - int32_t timestamp_delta;  
228 - /**  
229 - * Three-byte field that identifies the stream of the message. These  
230 - * bytes are set in big-endian format.  
231 - */  
232 - int32_t stream_id;  
233 -  
234 - /**  
235 - * Four-byte field that contains a timestamp of the message.  
236 - * The 4 bytes are packed in the big-endian order.  
237 - * @remark, used as calc timestamp when decode and encode time.  
238 - * @remark, we use 64bits for large time for jitter detect and hls.  
239 - */  
240 - int64_t timestamp;  
241 -  
242 - SrsMessageHeader();  
243 - virtual ~SrsMessageHeader();  
244 -  
245 - bool is_audio();  
246 - bool is_video();  
247 - bool is_amf0_command();  
248 - bool is_amf0_data();  
249 - bool is_amf3_command();  
250 - bool is_amf3_data();  
251 - bool is_window_ackledgement_size();  
252 - bool is_set_chunk_size();  
253 - bool is_user_control_message();  
254 -};  
255 -  
256 -/**  
257 -* incoming chunk stream maybe interlaced,  
258 -* use the chunk stream to cache the input RTMP chunk streams.  
259 -*/  
260 -class SrsChunkStream  
261 -{  
262 -public:  
263 - /**  
264 - * represents the basic header fmt,  
265 - * which used to identify the variant message header type.  
266 - */  
267 - char fmt;  
268 - /**  
269 - * represents the basic header cid,  
270 - * which is the chunk stream id.  
271 - */  
272 - int cid;  
273 - /**  
274 - * cached message header  
275 - */  
276 - SrsMessageHeader header;  
277 - /**  
278 - * whether the chunk message header has extended timestamp.  
279 - */  
280 - bool extended_timestamp;  
281 - /**  
282 - * partially read message.  
283 - */  
284 - SrsCommonMessage* msg;  
285 - /**  
286 - * decoded msg count, to identify whether the chunk stream is fresh.  
287 - */  
288 - int64_t msg_count;  
289 -public:  
290 - SrsChunkStream(int _cid);  
291 - virtual ~SrsChunkStream();  
292 -};  
293 -  
294 -/**  
295 -* message to output.  
296 -*/  
297 -class ISrsMessage  
298 -{  
299 -// 4.1. Message Header  
300 -public:  
301 - SrsMessageHeader header;  
302 -// 4.2. Message Payload  
303 -public:  
304 - /**  
305 - * The other part which is the payload is the actual data that is  
306 - * contained in the message. For example, it could be some audio samples  
307 - * or compressed video data. The payload format and interpretation are  
308 - * beyond the scope of this document.  
309 - */  
310 - int32_t size;  
311 - int8_t* payload;  
312 -public:  
313 - ISrsMessage();  
314 - virtual ~ISrsMessage();  
315 -public:  
316 - /**  
317 - * whether message canbe decoded.  
318 - * only update the context when message canbe decoded.  
319 - */  
320 - virtual bool can_decode() = 0;  
321 -/**  
322 -* encode functions.  
323 -*/  
324 -public:  
325 - /**  
326 - * get the perfered cid(chunk stream id) which sendout over.  
327 - */  
328 - virtual int get_perfer_cid() = 0;  
329 - /**  
330 - * encode the packet to message payload bytes.  
331 - * @remark there exists empty packet, so maybe the payload is NULL.  
332 - */  
333 - virtual int encode_packet() = 0;  
334 -};  
335 -  
336 -/**  
337 -* common RTMP message defines in rtmp.part2.Message-Formats.pdf.  
338 -* cannbe parse and decode.  
339 -*/  
340 -class SrsCommonMessage : public ISrsMessage  
341 -{  
342 -private:  
343 - typedef ISrsMessage super;  
344 - disable_default_copy(SrsCommonMessage);  
345 -// decoded message payload.  
346 -private:  
347 - SrsStream* stream;  
348 - SrsPacket* packet;  
349 -public:  
350 - SrsCommonMessage();  
351 - virtual ~SrsCommonMessage();  
352 -public:  
353 - virtual bool can_decode();  
354 -/**  
355 -* decode functions.  
356 -*/  
357 -public:  
358 - /**  
359 - * decode packet from message payload.  
360 - */  
361 - // TODO: use protocol to decode it.  
362 - virtual int decode_packet(SrsProtocol* protocol);  
363 - /**  
364 - * get the decoded packet which decoded by decode_packet().  
365 - * @remark, user never free the pkt, the message will auto free it.  
366 - */  
367 - virtual SrsPacket* get_packet();  
368 -/**  
369 -* encode functions.  
370 -*/  
371 -public:  
372 - /**  
373 - * get the perfered cid(chunk stream id) which sendout over.  
374 - */  
375 - virtual int get_perfer_cid();  
376 - /**  
377 - * set the encoded packet to encode_packet() to payload.  
378 - * @stream_id, the id of stream which is created by createStream.  
379 - * @remark, user never free the pkt, the message will auto free it.  
380 - * @return message itself.  
381 - */  
382 - // TODO: refine the send methods.  
383 - virtual SrsCommonMessage* set_packet(SrsPacket* pkt, int stream_id);  
384 - /**  
385 - * encode the packet to message payload bytes.  
386 - * @remark there exists empty packet, so maybe the payload is NULL.  
387 - */  
388 - virtual int encode_packet();  
389 -};  
390 -  
391 -/**  
392 -* shared ptr message.  
393 -* for audio/video/data message that need less memory copy.  
394 -* and only for output.  
395 -*/  
396 -class SrsSharedPtrMessage : public ISrsMessage  
397 -{  
398 -private:  
399 - typedef ISrsMessage super;  
400 -private:  
401 - struct SrsSharedPtr  
402 - {  
403 - char* payload;  
404 - int size;  
405 - int perfer_cid;  
406 - int shared_count;  
407 -  
408 - SrsSharedPtr();  
409 - virtual ~SrsSharedPtr();  
410 - };  
411 - SrsSharedPtr* ptr;  
412 -public:  
413 - SrsSharedPtrMessage();  
414 - virtual ~SrsSharedPtrMessage();  
415 -public:  
416 - virtual bool can_decode();  
417 -public:  
418 - /**  
419 - * set the shared payload.  
420 - * we will detach the payload of source,  
421 - * so ensure donot use it before.  
422 - */  
423 - virtual int initialize(SrsCommonMessage* source);  
424 - /**  
425 - * set the shared payload.  
426 - * we will use the payload, donot use the payload of source.  
427 - */  
428 - virtual int initialize(SrsCommonMessage* source, char* payload, int size);  
429 - virtual SrsSharedPtrMessage* copy();  
430 -public:  
431 - /**  
432 - * get the perfered cid(chunk stream id) which sendout over.  
433 - */  
434 - virtual int get_perfer_cid();  
435 - /**  
436 - * ignored.  
437 - * for shared message, nothing should be done.  
438 - * use initialize() to set the data.  
439 - */  
440 - virtual int encode_packet();  
441 -};  
442 -  
443 -/**  
444 -* the decoded message payload.  
445 -* @remark we seperate the packet from message,  
446 -* for the packet focus on logic and domain data,  
447 -* the message bind to the protocol and focus on protocol, such as header.  
448 -* we can merge the message and packet, using OOAD hierachy, packet extends from message,  
449 -* it's better for me to use components -- the message use the packet as payload.  
450 -*/  
451 -class SrsPacket  
452 -{  
453 -protected:  
454 - /**  
455 - * subpacket must override to provide the right class name.  
456 - */  
457 - virtual const char* get_class_name()  
458 - {  
459 - return CLASS_NAME_STRING(SrsPacket);  
460 - }  
461 -public:  
462 - SrsPacket();  
463 - virtual ~SrsPacket();  
464 -/**  
465 -* decode functions.  
466 -*/  
467 -public:  
468 - /**  
469 - * subpacket must override to decode packet from stream.  
470 - * @remark never invoke the super.decode, it always failed.  
471 - */  
472 - virtual int decode(SrsStream* stream);  
473 -/**  
474 -* encode functions.  
475 -*/  
476 -public:  
477 - virtual int get_perfer_cid();  
478 - virtual int get_payload_length();  
479 -public:  
480 - /**  
481 - * subpacket must override to provide the right message type.  
482 - */  
483 - virtual int get_message_type();  
484 - /**  
485 - * the subpacket can override this encode,  
486 - * for example, video and audio will directly set the payload withou memory copy,  
487 - * other packet which need to serialize/encode to bytes by override the  
488 - * get_size and encode_packet.  
489 - */  
490 - virtual int encode(int& size, char*& payload);  
491 -protected:  
492 - /**  
493 - * subpacket can override to calc the packet size.  
494 - */  
495 - virtual int get_size();  
496 - /**  
497 - * subpacket can override to encode the payload to stream.  
498 - * @remark never invoke the super.encode_packet, it always failed.  
499 - */  
500 - virtual int encode_packet(SrsStream* stream);  
501 -};  
502 -  
503 -/**  
504 -* 4.1.1. connect  
505 -* The client sends the connect command to the server to request  
506 -* connection to a server application instance.  
507 -*/  
508 -class SrsConnectAppPacket : public SrsPacket  
509 -{  
510 -private:  
511 - typedef SrsPacket super;  
512 -protected:  
513 - virtual const char* get_class_name()  
514 - {  
515 - return CLASS_NAME_STRING(SrsConnectAppPacket);  
516 - }  
517 -public:  
518 - std::string command_name;  
519 - double transaction_id;  
520 - SrsAmf0Object* command_object;  
521 -public:  
522 - SrsConnectAppPacket();  
523 - virtual ~SrsConnectAppPacket();  
524 -public:  
525 - virtual int decode(SrsStream* stream);  
526 -public:  
527 - virtual int get_perfer_cid();  
528 -public:  
529 - virtual int get_message_type();  
530 -protected:  
531 - virtual int get_size();  
532 - virtual int encode_packet(SrsStream* stream);  
533 -};  
534 -/**  
535 -* response for SrsConnectAppPacket.  
536 -*/  
537 -class SrsConnectAppResPacket : public SrsPacket  
538 -{  
539 -private:  
540 - typedef SrsPacket super;  
541 -protected:  
542 - virtual const char* get_class_name()  
543 - {  
544 - return CLASS_NAME_STRING(SrsConnectAppResPacket);  
545 - }  
546 -public:  
547 - std::string command_name;  
548 - double transaction_id;  
549 - SrsAmf0Object* props;  
550 - SrsAmf0Object* info;  
551 -public:  
552 - SrsConnectAppResPacket();  
553 - virtual ~SrsConnectAppResPacket();  
554 -public:  
555 - virtual int decode(SrsStream* stream);  
556 -public:  
557 - virtual int get_perfer_cid();  
558 -public:  
559 - virtual int get_message_type();  
560 -protected:  
561 - virtual int get_size();  
562 - virtual int encode_packet(SrsStream* stream);  
563 -};  
564 -  
565 -/**  
566 -* 4.1.3. createStream  
567 -* The client sends this command to the server to create a logical  
568 -* channel for message communication The publishing of audio, video, and  
569 -* metadata is carried out over stream channel created using the  
570 -* createStream command.  
571 -*/  
572 -class SrsCreateStreamPacket : public SrsPacket  
573 -{  
574 -private:  
575 - typedef SrsPacket super;  
576 -protected:  
577 - virtual const char* get_class_name()  
578 - {  
579 - return CLASS_NAME_STRING(SrsCreateStreamPacket);  
580 - }  
581 -public:  
582 - std::string command_name;  
583 - double transaction_id;  
584 - SrsAmf0Null* command_object;  
585 -public:  
586 - SrsCreateStreamPacket();  
587 - virtual ~SrsCreateStreamPacket();  
588 -public:  
589 - virtual int decode(SrsStream* stream);  
590 -public:  
591 - virtual int get_perfer_cid();  
592 -public:  
593 - virtual int get_message_type();  
594 -protected:  
595 - virtual int get_size();  
596 - virtual int encode_packet(SrsStream* stream);  
597 -};  
598 -/**  
599 -* response for SrsCreateStreamPacket.  
600 -*/  
601 -class SrsCreateStreamResPacket : public SrsPacket  
602 -{  
603 -private:  
604 - typedef SrsPacket super;  
605 -protected:  
606 - virtual const char* get_class_name()  
607 - {  
608 - return CLASS_NAME_STRING(SrsCreateStreamResPacket);  
609 - }  
610 -public:  
611 - std::string command_name;  
612 - double transaction_id;  
613 - SrsAmf0Null* command_object;  
614 - double stream_id;  
615 -public:  
616 - SrsCreateStreamResPacket(double _transaction_id, double _stream_id);  
617 - virtual ~SrsCreateStreamResPacket();  
618 -public:  
619 - virtual int decode(SrsStream* stream);  
620 -public:  
621 - virtual int get_perfer_cid();  
622 -public:  
623 - virtual int get_message_type();  
624 -protected:  
625 - virtual int get_size();  
626 - virtual int encode_packet(SrsStream* stream);  
627 -};  
628 -  
629 -/**  
630 -* FMLE start publish: ReleaseStream/PublishStream  
631 -*/  
632 -class SrsFMLEStartPacket : public SrsPacket  
633 -{  
634 -private:  
635 - typedef SrsPacket super;  
636 -protected:  
637 - virtual const char* get_class_name()  
638 - {  
639 - return CLASS_NAME_STRING(SrsFMLEStartPacket);  
640 - }  
641 -public:  
642 - std::string command_name;  
643 - double transaction_id;  
644 - SrsAmf0Null* command_object;  
645 - std::string stream_name;  
646 -public:  
647 - SrsFMLEStartPacket();  
648 - virtual ~SrsFMLEStartPacket();  
649 -public:  
650 - virtual int decode(SrsStream* stream);  
651 -};  
652 -/**  
653 -* response for SrsFMLEStartPacket.  
654 -*/  
655 -class SrsFMLEStartResPacket : public SrsPacket  
656 -{  
657 -private:  
658 - typedef SrsPacket super;  
659 -protected:  
660 - virtual const char* get_class_name()  
661 - {  
662 - return CLASS_NAME_STRING(SrsFMLEStartResPacket);  
663 - }  
664 -public:  
665 - std::string command_name;  
666 - double transaction_id;  
667 - SrsAmf0Null* command_object;  
668 - SrsAmf0Undefined* args;  
669 -public:  
670 - SrsFMLEStartResPacket(double _transaction_id);  
671 - virtual ~SrsFMLEStartResPacket();  
672 -public:  
673 - virtual int get_perfer_cid();  
674 -public:  
675 - virtual int get_message_type();  
676 -protected:  
677 - virtual int get_size();  
678 - virtual int encode_packet(SrsStream* stream);  
679 -};  
680 -  
681 -/**  
682 -* FMLE/flash publish  
683 -* 4.2.6. Publish  
684 -* The client sends the publish command to publish a named stream to the  
685 -* server. Using this name, any client can play this stream and receive  
686 -* the published audio, video, and data messages.  
687 -*/  
688 -class SrsPublishPacket : public SrsPacket  
689 -{  
690 -private:  
691 - typedef SrsPacket super;  
692 -protected:  
693 - virtual const char* get_class_name()  
694 - {  
695 - return CLASS_NAME_STRING(SrsPublishPacket);  
696 - }  
697 -public:  
698 - std::string command_name;  
699 - double transaction_id;  
700 - SrsAmf0Null* command_object;  
701 - std::string stream_name;  
702 - // optional, default to live.  
703 - std::string type;  
704 -public:  
705 - SrsPublishPacket();  
706 - virtual ~SrsPublishPacket();  
707 -public:  
708 - virtual int decode(SrsStream* stream);  
709 -public:  
710 - virtual int get_perfer_cid();  
711 -public:  
712 - virtual int get_message_type();  
713 -protected:  
714 - virtual int get_size();  
715 - virtual int encode_packet(SrsStream* stream);  
716 -};  
717 -  
718 -/**  
719 -* 4.2.8. pause  
720 -* The client sends the pause command to tell the server to pause or  
721 -* start playing.  
722 -*/  
723 -class SrsPausePacket : public SrsPacket  
724 -{  
725 -private:  
726 - typedef SrsPacket super;  
727 -protected:  
728 - virtual const char* get_class_name()  
729 - {  
730 - return CLASS_NAME_STRING(SrsPausePacket);  
731 - }  
732 -public:  
733 - std::string command_name;  
734 - double transaction_id;  
735 - SrsAmf0Null* command_object;  
736 - bool is_pause;  
737 - double time_ms;  
738 -public:  
739 - SrsPausePacket();  
740 - virtual ~SrsPausePacket();  
741 -public:  
742 - virtual int decode(SrsStream* stream);  
743 -};  
744 -  
745 -/**  
746 -* 4.2.1. play  
747 -* The client sends this command to the server to play a stream.  
748 -*/  
749 -class SrsPlayPacket : public SrsPacket  
750 -{  
751 -private:  
752 - typedef SrsPacket super;  
753 -protected:  
754 - virtual const char* get_class_name()  
755 - {  
756 - return CLASS_NAME_STRING(SrsPlayPacket);  
757 - }  
758 -public:  
759 - std::string command_name;  
760 - double transaction_id;  
761 - SrsAmf0Null* command_object;  
762 - std::string stream_name;  
763 - double start;  
764 - double duration;  
765 - bool reset;  
766 -public:  
767 - SrsPlayPacket();  
768 - virtual ~SrsPlayPacket();  
769 -public:  
770 - virtual int decode(SrsStream* stream);  
771 -public:  
772 - virtual int get_perfer_cid();  
773 -public:  
774 - virtual int get_message_type();  
775 -protected:  
776 - virtual int get_size();  
777 - virtual int encode_packet(SrsStream* stream);  
778 -};  
779 -/**  
780 -* response for SrsPlayPacket.  
781 -* @remark, user must set the stream_id in header.  
782 -*/  
783 -class SrsPlayResPacket : public SrsPacket  
784 -{  
785 -private:  
786 - typedef SrsPacket super;  
787 -protected:  
788 - virtual const char* get_class_name()  
789 - {  
790 - return CLASS_NAME_STRING(SrsPlayResPacket);  
791 - }  
792 -public:  
793 - std::string command_name;  
794 - double transaction_id;  
795 - SrsAmf0Null* command_object;  
796 - SrsAmf0Object* desc;  
797 -public:  
798 - SrsPlayResPacket();  
799 - virtual ~SrsPlayResPacket();  
800 -public:  
801 - virtual int get_perfer_cid();  
802 -public:  
803 - virtual int get_message_type();  
804 -protected:  
805 - virtual int get_size();  
806 - virtual int encode_packet(SrsStream* stream);  
807 -};  
808 -  
809 -/**  
810 -* when bandwidth test done, notice client.  
811 -*/  
812 -class SrsOnBWDonePacket : public SrsPacket  
813 -{  
814 -private:  
815 - typedef SrsPacket super;  
816 -protected:  
817 - virtual const char* get_class_name()  
818 - {  
819 - return CLASS_NAME_STRING(SrsOnBWDonePacket);  
820 - }  
821 -public:  
822 - std::string command_name;  
823 - double transaction_id;  
824 - SrsAmf0Null* args;  
825 -public:  
826 - SrsOnBWDonePacket();  
827 - virtual ~SrsOnBWDonePacket();  
828 -public:  
829 - virtual int get_perfer_cid();  
830 -public:  
831 - virtual int get_message_type();  
832 -protected:  
833 - virtual int get_size();  
834 - virtual int encode_packet(SrsStream* stream);  
835 -};  
836 -  
837 -/**  
838 -* onStatus command, AMF0 Call  
839 -* @remark, user must set the stream_id by SrsMessage.set_packet().  
840 -*/  
841 -class SrsOnStatusCallPacket : public SrsPacket  
842 -{  
843 -private:  
844 - typedef SrsPacket super;  
845 -protected:  
846 - virtual const char* get_class_name()  
847 - {  
848 - return CLASS_NAME_STRING(SrsOnStatusCallPacket);  
849 - }  
850 -public:  
851 - std::string command_name;  
852 - double transaction_id;  
853 - SrsAmf0Null* args;  
854 - SrsAmf0Object* data;  
855 -public:  
856 - SrsOnStatusCallPacket();  
857 - virtual ~SrsOnStatusCallPacket();  
858 -public:  
859 - virtual int get_perfer_cid();  
860 -public:  
861 - virtual int get_message_type();  
862 -protected:  
863 - virtual int get_size();  
864 - virtual int encode_packet(SrsStream* stream);  
865 -};  
866 -  
867 -/**  
868 -* the special packet for the bandwidth test.  
869 -* actually, it's a SrsOnStatusCallPacket, but  
870 -* 1. encode with data field, to send data to client.  
871 -* 2. decode ignore the data field, donot care.  
872 -*/  
873 -class SrsBandwidthPacket : public SrsPacket  
874 -{  
875 -private:  
876 - typedef SrsPacket super;  
877 - disable_default_copy(SrsBandwidthPacket);  
878 -protected:  
879 - virtual const char* get_class_name()  
880 - {  
881 - return CLASS_NAME_STRING(SrsBandwidthPacket);  
882 - }  
883 -public:  
884 - std::string command_name;  
885 - double transaction_id;  
886 - SrsAmf0Null* args;  
887 - SrsAmf0Object* data;  
888 -public:  
889 - SrsBandwidthPacket();  
890 - virtual ~SrsBandwidthPacket();  
891 -public:  
892 - virtual int get_perfer_cid();  
893 -public:  
894 - virtual int get_message_type();  
895 -protected:  
896 - virtual int get_size();  
897 - virtual int encode_packet(SrsStream* stream);  
898 -public:  
899 - virtual int decode(SrsStream* stream);  
900 -public:  
901 - virtual bool is_starting_play();  
902 - virtual bool is_stopped_play();  
903 - virtual bool is_starting_publish();  
904 - virtual bool is_stopped_publish();  
905 - virtual bool is_flash_final();  
906 - static SrsBandwidthPacket* create_finish();  
907 - static SrsBandwidthPacket* create_start_play();  
908 - static SrsBandwidthPacket* create_playing();  
909 - static SrsBandwidthPacket* create_stop_play();  
910 - static SrsBandwidthPacket* create_start_publish();  
911 - static SrsBandwidthPacket* create_stop_publish();  
912 -private:  
913 - virtual SrsBandwidthPacket* set_command(std::string command);  
914 -};  
915 -  
916 -/**  
917 -* onStatus data, AMF0 Data  
918 -* @remark, user must set the stream_id by SrsMessage.set_packet().  
919 -*/  
920 -class SrsOnStatusDataPacket : public SrsPacket  
921 -{  
922 -private:  
923 - typedef SrsPacket super;  
924 -protected:  
925 - virtual const char* get_class_name()  
926 - {  
927 - return CLASS_NAME_STRING(SrsOnStatusDataPacket);  
928 - }  
929 -public:  
930 - std::string command_name;  
931 - SrsAmf0Object* data;  
932 -public:  
933 - SrsOnStatusDataPacket();  
934 - virtual ~SrsOnStatusDataPacket();  
935 -public:  
936 - virtual int get_perfer_cid();  
937 -public:  
938 - virtual int get_message_type();  
939 -protected:  
940 - virtual int get_size();  
941 - virtual int encode_packet(SrsStream* stream);  
942 -};  
943 -  
944 -/**  
945 -* AMF0Data RtmpSampleAccess  
946 -* @remark, user must set the stream_id by SrsMessage.set_packet().  
947 -*/  
948 -class SrsSampleAccessPacket : public SrsPacket  
949 -{  
950 -private:  
951 - typedef SrsPacket super;  
952 -protected:  
953 - virtual const char* get_class_name()  
954 - {  
955 - return CLASS_NAME_STRING(SrsSampleAccessPacket);  
956 - }  
957 -public:  
958 - std::string command_name;  
959 - bool video_sample_access;  
960 - bool audio_sample_access;  
961 -public:  
962 - SrsSampleAccessPacket();  
963 - virtual ~SrsSampleAccessPacket();  
964 -public:  
965 - virtual int get_perfer_cid();  
966 -public:  
967 - virtual int get_message_type();  
968 -protected:  
969 - virtual int get_size();  
970 - virtual int encode_packet(SrsStream* stream);  
971 -};  
972 -  
973 -/**  
974 -* the stream metadata.  
975 -* FMLE: @setDataFrame  
976 -* others: onMetaData  
977 -*/  
978 -class SrsOnMetaDataPacket : public SrsPacket  
979 -{  
980 -private:  
981 - typedef SrsPacket super;  
982 -protected:  
983 - virtual const char* get_class_name()  
984 - {  
985 - return CLASS_NAME_STRING(SrsOnMetaDataPacket);  
986 - }  
987 -public:  
988 - std::string name;  
989 - SrsAmf0Object* metadata;  
990 -public:  
991 - SrsOnMetaDataPacket();  
992 - virtual ~SrsOnMetaDataPacket();  
993 -public:  
994 - virtual int decode(SrsStream* stream);  
995 -public:  
996 - virtual int get_perfer_cid();  
997 -public:  
998 - virtual int get_message_type();  
999 -protected:  
1000 - virtual int get_size();  
1001 - virtual int encode_packet(SrsStream* stream);  
1002 -};  
1003 -  
1004 -/**  
1005 -* 5.5. Window Acknowledgement Size (5)  
1006 -* The client or the server sends this message to inform the peer which  
1007 -* window size to use when sending acknowledgment.  
1008 -*/  
1009 -class SrsSetWindowAckSizePacket : public SrsPacket  
1010 -{  
1011 -private:  
1012 - typedef SrsPacket super;  
1013 -protected:  
1014 - virtual const char* get_class_name()  
1015 - {  
1016 - return CLASS_NAME_STRING(SrsSetWindowAckSizePacket);  
1017 - }  
1018 -public:  
1019 - int32_t ackowledgement_window_size;  
1020 -public:  
1021 - SrsSetWindowAckSizePacket();  
1022 - virtual ~SrsSetWindowAckSizePacket();  
1023 -public:  
1024 - virtual int decode(SrsStream* stream);  
1025 -public:  
1026 - virtual int get_perfer_cid();  
1027 -public:  
1028 - virtual int get_message_type();  
1029 -protected:  
1030 - virtual int get_size();  
1031 - virtual int encode_packet(SrsStream* stream);  
1032 -};  
1033 -  
1034 -/**  
1035 -* 5.3. Acknowledgement (3)  
1036 -* The client or the server sends the acknowledgment to the peer after  
1037 -* receiving bytes equal to the window size.  
1038 -*/  
1039 -class SrsAcknowledgementPacket : public SrsPacket  
1040 -{  
1041 -private:  
1042 - typedef SrsPacket super;  
1043 -protected:  
1044 - virtual const char* get_class_name()  
1045 - {  
1046 - return CLASS_NAME_STRING(SrsAcknowledgementPacket);  
1047 - }  
1048 -public:  
1049 - int32_t sequence_number;  
1050 -public:  
1051 - SrsAcknowledgementPacket();  
1052 - virtual ~SrsAcknowledgementPacket();  
1053 -public:  
1054 - virtual int get_perfer_cid();  
1055 -public:  
1056 - virtual int get_message_type();  
1057 -protected:  
1058 - virtual int get_size();  
1059 - virtual int encode_packet(SrsStream* stream);  
1060 -};  
1061 -  
1062 -/**  
1063 -* 7.1. Set Chunk Size  
1064 -* Protocol control message 1, Set Chunk Size, is used to notify the  
1065 -* peer about the new maximum chunk size.  
1066 -*/  
1067 -class SrsSetChunkSizePacket : public SrsPacket  
1068 -{  
1069 -private:  
1070 - typedef SrsPacket super;  
1071 -protected:  
1072 - virtual const char* get_class_name()  
1073 - {  
1074 - return CLASS_NAME_STRING(SrsSetChunkSizePacket);  
1075 - }  
1076 -public:  
1077 - int32_t chunk_size;  
1078 -public:  
1079 - SrsSetChunkSizePacket();  
1080 - virtual ~SrsSetChunkSizePacket();  
1081 -public:  
1082 - virtual int decode(SrsStream* stream);  
1083 -public:  
1084 - virtual int get_perfer_cid();  
1085 -public:  
1086 - virtual int get_message_type();  
1087 -protected:  
1088 - virtual int get_size();  
1089 - virtual int encode_packet(SrsStream* stream);  
1090 -};  
1091 -  
1092 -/**  
1093 -* 5.6. Set Peer Bandwidth (6)  
1094 -* The client or the server sends this message to update the output  
1095 -* bandwidth of the peer.  
1096 -*/  
1097 -class SrsSetPeerBandwidthPacket : public SrsPacket  
1098 -{  
1099 -private:  
1100 - typedef SrsPacket super;  
1101 -protected:  
1102 - virtual const char* get_class_name()  
1103 - {  
1104 - return CLASS_NAME_STRING(SrsSetPeerBandwidthPacket);  
1105 - }  
1106 -public:  
1107 - int32_t bandwidth;  
1108 - int8_t type;  
1109 -public:  
1110 - SrsSetPeerBandwidthPacket();  
1111 - virtual ~SrsSetPeerBandwidthPacket();  
1112 -public:  
1113 - virtual int get_perfer_cid();  
1114 -public:  
1115 - virtual int get_message_type();  
1116 -protected:  
1117 - virtual int get_size();  
1118 - virtual int encode_packet(SrsStream* stream);  
1119 -};  
1120 -  
1121 -// 3.7. User Control message  
1122 -enum SrcPCUCEventType  
1123 -{  
1124 - // generally, 4bytes event-data  
1125 - SrcPCUCStreamBegin = 0x00,  
1126 - SrcPCUCStreamEOF = 0x01,  
1127 - SrcPCUCStreamDry = 0x02,  
1128 - SrcPCUCSetBufferLength = 0x03, // 8bytes event-data  
1129 - SrcPCUCStreamIsRecorded = 0x04,  
1130 - SrcPCUCPingRequest = 0x06,  
1131 - SrcPCUCPingResponse = 0x07,  
1132 -};  
1133 -  
1134 -/**  
1135 -* for the EventData is 4bytes.  
1136 -* Stream Begin(=0) 4-bytes stream ID  
1137 -* Stream EOF(=1) 4-bytes stream ID  
1138 -* StreamDry(=2) 4-bytes stream ID  
1139 -* SetBufferLength(=3) 8-bytes 4bytes stream ID, 4bytes buffer length.  
1140 -* StreamIsRecorded(=4) 4-bytes stream ID  
1141 -* PingRequest(=6) 4-bytes timestamp local server time  
1142 -* PingResponse(=7) 4-bytes timestamp received ping request.  
1143 -*  
1144 -* 3.7. User Control message  
1145 -* +------------------------------+-------------------------  
1146 -* | Event Type ( 2- bytes ) | Event Data  
1147 -* +------------------------------+-------------------------  
1148 -* Figure 5 Pay load for the ‘User Control Message’.  
1149 -*/  
1150 -class SrsUserControlPacket : public SrsPacket  
1151 -{  
1152 -private:  
1153 - typedef SrsPacket super;  
1154 -protected:  
1155 - virtual const char* get_class_name()  
1156 - {  
1157 - return CLASS_NAME_STRING(SrsUserControlPacket);  
1158 - }  
1159 -public:  
1160 - // @see: SrcPCUCEventType  
1161 - int16_t event_type;  
1162 - int32_t event_data;  
1163 - /**  
1164 - * 4bytes if event_type is SetBufferLength; otherwise 0.  
1165 - */  
1166 - int32_t extra_data;  
1167 -public:  
1168 - SrsUserControlPacket();  
1169 - virtual ~SrsUserControlPacket();  
1170 -public:  
1171 - virtual int decode(SrsStream* stream);  
1172 -public:  
1173 - virtual int get_perfer_cid();  
1174 -public:  
1175 - virtual int get_message_type();  
1176 -protected:  
1177 - virtual int get_size();  
1178 - virtual int encode_packet(SrsStream* stream);  
1179 -};  
1180 -  
1181 -/**  
1182 -* expect a specified message, drop others util got specified one.  
1183 -* @pmsg, user must free it. NULL if not success.  
1184 -* @ppacket, store in the pmsg, user must never free it. NULL if not success.  
1185 -* @remark, only when success, user can use and must free the pmsg/ppacket.  
1186 -*/  
1187 -template<class T>  
1188 -int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T** ppacket)  
1189 -{  
1190 - *pmsg = NULL;  
1191 - *ppacket = NULL;  
1192 -  
1193 - int ret = ERROR_SUCCESS;  
1194 -  
1195 - while (true) {  
1196 - SrsCommonMessage* msg = NULL;  
1197 - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) {  
1198 - srs_error("recv message failed. ret=%d", ret);  
1199 - return ret;  
1200 - }  
1201 - srs_verbose("recv message success.");  
1202 -  
1203 - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) {  
1204 - delete msg;  
1205 - srs_error("decode message failed. ret=%d", ret);  
1206 - return ret;  
1207 - }  
1208 -  
1209 - T* pkt = dynamic_cast<T*>(msg->get_packet());  
1210 - if (!pkt) {  
1211 - delete msg;  
1212 - srs_trace("drop message(type=%d, size=%d, time=%"PRId64", sid=%d).",  
1213 - msg->header.message_type, msg->header.payload_length,  
1214 - msg->header.timestamp, msg->header.stream_id);  
1215 - continue;  
1216 - }  
1217 -  
1218 - *pmsg = msg;  
1219 - *ppacket = pkt;  
1220 - break;  
1221 - }  
1222 -  
1223 - return ret;  
1224 -}  
1225 - 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_CORE_PROTOCOL_HPP
  25 +#define SRS_CORE_PROTOCOL_HPP
  26 +
  27 +/*
  28 +#include <srs_core_protocol.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <map>
  34 +#include <string>
  35 +
  36 +#include <srs_core_log.hpp>
  37 +#include <srs_core_error.hpp>
  38 +
  39 +// the following is the timeout for rtmp protocol,
  40 +// to avoid death connection.
  41 +
  42 +// when got a messae header, there must be some data,
  43 +// increase recv timeout to got an entire message.
  44 +#define SRS_MIN_RECV_TIMEOUT_US 60*1000*1000L
  45 +
  46 +// the timeout to wait for client control message,
  47 +// if timeout, we generally ignore and send the data to client,
  48 +// generally, it's the pulse time for data seding.
  49 +#define SRS_PULSE_TIMEOUT_US 200*1000L
  50 +
  51 +// the timeout to wait client data,
  52 +// if timeout, close the connection.
  53 +#define SRS_SEND_TIMEOUT_US 30*1000*1000L
  54 +
  55 +// the timeout to send data to client,
  56 +// if timeout, close the connection.
  57 +#define SRS_RECV_TIMEOUT_US 30*1000*1000L
  58 +
  59 +// the timeout to wait client data, when client paused
  60 +// if timeout, close the connection.
  61 +#define SRS_PAUSED_SEND_TIMEOUT_US 30*60*1000*1000L
  62 +
  63 +// the timeout to send data to client, when client paused
  64 +// if timeout, close the connection.
  65 +#define SRS_PAUSED_RECV_TIMEOUT_US 30*60*1000*1000L
  66 +
  67 +// when stream is busy, for example, streaming is already
  68 +// publishing, when a new client to request to publish,
  69 +// sleep a while and close the connection.
  70 +#define SRS_STREAM_BUSY_SLEEP_US 3*1000*1000L
  71 +
  72 +// when error, forwarder sleep for a while and retry.
  73 +#define SRS_FORWARDER_SLEEP_US 3*1000*1000L
  74 +
  75 +// when error, encoder sleep for a while and retry.
  76 +#define SRS_ENCODER_SLEEP_US 3*1000*1000L
  77 +
  78 +class SrsSocket;
  79 +class SrsBuffer;
  80 +class SrsPacket;
  81 +class SrsStream;
  82 +class SrsCommonMessage;
  83 +class SrsChunkStream;
  84 +class SrsAmf0Object;
  85 +class SrsAmf0Null;
  86 +class SrsAmf0Undefined;
  87 +class ISrsMessage;
  88 +
  89 +// convert class name to string.
  90 +#define CLASS_NAME_STRING(className) #className
  91 +
  92 +/**
  93 +* max rtmp header size:
  94 +* 1bytes basic header,
  95 +* 11bytes message header,
  96 +* 4bytes timestamp header,
  97 +* that is, 1+11+4=16bytes.
  98 +*/
  99 +#define RTMP_MAX_FMT0_HEADER_SIZE 16
  100 +/**
  101 +* max rtmp header size:
  102 +* 1bytes basic header,
  103 +* 4bytes timestamp header,
  104 +* that is, 1+4=5bytes.
  105 +*/
  106 +#define RTMP_MAX_FMT3_HEADER_SIZE 5
  107 +
  108 +/**
  109 +* the protocol provides the rtmp-message-protocol services,
  110 +* to recv RTMP message from RTMP chunk stream,
  111 +* and to send out RTMP message over RTMP chunk stream.
  112 +*/
  113 +class SrsProtocol
  114 +{
  115 +private:
  116 + struct AckWindowSize
  117 + {
  118 + int ack_window_size;
  119 + int64_t acked_size;
  120 +
  121 + AckWindowSize();
  122 + };
  123 +// peer in/out
  124 +private:
  125 + st_netfd_t stfd;
  126 + SrsSocket* skt;
  127 + char* pp;
  128 + /**
  129 + * requests sent out, used to build the response.
  130 + * key: transactionId
  131 + * value: the request command name
  132 + */
  133 + std::map<double, std::string> requests;
  134 +// peer in
  135 +private:
  136 + std::map<int, SrsChunkStream*> chunk_streams;
  137 + SrsBuffer* buffer;
  138 + int32_t in_chunk_size;
  139 + AckWindowSize in_ack_size;
  140 +// peer out
  141 +private:
  142 + char out_header_fmt0[RTMP_MAX_FMT0_HEADER_SIZE];
  143 + char out_header_fmt3[RTMP_MAX_FMT3_HEADER_SIZE];
  144 + int32_t out_chunk_size;
  145 +public:
  146 + SrsProtocol(st_netfd_t client_stfd);
  147 + virtual ~SrsProtocol();
  148 +public:
  149 + std::string get_request_name(double transcationId);
  150 + /**
  151 + * set the timeout in us.
  152 + * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT.
  153 + */
  154 + virtual void set_recv_timeout(int64_t timeout_us);
  155 + virtual int64_t get_recv_timeout();
  156 + virtual void set_send_timeout(int64_t timeout_us);
  157 + virtual int64_t get_send_timeout();
  158 + virtual int64_t get_recv_bytes();
  159 + virtual int64_t get_send_bytes();
  160 + virtual int get_recv_kbps();
  161 + virtual int get_send_kbps();
  162 + /**
  163 + * recv a message with raw/undecoded payload from peer.
  164 + * the payload is not decoded, use srs_rtmp_expect_message<T> if requires
  165 + * specifies message.
  166 + * @pmsg, user must free it. NULL if not success.
  167 + * @remark, only when success, user can use and must free the pmsg.
  168 + */
  169 + virtual int recv_message(SrsCommonMessage** pmsg);
  170 + /**
  171 + * send out message with encoded payload to peer.
  172 + * use the message encode method to encode to payload,
  173 + * then sendout over socket.
  174 + * @msg this method will free it whatever return value.
  175 + */
  176 + virtual int send_message(ISrsMessage* msg);
  177 +private:
  178 + /**
  179 + * when recv message, update the context.
  180 + */
  181 + virtual int on_recv_message(SrsCommonMessage* msg);
  182 + virtual int response_acknowledgement_message();
  183 + virtual int response_ping_message(int32_t timestamp);
  184 + /**
  185 + * when message sentout, update the context.
  186 + */
  187 + virtual int on_send_message(ISrsMessage* msg);
  188 + /**
  189 + * try to recv interlaced message from peer,
  190 + * return error if error occur and nerver set the pmsg,
  191 + * return success and pmsg set to NULL if no entire message got,
  192 + * return success and pmsg set to entire message if got one.
  193 + */
  194 + virtual int recv_interlaced_message(SrsCommonMessage** pmsg);
  195 + /**
  196 + * read the chunk basic header(fmt, cid) from chunk stream.
  197 + * user can discovery a SrsChunkStream by cid.
  198 + * @bh_size return the chunk basic header size, to remove the used bytes when finished.
  199 + */
  200 + virtual int read_basic_header(char& fmt, int& cid, int& bh_size);
  201 + /**
  202 + * read the chunk message header(timestamp, payload_length, message_type, stream_id)
  203 + * from chunk stream and save to SrsChunkStream.
  204 + * @mh_size return the chunk message header size, to remove the used bytes when finished.
  205 + */
  206 + virtual int read_message_header(SrsChunkStream* chunk, char fmt, int bh_size, int& mh_size);
  207 + /**
  208 + * read the chunk payload, remove the used bytes in buffer,
  209 + * if got entire message, set the pmsg.
  210 + * @payload_size read size in this roundtrip, generally a chunk size or left message size.
  211 + */
  212 + virtual int read_message_payload(SrsChunkStream* chunk, int bh_size, int mh_size, int& payload_size, SrsCommonMessage** pmsg);
  213 +};
  214 +
  215 +/**
  216 +* 4.1. Message Header
  217 +*/
  218 +struct SrsMessageHeader
  219 +{
  220 + /**
  221 + * One byte field to represent the message type. A range of type IDs
  222 + * (1-7) are reserved for protocol control messages.
  223 + */
  224 + int8_t message_type;
  225 + /**
  226 + * Three-byte field that represents the size of the payload in bytes.
  227 + * It is set in big-endian format.
  228 + */
  229 + int32_t payload_length;
  230 + /**
  231 + * Three-byte field that contains a timestamp delta of the message.
  232 + * The 4 bytes are packed in the big-endian order.
  233 + * @remark, only used for decoding message from chunk stream.
  234 + */
  235 + int32_t timestamp_delta;
  236 + /**
  237 + * Three-byte field that identifies the stream of the message. These
  238 + * bytes are set in big-endian format.
  239 + */
  240 + int32_t stream_id;
  241 +
  242 + /**
  243 + * Four-byte field that contains a timestamp of the message.
  244 + * The 4 bytes are packed in the big-endian order.
  245 + * @remark, used as calc timestamp when decode and encode time.
  246 + * @remark, we use 64bits for large time for jitter detect and hls.
  247 + */
  248 + int64_t timestamp;
  249 +
  250 + SrsMessageHeader();
  251 + virtual ~SrsMessageHeader();
  252 +
  253 + bool is_audio();
  254 + bool is_video();
  255 + bool is_amf0_command();
  256 + bool is_amf0_data();
  257 + bool is_amf3_command();
  258 + bool is_amf3_data();
  259 + bool is_window_ackledgement_size();
  260 + bool is_set_chunk_size();
  261 + bool is_user_control_message();
  262 +};
  263 +
  264 +/**
  265 +* incoming chunk stream maybe interlaced,
  266 +* use the chunk stream to cache the input RTMP chunk streams.
  267 +*/
  268 +class SrsChunkStream
  269 +{
  270 +public:
  271 + /**
  272 + * represents the basic header fmt,
  273 + * which used to identify the variant message header type.
  274 + */
  275 + char fmt;
  276 + /**
  277 + * represents the basic header cid,
  278 + * which is the chunk stream id.
  279 + */
  280 + int cid;
  281 + /**
  282 + * cached message header
  283 + */
  284 + SrsMessageHeader header;
  285 + /**
  286 + * whether the chunk message header has extended timestamp.
  287 + */
  288 + bool extended_timestamp;
  289 + /**
  290 + * partially read message.
  291 + */
  292 + SrsCommonMessage* msg;
  293 + /**
  294 + * decoded msg count, to identify whether the chunk stream is fresh.
  295 + */
  296 + int64_t msg_count;
  297 +public:
  298 + SrsChunkStream(int _cid);
  299 + virtual ~SrsChunkStream();
  300 +};
  301 +
  302 +/**
  303 +* message to output.
  304 +*/
  305 +class ISrsMessage
  306 +{
  307 +// 4.1. Message Header
  308 +public:
  309 + SrsMessageHeader header;
  310 +// 4.2. Message Payload
  311 +public:
  312 + /**
  313 + * The other part which is the payload is the actual data that is
  314 + * contained in the message. For example, it could be some audio samples
  315 + * or compressed video data. The payload format and interpretation are
  316 + * beyond the scope of this document.
  317 + */
  318 + int32_t size;
  319 + int8_t* payload;
  320 +public:
  321 + ISrsMessage();
  322 + virtual ~ISrsMessage();
  323 +public:
  324 + /**
  325 + * whether message canbe decoded.
  326 + * only update the context when message canbe decoded.
  327 + */
  328 + virtual bool can_decode() = 0;
  329 +/**
  330 +* encode functions.
  331 +*/
  332 +public:
  333 + /**
  334 + * get the perfered cid(chunk stream id) which sendout over.
  335 + */
  336 + virtual int get_perfer_cid() = 0;
  337 + /**
  338 + * encode the packet to message payload bytes.
  339 + * @remark there exists empty packet, so maybe the payload is NULL.
  340 + */
  341 + virtual int encode_packet() = 0;
  342 +};
  343 +
  344 +/**
  345 +* common RTMP message defines in rtmp.part2.Message-Formats.pdf.
  346 +* cannbe parse and decode.
  347 +*/
  348 +class SrsCommonMessage : public ISrsMessage
  349 +{
  350 +private:
  351 + typedef ISrsMessage super;
  352 + disable_default_copy(SrsCommonMessage);
  353 +// decoded message payload.
  354 +private:
  355 + SrsStream* stream;
  356 + SrsPacket* packet;
  357 +public:
  358 + SrsCommonMessage();
  359 + virtual ~SrsCommonMessage();
  360 +public:
  361 + virtual bool can_decode();
  362 +/**
  363 +* decode functions.
  364 +*/
  365 +public:
  366 + /**
  367 + * decode packet from message payload.
  368 + */
  369 + // TODO: use protocol to decode it.
  370 + virtual int decode_packet(SrsProtocol* protocol);
  371 + /**
  372 + * get the decoded packet which decoded by decode_packet().
  373 + * @remark, user never free the pkt, the message will auto free it.
  374 + */
  375 + virtual SrsPacket* get_packet();
  376 +/**
  377 +* encode functions.
  378 +*/
  379 +public:
  380 + /**
  381 + * get the perfered cid(chunk stream id) which sendout over.
  382 + */
  383 + virtual int get_perfer_cid();
  384 + /**
  385 + * set the encoded packet to encode_packet() to payload.
  386 + * @stream_id, the id of stream which is created by createStream.
  387 + * @remark, user never free the pkt, the message will auto free it.
  388 + * @return message itself.
  389 + */
  390 + // TODO: refine the send methods.
  391 + virtual SrsCommonMessage* set_packet(SrsPacket* pkt, int stream_id);
  392 + /**
  393 + * encode the packet to message payload bytes.
  394 + * @remark there exists empty packet, so maybe the payload is NULL.
  395 + */
  396 + virtual int encode_packet();
  397 +};
  398 +
  399 +/**
  400 +* shared ptr message.
  401 +* for audio/video/data message that need less memory copy.
  402 +* and only for output.
  403 +*/
  404 +class SrsSharedPtrMessage : public ISrsMessage
  405 +{
  406 +private:
  407 + typedef ISrsMessage super;
  408 +private:
  409 + struct SrsSharedPtr
  410 + {
  411 + char* payload;
  412 + int size;
  413 + int perfer_cid;
  414 + int shared_count;
  415 +
  416 + SrsSharedPtr();
  417 + virtual ~SrsSharedPtr();
  418 + };
  419 + SrsSharedPtr* ptr;
  420 +public:
  421 + SrsSharedPtrMessage();
  422 + virtual ~SrsSharedPtrMessage();
  423 +public:
  424 + virtual bool can_decode();
  425 +public:
  426 + /**
  427 + * set the shared payload.
  428 + * we will detach the payload of source,
  429 + * so ensure donot use it before.
  430 + */
  431 + virtual int initialize(SrsCommonMessage* source);
  432 + /**
  433 + * set the shared payload.
  434 + * we will use the payload, donot use the payload of source.
  435 + */
  436 + virtual int initialize(SrsCommonMessage* source, char* payload, int size);
  437 + virtual SrsSharedPtrMessage* copy();
  438 +public:
  439 + /**
  440 + * get the perfered cid(chunk stream id) which sendout over.
  441 + */
  442 + virtual int get_perfer_cid();
  443 + /**
  444 + * ignored.
  445 + * for shared message, nothing should be done.
  446 + * use initialize() to set the data.
  447 + */
  448 + virtual int encode_packet();
  449 +};
  450 +
  451 +/**
  452 +* the decoded message payload.
  453 +* @remark we seperate the packet from message,
  454 +* for the packet focus on logic and domain data,
  455 +* the message bind to the protocol and focus on protocol, such as header.
  456 +* we can merge the message and packet, using OOAD hierachy, packet extends from message,
  457 +* it's better for me to use components -- the message use the packet as payload.
  458 +*/
  459 +class SrsPacket
  460 +{
  461 +protected:
  462 + /**
  463 + * subpacket must override to provide the right class name.
  464 + */
  465 + virtual const char* get_class_name()
  466 + {
  467 + return CLASS_NAME_STRING(SrsPacket);
  468 + }
  469 +public:
  470 + SrsPacket();
  471 + virtual ~SrsPacket();
  472 +/**
  473 +* decode functions.
  474 +*/
  475 +public:
  476 + /**
  477 + * subpacket must override to decode packet from stream.
  478 + * @remark never invoke the super.decode, it always failed.
  479 + */
  480 + virtual int decode(SrsStream* stream);
  481 +/**
  482 +* encode functions.
  483 +*/
  484 +public:
  485 + virtual int get_perfer_cid();
  486 + virtual int get_payload_length();
  487 +public:
  488 + /**
  489 + * subpacket must override to provide the right message type.
  490 + */
  491 + virtual int get_message_type();
  492 + /**
  493 + * the subpacket can override this encode,
  494 + * for example, video and audio will directly set the payload withou memory copy,
  495 + * other packet which need to serialize/encode to bytes by override the
  496 + * get_size and encode_packet.
  497 + */
  498 + virtual int encode(int& size, char*& payload);
  499 +protected:
  500 + /**
  501 + * subpacket can override to calc the packet size.
  502 + */
  503 + virtual int get_size();
  504 + /**
  505 + * subpacket can override to encode the payload to stream.
  506 + * @remark never invoke the super.encode_packet, it always failed.
  507 + */
  508 + virtual int encode_packet(SrsStream* stream);
  509 +};
  510 +
  511 +/**
  512 +* 4.1.1. connect
  513 +* The client sends the connect command to the server to request
  514 +* connection to a server application instance.
  515 +*/
  516 +class SrsConnectAppPacket : public SrsPacket
  517 +{
  518 +private:
  519 + typedef SrsPacket super;
  520 +protected:
  521 + virtual const char* get_class_name()
  522 + {
  523 + return CLASS_NAME_STRING(SrsConnectAppPacket);
  524 + }
  525 +public:
  526 + std::string command_name;
  527 + double transaction_id;
  528 + SrsAmf0Object* command_object;
  529 +public:
  530 + SrsConnectAppPacket();
  531 + virtual ~SrsConnectAppPacket();
  532 +public:
  533 + virtual int decode(SrsStream* stream);
  534 +public:
  535 + virtual int get_perfer_cid();
  536 +public:
  537 + virtual int get_message_type();
  538 +protected:
  539 + virtual int get_size();
  540 + virtual int encode_packet(SrsStream* stream);
  541 +};
  542 +/**
  543 +* response for SrsConnectAppPacket.
  544 +*/
  545 +class SrsConnectAppResPacket : public SrsPacket
  546 +{
  547 +private:
  548 + typedef SrsPacket super;
  549 +protected:
  550 + virtual const char* get_class_name()
  551 + {
  552 + return CLASS_NAME_STRING(SrsConnectAppResPacket);
  553 + }
  554 +public:
  555 + std::string command_name;
  556 + double transaction_id;
  557 + SrsAmf0Object* props;
  558 + SrsAmf0Object* info;
  559 +public:
  560 + SrsConnectAppResPacket();
  561 + virtual ~SrsConnectAppResPacket();
  562 +public:
  563 + virtual int decode(SrsStream* stream);
  564 +public:
  565 + virtual int get_perfer_cid();
  566 +public:
  567 + virtual int get_message_type();
  568 +protected:
  569 + virtual int get_size();
  570 + virtual int encode_packet(SrsStream* stream);
  571 +};
  572 +
  573 +/**
  574 +* 4.1.3. createStream
  575 +* The client sends this command to the server to create a logical
  576 +* channel for message communication The publishing of audio, video, and
  577 +* metadata is carried out over stream channel created using the
  578 +* createStream command.
  579 +*/
  580 +class SrsCreateStreamPacket : public SrsPacket
  581 +{
  582 +private:
  583 + typedef SrsPacket super;
  584 +protected:
  585 + virtual const char* get_class_name()
  586 + {
  587 + return CLASS_NAME_STRING(SrsCreateStreamPacket);
  588 + }
  589 +public:
  590 + std::string command_name;
  591 + double transaction_id;
  592 + SrsAmf0Null* command_object;
  593 +public:
  594 + SrsCreateStreamPacket();
  595 + virtual ~SrsCreateStreamPacket();
  596 +public:
  597 + virtual int decode(SrsStream* stream);
  598 +public:
  599 + virtual int get_perfer_cid();
  600 +public:
  601 + virtual int get_message_type();
  602 +protected:
  603 + virtual int get_size();
  604 + virtual int encode_packet(SrsStream* stream);
  605 +};
  606 +/**
  607 +* response for SrsCreateStreamPacket.
  608 +*/
  609 +class SrsCreateStreamResPacket : public SrsPacket
  610 +{
  611 +private:
  612 + typedef SrsPacket super;
  613 +protected:
  614 + virtual const char* get_class_name()
  615 + {
  616 + return CLASS_NAME_STRING(SrsCreateStreamResPacket);
  617 + }
  618 +public:
  619 + std::string command_name;
  620 + double transaction_id;
  621 + SrsAmf0Null* command_object;
  622 + double stream_id;
  623 +public:
  624 + SrsCreateStreamResPacket(double _transaction_id, double _stream_id);
  625 + virtual ~SrsCreateStreamResPacket();
  626 +public:
  627 + virtual int decode(SrsStream* stream);
  628 +public:
  629 + virtual int get_perfer_cid();
  630 +public:
  631 + virtual int get_message_type();
  632 +protected:
  633 + virtual int get_size();
  634 + virtual int encode_packet(SrsStream* stream);
  635 +};
  636 +/**
  637 +* client close stream packet.
  638 +*/
  639 +class SrsCloseStreamPacket : public SrsPacket
  640 +{
  641 +private:
  642 + typedef SrsPacket super;
  643 +protected:
  644 + virtual const char* get_class_name()
  645 + {
  646 + return CLASS_NAME_STRING(SrsCloseStreamPacket);
  647 + }
  648 +public:
  649 + std::string command_name;
  650 + double transaction_id;
  651 + SrsAmf0Null* command_object;
  652 +public:
  653 + SrsCloseStreamPacket();
  654 + virtual ~SrsCloseStreamPacket();
  655 +public:
  656 + virtual int decode(SrsStream* stream);
  657 +};
  658 +
  659 +/**
  660 +* FMLE start publish: ReleaseStream/PublishStream
  661 +*/
  662 +class SrsFMLEStartPacket : public SrsPacket
  663 +{
  664 +private:
  665 + typedef SrsPacket super;
  666 +protected:
  667 + virtual const char* get_class_name()
  668 + {
  669 + return CLASS_NAME_STRING(SrsFMLEStartPacket);
  670 + }
  671 +public:
  672 + std::string command_name;
  673 + double transaction_id;
  674 + SrsAmf0Null* command_object;
  675 + std::string stream_name;
  676 +public:
  677 + SrsFMLEStartPacket();
  678 + virtual ~SrsFMLEStartPacket();
  679 +public:
  680 + virtual int decode(SrsStream* stream);
  681 +};
  682 +/**
  683 +* response for SrsFMLEStartPacket.
  684 +*/
  685 +class SrsFMLEStartResPacket : public SrsPacket
  686 +{
  687 +private:
  688 + typedef SrsPacket super;
  689 +protected:
  690 + virtual const char* get_class_name()
  691 + {
  692 + return CLASS_NAME_STRING(SrsFMLEStartResPacket);
  693 + }
  694 +public:
  695 + std::string command_name;
  696 + double transaction_id;
  697 + SrsAmf0Null* command_object;
  698 + SrsAmf0Undefined* args;
  699 +public:
  700 + SrsFMLEStartResPacket(double _transaction_id);
  701 + virtual ~SrsFMLEStartResPacket();
  702 +public:
  703 + virtual int get_perfer_cid();
  704 +public:
  705 + virtual int get_message_type();
  706 +protected:
  707 + virtual int get_size();
  708 + virtual int encode_packet(SrsStream* stream);
  709 +};
  710 +
  711 +/**
  712 +* FMLE/flash publish
  713 +* 4.2.6. Publish
  714 +* The client sends the publish command to publish a named stream to the
  715 +* server. Using this name, any client can play this stream and receive
  716 +* the published audio, video, and data messages.
  717 +*/
  718 +class SrsPublishPacket : public SrsPacket
  719 +{
  720 +private:
  721 + typedef SrsPacket super;
  722 +protected:
  723 + virtual const char* get_class_name()
  724 + {
  725 + return CLASS_NAME_STRING(SrsPublishPacket);
  726 + }
  727 +public:
  728 + std::string command_name;
  729 + double transaction_id;
  730 + SrsAmf0Null* command_object;
  731 + std::string stream_name;
  732 + // optional, default to live.
  733 + std::string type;
  734 +public:
  735 + SrsPublishPacket();
  736 + virtual ~SrsPublishPacket();
  737 +public:
  738 + virtual int decode(SrsStream* stream);
  739 +public:
  740 + virtual int get_perfer_cid();
  741 +public:
  742 + virtual int get_message_type();
  743 +protected:
  744 + virtual int get_size();
  745 + virtual int encode_packet(SrsStream* stream);
  746 +};
  747 +
  748 +/**
  749 +* 4.2.8. pause
  750 +* The client sends the pause command to tell the server to pause or
  751 +* start playing.
  752 +*/
  753 +class SrsPausePacket : public SrsPacket
  754 +{
  755 +private:
  756 + typedef SrsPacket super;
  757 +protected:
  758 + virtual const char* get_class_name()
  759 + {
  760 + return CLASS_NAME_STRING(SrsPausePacket);
  761 + }
  762 +public:
  763 + std::string command_name;
  764 + double transaction_id;
  765 + SrsAmf0Null* command_object;
  766 + bool is_pause;
  767 + double time_ms;
  768 +public:
  769 + SrsPausePacket();
  770 + virtual ~SrsPausePacket();
  771 +public:
  772 + virtual int decode(SrsStream* stream);
  773 +};
  774 +
  775 +/**
  776 +* 4.2.1. play
  777 +* The client sends this command to the server to play a stream.
  778 +*/
  779 +class SrsPlayPacket : public SrsPacket
  780 +{
  781 +private:
  782 + typedef SrsPacket super;
  783 +protected:
  784 + virtual const char* get_class_name()
  785 + {
  786 + return CLASS_NAME_STRING(SrsPlayPacket);
  787 + }
  788 +public:
  789 + std::string command_name;
  790 + double transaction_id;
  791 + SrsAmf0Null* command_object;
  792 + std::string stream_name;
  793 + double start;
  794 + double duration;
  795 + bool reset;
  796 +public:
  797 + SrsPlayPacket();
  798 + virtual ~SrsPlayPacket();
  799 +public:
  800 + virtual int decode(SrsStream* stream);
  801 +public:
  802 + virtual int get_perfer_cid();
  803 +public:
  804 + virtual int get_message_type();
  805 +protected:
  806 + virtual int get_size();
  807 + virtual int encode_packet(SrsStream* stream);
  808 +};
  809 +/**
  810 +* response for SrsPlayPacket.
  811 +* @remark, user must set the stream_id in header.
  812 +*/
  813 +class SrsPlayResPacket : public SrsPacket
  814 +{
  815 +private:
  816 + typedef SrsPacket super;
  817 +protected:
  818 + virtual const char* get_class_name()
  819 + {
  820 + return CLASS_NAME_STRING(SrsPlayResPacket);
  821 + }
  822 +public:
  823 + std::string command_name;
  824 + double transaction_id;
  825 + SrsAmf0Null* command_object;
  826 + SrsAmf0Object* desc;
  827 +public:
  828 + SrsPlayResPacket();
  829 + virtual ~SrsPlayResPacket();
  830 +public:
  831 + virtual int get_perfer_cid();
  832 +public:
  833 + virtual int get_message_type();
  834 +protected:
  835 + virtual int get_size();
  836 + virtual int encode_packet(SrsStream* stream);
  837 +};
  838 +
  839 +/**
  840 +* when bandwidth test done, notice client.
  841 +*/
  842 +class SrsOnBWDonePacket : public SrsPacket
  843 +{
  844 +private:
  845 + typedef SrsPacket super;
  846 +protected:
  847 + virtual const char* get_class_name()
  848 + {
  849 + return CLASS_NAME_STRING(SrsOnBWDonePacket);
  850 + }
  851 +public:
  852 + std::string command_name;
  853 + double transaction_id;
  854 + SrsAmf0Null* args;
  855 +public:
  856 + SrsOnBWDonePacket();
  857 + virtual ~SrsOnBWDonePacket();
  858 +public:
  859 + virtual int get_perfer_cid();
  860 +public:
  861 + virtual int get_message_type();
  862 +protected:
  863 + virtual int get_size();
  864 + virtual int encode_packet(SrsStream* stream);
  865 +};
  866 +
  867 +/**
  868 +* onStatus command, AMF0 Call
  869 +* @remark, user must set the stream_id by SrsMessage.set_packet().
  870 +*/
  871 +class SrsOnStatusCallPacket : public SrsPacket
  872 +{
  873 +private:
  874 + typedef SrsPacket super;
  875 +protected:
  876 + virtual const char* get_class_name()
  877 + {
  878 + return CLASS_NAME_STRING(SrsOnStatusCallPacket);
  879 + }
  880 +public:
  881 + std::string command_name;
  882 + double transaction_id;
  883 + SrsAmf0Null* args;
  884 + SrsAmf0Object* data;
  885 +public:
  886 + SrsOnStatusCallPacket();
  887 + virtual ~SrsOnStatusCallPacket();
  888 +public:
  889 + virtual int get_perfer_cid();
  890 +public:
  891 + virtual int get_message_type();
  892 +protected:
  893 + virtual int get_size();
  894 + virtual int encode_packet(SrsStream* stream);
  895 +};
  896 +
  897 +/**
  898 +* the special packet for the bandwidth test.
  899 +* actually, it's a SrsOnStatusCallPacket, but
  900 +* 1. encode with data field, to send data to client.
  901 +* 2. decode ignore the data field, donot care.
  902 +*/
  903 +class SrsBandwidthPacket : public SrsPacket
  904 +{
  905 +private:
  906 + typedef SrsPacket super;
  907 + disable_default_copy(SrsBandwidthPacket);
  908 +protected:
  909 + virtual const char* get_class_name()
  910 + {
  911 + return CLASS_NAME_STRING(SrsBandwidthPacket);
  912 + }
  913 +public:
  914 + std::string command_name;
  915 + double transaction_id;
  916 + SrsAmf0Null* args;
  917 + SrsAmf0Object* data;
  918 +public:
  919 + SrsBandwidthPacket();
  920 + virtual ~SrsBandwidthPacket();
  921 +public:
  922 + virtual int get_perfer_cid();
  923 +public:
  924 + virtual int get_message_type();
  925 +protected:
  926 + virtual int get_size();
  927 + virtual int encode_packet(SrsStream* stream);
  928 +public:
  929 + virtual int decode(SrsStream* stream);
  930 +public:
  931 + virtual bool is_starting_play();
  932 + virtual bool is_stopped_play();
  933 + virtual bool is_starting_publish();
  934 + virtual bool is_stopped_publish();
  935 + virtual bool is_flash_final();
  936 + static SrsBandwidthPacket* create_finish();
  937 + static SrsBandwidthPacket* create_start_play();
  938 + static SrsBandwidthPacket* create_playing();
  939 + static SrsBandwidthPacket* create_stop_play();
  940 + static SrsBandwidthPacket* create_start_publish();
  941 + static SrsBandwidthPacket* create_stop_publish();
  942 +private:
  943 + virtual SrsBandwidthPacket* set_command(std::string command);
  944 +};
  945 +
  946 +/**
  947 +* onStatus data, AMF0 Data
  948 +* @remark, user must set the stream_id by SrsMessage.set_packet().
  949 +*/
  950 +class SrsOnStatusDataPacket : public SrsPacket
  951 +{
  952 +private:
  953 + typedef SrsPacket super;
  954 +protected:
  955 + virtual const char* get_class_name()
  956 + {
  957 + return CLASS_NAME_STRING(SrsOnStatusDataPacket);
  958 + }
  959 +public:
  960 + std::string command_name;
  961 + SrsAmf0Object* data;
  962 +public:
  963 + SrsOnStatusDataPacket();
  964 + virtual ~SrsOnStatusDataPacket();
  965 +public:
  966 + virtual int get_perfer_cid();
  967 +public:
  968 + virtual int get_message_type();
  969 +protected:
  970 + virtual int get_size();
  971 + virtual int encode_packet(SrsStream* stream);
  972 +};
  973 +
  974 +/**
  975 +* AMF0Data RtmpSampleAccess
  976 +* @remark, user must set the stream_id by SrsMessage.set_packet().
  977 +*/
  978 +class SrsSampleAccessPacket : public SrsPacket
  979 +{
  980 +private:
  981 + typedef SrsPacket super;
  982 +protected:
  983 + virtual const char* get_class_name()
  984 + {
  985 + return CLASS_NAME_STRING(SrsSampleAccessPacket);
  986 + }
  987 +public:
  988 + std::string command_name;
  989 + bool video_sample_access;
  990 + bool audio_sample_access;
  991 +public:
  992 + SrsSampleAccessPacket();
  993 + virtual ~SrsSampleAccessPacket();
  994 +public:
  995 + virtual int get_perfer_cid();
  996 +public:
  997 + virtual int get_message_type();
  998 +protected:
  999 + virtual int get_size();
  1000 + virtual int encode_packet(SrsStream* stream);
  1001 +};
  1002 +
  1003 +/**
  1004 +* the stream metadata.
  1005 +* FMLE: @setDataFrame
  1006 +* others: onMetaData
  1007 +*/
  1008 +class SrsOnMetaDataPacket : public SrsPacket
  1009 +{
  1010 +private:
  1011 + typedef SrsPacket super;
  1012 +protected:
  1013 + virtual const char* get_class_name()
  1014 + {
  1015 + return CLASS_NAME_STRING(SrsOnMetaDataPacket);
  1016 + }
  1017 +public:
  1018 + std::string name;
  1019 + SrsAmf0Object* metadata;
  1020 +public:
  1021 + SrsOnMetaDataPacket();
  1022 + virtual ~SrsOnMetaDataPacket();
  1023 +public:
  1024 + virtual int decode(SrsStream* stream);
  1025 +public:
  1026 + virtual int get_perfer_cid();
  1027 +public:
  1028 + virtual int get_message_type();
  1029 +protected:
  1030 + virtual int get_size();
  1031 + virtual int encode_packet(SrsStream* stream);
  1032 +};
  1033 +
  1034 +/**
  1035 +* 5.5. Window Acknowledgement Size (5)
  1036 +* The client or the server sends this message to inform the peer which
  1037 +* window size to use when sending acknowledgment.
  1038 +*/
  1039 +class SrsSetWindowAckSizePacket : public SrsPacket
  1040 +{
  1041 +private:
  1042 + typedef SrsPacket super;
  1043 +protected:
  1044 + virtual const char* get_class_name()
  1045 + {
  1046 + return CLASS_NAME_STRING(SrsSetWindowAckSizePacket);
  1047 + }
  1048 +public:
  1049 + int32_t ackowledgement_window_size;
  1050 +public:
  1051 + SrsSetWindowAckSizePacket();
  1052 + virtual ~SrsSetWindowAckSizePacket();
  1053 +public:
  1054 + virtual int decode(SrsStream* stream);
  1055 +public:
  1056 + virtual int get_perfer_cid();
  1057 +public:
  1058 + virtual int get_message_type();
  1059 +protected:
  1060 + virtual int get_size();
  1061 + virtual int encode_packet(SrsStream* stream);
  1062 +};
  1063 +
  1064 +/**
  1065 +* 5.3. Acknowledgement (3)
  1066 +* The client or the server sends the acknowledgment to the peer after
  1067 +* receiving bytes equal to the window size.
  1068 +*/
  1069 +class SrsAcknowledgementPacket : public SrsPacket
  1070 +{
  1071 +private:
  1072 + typedef SrsPacket super;
  1073 +protected:
  1074 + virtual const char* get_class_name()
  1075 + {
  1076 + return CLASS_NAME_STRING(SrsAcknowledgementPacket);
  1077 + }
  1078 +public:
  1079 + int32_t sequence_number;
  1080 +public:
  1081 + SrsAcknowledgementPacket();
  1082 + virtual ~SrsAcknowledgementPacket();
  1083 +public:
  1084 + virtual int get_perfer_cid();
  1085 +public:
  1086 + virtual int get_message_type();
  1087 +protected:
  1088 + virtual int get_size();
  1089 + virtual int encode_packet(SrsStream* stream);
  1090 +};
  1091 +
  1092 +/**
  1093 +* 7.1. Set Chunk Size
  1094 +* Protocol control message 1, Set Chunk Size, is used to notify the
  1095 +* peer about the new maximum chunk size.
  1096 +*/
  1097 +class SrsSetChunkSizePacket : public SrsPacket
  1098 +{
  1099 +private:
  1100 + typedef SrsPacket super;
  1101 +protected:
  1102 + virtual const char* get_class_name()
  1103 + {
  1104 + return CLASS_NAME_STRING(SrsSetChunkSizePacket);
  1105 + }
  1106 +public:
  1107 + int32_t chunk_size;
  1108 +public:
  1109 + SrsSetChunkSizePacket();
  1110 + virtual ~SrsSetChunkSizePacket();
  1111 +public:
  1112 + virtual int decode(SrsStream* stream);
  1113 +public:
  1114 + virtual int get_perfer_cid();
  1115 +public:
  1116 + virtual int get_message_type();
  1117 +protected:
  1118 + virtual int get_size();
  1119 + virtual int encode_packet(SrsStream* stream);
  1120 +};
  1121 +
  1122 +/**
  1123 +* 5.6. Set Peer Bandwidth (6)
  1124 +* The client or the server sends this message to update the output
  1125 +* bandwidth of the peer.
  1126 +*/
  1127 +class SrsSetPeerBandwidthPacket : public SrsPacket
  1128 +{
  1129 +private:
  1130 + typedef SrsPacket super;
  1131 +protected:
  1132 + virtual const char* get_class_name()
  1133 + {
  1134 + return CLASS_NAME_STRING(SrsSetPeerBandwidthPacket);
  1135 + }
  1136 +public:
  1137 + int32_t bandwidth;
  1138 + int8_t type;
  1139 +public:
  1140 + SrsSetPeerBandwidthPacket();
  1141 + virtual ~SrsSetPeerBandwidthPacket();
  1142 +public:
  1143 + virtual int get_perfer_cid();
  1144 +public:
  1145 + virtual int get_message_type();
  1146 +protected:
  1147 + virtual int get_size();
  1148 + virtual int encode_packet(SrsStream* stream);
  1149 +};
  1150 +
  1151 +// 3.7. User Control message
  1152 +enum SrcPCUCEventType
  1153 +{
  1154 + // generally, 4bytes event-data
  1155 + SrcPCUCStreamBegin = 0x00,
  1156 + SrcPCUCStreamEOF = 0x01,
  1157 + SrcPCUCStreamDry = 0x02,
  1158 + SrcPCUCSetBufferLength = 0x03, // 8bytes event-data
  1159 + SrcPCUCStreamIsRecorded = 0x04,
  1160 + SrcPCUCPingRequest = 0x06,
  1161 + SrcPCUCPingResponse = 0x07,
  1162 +};
  1163 +
  1164 +/**
  1165 +* for the EventData is 4bytes.
  1166 +* Stream Begin(=0) 4-bytes stream ID
  1167 +* Stream EOF(=1) 4-bytes stream ID
  1168 +* StreamDry(=2) 4-bytes stream ID
  1169 +* SetBufferLength(=3) 8-bytes 4bytes stream ID, 4bytes buffer length.
  1170 +* StreamIsRecorded(=4) 4-bytes stream ID
  1171 +* PingRequest(=6) 4-bytes timestamp local server time
  1172 +* PingResponse(=7) 4-bytes timestamp received ping request.
  1173 +*
  1174 +* 3.7. User Control message
  1175 +* +------------------------------+-------------------------
  1176 +* | Event Type ( 2- bytes ) | Event Data
  1177 +* +------------------------------+-------------------------
  1178 +* Figure 5 Pay load for the ‘User Control Message’.
  1179 +*/
  1180 +class SrsUserControlPacket : public SrsPacket
  1181 +{
  1182 +private:
  1183 + typedef SrsPacket super;
  1184 +protected:
  1185 + virtual const char* get_class_name()
  1186 + {
  1187 + return CLASS_NAME_STRING(SrsUserControlPacket);
  1188 + }
  1189 +public:
  1190 + // @see: SrcPCUCEventType
  1191 + int16_t event_type;
  1192 + int32_t event_data;
  1193 + /**
  1194 + * 4bytes if event_type is SetBufferLength; otherwise 0.
  1195 + */
  1196 + int32_t extra_data;
  1197 +public:
  1198 + SrsUserControlPacket();
  1199 + virtual ~SrsUserControlPacket();
  1200 +public:
  1201 + virtual int decode(SrsStream* stream);
  1202 +public:
  1203 + virtual int get_perfer_cid();
  1204 +public:
  1205 + virtual int get_message_type();
  1206 +protected:
  1207 + virtual int get_size();
  1208 + virtual int encode_packet(SrsStream* stream);
  1209 +};
  1210 +
  1211 +/**
  1212 +* expect a specified message, drop others util got specified one.
  1213 +* @pmsg, user must free it. NULL if not success.
  1214 +* @ppacket, store in the pmsg, user must never free it. NULL if not success.
  1215 +* @remark, only when success, user can use and must free the pmsg/ppacket.
  1216 +*/
  1217 +template<class T>
  1218 +int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T** ppacket)
  1219 +{
  1220 + *pmsg = NULL;
  1221 + *ppacket = NULL;
  1222 +
  1223 + int ret = ERROR_SUCCESS;
  1224 +
  1225 + while (true) {
  1226 + SrsCommonMessage* msg = NULL;
  1227 + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) {
  1228 + srs_error("recv message failed. ret=%d", ret);
  1229 + return ret;
  1230 + }
  1231 + srs_verbose("recv message success.");
  1232 +
  1233 + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) {
  1234 + delete msg;
  1235 + srs_error("decode message failed. ret=%d", ret);
  1236 + return ret;
  1237 + }
  1238 +
  1239 + T* pkt = dynamic_cast<T*>(msg->get_packet());
  1240 + if (!pkt) {
  1241 + delete msg;
  1242 + srs_trace("drop message(type=%d, size=%d, time=%"PRId64", sid=%d).",
  1243 + msg->header.message_type, msg->header.payload_length,
  1244 + msg->header.timestamp, msg->header.stream_id);
  1245 + continue;
  1246 + }
  1247 +
  1248 + *pmsg = msg;
  1249 + *ppacket = pkt;
  1250 + break;
  1251 + }
  1252 +
  1253 + return ret;
  1254 +}
  1255 +
1226 #endif 1256 #endif