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