winlin

add rtmp client

@@ -15,7 +15,7 @@ vhost __defaultVhost__ { @@ -15,7 +15,7 @@ vhost __defaultVhost__ {
15 hls_path ./objs/nginx/html; 15 hls_path ./objs/nginx/html;
16 hls_fragment 5; 16 hls_fragment 5;
17 hls_window 30; 17 hls_window 30;
18 - forward 127.0.0.1:1936; 18 + forward 192.168.1.50;
19 } 19 }
20 # the vhost which forward publish streams. 20 # the vhost which forward publish streams.
21 vhost forward.vhost.com { 21 vhost forward.vhost.com {
@@ -39,8 +39,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -39,8 +39,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 #include <srs_core_hls.hpp> 39 #include <srs_core_hls.hpp>
40 40
41 #define SRS_PULSE_TIMEOUT_MS 100 41 #define SRS_PULSE_TIMEOUT_MS 100
42 -#define SRS_SEND_TIMEOUT_MS 5000000L  
43 -#define SRS_RECV_TIMEOUT_MS SRS_SEND_TIMEOUT_MS 42 +#define SRS_SEND_TIMEOUT_US 5000000L
  43 +#define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US
44 #define SRS_STREAM_BUSY_SLEEP_MS 2000 44 #define SRS_STREAM_BUSY_SLEEP_MS 2000
45 45
46 SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd) 46 SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd)
@@ -72,10 +72,10 @@ int SrsClient::do_cycle() @@ -72,10 +72,10 @@ int SrsClient::do_cycle()
72 return ret; 72 return ret;
73 } 73 }
74 srs_trace("get peer ip success. ip=%s, send_to=%"PRId64", recv_to=%"PRId64"", 74 srs_trace("get peer ip success. ip=%s, send_to=%"PRId64", recv_to=%"PRId64"",
75 - ip, SRS_SEND_TIMEOUT_MS, SRS_RECV_TIMEOUT_MS); 75 + ip, SRS_SEND_TIMEOUT_US, SRS_RECV_TIMEOUT_US);
76 76
77 - rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_MS * 1000);  
78 - rtmp->set_send_timeout(SRS_SEND_TIMEOUT_MS * 1000); 77 + rtmp->set_recv_timeout(SRS_RECV_TIMEOUT_US);
  78 + rtmp->set_send_timeout(SRS_SEND_TIMEOUT_US);
79 79
80 if ((ret = rtmp->handshake()) != ERROR_SUCCESS) { 80 if ((ret = rtmp->handshake()) != ERROR_SUCCESS) {
81 srs_error("rtmp handshake failed. ret=%d", ret); 81 srs_error("rtmp handshake failed. ret=%d", ret);
@@ -400,7 +400,7 @@ int SrsClient::process_publish_message(SrsSource* source, SrsCommonMessage* msg, @@ -400,7 +400,7 @@ int SrsClient::process_publish_message(SrsSource* source, SrsCommonMessage* msg,
400 400
401 // process onMetaData 401 // process onMetaData
402 if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) { 402 if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
403 - if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { 403 + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {
404 srs_error("decode onMetaData message failed. ret=%d", ret); 404 srs_error("decode onMetaData message failed. ret=%d", ret);
405 return ret; 405 return ret;
406 } 406 }
@@ -422,7 +422,7 @@ int SrsClient::process_publish_message(SrsSource* source, SrsCommonMessage* msg, @@ -422,7 +422,7 @@ int SrsClient::process_publish_message(SrsSource* source, SrsCommonMessage* msg,
422 422
423 // process UnPublish event. 423 // process UnPublish event.
424 if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) { 424 if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) {
425 - if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { 425 + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {
426 srs_error("decode unpublish message failed. ret=%d", ret); 426 srs_error("decode unpublish message failed. ret=%d", ret);
427 return ret; 427 return ret;
428 } 428 }
@@ -496,7 +496,7 @@ int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* @@ -496,7 +496,7 @@ int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage*
496 return ret; 496 return ret;
497 } 497 }
498 498
499 - if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { 499 + if ((ret = msg->decode_packet(rtmp->get_protocol())) != ERROR_SUCCESS) {
500 srs_error("decode the amf0/amf3 command packet failed. ret=%d", ret); 500 srs_error("decode the amf0/amf3 command packet failed. ret=%d", ret);
501 return ret; 501 return ret;
502 } 502 }
@@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 #define ERROR_ST_OPEN_SOCKET 102 37 #define ERROR_ST_OPEN_SOCKET 102
38 #define ERROR_ST_CREATE_LISTEN_THREAD 103 38 #define ERROR_ST_CREATE_LISTEN_THREAD 103
39 #define ERROR_ST_CREATE_CYCLE_THREAD 104 39 #define ERROR_ST_CREATE_CYCLE_THREAD 104
  40 +#define ERROR_ST_CREATE_FORWARD_THREAD 105
  41 +#define ERROR_ST_CONNECT 106
40 42
41 #define ERROR_SOCKET_CREATE 200 43 #define ERROR_SOCKET_CREATE 200
42 #define ERROR_SOCKET_SETREUSE 201 44 #define ERROR_SOCKET_SETREUSE 201
@@ -67,6 +69,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -67,6 +69,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
67 #define ERROR_RTMP_PACKET_SIZE 313 69 #define ERROR_RTMP_PACKET_SIZE 313
68 #define ERROR_RTMP_VHOST_NOT_FOUND 314 70 #define ERROR_RTMP_VHOST_NOT_FOUND 314
69 #define ERROR_RTMP_ACCESS_DENIED 315 71 #define ERROR_RTMP_ACCESS_DENIED 315
  72 +#define ERROR_RTMP_HANDSHAKE 316
  73 +#define ERROR_RTMP_NO_REQUEST 317
70 74
71 #define ERROR_SYSTEM_STREAM_INIT 400 75 #define ERROR_SYSTEM_STREAM_INIT 400
72 #define ERROR_SYSTEM_PACKET_INVALID 401 76 #define ERROR_SYSTEM_PACKET_INVALID 401
@@ -79,6 +83,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -79,6 +83,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
79 #define ERROR_SYSTEM_CONFIG_BLOCK_END 408 83 #define ERROR_SYSTEM_CONFIG_BLOCK_END 408
80 #define ERROR_SYSTEM_CONFIG_EOF 409 84 #define ERROR_SYSTEM_CONFIG_EOF 409
81 #define ERROR_SYSTEM_STREAM_BUSY 410 85 #define ERROR_SYSTEM_STREAM_BUSY 410
  86 +#define ERROR_SYSTEM_IP_INVALID 411
82 87
83 // see librtmp. 88 // see librtmp.
84 // failed when open ssl create the dh 89 // failed when open ssl create the dh
@@ -24,42 +24,47 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -24,42 +24,47 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include <srs_core_forward.hpp> 24 #include <srs_core_forward.hpp>
25 25
26 #include <stdlib.h> 26 #include <stdlib.h>
  27 +#include <sys/socket.h>
  28 +#include <netinet/in.h>
  29 +#include <arpa/inet.h>
  30 +#include <netdb.h>
27 31
28 #include <srs_core_error.hpp> 32 #include <srs_core_error.hpp>
29 #include <srs_core_rtmp.hpp> 33 #include <srs_core_rtmp.hpp>
30 #include <srs_core_log.hpp> 34 #include <srs_core_log.hpp>
31 35
  36 +#define SRS_FORWARDER_SLEEP_MS 2000
  37 +#define SRS_SEND_TIMEOUT_US 3000000L
  38 +#define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US
  39 +
32 SrsForwarder::SrsForwarder() 40 SrsForwarder::SrsForwarder()
33 { 41 {
34 - client = new SrsRtmpClient(); 42 + client = NULL;
35 tid = NULL; 43 tid = NULL;
  44 + stfd = NULL;
36 loop = false; 45 loop = false;
  46 + stream_id = 0;
37 } 47 }
38 48
39 SrsForwarder::~SrsForwarder() 49 SrsForwarder::~SrsForwarder()
40 { 50 {
41 - if (tid) {  
42 - loop = false;  
43 - st_thread_interrupt(tid);  
44 - st_thread_join(tid, NULL);  
45 - tid = NULL;  
46 - }  
47 -  
48 - srs_freep(client); 51 + on_unpublish();
49 } 52 }
50 53
51 -int SrsForwarder::on_publish(std::string vhost, std::string app, std::string stream, std::string forward_server) 54 +int SrsForwarder::on_publish(std::string vhost, std::string _app, std::string stream, std::string forward_server)
52 { 55 {
53 int ret = ERROR_SUCCESS; 56 int ret = ERROR_SUCCESS;
54 57
55 - std::string tc_url = "rtmp://"; 58 + app = _app;
  59 +
  60 + tc_url = "rtmp://";
56 tc_url += vhost; 61 tc_url += vhost;
57 tc_url += "/"; 62 tc_url += "/";
58 tc_url += app; 63 tc_url += app;
59 64
60 - std::string stream_name = stream;  
61 - std::string server = forward_server;  
62 - int port = 1935; 65 + stream_name = stream;
  66 + server = forward_server;
  67 + port = 1935;
63 68
64 size_t pos = forward_server.find(":"); 69 size_t pos = forward_server.find(":");
65 if (pos != std::string::npos) { 70 if (pos != std::string::npos) {
@@ -67,14 +72,40 @@ int SrsForwarder::on_publish(std::string vhost, std::string app, std::string str @@ -67,14 +72,40 @@ int SrsForwarder::on_publish(std::string vhost, std::string app, std::string str
67 server = forward_server.substr(0, pos); 72 server = forward_server.substr(0, pos);
68 } 73 }
69 74
70 - srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",  
71 - stream_name.c_str(), tc_url.c_str(), server.c_str(), port); 75 + if ((ret = open_socket()) != ERROR_SUCCESS) {
  76 + return ret;
  77 + }
  78 +
  79 + srs_assert(!tid);
  80 + if((tid = st_thread_create(forward_thread, this, 1, 0)) == NULL){
  81 + ret = ERROR_ST_CREATE_FORWARD_THREAD;
  82 + srs_error("st_thread_create failed. ret=%d", ret);
  83 + return ret;
  84 + }
72 85
73 return ret; 86 return ret;
74 } 87 }
75 88
76 void SrsForwarder::on_unpublish() 89 void SrsForwarder::on_unpublish()
77 { 90 {
  91 + if (tid) {
  92 + loop = false;
  93 + st_thread_interrupt(tid);
  94 + st_thread_join(tid, NULL);
  95 + tid = NULL;
  96 + }
  97 +
  98 + if (stfd) {
  99 + int fd = st_netfd_fileno(stfd);
  100 + st_netfd_close(stfd);
  101 + stfd = NULL;
  102 +
  103 + // st does not close it sometimes,
  104 + // close it manually.
  105 + close(fd);
  106 + }
  107 +
  108 + srs_freep(client);
78 } 109 }
79 110
80 int SrsForwarder::on_meta_data(SrsOnMetaDataPacket* metadata) 111 int SrsForwarder::on_meta_data(SrsOnMetaDataPacket* metadata)
@@ -95,3 +126,147 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* msg) @@ -95,3 +126,147 @@ int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
95 return ret; 126 return ret;
96 } 127 }
97 128
  129 +int SrsForwarder::open_socket()
  130 +{
  131 + int ret = ERROR_SUCCESS;
  132 +
  133 + srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
  134 + stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
  135 +
  136 + int sock = socket(AF_INET, SOCK_STREAM, 0);
  137 + if(sock == -1){
  138 + ret = ERROR_SOCKET_CREATE;
  139 + srs_error("create socket error. ret=%d", ret);
  140 + return ret;
  141 + }
  142 +
  143 + stfd = st_netfd_open_socket(sock);
  144 + if(stfd == NULL){
  145 + ret = ERROR_ST_OPEN_SOCKET;
  146 + srs_error("st_netfd_open_socket failed. ret=%d", ret);
  147 + return ret;
  148 + }
  149 +
  150 + srs_freep(client);
  151 + client = new SrsRtmpClient(stfd);
  152 +
  153 + return ret;
  154 +}
  155 +
  156 +int SrsForwarder::connect_server()
  157 +{
  158 + int ret = ERROR_SUCCESS;
  159 +
  160 + std::string ip = parse_server(server);
  161 + if (ip.empty()) {
  162 + ret = ERROR_SYSTEM_IP_INVALID;
  163 + srs_error("dns resolve server error, ip empty. ret=%d", ret);
  164 + return ret;
  165 + }
  166 +
  167 + sockaddr_in addr;
  168 + addr.sin_family = AF_INET;
  169 + addr.sin_port = htons(port);
  170 + addr.sin_addr.s_addr = inet_addr(ip.c_str());
  171 +
  172 + if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
  173 + ret = ERROR_ST_CONNECT;
  174 + srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret);
  175 + return ret;
  176 + }
  177 + srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
  178 +
  179 + return ret;
  180 +}
  181 +
  182 +std::string SrsForwarder::parse_server(std::string host)
  183 +{
  184 + if (inet_addr(host.c_str()) != INADDR_NONE) {
  185 + return host;
  186 + }
  187 +
  188 + hostent* answer = gethostbyname(host.c_str());
  189 + if (answer == NULL) {
  190 + srs_error("dns resolve host %s error.", host.c_str());
  191 + return "";
  192 + }
  193 +
  194 + char ipv4[16];
  195 + memset(ipv4, 0, sizeof(ipv4));
  196 + for (int i = 0; i < answer->h_length; i++) {
  197 + inet_ntop(AF_INET, answer->h_addr_list[i], ipv4, sizeof(ipv4));
  198 + srs_info("dns resolve host %s to %s.", host.c_str(), ipv4);
  199 + break;
  200 + }
  201 +
  202 + return ipv4;
  203 +}
  204 +
  205 +int SrsForwarder::forward_cycle_imp()
  206 +{
  207 + int ret = ERROR_SUCCESS;
  208 +
  209 + client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
  210 + client->set_send_timeout(SRS_SEND_TIMEOUT_US);
  211 +
  212 + if ((ret = connect_server()) != ERROR_SUCCESS) {
  213 + return ret;
  214 + }
  215 + srs_assert(client);
  216 +
  217 + if ((ret = client->handshake()) != ERROR_SUCCESS) {
  218 + srs_error("handshake with server failed. ret=%d", ret);
  219 + return ret;
  220 + }
  221 + if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
  222 + srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
  223 + return ret;
  224 + }
  225 + if ((ret = client->play_stream(stream_name, stream_id)) != ERROR_SUCCESS) {
  226 + srs_error("connect with server failed, stream_name=%s. ret=%d", stream_name.c_str(), ret);
  227 + return ret;
  228 + }
  229 +
  230 + return ret;
  231 +}
  232 +
  233 +void SrsForwarder::forward_cycle()
  234 +{
  235 + int ret = ERROR_SUCCESS;
  236 +
  237 + log_context->generate_id();
  238 + srs_trace("forward cycle start");
  239 +
  240 + while (loop) {
  241 + if ((ret = forward_cycle_imp()) != ERROR_SUCCESS) {
  242 + srs_warn("forward cycle failed, ignored and retry, ret=%d", ret);
  243 + } else {
  244 + srs_info("forward cycle success, retry");
  245 + }
  246 +
  247 + if (!loop) {
  248 + break;
  249 + }
  250 +
  251 + st_usleep(SRS_FORWARDER_SLEEP_MS * 1000);
  252 +
  253 + if ((ret = open_socket()) != ERROR_SUCCESS) {
  254 + srs_warn("forward cycle reopen failed, ignored and retry, ret=%d", ret);
  255 + } else {
  256 + srs_info("forward cycle reopen success");
  257 + }
  258 + }
  259 + srs_trace("forward cycle finished");
  260 +}
  261 +
  262 +void* SrsForwarder::forward_thread(void* arg)
  263 +{
  264 + SrsForwarder* obj = (SrsForwarder*)arg;
  265 + srs_assert(obj != NULL);
  266 +
  267 + obj->loop = true;
  268 + obj->forward_cycle();
  269 +
  270 + return NULL;
  271 +}
  272 +
@@ -43,11 +43,14 @@ class SrsRtmpClient; @@ -43,11 +43,14 @@ class SrsRtmpClient;
43 class SrsForwarder 43 class SrsForwarder
44 { 44 {
45 private: 45 private:
  46 + std::string app;
46 std::string tc_url; 47 std::string tc_url;
47 std::string stream_name; 48 std::string stream_name;
  49 + int stream_id;
48 std::string server; 50 std::string server;
49 int port; 51 int port;
50 private: 52 private:
  53 + st_netfd_t stfd;
51 st_thread_t tid; 54 st_thread_t tid;
52 bool loop; 55 bool loop;
53 private: 56 private:
@@ -61,6 +64,14 @@ public: @@ -61,6 +64,14 @@ public:
61 virtual int on_meta_data(SrsOnMetaDataPacket* metadata); 64 virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
62 virtual int on_audio(SrsSharedPtrMessage* msg); 65 virtual int on_audio(SrsSharedPtrMessage* msg);
63 virtual int on_video(SrsSharedPtrMessage* msg); 66 virtual int on_video(SrsSharedPtrMessage* msg);
  67 +private:
  68 + virtual int open_socket();
  69 + virtual int connect_server();
  70 + std::string parse_server(std::string host);
  71 +private:
  72 + virtual int forward_cycle_imp();
  73 + virtual void forward_cycle();
  74 + static void* forward_thread(void* arg);
64 }; 75 };
65 76
66 #endif 77 #endif
@@ -1067,7 +1067,7 @@ SrsSimpleHandshake::~SrsSimpleHandshake() @@ -1067,7 +1067,7 @@ SrsSimpleHandshake::~SrsSimpleHandshake()
1067 { 1067 {
1068 } 1068 }
1069 1069
1070 -int SrsSimpleHandshake::handshake(SrsSocket& skt, SrsComplexHandshake& complex_hs) 1070 +int SrsSimpleHandshake::handshake_with_client(SrsSocket& skt, SrsComplexHandshake& complex_hs)
1071 { 1071 {
1072 int ret = ERROR_SUCCESS; 1072 int ret = ERROR_SUCCESS;
1073 1073
@@ -1090,7 +1090,7 @@ int SrsSimpleHandshake::handshake(SrsSocket& skt, SrsComplexHandshake& complex_h @@ -1090,7 +1090,7 @@ int SrsSimpleHandshake::handshake(SrsSocket& skt, SrsComplexHandshake& complex_h
1090 srs_verbose("check c0 success, required plain text."); 1090 srs_verbose("check c0 success, required plain text.");
1091 1091
1092 // try complex handshake 1092 // try complex handshake
1093 - ret = complex_hs.handshake(skt, c0c1 + 1); 1093 + ret = complex_hs.handshake_with_client(skt, c0c1 + 1);
1094 if (ret == ERROR_SUCCESS) { 1094 if (ret == ERROR_SUCCESS) {
1095 srs_trace("complex handshake success."); 1095 srs_trace("complex handshake success.");
1096 return ret; 1096 return ret;
@@ -1125,6 +1125,67 @@ int SrsSimpleHandshake::handshake(SrsSocket& skt, SrsComplexHandshake& complex_h @@ -1125,6 +1125,67 @@ int SrsSimpleHandshake::handshake(SrsSocket& skt, SrsComplexHandshake& complex_h
1125 return ret; 1125 return ret;
1126 } 1126 }
1127 1127
  1128 +int SrsSimpleHandshake::handshake_with_server(SrsSocket& skt, SrsComplexHandshake& complex_hs)
  1129 +{
  1130 + int ret = ERROR_SUCCESS;
  1131 +
  1132 + // try complex handshake
  1133 + ret = complex_hs.handshake_with_server(skt);
  1134 + if (ret == ERROR_SUCCESS) {
  1135 + srs_trace("complex handshake success.");
  1136 + return ret;
  1137 + }
  1138 + if (ret != ERROR_RTMP_TRY_SIMPLE_HS) {
  1139 + srs_error("complex handshake failed. ret=%d", ret);
  1140 + return ret;
  1141 + }
  1142 + srs_info("rollback complex to simple handshake. ret=%d", ret);
  1143 +
  1144 + // simple handshake
  1145 + ssize_t nsize;
  1146 +
  1147 + char* c0c1 = new char[1537];
  1148 + SrsAutoFree(char, c0c1, true);
  1149 +
  1150 + srs_random_generate(c0c1, 1537);
  1151 + // plain text required.
  1152 + c0c1[0] = 0x03;
  1153 +
  1154 + if ((ret = skt.write(c0c1, 1537, &nsize)) != ERROR_SUCCESS) {
  1155 + srs_warn("write c0c1 failed. ret=%d", ret);
  1156 + return ret;
  1157 + }
  1158 + srs_verbose("write c0c1 success.");
  1159 +
  1160 + char* s0s1s2 = new char[3073];
  1161 + SrsAutoFree(char, s0s1s2, true);
  1162 + if ((ret = skt.read_fully(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) {
  1163 + srs_warn("simple handshake recv s0s1s2 failed. ret=%d", ret);
  1164 + return ret;
  1165 + }
  1166 + srs_verbose("simple handshake recv s0s1s2 success.");
  1167 +
  1168 + // plain text required.
  1169 + if (s0s1s2[0] != 0x03) {
  1170 + ret = ERROR_RTMP_HANDSHAKE;
  1171 + srs_warn("handshake failed, plain text required. ret=%d", ret);
  1172 + return ret;
  1173 + }
  1174 +
  1175 + char* c2 = new char[1536];
  1176 + SrsAutoFree(char, c2, true);
  1177 + srs_random_generate(c2, 1536);
  1178 + if ((ret = skt.write(c2, 1536, &nsize)) != ERROR_SUCCESS) {
  1179 + srs_warn("simple handshake write c2 failed. ret=%d", ret);
  1180 + return ret;
  1181 + }
  1182 + srs_verbose("simple handshake write c2 success.");
  1183 +
  1184 + srs_trace("simple handshake success.");
  1185 +
  1186 + return ret;
  1187 +}
  1188 +
1128 SrsComplexHandshake::SrsComplexHandshake() 1189 SrsComplexHandshake::SrsComplexHandshake()
1129 { 1190 {
1130 } 1191 }
@@ -1134,12 +1195,12 @@ SrsComplexHandshake::~SrsComplexHandshake() @@ -1134,12 +1195,12 @@ SrsComplexHandshake::~SrsComplexHandshake()
1134 } 1195 }
1135 1196
1136 #ifndef SRS_SSL 1197 #ifndef SRS_SSL
1137 -int SrsComplexHandshake::handshake(SrsSocket& /*skt*/, char* /*_c1*/) 1198 +int SrsComplexHandshake::handshake_with_client(SrsSocket& /*skt*/, char* /*_c1*/)
1138 { 1199 {
1139 return ERROR_RTMP_TRY_SIMPLE_HS; 1200 return ERROR_RTMP_TRY_SIMPLE_HS;
1140 } 1201 }
1141 #else 1202 #else
1142 -int SrsComplexHandshake::handshake(SrsSocket& skt, char* _c1) 1203 +int SrsComplexHandshake::handshake_with_client(SrsSocket& skt, char* _c1)
1143 { 1204 {
1144 int ret = ERROR_SUCCESS; 1205 int ret = ERROR_SUCCESS;
1145 1206
@@ -1216,3 +1277,20 @@ int SrsComplexHandshake::handshake(SrsSocket& skt, char* _c1) @@ -1216,3 +1277,20 @@ int SrsComplexHandshake::handshake(SrsSocket& skt, char* _c1)
1216 } 1277 }
1217 #endif 1278 #endif
1218 1279
  1280 +#ifndef SRS_SSL
  1281 +int SrsComplexHandshake::handshake_with_server(SrsSocket& /*skt*/)
  1282 +{
  1283 + return ERROR_RTMP_TRY_SIMPLE_HS;
  1284 +}
  1285 +#else
  1286 +int SrsComplexHandshake::handshake_with_server(SrsSocket& /*skt*/)
  1287 +{
  1288 + int ret = ERROR_SUCCESS;
  1289 +
  1290 + // TODO: implements complex handshake.
  1291 + ret = ERROR_RTMP_TRY_SIMPLE_HS;
  1292 +
  1293 + return ret;
  1294 +}
  1295 +#endif
  1296 +
@@ -47,7 +47,8 @@ public: @@ -47,7 +47,8 @@ public:
47 * @param complex_hs, try complex handshake first, 47 * @param complex_hs, try complex handshake first,
48 * if failed, rollback to simple handshake. 48 * if failed, rollback to simple handshake.
49 */ 49 */
50 - virtual int handshake(SrsSocket& skt, SrsComplexHandshake& complex_hs); 50 + virtual int handshake_with_client(SrsSocket& skt, SrsComplexHandshake& complex_hs);
  51 + virtual int handshake_with_server(SrsSocket& skt, SrsComplexHandshake& complex_hs);
51 }; 52 };
52 53
53 /** 54 /**
@@ -70,7 +71,8 @@ public: @@ -70,7 +71,8 @@ public:
70 * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS, 71 * try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
71 * otherwise, disconnect 72 * otherwise, disconnect
72 */ 73 */
73 - virtual int handshake(SrsSocket& skt, char* _c1); 74 + virtual int handshake_with_client(SrsSocket& skt, char* _c1);
  75 + virtual int handshake_with_server(SrsSocket& skt);
74 }; 76 };
75 77
76 #endif 78 #endif
@@ -199,6 +199,7 @@ messages. @@ -199,6 +199,7 @@ messages.
199 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" 199 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone"
200 #define RTMP_AMF0_COMMAND_ON_STATUS "onStatus" 200 #define RTMP_AMF0_COMMAND_ON_STATUS "onStatus"
201 #define RTMP_AMF0_COMMAND_RESULT "_result" 201 #define RTMP_AMF0_COMMAND_RESULT "_result"
  202 +#define RTMP_AMF0_COMMAND_ERROR "_error"
202 #define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream" 203 #define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream"
203 #define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish" 204 #define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish"
204 #define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish" 205 #define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish"
@@ -282,6 +283,15 @@ SrsProtocol::~SrsProtocol() @@ -282,6 +283,15 @@ SrsProtocol::~SrsProtocol()
282 srs_freep(skt); 283 srs_freep(skt);
283 } 284 }
284 285
  286 +std::string SrsProtocol::get_request_name(double transcationId)
  287 +{
  288 + if (requests.find(transcationId) == requests.end()) {
  289 + return "";
  290 + }
  291 +
  292 + return requests[transcationId];
  293 +}
  294 +
285 void SrsProtocol::set_recv_timeout(int64_t timeout_us) 295 void SrsProtocol::set_recv_timeout(int64_t timeout_us)
286 { 296 {
287 return skt->set_recv_timeout(timeout_us); 297 return skt->set_recv_timeout(timeout_us);
@@ -548,7 +558,7 @@ int SrsProtocol::on_recv_message(SrsCommonMessage* msg) @@ -548,7 +558,7 @@ int SrsProtocol::on_recv_message(SrsCommonMessage* msg)
548 case RTMP_MSG_SetChunkSize: 558 case RTMP_MSG_SetChunkSize:
549 case RTMP_MSG_UserControlMessage: 559 case RTMP_MSG_UserControlMessage:
550 case RTMP_MSG_WindowAcknowledgementSize: 560 case RTMP_MSG_WindowAcknowledgementSize:
551 - if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { 561 + if ((ret = msg->decode_packet(this)) != ERROR_SUCCESS) {
552 srs_error("decode packet from message payload failed. ret=%d", ret); 562 srs_error("decode packet from message payload failed. ret=%d", ret);
553 return ret; 563 return ret;
554 } 564 }
@@ -624,6 +634,17 @@ int SrsProtocol::on_send_message(ISrsMessage* msg) @@ -624,6 +634,17 @@ int SrsProtocol::on_send_message(ISrsMessage* msg)
624 srs_trace("set output chunk size to %d", pkt->chunk_size); 634 srs_trace("set output chunk size to %d", pkt->chunk_size);
625 break; 635 break;
626 } 636 }
  637 + case RTMP_MSG_AMF0CommandMessage:
  638 + case RTMP_MSG_AMF3CommandMessage: {
  639 + if (true) {
  640 + SrsConnectAppPacket* pkt = NULL;
  641 + pkt = dynamic_cast<SrsConnectAppPacket*>(common_msg->get_packet());
  642 + if (pkt) {
  643 + requests[pkt->transaction_id] = RTMP_AMF0_COMMAND_CONNECT;
  644 + }
  645 + }
  646 + break;
  647 + }
627 } 648 }
628 649
629 return ret; 650 return ret;
@@ -1157,7 +1178,7 @@ bool SrsCommonMessage::can_decode() @@ -1157,7 +1178,7 @@ bool SrsCommonMessage::can_decode()
1157 return true; 1178 return true;
1158 } 1179 }
1159 1180
1160 -int SrsCommonMessage::decode_packet() 1181 +int SrsCommonMessage::decode_packet(SrsProtocol* protocol)
1161 { 1182 {
1162 int ret = ERROR_SUCCESS; 1183 int ret = ERROR_SUCCESS;
1163 1184
@@ -1201,6 +1222,39 @@ int SrsCommonMessage::decode_packet() @@ -1201,6 +1222,39 @@ int SrsCommonMessage::decode_packet()
1201 } 1222 }
1202 srs_verbose("AMF0/AMF3 command message, command_name=%s", command.c_str()); 1223 srs_verbose("AMF0/AMF3 command message, command_name=%s", command.c_str());
1203 1224
  1225 + // result/error packet
  1226 + if (command == RTMP_AMF0_COMMAND_RESULT || command == RTMP_AMF0_COMMAND_ERROR) {
  1227 + double transactionId = 0.0;
  1228 + if ((ret = srs_amf0_read_number(stream, transactionId)) != ERROR_SUCCESS) {
  1229 + srs_error("decode AMF0/AMF3 transcationId failed. ret=%d", ret);
  1230 + return ret;
  1231 + }
  1232 + srs_verbose("AMF0/AMF3 command id, transcationId=%.2f", transactionId);
  1233 +
  1234 + // reset stream, for header read completed.
  1235 + stream->reset();
  1236 +
  1237 + std::string request_name = protocol->get_request_name(transactionId);
  1238 + if (request_name.empty()) {
  1239 + ret = ERROR_RTMP_NO_REQUEST;
  1240 + srs_error("decode AMF0/AMF3 request failed. ret=%d", ret);
  1241 + return ret;
  1242 + }
  1243 + srs_verbose("AMF0/AMF3 request parsed. request_name=%s", request_name.c_str());
  1244 +
  1245 + if (request_name == RTMP_AMF0_COMMAND_CONNECT) {
  1246 + srs_info("decode the AMF0/AMF3 response command(connect vhost/app message).");
  1247 + packet = new SrsConnectAppResPacket();
  1248 + return packet->decode(stream);
  1249 + } else {
  1250 + ret = ERROR_RTMP_NO_REQUEST;
  1251 + srs_error("decode AMF0/AMF3 request failed. "
  1252 + "request_name=%s, transactionId=%.2f, ret=%d",
  1253 + request_name.c_str(), transactionId, ret);
  1254 + return ret;
  1255 + }
  1256 + }
  1257 +
1204 // reset to zero(amf3 to 1) to restart decode. 1258 // reset to zero(amf3 to 1) to restart decode.
1205 stream->reset(); 1259 stream->reset();
1206 if (header.is_amf3_command()) { 1260 if (header.is_amf3_command()) {
@@ -1319,7 +1373,13 @@ int SrsCommonMessage::encode_packet() @@ -1319,7 +1373,13 @@ int SrsCommonMessage::encode_packet()
1319 size = 0; 1373 size = 0;
1320 srs_freepa(payload); 1374 srs_freepa(payload);
1321 1375
1322 - return packet->encode(size, (char*&)payload); 1376 + if ((ret = packet->encode(size, (char*&)payload)) != ERROR_SUCCESS) {
  1377 + return ret;
  1378 + }
  1379 +
  1380 + header.payload_length = size;
  1381 +
  1382 + return ret;
1323 } 1383 }
1324 1384
1325 SrsSharedPtrMessage::SrsSharedPtr::SrsSharedPtr() 1385 SrsSharedPtrMessage::SrsSharedPtr::SrsSharedPtr()
@@ -1582,6 +1642,49 @@ int SrsConnectAppPacket::decode(SrsStream* stream) @@ -1582,6 +1642,49 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
1582 return ret; 1642 return ret;
1583 } 1643 }
1584 1644
  1645 +int SrsConnectAppPacket::get_perfer_cid()
  1646 +{
  1647 + return RTMP_CID_OverConnection;
  1648 +}
  1649 +
  1650 +int SrsConnectAppPacket::get_message_type()
  1651 +{
  1652 + return RTMP_MSG_AMF0CommandMessage;
  1653 +}
  1654 +
  1655 +int SrsConnectAppPacket::get_size()
  1656 +{
  1657 + return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size()
  1658 + + srs_amf0_get_object_size(command_object);
  1659 +}
  1660 +
  1661 +int SrsConnectAppPacket::encode_packet(SrsStream* stream)
  1662 +{
  1663 + int ret = ERROR_SUCCESS;
  1664 +
  1665 + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) {
  1666 + srs_error("encode command_name failed. ret=%d", ret);
  1667 + return ret;
  1668 + }
  1669 + srs_verbose("encode command_name success.");
  1670 +
  1671 + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) {
  1672 + srs_error("encode transaction_id failed. ret=%d", ret);
  1673 + return ret;
  1674 + }
  1675 + srs_verbose("encode transaction_id success.");
  1676 +
  1677 + if ((ret = srs_amf0_write_object(stream, command_object)) != ERROR_SUCCESS) {
  1678 + srs_error("encode command_object failed. ret=%d", ret);
  1679 + return ret;
  1680 + }
  1681 + srs_verbose("encode command_object success.");
  1682 +
  1683 + srs_info("encode connect app request packet success.");
  1684 +
  1685 + return ret;
  1686 +}
  1687 +
1585 SrsConnectAppResPacket::SrsConnectAppResPacket() 1688 SrsConnectAppResPacket::SrsConnectAppResPacket()
1586 { 1689 {
1587 command_name = RTMP_AMF0_COMMAND_RESULT; 1690 command_name = RTMP_AMF0_COMMAND_RESULT;
@@ -1596,6 +1699,57 @@ SrsConnectAppResPacket::~SrsConnectAppResPacket() @@ -1596,6 +1699,57 @@ SrsConnectAppResPacket::~SrsConnectAppResPacket()
1596 srs_freep(info); 1699 srs_freep(info);
1597 } 1700 }
1598 1701
  1702 +int SrsConnectAppResPacket::decode(SrsStream* stream)
  1703 +{
  1704 + int ret = ERROR_SUCCESS;
  1705 +
  1706 + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
  1707 + srs_error("amf0 decode connect command_name failed. ret=%d", ret);
  1708 + return ret;
  1709 + }
  1710 + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_RESULT) {
  1711 + ret = ERROR_RTMP_AMF0_DECODE;
  1712 + srs_error("amf0 decode connect command_name failed. "
  1713 + "command_name=%s, ret=%d", command_name.c_str(), ret);
  1714 + return ret;
  1715 + }
  1716 +
  1717 + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) {
  1718 + srs_error("amf0 decode connect transaction_id failed. ret=%d", ret);
  1719 + return ret;
  1720 + }
  1721 + if (transaction_id != 1.0) {
  1722 + ret = ERROR_RTMP_AMF0_DECODE;
  1723 + srs_error("amf0 decode connect transaction_id failed. "
  1724 + "required=%.1f, actual=%.1f, ret=%d", 1.0, transaction_id, ret);
  1725 + return ret;
  1726 + }
  1727 +
  1728 + if ((ret = srs_amf0_read_object(stream, props)) != ERROR_SUCCESS) {
  1729 + srs_error("amf0 decode connect props failed. ret=%d", ret);
  1730 + return ret;
  1731 + }
  1732 + if (props == NULL) {
  1733 + ret = ERROR_RTMP_AMF0_DECODE;
  1734 + srs_error("amf0 decode connect props failed. ret=%d", ret);
  1735 + return ret;
  1736 + }
  1737 +
  1738 + if ((ret = srs_amf0_read_object(stream, info)) != ERROR_SUCCESS) {
  1739 + srs_error("amf0 decode connect info failed. ret=%d", ret);
  1740 + return ret;
  1741 + }
  1742 + if (info == NULL) {
  1743 + ret = ERROR_RTMP_AMF0_DECODE;
  1744 + srs_error("amf0 decode connect info failed. ret=%d", ret);
  1745 + return ret;
  1746 + }
  1747 +
  1748 + srs_info("amf0 decode connect response packet success");
  1749 +
  1750 + return ret;
  1751 +}
  1752 +
1599 int SrsConnectAppResPacket::get_perfer_cid() 1753 int SrsConnectAppResPacket::get_perfer_cid()
1600 { 1754 {
1601 return RTMP_CID_OverConnection; 1755 return RTMP_CID_OverConnection;
@@ -88,6 +88,12 @@ private: @@ -88,6 +88,12 @@ private:
88 st_netfd_t stfd; 88 st_netfd_t stfd;
89 SrsSocket* skt; 89 SrsSocket* skt;
90 char* pp; 90 char* pp;
  91 + /**
  92 + * requests sent out, used to build the response.
  93 + * key: transactionId
  94 + * value: the request command name
  95 + */
  96 + std::map<double, std::string> requests;
91 // peer in 97 // peer in
92 private: 98 private:
93 std::map<int, SrsChunkStream*> chunk_streams; 99 std::map<int, SrsChunkStream*> chunk_streams;
@@ -103,6 +109,7 @@ public: @@ -103,6 +109,7 @@ public:
103 SrsProtocol(st_netfd_t client_stfd); 109 SrsProtocol(st_netfd_t client_stfd);
104 virtual ~SrsProtocol(); 110 virtual ~SrsProtocol();
105 public: 111 public:
  112 + std::string get_request_name(double transcationId);
106 /** 113 /**
107 * set the timeout in us. 114 * set the timeout in us.
108 * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT. 115 * if timeout, recv/send message return ERROR_SOCKET_TIMEOUT.
@@ -319,7 +326,7 @@ public: @@ -319,7 +326,7 @@ public:
319 /** 326 /**
320 * decode packet from message payload. 327 * decode packet from message payload.
321 */ 328 */
322 - virtual int decode_packet(); 329 + virtual int decode_packet(SrsProtocol* protocol);
323 /** 330 /**
324 * get the decoded packet which decoded by decode_packet(). 331 * get the decoded packet which decoded by decode_packet().
325 * @remark, user never free the pkt, the message will auto free it. 332 * @remark, user never free the pkt, the message will auto free it.
@@ -481,6 +488,13 @@ public: @@ -481,6 +488,13 @@ public:
481 virtual ~SrsConnectAppPacket(); 488 virtual ~SrsConnectAppPacket();
482 public: 489 public:
483 virtual int decode(SrsStream* stream); 490 virtual int decode(SrsStream* stream);
  491 +public:
  492 + virtual int get_perfer_cid();
  493 +public:
  494 + virtual int get_message_type();
  495 +protected:
  496 + virtual int get_size();
  497 + virtual int encode_packet(SrsStream* stream);
484 }; 498 };
485 /** 499 /**
486 * response for SrsConnectAppPacket. 500 * response for SrsConnectAppPacket.
@@ -503,6 +517,8 @@ public: @@ -503,6 +517,8 @@ public:
503 SrsConnectAppResPacket(); 517 SrsConnectAppResPacket();
504 virtual ~SrsConnectAppResPacket(); 518 virtual ~SrsConnectAppResPacket();
505 public: 519 public:
  520 + virtual int decode(SrsStream* stream);
  521 +public:
506 virtual int get_perfer_cid(); 522 virtual int get_perfer_cid();
507 public: 523 public:
508 virtual int get_message_type(); 524 virtual int get_message_type();
@@ -1076,7 +1092,7 @@ int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T** @@ -1076,7 +1092,7 @@ int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T**
1076 } 1092 }
1077 srs_verbose("recv message success."); 1093 srs_verbose("recv message success.");
1078 1094
1079 - if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { 1095 + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) {
1080 delete msg; 1096 delete msg;
1081 srs_error("decode message failed. ret=%d", ret); 1097 srs_error("decode message failed. ret=%d", ret);
1082 return ret; 1098 return ret;
@@ -23,11 +23,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -23,11 +23,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 23
24 #include <srs_core_rtmp.hpp> 24 #include <srs_core_rtmp.hpp>
25 25
26 -#include <sys/socket.h>  
27 -#include <netinet/in.h>  
28 -#include <arpa/inet.h>  
29 -#include <netdb.h>  
30 -  
31 #include <srs_core_log.hpp> 26 #include <srs_core_log.hpp>
32 #include <srs_core_error.hpp> 27 #include <srs_core_error.hpp>
33 #include <srs_core_socket.hpp> 28 #include <srs_core_socket.hpp>
@@ -168,50 +163,104 @@ SrsResponse::~SrsResponse() @@ -168,50 +163,104 @@ SrsResponse::~SrsResponse()
168 { 163 {
169 } 164 }
170 165
171 -SrsRtmpClient::SrsRtmpClient() 166 +SrsRtmpClient::SrsRtmpClient(st_netfd_t _stfd)
172 { 167 {
173 - stfd = NULL; 168 + stfd = _stfd;
  169 + protocol = new SrsProtocol(stfd);
174 } 170 }
175 171
176 SrsRtmpClient::~SrsRtmpClient() 172 SrsRtmpClient::~SrsRtmpClient()
177 { 173 {
178 - if (stfd) {  
179 - int fd = st_netfd_fileno(stfd);  
180 - st_netfd_close(stfd);  
181 - stfd = NULL;  
182 -  
183 - // st does not close it sometimes,  
184 - // close it manually.  
185 - close(fd);  
186 - } 174 + srs_freep(protocol);
187 } 175 }
188 176
189 -int SrsRtmpClient::connect_to(std::string server, int port) 177 +void SrsRtmpClient::set_recv_timeout(int64_t timeout_us)
190 { 178 {
191 - int ret = ERROR_SUCCESS;  
192 - return ret; 179 + protocol->set_recv_timeout(timeout_us);
193 } 180 }
194 181
195 -std::string SrsRtmpClient::parse_server(std::string host){  
196 - if(inet_addr(host.c_str()) != INADDR_NONE){  
197 - return host;  
198 - }  
199 -  
200 - hostent* answer = gethostbyname(host.c_str());  
201 - if(answer == NULL){  
202 - srs_error("dns resolve host %s error.", host.c_str());  
203 - return "";  
204 - } 182 +void SrsRtmpClient::set_send_timeout(int64_t timeout_us)
  183 +{
  184 + protocol->set_send_timeout(timeout_us);
  185 +}
  186 +
  187 +int SrsRtmpClient::handshake()
  188 +{
  189 + int ret = ERROR_SUCCESS;
  190 +
  191 + SrsSocket skt(stfd);
205 192
206 - char ipv4[16];  
207 - memset(ipv4, 0, sizeof(ipv4));  
208 - for(int i = 0; i < answer->h_length; i++){  
209 - inet_ntop(AF_INET, answer->h_addr_list[i], ipv4, sizeof(ipv4));  
210 - srs_info("dns resolve host %s to %s.", host.c_str(), ipv4);  
211 - break; 193 + SrsComplexHandshake complex_hs;
  194 + SrsSimpleHandshake simple_hs;
  195 + if ((ret = simple_hs.handshake_with_server(skt, complex_hs)) != ERROR_SUCCESS) {
  196 + return ret;
212 } 197 }
213 198
214 - return ipv4; 199 + return ret;
  200 +}
  201 +
  202 +int SrsRtmpClient::connect_app(std::string app, std::string tc_url)
  203 +{
  204 + int ret = ERROR_SUCCESS;
  205 +
  206 + // Connect(vhost, app)
  207 + if (true) {
  208 + SrsCommonMessage* msg = new SrsCommonMessage();
  209 + SrsConnectAppPacket* pkt = new SrsConnectAppPacket();
  210 + msg->set_packet(pkt, 0);
  211 +
  212 + pkt->command_object = new SrsAmf0Object();
  213 + pkt->command_object->set("app", new SrsAmf0String(app.c_str()));
  214 + pkt->command_object->set("swfUrl", new SrsAmf0String());
  215 + pkt->command_object->set("tcUrl", new SrsAmf0String(tc_url.c_str()));
  216 + pkt->command_object->set("fpad", new SrsAmf0Boolean(false));
  217 + pkt->command_object->set("capabilities", new SrsAmf0Number(239));
  218 + pkt->command_object->set("audioCodecs", new SrsAmf0Number(3575));
  219 + pkt->command_object->set("videoCodecs", new SrsAmf0Number(252));
  220 + pkt->command_object->set("videoFunction", new SrsAmf0Number(1));
  221 + pkt->command_object->set("pageUrl", new SrsAmf0String());
  222 + pkt->command_object->set("objectEncoding", new SrsAmf0Number(0));
  223 +
  224 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  225 + return ret;
  226 + }
  227 + }
  228 +
  229 + // Set Window Acknowledgement size(2500000)
  230 + if (true) {
  231 + SrsCommonMessage* msg = new SrsCommonMessage();
  232 + SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket();
  233 +
  234 + pkt->ackowledgement_window_size = 2500000;
  235 + msg->set_packet(pkt, 0);
  236 +
  237 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  238 + return ret;
  239 + }
  240 + }
  241 +
  242 + // expect connect _result
  243 + SrsCommonMessage* msg = NULL;
  244 + SrsConnectAppResPacket* pkt = NULL;
  245 + if ((ret = srs_rtmp_expect_message<SrsConnectAppResPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
  246 + srs_error("expect connect app response message failed. ret=%d", ret);
  247 + return ret;
  248 + }
  249 + SrsAutoFree(SrsCommonMessage, msg, false);
  250 + srs_info("get connect app response message");
  251 +
  252 + return ret;
  253 +}
  254 +
  255 +int SrsRtmpClient::play_stream(std::string stream, int& stream_id)
  256 +{
  257 + int ret = ERROR_SUCCESS;
  258 +
  259 + // CreateStream
  260 + if (true) {
  261 + }
  262 +
  263 + return ret;
215 } 264 }
216 265
217 SrsRtmp::SrsRtmp(st_netfd_t client_stfd) 266 SrsRtmp::SrsRtmp(st_netfd_t client_stfd)
@@ -225,9 +274,14 @@ SrsRtmp::~SrsRtmp() @@ -225,9 +274,14 @@ SrsRtmp::~SrsRtmp()
225 srs_freep(protocol); 274 srs_freep(protocol);
226 } 275 }
227 276
  277 +SrsProtocol* SrsRtmp::get_protocol()
  278 +{
  279 + return protocol;
  280 +}
  281 +
228 void SrsRtmp::set_recv_timeout(int64_t timeout_us) 282 void SrsRtmp::set_recv_timeout(int64_t timeout_us)
229 { 283 {
230 - return protocol->set_recv_timeout(timeout_us); 284 + protocol->set_recv_timeout(timeout_us);
231 } 285 }
232 286
233 int64_t SrsRtmp::get_recv_timeout() 287 int64_t SrsRtmp::get_recv_timeout()
@@ -237,7 +291,7 @@ int64_t SrsRtmp::get_recv_timeout() @@ -237,7 +291,7 @@ int64_t SrsRtmp::get_recv_timeout()
237 291
238 void SrsRtmp::set_send_timeout(int64_t timeout_us) 292 void SrsRtmp::set_send_timeout(int64_t timeout_us)
239 { 293 {
240 - return protocol->set_send_timeout(timeout_us); 294 + protocol->set_send_timeout(timeout_us);
241 } 295 }
242 296
243 int64_t SrsRtmp::get_recv_bytes() 297 int64_t SrsRtmp::get_recv_bytes()
@@ -278,7 +332,7 @@ int SrsRtmp::handshake() @@ -278,7 +332,7 @@ int SrsRtmp::handshake()
278 332
279 SrsComplexHandshake complex_hs; 333 SrsComplexHandshake complex_hs;
280 SrsSimpleHandshake simple_hs; 334 SrsSimpleHandshake simple_hs;
281 - if ((ret = simple_hs.handshake(skt, complex_hs)) != ERROR_SUCCESS) { 335 + if ((ret = simple_hs.handshake_with_client(skt, complex_hs)) != ERROR_SUCCESS) {
282 return ret; 336 return ret;
283 } 337 }
284 338
@@ -441,7 +495,7 @@ int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& st @@ -441,7 +495,7 @@ int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& st
441 continue; 495 continue;
442 } 496 }
443 497
444 - if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { 498 + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) {
445 srs_error("identify decode message failed. ret=%d", ret); 499 srs_error("identify decode message failed. ret=%d", ret);
446 return ret; 500 return ret;
447 } 501 }
@@ -884,7 +938,7 @@ int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int strea @@ -884,7 +938,7 @@ int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int strea
884 continue; 938 continue;
885 } 939 }
886 940
887 - if ((ret = msg->decode_packet()) != ERROR_SUCCESS) { 941 + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) {
888 srs_error("identify decode message failed. ret=%d", ret); 942 srs_error("identify decode message failed. ret=%d", ret);
889 return ret; 943 return ret;
890 } 944 }
@@ -100,13 +100,18 @@ enum SrsClientType @@ -100,13 +100,18 @@ enum SrsClientType
100 class SrsRtmpClient 100 class SrsRtmpClient
101 { 101 {
102 private: 102 private:
  103 + SrsProtocol* protocol;
103 st_netfd_t stfd; 104 st_netfd_t stfd;
104 public: 105 public:
105 - SrsRtmpClient(); 106 + SrsRtmpClient(st_netfd_t _stfd);
106 virtual ~SrsRtmpClient(); 107 virtual ~SrsRtmpClient();
107 -private:  
108 - virtual int connect_to(std::string server, int port);  
109 - std::string parse_server(std::string host); 108 +public:
  109 + virtual void set_recv_timeout(int64_t timeout_us);
  110 + virtual void set_send_timeout(int64_t timeout_us);
  111 +public:
  112 + virtual int handshake();
  113 + virtual int connect_app(std::string app, std::string tc_url);
  114 + virtual int play_stream(std::string stream, int& stream_id);
110 }; 115 };
111 116
112 /** 117 /**
@@ -123,6 +128,7 @@ public: @@ -123,6 +128,7 @@ public:
123 SrsRtmp(st_netfd_t client_stfd); 128 SrsRtmp(st_netfd_t client_stfd);
124 virtual ~SrsRtmp(); 129 virtual ~SrsRtmp();
125 public: 130 public:
  131 + virtual SrsProtocol* get_protocol();
126 virtual void set_recv_timeout(int64_t timeout_us); 132 virtual void set_recv_timeout(int64_t timeout_us);
127 virtual int64_t get_recv_timeout(); 133 virtual int64_t get_recv_timeout();
128 virtual void set_send_timeout(int64_t timeout_us); 134 virtual void set_send_timeout(int64_t timeout_us);