winlin

for #319, support HTTP RAW API config_query global data.

@@ -47,6 +47,7 @@ using namespace std; @@ -47,6 +47,7 @@ using namespace std;
47 #include <srs_app_utility.hpp> 47 #include <srs_app_utility.hpp>
48 #include <srs_core_performance.hpp> 48 #include <srs_core_performance.hpp>
49 #include <srs_kernel_file.hpp> 49 #include <srs_kernel_file.hpp>
  50 +#include <srs_rtmp_amf0.hpp>
50 51
51 using namespace _srs_internal; 52 using namespace _srs_internal;
52 53
@@ -332,6 +333,31 @@ int SrsConfDirective::persistence(SrsFileWriter* writer, int level) @@ -332,6 +333,31 @@ int SrsConfDirective::persistence(SrsFileWriter* writer, int level)
332 return ret; 333 return ret;
333 } 334 }
334 335
  336 +SrsAmf0StrictArray* SrsConfDirective::dumps_args()
  337 +{
  338 + SrsAmf0StrictArray* arr = SrsAmf0Any::strict_array();
  339 + for (int i = 0; i < (int)args.size(); i++) {
  340 + string arg = args.at(i);
  341 + arr->append(SrsAmf0Any::str(arg.c_str()));
  342 + }
  343 + return arr;
  344 +}
  345 +
  346 +SrsAmf0Any* SrsConfDirective::dumps_arg0_to_str()
  347 +{
  348 + return SrsAmf0Any::str(arg0().c_str());
  349 +}
  350 +
  351 +SrsAmf0Any* SrsConfDirective::dumps_arg0_to_number()
  352 +{
  353 + return SrsAmf0Any::number(::atof(arg0().c_str()));
  354 +}
  355 +
  356 +SrsAmf0Any* SrsConfDirective::dumps_arg0_to_boolean()
  357 +{
  358 + return SrsAmf0Any::boolean(arg0() == "on");
  359 +}
  360 +
335 // see: ngx_conf_parse 361 // see: ngx_conf_parse
336 int SrsConfDirective::parse_conf(SrsConfigBuffer* buffer, SrsDirectiveType type) 362 int SrsConfDirective::parse_conf(SrsConfigBuffer* buffer, SrsDirectiveType type)
337 { 363 {
@@ -1547,6 +1573,208 @@ int SrsConfig::persistence() @@ -1547,6 +1573,208 @@ int SrsConfig::persistence()
1547 return ret; 1573 return ret;
1548 } 1574 }
1549 1575
  1576 +int SrsConfig::global_to_json(SrsAmf0Object* obj)
  1577 +{
  1578 + int ret = ERROR_SUCCESS;
  1579 +
  1580 + for (int i = 0; i < (int)root->directives.size(); i++) {
  1581 + SrsConfDirective* dir = root->directives.at(i);
  1582 + if (dir->is_vhost()) {
  1583 + continue;
  1584 + }
  1585 +
  1586 + if (dir->name == "listen") {
  1587 + obj->set(dir->name, dir->dumps_args());
  1588 + } else if (dir->name == "pid") {
  1589 + obj->set(dir->name, dir->dumps_arg0_to_str());
  1590 + } else if (dir->name == "chunk_size") {
  1591 + obj->set(dir->name, dir->dumps_arg0_to_number());
  1592 + } else if (dir->name == "ff_log_dir") {
  1593 + obj->set(dir->name, dir->dumps_arg0_to_str());
  1594 + } else if (dir->name == "srs_log_tank") {
  1595 + obj->set(dir->name, dir->dumps_arg0_to_str());
  1596 + } else if (dir->name == "srs_log_level") {
  1597 + obj->set(dir->name, dir->dumps_arg0_to_str());
  1598 + } else if (dir->name == "srs_log_file") {
  1599 + obj->set(dir->name, dir->dumps_arg0_to_str());
  1600 + } else if (dir->name == "max_connections") {
  1601 + obj->set(dir->name, dir->dumps_arg0_to_number());
  1602 + } else if (dir->name == "daemon") {
  1603 + obj->set(dir->name, dir->dumps_arg0_to_boolean());
  1604 + } else if (dir->name == "utc_time") {
  1605 + obj->set(dir->name, dir->dumps_arg0_to_boolean());
  1606 + } else if (dir->name == "pithy_print_ms") {
  1607 + obj->set(dir->name, dir->dumps_arg0_to_number());
  1608 + } else if (dir->name == "heartbeat") {
  1609 + SrsAmf0Object* sobj = SrsAmf0Any::object();
  1610 + for (int j = 0; j < (int)dir->directives.size(); j++) {
  1611 + SrsConfDirective* sdir = dir->directives.at(j);
  1612 + if (sdir->name == "enabled") {
  1613 + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean());
  1614 + } else if (sdir->name == "interval") {
  1615 + sobj->set(sdir->name, sdir->dumps_arg0_to_number());
  1616 + } else if (sdir->name == "url") {
  1617 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1618 + } else if (sdir->name == "device_id") {
  1619 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1620 + } else if (sdir->name == "summaries") {
  1621 + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean());
  1622 + }
  1623 + }
  1624 + obj->set(dir->name, sobj);
  1625 + } else if (dir->name == "stats") {
  1626 + SrsAmf0Object* sobj = SrsAmf0Any::object();
  1627 + for (int j = 0; j < (int)dir->directives.size(); j++) {
  1628 + SrsConfDirective* sdir = dir->directives.at(j);
  1629 + if (sdir->name == "network") {
  1630 + sobj->set(sdir->name, sdir->dumps_arg0_to_number());
  1631 + } else if (sdir->name == "disk") {
  1632 + sobj->set(sdir->name, sdir->dumps_args());
  1633 + }
  1634 + }
  1635 + obj->set(dir->name, sobj);
  1636 + } else if (dir->name == "http_api") {
  1637 + SrsAmf0Object* sobj = SrsAmf0Any::object();
  1638 + for (int j = 0; j < (int)dir->directives.size(); j++) {
  1639 + SrsConfDirective* sdir = dir->directives.at(j);
  1640 + if (sdir->name == "enabled") {
  1641 + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean());
  1642 + } else if (sdir->name == "listen") {
  1643 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1644 + } else if (sdir->name == "crossdomain") {
  1645 + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean());
  1646 + } else if (sdir->name == "raw_api") {
  1647 + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean());
  1648 + }
  1649 + }
  1650 + obj->set(dir->name, sobj);
  1651 + } else if (dir->name == "http_server") {
  1652 + SrsAmf0Object* sobj = SrsAmf0Any::object();
  1653 + for (int j = 0; j < (int)dir->directives.size(); j++) {
  1654 + SrsConfDirective* sdir = dir->directives.at(j);
  1655 + if (sdir->name == "enabled") {
  1656 + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean());
  1657 + } else if (sdir->name == "listen") {
  1658 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1659 + } else if (sdir->name == "dir") {
  1660 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1661 + }
  1662 + }
  1663 + obj->set(dir->name, sobj);
  1664 + } else if (dir->name == "stream_caster") {
  1665 + SrsAmf0Object* sobj = SrsAmf0Any::object();
  1666 + for (int j = 0; j < (int)dir->directives.size(); j++) {
  1667 + SrsConfDirective* sdir = dir->directives.at(j);
  1668 + if (sdir->name == "enabled") {
  1669 + sobj->set(sdir->name, sdir->dumps_arg0_to_boolean());
  1670 + } else if (sdir->name == "caster") {
  1671 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1672 + } else if (sdir->name == "output") {
  1673 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1674 + } else if (sdir->name == "listen") {
  1675 + sobj->set(sdir->name, sdir->dumps_arg0_to_str());
  1676 + } else if (sdir->name == "rtp_port_min") {
  1677 + sobj->set(sdir->name, sdir->dumps_arg0_to_number());
  1678 + } else if (sdir->name == "rtp_port_max") {
  1679 + sobj->set(sdir->name, sdir->dumps_arg0_to_number());
  1680 + }
  1681 + }
  1682 + obj->set(dir->name, sobj);
  1683 + } else {
  1684 + continue;
  1685 + }
  1686 + }
  1687 +
  1688 + SrsAmf0Object* sobjs = SrsAmf0Any::object();
  1689 + int nb_vhosts = 0;
  1690 +
  1691 + for (int i = 0; i < (int)root->directives.size(); i++) {
  1692 + SrsConfDirective* dir = root->directives.at(i);
  1693 + if (!dir->is_vhost()) {
  1694 + continue;
  1695 + }
  1696 +
  1697 + nb_vhosts++;
  1698 + SrsAmf0Object* sobj = SrsAmf0Any::object();
  1699 + sobjs->set(dir->arg0(), sobj);
  1700 +
  1701 + sobj->set("enabled", SrsAmf0Any::boolean(get_vhost_enabled(dir->name)));
  1702 + sobj->set("dvr", SrsAmf0Any::boolean(get_dvr_enabled(dir->name)));
  1703 + sobj->set("http_static", SrsAmf0Any::boolean(get_vhost_http_enabled(dir->name)));
  1704 + sobj->set("http_remux", SrsAmf0Any::boolean(get_vhost_http_remux_enabled(dir->name)));
  1705 + sobj->set("hls", SrsAmf0Any::boolean(get_hls_enabled(dir->name)));
  1706 + sobj->set("hds", SrsAmf0Any::boolean(get_hds_enabled(dir->name)));
  1707 + sobj->set("http_hooks", SrsAmf0Any::boolean(get_vhost_http_hooks(dir->name)));
  1708 + sobj->set("exec", SrsAmf0Any::boolean(get_exec_enabled(dir->name)));
  1709 + sobj->set("bandcheck", SrsAmf0Any::boolean(get_bw_check_enabled(dir->name)));
  1710 + sobj->set("origin", SrsAmf0Any::boolean(!get_vhost_is_edge(dir->name)));
  1711 + sobj->set("forward", SrsAmf0Any::boolean(get_forward(dir->name)));
  1712 +
  1713 + sobj->set("security", SrsAmf0Any::boolean(get_security_enabled(dir->name)));
  1714 + sobj->set("refer", SrsAmf0Any::boolean(get_refer(dir->name) || get_refer_play(dir->name) || get_refer_publish(dir->name)));
  1715 +
  1716 + sobj->set("mr", SrsAmf0Any::boolean(get_mr_enabled(dir->name)));
  1717 + sobj->set("min_latency", SrsAmf0Any::boolean(get_realtime_enabled(dir->name)));
  1718 + sobj->set("gop_cache", SrsAmf0Any::boolean(get_gop_cache(dir->name)));
  1719 + sobj->set("tcp_nodelay", SrsAmf0Any::boolean(get_tcp_nodelay(dir->name)));
  1720 +
  1721 + sobj->set("mix_correct", SrsAmf0Any::boolean(get_mix_correct(dir->name)));
  1722 + sobj->set("time_jitter", SrsAmf0Any::boolean(get_time_jitter(dir->name) != SrsRtmpJitterAlgorithmOFF));
  1723 + sobj->set("atc", SrsAmf0Any::boolean(get_atc(dir->name)));
  1724 +
  1725 + bool has_transcode = false;
  1726 + for (int j = 0; !has_transcode && j < (int)dir->directives.size(); j++) {
  1727 + SrsConfDirective* sdir = dir->directives.at(j);
  1728 + if (sdir->name != "transcode") {
  1729 + continue;
  1730 + }
  1731 +
  1732 + if (!get_transcode_enabled(sdir)) {
  1733 + continue;
  1734 + }
  1735 +
  1736 + for (int k = 0; !has_transcode && k < (int)sdir->directives.size(); k++) {
  1737 + SrsConfDirective* ssdir = sdir->directives.at(k);
  1738 + if (ssdir->name != "engine") {
  1739 + continue;
  1740 + }
  1741 +
  1742 + if (get_engine_enabled(ssdir)) {
  1743 + has_transcode = true;
  1744 + break;
  1745 + }
  1746 + }
  1747 + }
  1748 + sobj->set("transcode", SrsAmf0Any::boolean(has_transcode));
  1749 +
  1750 + bool has_ingest = false;
  1751 + for (int j = 0; !has_ingest && j < (int)dir->directives.size(); j++) {
  1752 + SrsConfDirective* sdir = dir->directives.at(j);
  1753 + if (sdir->name != "ingest") {
  1754 + continue;
  1755 + }
  1756 +
  1757 + if (get_ingest_enabled(sdir)) {
  1758 + has_ingest = true;
  1759 + break;
  1760 + }
  1761 + }
  1762 + sobj->set("ingest", SrsAmf0Any::boolean(has_ingest));
  1763 + }
  1764 +
  1765 + obj->set("nb_vhosts", SrsAmf0Any::number(nb_vhosts));
  1766 + obj->set("vhosts", sobjs);
  1767 +
  1768 + return ret;
  1769 +}
  1770 +
  1771 +int SrsConfig::vhost_to_json(SrsConfDirective* vhost, SrsAmf0Object* obj)
  1772 +{
  1773 + int ret = ERROR_SUCCESS;
  1774 +
  1775 + return ret;
  1776 +}
  1777 +
1550 string SrsConfig::config() 1778 string SrsConfig::config()
1551 { 1779 {
1552 return config_file; 1780 return config_file;
@@ -31,10 +31,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,10 +31,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 31
32 #include <vector> 32 #include <vector>
33 #include <string> 33 #include <string>
  34 +#include <sstream>
34 35
35 #include <srs_app_reload.hpp> 36 #include <srs_app_reload.hpp>
36 37
37 class SrsFileWriter; 38 class SrsFileWriter;
  39 +class SrsAmf0Object;
  40 +class SrsAmf0StrictArray;
  41 +class SrsAmf0Any;
38 42
39 namespace _srs_internal 43 namespace _srs_internal
40 { 44 {
@@ -143,6 +147,16 @@ public: @@ -143,6 +147,16 @@ public:
143 * @param level, the root is level0, all its directives are level1, and so on. 147 * @param level, the root is level0, all its directives are level1, and so on.
144 */ 148 */
145 virtual int persistence(SrsFileWriter* writer, int level); 149 virtual int persistence(SrsFileWriter* writer, int level);
  150 + /**
  151 + * dumps the args[0-N] to array(string).
  152 + */
  153 + virtual SrsAmf0StrictArray* dumps_args();
  154 + /**
  155 + * dumps arg0 to str, number or boolean.
  156 + */
  157 + virtual SrsAmf0Any* dumps_arg0_to_str();
  158 + virtual SrsAmf0Any* dumps_arg0_to_number();
  159 + virtual SrsAmf0Any* dumps_arg0_to_boolean();
146 // private parse. 160 // private parse.
147 private: 161 private:
148 /** 162 /**
@@ -299,6 +313,14 @@ public: @@ -299,6 +313,14 @@ public:
299 */ 313 */
300 virtual int persistence(); 314 virtual int persistence();
301 /** 315 /**
  316 + * dumps the global sections to json.
  317 + */
  318 + virtual int global_to_json(SrsAmf0Object* obj);
  319 + /**
  320 + * dumps the vhost section to json.
  321 + */
  322 + virtual int vhost_to_json(SrsConfDirective* vhost, SrsAmf0Object* obj);
  323 + /**
302 * get the config file path. 324 * get the config file path.
303 */ 325 */
304 virtual std::string config(); 326 virtual std::string config();
@@ -44,6 +44,7 @@ using namespace std; @@ -44,6 +44,7 @@ using namespace std;
44 #include <srs_app_http_conn.hpp> 44 #include <srs_app_http_conn.hpp>
45 #include <srs_kernel_consts.hpp> 45 #include <srs_kernel_consts.hpp>
46 #include <srs_app_server.hpp> 46 #include <srs_app_server.hpp>
  47 +#include <srs_rtmp_amf0.hpp>
47 48
48 int srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data) 49 int srs_api_response_jsonp(ISrsHttpResponseWriter* w, string callback, string data)
49 { 50 {
@@ -872,6 +873,63 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -872,6 +873,63 @@ int SrsGoApiRaw::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
872 return srs_api_response_code(w, r, ret); 873 return srs_api_response_code(w, r, ret);
873 } 874 }
874 875
  876 + // for rpc=config_query, to get the configs of server.
  877 + // @param scope the scope to query for config, it can be:
  878 + // global, the configs belongs to the root, donot includes any sub directives.
  879 + // vhost, the configs for specified vhost by @param vhost.
  880 + // @param vhost the vhost name for @param scope is vhost to query config.
  881 + // for the default vhost, must be __defaultVhost__
  882 + if (rpc == "config_query") {
  883 + std::string scope = r->query_get("scope");
  884 + std::string vhost = r->query_get("vhost");
  885 + if (scope.empty() || (scope != "global" && scope != "vhost")) {
  886 + ret = ERROR_SYSTEM_CONFIG_RAW_PARAMS;
  887 + srs_error("raw api config_query invalid scope=%s. ret=%d", scope.c_str(), ret);
  888 + return srs_api_response_code(w, r, ret);
  889 + }
  890 +
  891 + // config query.
  892 + SrsAmf0Object* obj = SrsAmf0Any::object();
  893 + SrsAutoFree(SrsAmf0Object, obj);
  894 +
  895 + obj->set("code", SrsAmf0Any::number(ERROR_SUCCESS));
  896 +
  897 + if (scope == "vhost") {
  898 + // query vhost scope.
  899 + if (vhost.empty()) {
  900 + ret = ERROR_SYSTEM_CONFIG_RAW_PARAMS;
  901 + srs_error("raw api config_query vhost invalid vhost=%s. ret=%d", vhost.c_str(), ret);
  902 + return ret;
  903 + }
  904 +
  905 + SrsConfDirective* root = _srs_config->get_root();
  906 + SrsConfDirective* conf = root->get("vhost", vhost);
  907 + if (!conf) {
  908 + ret = ERROR_SYSTEM_CONFIG_RAW_PARAMS;
  909 + srs_error("raw api config_query vhost invalid vhost=%s. ret=%d", vhost.c_str(), ret);
  910 + return ret;
  911 + }
  912 +
  913 + SrsAmf0Object* data = SrsAmf0Any::object();
  914 + obj->set("vhost", data);
  915 + if ((ret = _srs_config->vhost_to_json(conf, data)) != ERROR_SUCCESS) {
  916 + srs_error("raw api config_query vhost failed. ret=%d", ret);
  917 + return srs_api_response_code(w, r, ret);
  918 + }
  919 + } else {
  920 + SrsAmf0Object* data = SrsAmf0Any::object();
  921 + obj->set("global", data);
  922 +
  923 + // query global scope.
  924 + if ((ret = _srs_config->global_to_json(data)) != ERROR_SUCCESS) {
  925 + srs_error("raw api config_query global failed. ret=%d", ret);
  926 + return srs_api_response_code(w, r, ret);
  927 + }
  928 + }
  929 +
  930 + return srs_api_response(w, r, obj->to_json());
  931 + }
  932 +
875 return ret; 933 return ret;
876 } 934 }
877 935
@@ -31,6 +31,7 @@ using namespace std; @@ -31,6 +31,7 @@ using namespace std;
31 #include <srs_kernel_log.hpp> 31 #include <srs_kernel_log.hpp>
32 #include <srs_kernel_error.hpp> 32 #include <srs_kernel_error.hpp>
33 #include <srs_kernel_stream.hpp> 33 #include <srs_kernel_stream.hpp>
  34 +#include <srs_protocol_json.hpp>
34 35
35 using namespace _srs_internal; 36 using namespace _srs_internal;
36 37
@@ -275,12 +276,58 @@ char* SrsAmf0Any::human_print(char** pdata, int* psize) @@ -275,12 +276,58 @@ char* SrsAmf0Any::human_print(char** pdata, int* psize)
275 *pdata = data; 276 *pdata = data;
276 } 277 }
277 if (psize) { 278 if (psize) {
278 - *psize = str.length(); 279 + *psize = (int)str.length();
279 } 280 }
280 281
281 return data; 282 return data;
282 } 283 }
283 284
  285 +string SrsAmf0Any::to_json()
  286 +{
  287 + switch (marker) {
  288 + case RTMP_AMF0_String: {
  289 + return "\"" + to_str() + "\"";
  290 + }
  291 + case RTMP_AMF0_Boolean: {
  292 + return to_boolean()? "true":"false";
  293 + }
  294 + case RTMP_AMF0_Number: {
  295 + // len(max int64_t) is 20, plus one "+-."
  296 + char tmp[22];
  297 + snprintf(tmp, 22, "%f", to_number());
  298 + return tmp;
  299 + }
  300 + case RTMP_AMF0_Null: {
  301 + return "null";
  302 + }
  303 + case RTMP_AMF0_Undefined: {
  304 + return "null";
  305 + }
  306 + case RTMP_AMF0_Object: {
  307 + SrsAmf0Object* obj = to_object();
  308 + return obj->to_json();
  309 + }
  310 + case RTMP_AMF0_EcmaArray: {
  311 + SrsAmf0EcmaArray* arr = to_ecma_array();
  312 + return arr->to_json();
  313 + }
  314 + case RTMP_AMF0_StrictArray: {
  315 + SrsAmf0StrictArray* arr = to_strict_array();
  316 + return arr->to_json();
  317 + }
  318 + case RTMP_AMF0_Date: {
  319 + // TODO: FIXME: support amf0 data to json.
  320 + return "null";
  321 + }
  322 + case RTMP_AMF0_Invalid:
  323 + default: {
  324 + break;
  325 + }
  326 + }
  327 +
  328 + return "null";
  329 +}
  330 +
284 SrsAmf0Any* SrsAmf0Any::str(const char* value) 331 SrsAmf0Any* SrsAmf0Any::str(const char* value)
285 { 332 {
286 return new SrsAmf0String(value); 333 return new SrsAmf0String(value);
@@ -742,6 +789,27 @@ SrsAmf0Any* SrsAmf0Object::copy() @@ -742,6 +789,27 @@ SrsAmf0Any* SrsAmf0Object::copy()
742 return copy; 789 return copy;
743 } 790 }
744 791
  792 +string SrsAmf0Object::to_json()
  793 +{
  794 + stringstream ss;
  795 +
  796 + ss << SRS_JOBJECT_START;
  797 +
  798 + for (int i = 0; i < properties->count(); i++) {
  799 + std::string name = this->key_at(i);
  800 + SrsAmf0Any* any = this->value_at(i);
  801 +
  802 + ss << SRS_JFIELD_NAME(name) << any->to_json();
  803 + if (i < properties->count() - 1) {
  804 + ss << SRS_JFIELD_CONT;
  805 + }
  806 + }
  807 +
  808 + ss << SRS_JOBJECT_END;
  809 +
  810 + return ss.str();
  811 +}
  812 +
745 void SrsAmf0Object::clear() 813 void SrsAmf0Object::clear()
746 { 814 {
747 properties->clear(); 815 properties->clear();
@@ -943,6 +1011,27 @@ SrsAmf0Any* SrsAmf0EcmaArray::copy() @@ -943,6 +1011,27 @@ SrsAmf0Any* SrsAmf0EcmaArray::copy()
943 return copy; 1011 return copy;
944 } 1012 }
945 1013
  1014 +string SrsAmf0EcmaArray::to_json()
  1015 +{
  1016 + stringstream ss;
  1017 +
  1018 + ss << SRS_JOBJECT_START;
  1019 +
  1020 + for (int i = 0; i < properties->count(); i++) {
  1021 + std::string name = this->key_at(i);
  1022 + SrsAmf0Any* any = this->value_at(i);
  1023 +
  1024 + ss << SRS_JFIELD_NAME(name) << any->to_json();
  1025 + if (i < properties->count() - 1) {
  1026 + ss << SRS_JFIELD_CONT;
  1027 + }
  1028 + }
  1029 +
  1030 + ss << SRS_JOBJECT_END;
  1031 +
  1032 + return ss.str();
  1033 +}
  1034 +
946 void SrsAmf0EcmaArray::clear() 1035 void SrsAmf0EcmaArray::clear()
947 { 1036 {
948 properties->clear(); 1037 properties->clear();
@@ -1118,6 +1207,27 @@ SrsAmf0Any* SrsAmf0StrictArray::copy() @@ -1118,6 +1207,27 @@ SrsAmf0Any* SrsAmf0StrictArray::copy()
1118 return copy; 1207 return copy;
1119 } 1208 }
1120 1209
  1210 +string SrsAmf0StrictArray::to_json()
  1211 +{
  1212 + stringstream ss;
  1213 +
  1214 + ss << SRS_JARRAY_START;
  1215 +
  1216 + for (int i = 0; i < (int)properties.size(); i++) {
  1217 + SrsAmf0Any* any = properties[i];
  1218 +
  1219 + ss << any->to_json();
  1220 +
  1221 + if (i < (int)properties.size() - 1) {
  1222 + ss << SRS_JFIELD_CONT;
  1223 + }
  1224 + }
  1225 +
  1226 + ss << SRS_JARRAY_END;
  1227 +
  1228 + return ss.str();
  1229 +}
  1230 +
1121 void SrsAmf0StrictArray::clear() 1231 void SrsAmf0StrictArray::clear()
1122 { 1232 {
1123 properties.clear(); 1233 properties.clear();
@@ -1125,7 +1235,7 @@ void SrsAmf0StrictArray::clear() @@ -1125,7 +1235,7 @@ void SrsAmf0StrictArray::clear()
1125 1235
1126 int SrsAmf0StrictArray::count() 1236 int SrsAmf0StrictArray::count()
1127 { 1237 {
1128 - return properties.size(); 1238 + return (int)properties.size();
1129 } 1239 }
1130 1240
1131 SrsAmf0Any* SrsAmf0StrictArray::at(int index) 1241 SrsAmf0Any* SrsAmf0StrictArray::at(int index)
@@ -272,6 +272,12 @@ public: @@ -272,6 +272,12 @@ public:
272 * @remark user must free the data returned or output by pdata. 272 * @remark user must free the data returned or output by pdata.
273 */ 273 */
274 virtual char* human_print(char** pdata, int* psize); 274 virtual char* human_print(char** pdata, int* psize);
  275 +// json
  276 +public:
  277 + /**
  278 + * convert the amf0 stuff to json.
  279 + */
  280 + virtual std::string to_json();
275 // create AMF0 instance. 281 // create AMF0 instance.
276 public: 282 public:
277 /** 283 /**
@@ -351,6 +357,12 @@ public: @@ -351,6 +357,12 @@ public:
351 virtual int read(SrsStream* stream); 357 virtual int read(SrsStream* stream);
352 virtual int write(SrsStream* stream); 358 virtual int write(SrsStream* stream);
353 virtual SrsAmf0Any* copy(); 359 virtual SrsAmf0Any* copy();
  360 +// json
  361 +public:
  362 + /**
  363 + * convert the amf0 object to json.
  364 + */
  365 + virtual std::string to_json();
354 // properties iteration 366 // properties iteration
355 public: 367 public:
356 /** 368 /**
@@ -434,6 +446,12 @@ public: @@ -434,6 +446,12 @@ public:
434 virtual int read(SrsStream* stream); 446 virtual int read(SrsStream* stream);
435 virtual int write(SrsStream* stream); 447 virtual int write(SrsStream* stream);
436 virtual SrsAmf0Any* copy(); 448 virtual SrsAmf0Any* copy();
  449 +// json
  450 +public:
  451 + /**
  452 + * convert the amf0 ecma array to json.
  453 + */
  454 + virtual std::string to_json();
437 // properties iteration 455 // properties iteration
438 public: 456 public:
439 /** 457 /**
@@ -515,6 +533,12 @@ public: @@ -515,6 +533,12 @@ public:
515 virtual int read(SrsStream* stream); 533 virtual int read(SrsStream* stream);
516 virtual int write(SrsStream* stream); 534 virtual int write(SrsStream* stream);
517 virtual SrsAmf0Any* copy(); 535 virtual SrsAmf0Any* copy();
  536 +// json
  537 +public:
  538 + /**
  539 + * convert the amf0 strict array to json.
  540 + */
  541 + virtual std::string to_json();
518 // properties iteration 542 // properties iteration
519 public: 543 public:
520 /** 544 /**