winlin

merge code

要显示太多修改。

为保证性能只显示 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 - 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 +#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 +}
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 -  
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 +#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 +
  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>  
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 +#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 +}
  30 +
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 -  
160 -#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 +#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 +
  160 +#endif
@@ -3365,4 +3365,3 @@ int SrsUserControlPacket::encode_packet(SrsStream* stream) @@ -3365,4 +3365,3 @@ int SrsUserControlPacket::encode_packet(SrsStream* stream)
3365 3365
3366 return ret; 3366 return ret;
3367 } 3367 }
3368 -  
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 -  
1256 -#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 +#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 +
  1256 +#endif