int SrsRtmpServer::connect_app(SrsRequest* req) { int ret = ERROR_SUCCESS; SrsMessage* msg = NULL; SrsConnectAppPacket* pkt = NULL; if ((ret = expect_message<SrsConnectAppPacket>(&msg, &pkt)) != ERROR_SUCCESS) { srs_error("expect connect app message failed. ret=%d", ret); return ret; } SrsAutoFree(SrsMessage, msg); SrsAutoFree(SrsConnectAppPacket, pkt); srs_info("get connect app message"); SrsAmf0Any* prop = NULL; if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { ret = ERROR_RTMP_REQ_CONNECT; srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); return ret; } req->tcUrl = prop->to_str(); if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { req->pageUrl = prop->to_str(); } if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { req->swfUrl = prop->to_str(); } if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { req->objectEncoding = prop->to_number(); } if (pkt->args) { srs_freep(req->args); req->args = pkt->args->copy()->to_object(); srs_info("copy edge traverse to origin auth args."); } srs_info("get connect app message params success."); srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->port, req->param); req->strip(); return ret; }
int SrsRtmpServer::connect_app(SrsRequest* req) { int ret = ERROR_SUCCESS; SrsMessage* msg = NULL; SrsConnectAppPacket* pkt = NULL; if ((ret = srs_rtmp_expect_message<SrsConnectAppPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { srs_error("expect connect app message failed. ret=%d", ret); return ret; } SrsAutoFree(SrsMessage, msg, false); SrsAutoFree(SrsConnectAppPacket, pkt, false); srs_info("get connect app message"); SrsAmf0Any* prop = NULL; if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { ret = ERROR_RTMP_REQ_CONNECT; srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); return ret; } req->tcUrl = prop->to_str(); if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { req->pageUrl = prop->to_str(); } if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { req->swfUrl = prop->to_str(); } if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { req->objectEncoding = prop->to_number(); } srs_info("get connect app message params success."); return req->discovery_app(); }
int SrsRtmpClient::connect_app2( string app, string tc_url, SrsRequest* req, bool debug_srs_upnode, string& srs_server_ip, string& srs_server, string& srs_primary_authors, string& srs_version, int& srs_id, int& srs_pid ){ int ret = ERROR_SUCCESS; // Connect(vhost, app) if (true) { SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); pkt->command_object->set("flashVer", SrsAmf0Any::str("WIN 12,0,0,41")); if (req) { pkt->command_object->set("swfUrl", SrsAmf0Any::str(req->swfUrl.c_str())); } else { pkt->command_object->set("swfUrl", SrsAmf0Any::str()); } pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); pkt->command_object->set("fpad", SrsAmf0Any::boolean(false)); pkt->command_object->set("capabilities", SrsAmf0Any::number(239)); pkt->command_object->set("audioCodecs", SrsAmf0Any::number(3575)); pkt->command_object->set("videoCodecs", SrsAmf0Any::number(252)); pkt->command_object->set("videoFunction", SrsAmf0Any::number(1)); if (req) { pkt->command_object->set("pageUrl", SrsAmf0Any::str(req->pageUrl.c_str())); } else { pkt->command_object->set("pageUrl", SrsAmf0Any::str()); } pkt->command_object->set("objectEncoding", SrsAmf0Any::number(0)); // @see https://github.com/winlinvip/simple-rtmp-server/issues/160 // the debug_srs_upnode is config in vhost and default to true. if (debug_srs_upnode && req && req->args) { srs_freep(pkt->args); pkt->args = req->args->copy()->to_object(); } if ((ret = protocol->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { return ret; } } // Set Window Acknowledgement size(2500000) if (true) { SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); pkt->ackowledgement_window_size = 2500000; if ((ret = protocol->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { return ret; } } // expect connect _result SrsMessage* msg = NULL; SrsConnectAppResPacket* pkt = NULL; if ((ret = expect_message<SrsConnectAppResPacket>(&msg, &pkt)) != ERROR_SUCCESS) { srs_error("expect connect app response message failed. ret=%d", ret); return ret; } SrsAutoFree(SrsMessage, msg); SrsAutoFree(SrsConnectAppResPacket, pkt); // server info SrsAmf0Any* data = pkt->info->get_property("data"); if (data && data->is_ecma_array()) { SrsAmf0EcmaArray* arr = data->to_ecma_array(); SrsAmf0Any* prop = NULL; if ((prop = arr->ensure_property_string("srs_primary_authors")) != NULL) { srs_primary_authors = prop->to_str(); } if ((prop = arr->ensure_property_string("srs_version")) != NULL) { srs_version = prop->to_str(); } if ((prop = arr->ensure_property_string("srs_server_ip")) != NULL) { srs_server_ip = prop->to_str(); } if ((prop = arr->ensure_property_string("srs_server")) != NULL) { srs_server = prop->to_str(); } if ((prop = arr->ensure_property_number("srs_id")) != NULL) { srs_id = (int)prop->to_number(); } if ((prop = arr->ensure_property_number("srs_pid")) != NULL) { srs_pid = (int)prop->to_number(); } } srs_trace("connected, version=%s, ip=%s, pid=%d, id=%d, dsu=%d", srs_version.c_str(), srs_server_ip.c_str(), srs_pid, srs_id, debug_srs_upnode); return ret; }
// TODO: return detail message when error for client. int SrsRtmpConn::do_cycle() { int ret = ERROR_SUCCESS; srs_trace("RTMP client ip=%s", ip.c_str()); rtmp->set_recv_timeout(SRS_CONSTS_RTMP_RECV_TIMEOUT_US); rtmp->set_send_timeout(SRS_CONSTS_RTMP_SEND_TIMEOUT_US); if ((ret = rtmp->handshake()) != ERROR_SUCCESS) { srs_error("rtmp handshake failed. ret=%d", ret); return ret; } srs_verbose("rtmp handshake success"); if ((ret = rtmp->connect_app(req)) != ERROR_SUCCESS) { srs_error("rtmp connect vhost/app failed. ret=%d", ret); return ret; } srs_verbose("rtmp connect app success"); // discovery vhost, resolve the vhost from config SrsConfDirective* parsed_vhost = _srs_config->get_vhost(req->vhost); if (parsed_vhost) { req->vhost = parsed_vhost->arg0(); } srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str()); if (req->schema.empty() || req->vhost.empty() || req->port.empty() || req->app.empty()) { ret = ERROR_RTMP_REQ_TCURL; srs_error("discovery tcUrl failed. " "tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d", req->tcUrl.c_str(), req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str(), ret); return ret; } // check vhost if ((ret = check_vhost()) != ERROR_SUCCESS) { srs_error("check vhost failed. ret=%d", ret); return ret; } srs_verbose("check vhost success."); srs_trace("connect app, " "tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, args=%s", req->tcUrl.c_str(), req->pageUrl.c_str(), req->swfUrl.c_str(), req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), req->app.c_str(), (req->args? "(obj)":"null")); // show client identity if(req->args) { std::string srs_version; std::string srs_server_ip; int srs_pid = 0; int srs_id = 0; SrsAmf0Any* prop = NULL; if ((prop = req->args->ensure_property_string("srs_version")) != NULL) { srs_version = prop->to_str(); } if ((prop = req->args->ensure_property_string("srs_server_ip")) != NULL) { srs_server_ip = prop->to_str(); } if ((prop = req->args->ensure_property_number("srs_pid")) != NULL) { srs_pid = (int)prop->to_number(); } if ((prop = req->args->ensure_property_number("srs_id")) != NULL) { srs_id = (int)prop->to_number(); } srs_info("edge-srs ip=%s, version=%s, pid=%d, id=%d", srs_server_ip.c_str(), srs_version.c_str(), srs_pid, srs_id); if (srs_pid > 0) { srs_trace("edge-srs ip=%s, version=%s, pid=%d, id=%d", srs_server_ip.c_str(), srs_version.c_str(), srs_pid, srs_id); } } ret = service_cycle(); http_hooks_on_close(); return ret; }
VOID TEST(AMF0Test, ApiAnyIO) { SrsStream s; SrsAmf0Any* o = NULL; char buf[1024]; memset(buf, 0, sizeof(buf)); EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); // object eof if (true) { s.reset(); s.current()[2] = 0x09; o = SrsAmf0Any::object_eof(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_EQ(3, s.pos()); s.reset(); s.current()[0] = 0x01; EXPECT_NE(ERROR_SUCCESS, o->read(&s)); } if (true) { s.reset(); o = SrsAmf0Any::object_eof(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_EQ(3, s.pos()); s.skip(-3); EXPECT_EQ(0x09, s.read_3bytes()); } // string if (true) { s.reset(); o = SrsAmf0Any::str("winlin"); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(2, s.read_1bytes()); EXPECT_EQ(6, s.read_2bytes()); EXPECT_EQ('w', s.current()[0]); EXPECT_EQ('n', s.current()[5]); s.reset(); s.current()[3] = 'x'; EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_STREQ("xinlin", o->to_str().c_str()); } // number if (true) { s.reset(); o = SrsAmf0Any::number(10); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(0, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_DOUBLE_EQ(10, o->to_number()); } // boolean if (true) { s.reset(); o = SrsAmf0Any::boolean(true); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(1, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_TRUE(o->to_boolean()); } if (true) { s.reset(); o = SrsAmf0Any::boolean(false); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(1, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_FALSE(o->to_boolean()); } // null if (true) { s.reset(); o = SrsAmf0Any::null(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(5, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_TRUE(o->is_null()); } // undefined if (true) { s.reset(); o = SrsAmf0Any::undefined(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(6, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_TRUE(o->is_undefined()); } // any: string if (true) { s.reset(); o = SrsAmf0Any::str("winlin"); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_string()); EXPECT_STREQ("winlin", po->to_str().c_str()); } // any: number if (true) { s.reset(); o = SrsAmf0Any::number(10); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_number()); EXPECT_DOUBLE_EQ(10, po->to_number()); } // any: boolean if (true) { s.reset(); o = SrsAmf0Any::boolean(true); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_boolean()); EXPECT_TRUE(po->to_boolean()); } // any: null if (true) { s.reset(); o = SrsAmf0Any::null(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_null()); } // any: undefined if (true) { s.reset(); o = SrsAmf0Any::undefined(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_undefined()); } // mixed any if (true) { s.reset(); o = SrsAmf0Any::str("winlin"); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::number(10); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::boolean(true); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::null(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::undefined(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_string()); EXPECT_STREQ("winlin", po->to_str().c_str()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_number()); EXPECT_DOUBLE_EQ(10, po->to_number()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_boolean()); EXPECT_TRUE(po->to_boolean()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_null()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_undefined()); srs_freep(po); } }
VOID TEST(AMF0Test, ApiAnyElem) { SrsAmf0Any* o = NULL; // string if (true) { o = SrsAmf0Any::str(); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_string()); EXPECT_STREQ("", o->to_str().c_str()); } if (true) { o = SrsAmf0Any::str("winlin"); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_string()); EXPECT_STREQ("winlin", o->to_str().c_str()); } // bool if (true) { o = SrsAmf0Any::boolean(); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_boolean()); EXPECT_FALSE(o->to_boolean()); } if (true) { o = SrsAmf0Any::boolean(false); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_boolean()); EXPECT_FALSE(o->to_boolean()); } if (true) { o = SrsAmf0Any::boolean(true); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_boolean()); EXPECT_TRUE(o->to_boolean()); } // number if (true) { o = SrsAmf0Any::number(); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_number()); EXPECT_DOUBLE_EQ(0, o->to_number()); } if (true) { o = SrsAmf0Any::number(100); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_number()); EXPECT_DOUBLE_EQ(100, o->to_number()); } if (true) { o = SrsAmf0Any::number(-100); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_number()); EXPECT_DOUBLE_EQ(-100, o->to_number()); } // null if (true) { o = SrsAmf0Any::null(); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_null()); } // undefined if (true) { o = SrsAmf0Any::undefined(); SrsAutoFree(SrsAmf0Any, o); ASSERT_TRUE(NULL != o); EXPECT_TRUE(o->is_undefined()); } }
// user scenario: coding and decoding with amf0 VOID TEST(AMF0Test, ScenarioMain) { // coded amf0 object int nb_bytes = 0; char* bytes = NULL; // coding data to binaries by amf0 // for example, send connect app response to client. if (true) { // props: object // fmsVer: string // capabilities: number // mode: number // info: object // level: string // code: string // descrption: string // objectEncoding: number // data: array // version: string // srs_sig: string SrsAmf0Object* props = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, props); props->set("fmsVer", SrsAmf0Any::str("FMS/3,5,3,888")); props->set("capabilities", SrsAmf0Any::number(253)); props->set("mode", SrsAmf0Any::number(123)); SrsAmf0Object* info = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, info); info->set("level", SrsAmf0Any::str("info")); info->set("code", SrsAmf0Any::str("NetStream.Connnect.Success")); info->set("descrption", SrsAmf0Any::str("connected")); info->set("objectEncoding", SrsAmf0Any::number(3)); SrsAmf0EcmaArray* data = SrsAmf0Any::ecma_array(); info->set("data", data); data->set("version", SrsAmf0Any::str("FMS/3,5,3,888")); data->set("srs_sig", SrsAmf0Any::str("srs")); // buf store the serialized props/info nb_bytes = props->total_size() + info->total_size(); ASSERT_GT(nb_bytes, 0); bytes = new char[nb_bytes]; // use SrsStream to write props/info to binary buf. SrsStream s; EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); EXPECT_EQ(ERROR_SUCCESS, props->write(&s)); EXPECT_EQ(ERROR_SUCCESS, info->write(&s)); EXPECT_TRUE(s.empty()); // now, user can use the buf EXPECT_EQ(0x03, bytes[0]); EXPECT_EQ(0x09, bytes[nb_bytes - 1]); } SrsAutoFree(char, bytes); // decoding amf0 object from bytes // when user know the schema if (true) { ASSERT_TRUE(NULL != bytes); // use SrsStream to assist amf0 object to read from bytes. SrsStream s; EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); // decoding // if user know the schema, for instance, it's an amf0 object, // user can use specified object to decoding. SrsAmf0Object* props = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, props); EXPECT_EQ(ERROR_SUCCESS, props->read(&s)); // user can use specified object to decoding. SrsAmf0Object* info = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, info); EXPECT_EQ(ERROR_SUCCESS, info->read(&s)); // use the decoded data. SrsAmf0Any* prop = NULL; // if user requires specified property, use ensure of amf0 object EXPECT_TRUE(NULL != (prop = props->ensure_property_string("fmsVer"))); // the property can assert to string. ASSERT_TRUE(prop->is_string()); // get the prop string value. EXPECT_STREQ("FMS/3,5,3,888", prop->to_str().c_str()); // get other type property value EXPECT_TRUE(NULL != (prop = info->get_property("data"))); // we cannot assert the property is ecma array if (prop->is_ecma_array()) { SrsAmf0EcmaArray* data = prop->to_ecma_array(); // it must be a ecma array. ASSERT_TRUE(NULL != data); // get property of array EXPECT_TRUE(NULL != (prop = data->ensure_property_string("srs_sig"))); ASSERT_TRUE(prop->is_string()); EXPECT_STREQ("srs", prop->to_str().c_str()); } // confidence about the schema EXPECT_TRUE(NULL != (prop = info->ensure_property_string("level"))); ASSERT_TRUE(prop->is_string()); EXPECT_STREQ("info", prop->to_str().c_str()); } // use any to decoding it, // if user donot know the schema if (true) { ASSERT_TRUE(NULL != bytes); // use SrsStream to assist amf0 object to read from bytes. SrsStream s; EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); // decoding a amf0 any, for user donot know SrsAmf0Any* any = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &any)); SrsAutoFree(SrsAmf0Any, any); // for amf0 object if (any->is_object()) { SrsAmf0Object* obj = any->to_object(); ASSERT_TRUE(NULL != obj); // use foreach to process properties for (int i = 0; i < obj->count(); ++i) { string name = obj->key_at(i); SrsAmf0Any* value = obj->value_at(i); // use the property name EXPECT_TRUE("" != name); // use the property value EXPECT_TRUE(NULL != value); } } } }
int SrsSource::on_meta_data(SrsMessage* msg, SrsOnMetaDataPacket* metadata) { int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HLS if (metadata && (ret = hls->on_meta_data(metadata->metadata)) != ERROR_SUCCESS) { srs_error("hls process onMetaData message failed. ret=%d", ret); return ret; } #endif #ifdef SRS_AUTO_DVR if (metadata && (ret = dvr->on_meta_data(metadata)) != ERROR_SUCCESS) { srs_error("dvr process onMetaData message failed. ret=%d", ret); return ret; } #endif SrsAmf0Any* prop = NULL; // generate metadata info to print std::stringstream ss; if ((prop = metadata->metadata->ensure_property_number("width")) != NULL) { ss << ", width=" << (int)prop->to_number(); } if ((prop = metadata->metadata->ensure_property_number("height")) != NULL) { ss << ", height=" << (int)prop->to_number(); } if ((prop = metadata->metadata->ensure_property_number("videocodecid")) != NULL) { ss << ", vcodec=" << (int)prop->to_number(); } if ((prop = metadata->metadata->ensure_property_number("audiocodecid")) != NULL) { ss << ", acodec=" << (int)prop->to_number(); } // add server info to metadata metadata->metadata->set("server", SrsAmf0Any::str(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); metadata->metadata->set("authors", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY_AUTHROS)); // version, for example, 1.0.0 // add version to metadata, please donot remove it, for debug. metadata->metadata->set("server_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION)); if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) { if (prop->is_number()) { sample_rate = (int)prop->to_number(); } } if ((prop = metadata->metadata->get_property("framerate")) != NULL) { if (prop->is_number()) { frame_rate = (int)prop->to_number(); } } // if allow atc_auto and bravo-atc detected, open atc for vhost. atc = _srs_config->get_atc(_req->vhost); if (_srs_config->get_atc_auto(_req->vhost)) { if ((prop = metadata->metadata->get_property("bravo_atc")) != NULL) { if (prop->is_string() && prop->to_str() == "true") { atc = true; } } } // encode the metadata to payload int size = 0; char* payload = NULL; if ((ret = metadata->encode(size, payload)) != ERROR_SUCCESS) { srs_error("encode metadata error. ret=%d", ret); srs_freep(payload); return ret; } srs_verbose("encode metadata success."); if (size <= 0) { srs_warn("ignore the invalid metadata. size=%d", size); return ret; } // create a shared ptr message. srs_freep(cache_metadata); cache_metadata = new SrsSharedPtrMessage(); // dump message to shared ptr message. // the payload/size managed by cache_metadata, user should not free it. if ((ret = cache_metadata->create(&msg->header, payload, size)) != ERROR_SUCCESS) { srs_error("initialize the cache metadata failed. ret=%d", ret); return ret; } srs_verbose("initialize shared ptr metadata success."); // copy to all consumer if (true) { std::vector<SrsConsumer*>::iterator it; for (it = consumers.begin(); it != consumers.end(); ++it) { SrsConsumer* consumer = *it; SrsSharedPtrMessage* copy = cache_metadata->copy(); if ((ret = consumer->enqueue(copy, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { srs_error("dispatch the metadata failed. ret=%d", ret); return ret; } } srs_trace("got metadata%s", ss.str().c_str()); } // copy to all forwarders if (true) { std::vector<SrsForwarder*>::iterator it; for (it = forwarders.begin(); it != forwarders.end(); ++it) { SrsForwarder* forwarder = *it; if ((ret = forwarder->on_meta_data(cache_metadata->copy())) != ERROR_SUCCESS) { srs_error("forwarder process onMetaData message failed. ret=%d", ret); return ret; } } } return ret; }
int SrsSource::on_meta_data(SrsMessage* msg, SrsOnMetaDataPacket* metadata) { int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_HLS if (metadata && (ret = hls->on_meta_data(metadata->metadata)) != ERROR_SUCCESS) { srs_error("hls process onMetaData message failed. ret=%d", ret); return ret; } #endif #ifdef SRS_AUTO_DVR if (metadata && (ret = dvr->on_meta_data(metadata)) != ERROR_SUCCESS) { srs_error("dvr process onMetaData message failed. ret=%d", ret); return ret; } #endif metadata->metadata->set("server", SrsAmf0Any::str(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); metadata->metadata->set("authors", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY_AUTHROS)); SrsAmf0Any* prop = NULL; if ((prop = metadata->metadata->get_property("audiosamplerate")) != NULL) { if (prop->is_number()) { sample_rate = (int)prop->to_number(); } } if ((prop = metadata->metadata->get_property("framerate")) != NULL) { if (prop->is_number()) { frame_rate = (int)prop->to_number(); } } // if allow atc_auto and bravo-atc detected, open atc for vhost. atc = _srs_config->get_atc(_req->vhost); if (_srs_config->get_atc_auto(_req->vhost)) { if ((prop = metadata->metadata->get_property("bravo_atc")) != NULL) { if (prop->is_string() && prop->to_str() == "true") { atc = true; } } } // encode the metadata to payload int size = 0; char* payload = NULL; if ((ret = metadata->encode(size, payload)) != ERROR_SUCCESS) { srs_error("encode metadata error. ret=%d", ret); srs_freep(payload); return ret; } srs_verbose("encode metadata success."); if (size <= 0) { srs_warn("ignore the invalid metadata. size=%d", size); return ret; } // create a shared ptr message. srs_freep(cache_metadata); cache_metadata = new SrsSharedPtrMessage(); // dump message to shared ptr message. if ((ret = cache_metadata->initialize(&msg->header, payload, size)) != ERROR_SUCCESS) { srs_error("initialize the cache metadata failed. ret=%d", ret); return ret; } srs_verbose("initialize shared ptr metadata success."); // copy to all consumer if (true) { std::vector<SrsConsumer*>::iterator it; for (it = consumers.begin(); it != consumers.end(); ++it) { SrsConsumer* consumer = *it; if ((ret = consumer->enqueue(cache_metadata->copy(), sample_rate, frame_rate)) != ERROR_SUCCESS) { srs_error("dispatch the metadata failed. ret=%d", ret); return ret; } } srs_trace("dispatch metadata success."); } // copy to all forwarders if (true) { std::vector<SrsForwarder*>::iterator it; for (it = forwarders.begin(); it != forwarders.end(); ++it) { SrsForwarder* forwarder = *it; if ((ret = forwarder->on_meta_data(cache_metadata->copy())) != ERROR_SUCCESS) { srs_error("forwarder process onMetaData message failed. ret=%d", ret); return ret; } } } return ret; }
int SrsRtmpClient::connect_app(string app, string tc_url) { int ret = ERROR_SUCCESS; // Connect(vhost, app) if (true) { SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); pkt->command_object->set("flashVer", SrsAmf0Any::str("WIN 12,0,0,41")); pkt->command_object->set("swfUrl", SrsAmf0Any::str()); pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); pkt->command_object->set("fpad", SrsAmf0Any::boolean(false)); pkt->command_object->set("capabilities", SrsAmf0Any::number(239)); pkt->command_object->set("audioCodecs", SrsAmf0Any::number(3575)); pkt->command_object->set("videoCodecs", SrsAmf0Any::number(252)); pkt->command_object->set("videoFunction", SrsAmf0Any::number(1)); pkt->command_object->set("pageUrl", SrsAmf0Any::str()); pkt->command_object->set("objectEncoding", SrsAmf0Any::number(0)); if ((ret = protocol->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { return ret; } } // Set Window Acknowledgement size(2500000) if (true) { SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); pkt->ackowledgement_window_size = 2500000; if ((ret = protocol->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { return ret; } } // expect connect _result SrsMessage* msg = NULL; SrsConnectAppResPacket* pkt = NULL; if ((ret = srs_rtmp_expect_message<SrsConnectAppResPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) { srs_error("expect connect app response message failed. ret=%d", ret); return ret; } SrsAutoFree(SrsMessage, msg); SrsAutoFree(SrsConnectAppResPacket, pkt); // server info std::string srs_version; std::string srs_server_ip; int srs_id = 0; int srs_pid = 0; SrsAmf0Any* data = pkt->info->get_property("data"); if (data && data->is_ecma_array()) { SrsAmf0EcmaArray* arr = data->to_ecma_array(); SrsAmf0Any* prop = NULL; if ((prop = arr->ensure_property_string("srs_version")) != NULL) { srs_version = prop->to_str(); } if ((prop = arr->ensure_property_string("srs_server_ip")) != NULL) { srs_server_ip = prop->to_str(); } if ((prop = arr->ensure_property_number("srs_id")) != NULL) { srs_id = (int)prop->to_number(); } if ((prop = arr->ensure_property_number("srs_pid")) != NULL) { srs_pid = (int)prop->to_number(); } } srs_trace("connected, version=%s, ip=%s, pid=%d, id=%d", srs_version.c_str(), srs_server_ip.c_str(), srs_pid, srs_id); return ret; }