int SrsRtmpConn::stream_service_cycle() { int ret = ERROR_SUCCESS; SrsRtmpConnType type; if ((ret = rtmp->identify_client(res->stream_id, type, req->stream, req->duration)) != ERROR_SUCCESS) { srs_error("identify client failed. ret=%d", ret); return ret; } req->strip(); srs_trace("identify client success. type=%s, stream_name=%s, duration=%.2f", srs_client_type_string(type).c_str(), req->stream.c_str(), req->duration); // client is identified, set the timeout to service timeout. rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US); rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US); // set chunk size to larger. int chunk_size = _srs_config->get_chunk_size(req->vhost); if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) { srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret); return ret; } srs_trace("set chunk_size=%d success", chunk_size); // find a source to serve. SrsSource* source = NULL; if ((ret = SrsSource::find(req, &source)) != ERROR_SUCCESS) { return ret; } srs_assert(source != NULL); bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost); // check publish available // for edge, never check it, for edge use proxy mode. if (!vhost_is_edge) { if (type != SrsRtmpConnPlay && !source->can_publish()) { ret = ERROR_SYSTEM_STREAM_BUSY; srs_warn("stream %s is already publishing. ret=%d", req->get_stream_url().c_str(), ret); // to delay request st_usleep(SRS_STREAM_BUSY_SLEEP_US); return ret; } } bool enabled_cache = _srs_config->get_gop_cache(req->vhost); srs_trace("source found, url=%s, enabled_cache=%d, edge=%d", req->get_stream_url().c_str(), enabled_cache, vhost_is_edge); source->set_cache(enabled_cache); switch (type) { case SrsRtmpConnPlay: { srs_verbose("start to play stream %s.", req->stream.c_str()); if (vhost_is_edge) { if ((ret = source->on_edge_start_play()) != ERROR_SUCCESS) { srs_error("notice edge start play stream failed. ret=%d", ret); return ret; } } if ((ret = rtmp->start_play(res->stream_id)) != ERROR_SUCCESS) { srs_error("start to play stream failed. ret=%d", ret); return ret; } if ((ret = http_hooks_on_play()) != ERROR_SUCCESS) { srs_error("http hook on_play failed. ret=%d", ret); return ret; } srs_info("start to play stream %s success", req->stream.c_str()); ret = playing(source); http_hooks_on_stop(); return ret; } case SrsRtmpConnFMLEPublish: { srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); if (vhost_is_edge) { if ((ret = source->on_edge_start_publish()) != ERROR_SUCCESS) { srs_error("notice edge start publish stream failed. ret=%d", ret); return ret; } } if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) { srs_error("start to publish stream failed. ret=%d", ret); return ret; } if ((ret = http_hooks_on_publish()) != ERROR_SUCCESS) { srs_error("http hook on_publish failed. ret=%d", ret); return ret; } srs_info("start to publish stream %s success", req->stream.c_str()); ret = fmle_publish(source); // when edge, notice edge to change state. // when origin, notice all service to unpublish. if (vhost_is_edge) { source->on_edge_proxy_unpublish(); } else { source->on_unpublish(); } http_hooks_on_unpublish(); return ret; } case SrsRtmpConnFlashPublish: { srs_verbose("flash start to publish stream %s.", req->stream.c_str()); if (vhost_is_edge) { if ((ret = source->on_edge_start_publish()) != ERROR_SUCCESS) { srs_error("notice edge start publish stream failed. ret=%d", ret); return ret; } } if ((ret = rtmp->start_flash_publish(res->stream_id)) != ERROR_SUCCESS) { srs_error("flash start to publish stream failed. ret=%d", ret); return ret; } if ((ret = http_hooks_on_publish()) != ERROR_SUCCESS) { srs_error("http hook on_publish failed. ret=%d", ret); return ret; } srs_info("flash start to publish stream %s success", req->stream.c_str()); ret = flash_publish(source); // when edge, notice edge to change state. // when origin, notice all service to unpublish. if (vhost_is_edge) { source->on_edge_proxy_unpublish(); } else { source->on_unpublish(); } http_hooks_on_unpublish(); return ret; } default: { ret = ERROR_SYSTEM_CLIENT_INVALID; srs_info("invalid client type=%d. ret=%d", type, ret); return ret; } } return ret; }
int SrsRtmpConn::stream_service_cycle() { int ret = ERROR_SUCCESS; SrsRtmpConnType type; if ((ret = rtmp->identify_client(res->stream_id, type, req->stream, req->duration)) != ERROR_SUCCESS) { if (!srs_is_client_gracefully_close(ret)) { srs_error("identify client failed. ret=%d", ret); } return ret; } req->strip(); srs_trace("client identified, type=%s, stream_name=%s, duration=%.2f", srs_client_type_string(type).c_str(), req->stream.c_str(), req->duration); // client is identified, set the timeout to service timeout. rtmp->set_recv_timeout(SRS_CONSTS_RTMP_RECV_TIMEOUT_US); rtmp->set_send_timeout(SRS_CONSTS_RTMP_SEND_TIMEOUT_US); // set chunk size to larger. int chunk_size = _srs_config->get_chunk_size(req->vhost); if ((ret = rtmp->set_chunk_size(chunk_size)) != ERROR_SUCCESS) { srs_error("set chunk_size=%d failed. ret=%d", chunk_size, ret); return ret; } srs_info("set chunk_size=%d success", chunk_size); // do token traverse before serve it. bool vhost_is_edge = _srs_config->get_vhost_is_edge(req->vhost); bool edge_traverse = _srs_config->get_vhost_edge_token_traverse(req->vhost); if (vhost_is_edge && edge_traverse) { if ((ret = check_edge_token_traverse_auth()) != ERROR_SUCCESS) { srs_warn("token auth failed, ret=%d", ret); return ret; } } // find a source to serve. SrsSource* source = NULL; if ((ret = SrsSource::find(req, &source)) != ERROR_SUCCESS) { return ret; } srs_assert(source != NULL); // check ASAP, to fail it faster if invalid. if (type != SrsRtmpConnPlay && !vhost_is_edge) { // check publish available // for edge, never check it, for edge use proxy mode. if (!source->can_publish()) { ret = ERROR_SYSTEM_STREAM_BUSY; srs_warn("stream %s is already publishing. ret=%d", req->get_stream_url().c_str(), ret); // to delay request st_usleep(SRS_STREAM_BUSY_SLEEP_US); return ret; } } bool enabled_cache = _srs_config->get_gop_cache(req->vhost); srs_trace("source url=%s, ip=%s, cache=%d, is_edge=%d, source_id=%d[%d]", req->get_stream_url().c_str(), ip.c_str(), enabled_cache, vhost_is_edge, source->source_id(), source->source_id()); source->set_cache(enabled_cache); switch (type) { case SrsRtmpConnPlay: { srs_verbose("start to play stream %s.", req->stream.c_str()); if (vhost_is_edge) { // notice edge to start for the first client. if ((ret = source->on_edge_start_play()) != ERROR_SUCCESS) { srs_error("notice edge start play stream failed. ret=%d", ret); return ret; } } // response connection start play if ((ret = rtmp->start_play(res->stream_id)) != ERROR_SUCCESS) { srs_error("start to play stream failed. ret=%d", ret); return ret; } if ((ret = http_hooks_on_play()) != ERROR_SUCCESS) { srs_error("http hook on_play failed. ret=%d", ret); return ret; } srs_info("start to play stream %s success", req->stream.c_str()); ret = playing(source); http_hooks_on_stop(); return ret; } case SrsRtmpConnFMLEPublish: { srs_verbose("FMLE start to publish stream %s.", req->stream.c_str()); if (vhost_is_edge) { if ((ret = source->on_edge_start_publish()) != ERROR_SUCCESS) { srs_error("notice edge start publish stream failed. ret=%d", ret); return ret; } } if ((ret = rtmp->start_fmle_publish(res->stream_id)) != ERROR_SUCCESS) { srs_error("start to publish stream failed. ret=%d", ret); return ret; } if (!vhost_is_edge) { if ((ret = source->acquire_publish()) != ERROR_SUCCESS) { return ret; } } ret = fmle_publishing(source); if (!vhost_is_edge) { source->release_publish(); } return ret; } case SrsRtmpConnFlashPublish: { srs_verbose("flash start to publish stream %s.", req->stream.c_str()); if (vhost_is_edge) { if ((ret = source->on_edge_start_publish()) != ERROR_SUCCESS) { srs_error("notice edge start publish stream failed. ret=%d", ret); return ret; } } if ((ret = rtmp->start_flash_publish(res->stream_id)) != ERROR_SUCCESS) { srs_error("flash start to publish stream failed. ret=%d", ret); return ret; } if (!vhost_is_edge) { if ((ret = source->acquire_publish()) != ERROR_SUCCESS) { return ret; } } ret = flash_publishing(source); if (!vhost_is_edge) { source->release_publish(); } return ret; } default: { ret = ERROR_SYSTEM_CLIENT_INVALID; srs_info("invalid client type=%d. ret=%d", type, ret); return ret; } } return ret; }