winlin

srs-librtmp: add make ssl/nossl support for sample

@@ -39,6 +39,13 @@ echo "" >> $SRS_AUTO_HEADERS_H @@ -39,6 +39,13 @@ echo "" >> $SRS_AUTO_HEADERS_H
39 ##################################################################################### 39 #####################################################################################
40 40
41 ##################################################################################### 41 #####################################################################################
  42 +# srs-librtmp sample entry
  43 +SrsLibrtmpSampleEntry="nossl"
  44 +if [ $SRS_SSL = YES ]; then
  45 + SrsLibrtmpSampleEntry="ssl"
  46 +fi
  47 +
  48 +# makefile
42 echo "generate Makefile" 49 echo "generate Makefile"
43 SRS_MAKEFILE="Makefile" 50 SRS_MAKEFILE="Makefile"
44 cat << END > ${SRS_MAKEFILE} 51 cat << END > ${SRS_MAKEFILE}
@@ -86,7 +93,7 @@ librtmp: _prepare_dir @@ -86,7 +93,7 @@ librtmp: _prepare_dir
86 93
87 librtmp-sample: 94 librtmp-sample:
88 @echo "build the srs-librtmp sample" 95 @echo "build the srs-librtmp sample"
89 - (cd research/librtmp; make) 96 + (cd research/librtmp; make ${SrsLibrtmpSampleEntry})
90 @echo "srs-librtmp sample build success" 97 @echo "srs-librtmp sample build success"
91 98
92 # the ./configure will generate it. 99 # the ./configure will generate it.
1 -.PHONY: default clean 1 +.PHONY: default clean help ssl nossl
2 2
3 -default: srs_publish srs_play 3 +default: help
  4 +
  5 +help:
  6 + @echo "Usage: make <help>|<clean>|<srs_publish_nossl>|<srs_play_nossl>|<srs_publish_ssl>|<srs_play_ssl>"
  7 + @echo " help display this help"
  8 + @echo " clean cleanup build"
  9 + @echo " ssl srs_publish_ssl, srs_play_ssl"
  10 + @echo " nossl srs_publish_nossl, srs_play_nossl"
  11 + @echo " srs_publish_nossl publish program using srs-librtmp, without ssl(simple handshake)"
  12 + @echo " srs_play_nossl play program using srs-librtmp, without ssl(simple handshake)"
  13 + @echo " srs_publish_ssl publish program using srs-librtmp, with ssl(complex handshake)"
  14 + @echo " srs_play_ssl play program using srs-librtmp, with ssl(complex handshake)"
  15 + @echo "Remark: about simple/complex handshake, see: http://blog.csdn.net/win_lin/article/details/13006803"
  16 + @echo "Remark: srs Makefile will auto invoke this by --with/without-ssl, "
  17 + @echo " that is, if user specified ssl(by --with-ssl), srs will make this by 'make ssl'"
  18 + @echo " that is, if user not use ssl(by --without-ssl), use 'make nossl'"
  19 + @echo " see: https://github.com/winlinvip/simple-rtmp-server/wiki/Build"
  20 + @echo "Remark: before make this sample, user must make the srs, with/without ssl"
4 21
5 clean: 22 clean:
6 - @rm -f srs_publish srs_play 23 + @rm -f srs_publish_nossl srs_play_nossl srs_publish_ssl srs_play_ssl
  24 +
  25 +# srs library root
  26 +SRS_OBJS = ../../objs
  27 +# srs-librtmp for publish/play, built by srs.
  28 +SRS_LIBRTMP_I = $(SRS_OBJS)/include/srs_librtmp.h
  29 +SRS_LIBRTMP_L = $(SRS_OBJS)/lib/srs_librtmp.a
  30 +# openssl for complex handshake, built by srs.
  31 +SRS_LIBSSL_L = $(SRS_OBJS)/openssl/lib/libssl.a $(SRS_OBJS)/openssl/lib/libcrypto.a
  32 +
  33 +srs_publish_nossl: srs_publish.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L)
  34 + gcc srs_publish.c $(SRS_LIBRTMP_L) -g -O0 -lstdc++ -o srs_publish_nossl
  35 +
  36 +srs_play_nossl: srs_play.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L)
  37 + gcc srs_play.c $(SRS_LIBRTMP_L) -g -O0 -lstdc++ -o srs_play_nossl
  38 +
  39 +srs_publish_ssl: srs_publish.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
  40 + gcc srs_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) -g -O0 -ldl -lstdc++ -o srs_publish_ssl
7 41
8 -srs_publish: srs_publish.c Makefile ../../objs/include/srs_librtmp.h ../../objs/lib/srs_librtmp.a  
9 - gcc srs_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_publish 42 +srs_play_ssl: srs_play.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
  43 + gcc srs_play.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) -g -O0 -ldl -lstdc++ -o srs_play_ssl
10 44
11 -srs_play: srs_play.c Makefile ../../objs/include/srs_librtmp.h ../../objs/lib/srs_librtmp.a  
12 - gcc srs_play.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_play 45 +# alias for publish/play with/without ssl
  46 +ssl: srs_publish_ssl srs_play_ssl
  47 +nossl: srs_publish_nossl srs_play_nossl
@@ -35,9 +35,10 @@ int main(int argc, char** argv) @@ -35,9 +35,10 @@ int main(int argc, char** argv)
35 printf("srs(simple-rtmp-server) client librtmp library.\n"); 35 printf("srs(simple-rtmp-server) client librtmp library.\n");
36 printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); 36 printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
37 37
38 - rtmp = srs_rtmp_create("rtmp://127.0.0.1/live/livestream"); 38 + rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live/show?vhost=__defaultVhost__/livestream");
39 39
40 - if (srs_simple_handshake(rtmp) != 0) { 40 + //if (srs_simple_handshake(rtmp) != 0) {
  41 + if (srs_complex_handshake(rtmp) != 0) {
41 printf("simple handshake failed.\n"); 42 printf("simple handshake failed.\n");
42 goto rtmp_destroy; 43 goto rtmp_destroy;
43 } 44 }
@@ -35,7 +35,7 @@ int main(int argc, char** argv) @@ -35,7 +35,7 @@ int main(int argc, char** argv)
35 printf("srs(simple-rtmp-server) client librtmp library.\n"); 35 printf("srs(simple-rtmp-server) client librtmp library.\n");
36 printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); 36 printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
37 37
38 - rtmp = srs_rtmp_create("rtmp://127.0.0.1/live/livestream"); 38 + rtmp = srs_rtmp_create("rtmp://127.0.0.1:1936/live/livestream");
39 39
40 if (srs_simple_handshake(rtmp) != 0) { 40 if (srs_simple_handshake(rtmp) != 0) {
41 printf("simple handshake failed.\n"); 41 printf("simple handshake failed.\n");
@@ -71,6 +71,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -71,6 +71,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
71 #define ERROR_RTMP_ACCESS_DENIED 315 71 #define ERROR_RTMP_ACCESS_DENIED 315
72 #define ERROR_RTMP_HANDSHAKE 316 72 #define ERROR_RTMP_HANDSHAKE 316
73 #define ERROR_RTMP_NO_REQUEST 317 73 #define ERROR_RTMP_NO_REQUEST 317
  74 +// if user use complex handshake, but without ssl,
  75 +// 1. srs is ok, ignore and turn to simple handshake.
  76 +// 2. srs-librtmp return error, to terminate the program.
  77 +#define ERROR_RTMP_HS_SSL_REQUIRE 318
74 78
75 #define ERROR_SYSTEM_STREAM_INIT 400 79 #define ERROR_SYSTEM_STREAM_INIT 400
76 #define ERROR_SYSTEM_PACKET_INVALID 401 80 #define ERROR_SYSTEM_PACKET_INVALID 401
@@ -28,6 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -28,6 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <unistd.h> 28 #include <unistd.h>
29 #include <sys/types.h> 29 #include <sys/types.h>
30 #include <sys/socket.h> 30 #include <sys/socket.h>
  31 +#include <netinet/in.h>
  32 +#include <arpa/inet.h>
31 33
32 SimpleSocketStream::SimpleSocketStream() 34 SimpleSocketStream::SimpleSocketStream()
33 { 35 {
@@ -44,11 +46,101 @@ SimpleSocketStream::~SimpleSocketStream() @@ -44,11 +46,101 @@ SimpleSocketStream::~SimpleSocketStream()
44 46
45 int SimpleSocketStream::create_socket() 47 int SimpleSocketStream::create_socket()
46 { 48 {
47 - fd = ::socket(AF_INET, SOCK_STREAM, 0);  
48 - if(fd == -1){ 49 + if((fd = ::socket(AF_INET, SOCK_STREAM, 0)) < 0){
49 return -1; 50 return -1;
50 } 51 }
51 52
52 return ERROR_SUCCESS; 53 return ERROR_SUCCESS;
53 } 54 }
54 55
  56 +int SimpleSocketStream::connect(const char* server_ip, int port)
  57 +{
  58 + sockaddr_in addr;
  59 + addr.sin_family = AF_INET;
  60 + addr.sin_port = htons(port);
  61 + addr.sin_addr.s_addr = inet_addr(server_ip);
  62 +
  63 + if(::connect(fd, (const struct sockaddr*)&addr, sizeof(sockaddr_in)) < 0){
  64 + return -1;
  65 + }
  66 +
  67 + return ERROR_SUCCESS;
  68 +}
  69 +
  70 +// ISrsBufferReader
  71 +int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread)
  72 +{
  73 + int ret = ERROR_SUCCESS;
  74 + return ret;
  75 +}
  76 +
  77 +// ISrsProtocolReader
  78 +void SimpleSocketStream::set_recv_timeout(int64_t timeout_us)
  79 +{
  80 +}
  81 +
  82 +int64_t SimpleSocketStream::get_recv_timeout()
  83 +{
  84 + int ret = ERROR_SUCCESS;
  85 + return ret;
  86 +}
  87 +
  88 +int64_t SimpleSocketStream::get_recv_bytes()
  89 +{
  90 + int ret = ERROR_SUCCESS;
  91 + return ret;
  92 +}
  93 +
  94 +int SimpleSocketStream::get_recv_kbps()
  95 +{
  96 + int ret = ERROR_SUCCESS;
  97 + return ret;
  98 +}
  99 +
  100 +// ISrsProtocolWriter
  101 +void SimpleSocketStream::set_send_timeout(int64_t timeout_us)
  102 +{
  103 +}
  104 +
  105 +int64_t SimpleSocketStream::get_send_timeout()
  106 +{
  107 + int ret = ERROR_SUCCESS;
  108 + return ret;
  109 +}
  110 +
  111 +int64_t SimpleSocketStream::get_send_bytes()
  112 +{
  113 + int ret = ERROR_SUCCESS;
  114 + return ret;
  115 +}
  116 +
  117 +int SimpleSocketStream::get_send_kbps()
  118 +{
  119 + int ret = ERROR_SUCCESS;
  120 + return ret;
  121 +}
  122 +
  123 +int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
  124 +{
  125 + int ret = ERROR_SUCCESS;
  126 + return ret;
  127 +}
  128 +
  129 +// ISrsProtocolReaderWriter
  130 +bool SimpleSocketStream::is_never_timeout(int64_t timeout_us)
  131 +{
  132 + return true;
  133 +}
  134 +
  135 +int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread)
  136 +{
  137 + int ret = ERROR_SUCCESS;
  138 + return ret;
  139 +}
  140 +
  141 +int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite)
  142 +{
  143 + int ret = ERROR_SUCCESS;
  144 + return ret;
  145 +}
  146 +
@@ -27,11 +27,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -27,11 +27,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 /* 27 /*
28 #include <srs_lib_simple_socket.hpp> 28 #include <srs_lib_simple_socket.hpp>
29 */ 29 */
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <srs_protocol_io.hpp>
30 34
31 /** 35 /**
32 -* the stream over epoll: never wait for data coming, that is async mode. 36 +* simple socket stream,
  37 +* use tcp socket, sync block mode, for client like srs-librtmp.
33 */ 38 */
34 -class SimpleSocketStream 39 +class SimpleSocketStream : public ISrsProtocolReaderWriter
35 { 40 {
36 private: 41 private:
37 int fd; 42 int fd;
@@ -40,6 +45,28 @@ public: @@ -40,6 +45,28 @@ public:
40 virtual ~SimpleSocketStream(); 45 virtual ~SimpleSocketStream();
41 public: 46 public:
42 virtual int create_socket(); 47 virtual int create_socket();
  48 + virtual int connect(const char* server, int port);
  49 +// ISrsBufferReader
  50 +public:
  51 + virtual int read(const void* buf, size_t size, ssize_t* nread);
  52 +// ISrsProtocolReader
  53 +public:
  54 + virtual void set_recv_timeout(int64_t timeout_us);
  55 + virtual int64_t get_recv_timeout();
  56 + virtual int64_t get_recv_bytes();
  57 + virtual int get_recv_kbps();
  58 +// ISrsProtocolWriter
  59 +public:
  60 + virtual void set_send_timeout(int64_t timeout_us);
  61 + virtual int64_t get_send_timeout();
  62 + virtual int64_t get_send_bytes();
  63 + virtual int get_send_kbps();
  64 + virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
  65 +// ISrsProtocolReaderWriter
  66 +public:
  67 + virtual bool is_never_timeout(int64_t timeout_us);
  68 + virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
  69 + virtual int write(const void* buf, size_t size, ssize_t* nwrite);
43 }; 70 };
44 71
45 #endif 72 #endif
@@ -31,6 +31,15 @@ using namespace std; @@ -31,6 +31,15 @@ using namespace std;
31 #include <srs_kernel_error.hpp> 31 #include <srs_kernel_error.hpp>
32 #include <srs_protocol_rtmp.hpp> 32 #include <srs_protocol_rtmp.hpp>
33 #include <srs_lib_simple_socket.hpp> 33 #include <srs_lib_simple_socket.hpp>
  34 +#include <srs_kernel_log.hpp>
  35 +#include <srs_protocol_utility.hpp>
  36 +
  37 +// if user want to define log, define the folowing macro.
  38 +#ifndef SRS_RTMP_USER_DEFINED_LOG
  39 + // kernel module.
  40 + ISrsLog* _srs_log = new ISrsLog();
  41 + ISrsThreadContext* _srs_context = new ISrsThreadContext();
  42 +#endif
34 43
35 /** 44 /**
36 * export runtime context. 45 * export runtime context.
@@ -38,6 +47,13 @@ using namespace std; @@ -38,6 +47,13 @@ using namespace std;
38 struct Context 47 struct Context
39 { 48 {
40 std::string url; 49 std::string url;
  50 + std::string tcUrl;
  51 + std::string host;
  52 + std::string port;
  53 + std::string vhost;
  54 + std::string app;
  55 + std::string stream;
  56 +
41 SrsRtmpClient* rtmp; 57 SrsRtmpClient* rtmp;
42 SimpleSocketStream* skt; 58 SimpleSocketStream* skt;
43 int stream_id; 59 int stream_id;
@@ -53,17 +69,85 @@ struct Context @@ -53,17 +69,85 @@ struct Context
53 } 69 }
54 }; 70 };
55 71
  72 +int srs_librtmp_context_connect(Context* context)
  73 +{
  74 + int ret = ERROR_SUCCESS;
  75 +
  76 + // parse uri
  77 + size_t pos = string::npos;
  78 + string uri = context->url;
  79 + // tcUrl, stream
  80 + if ((pos = uri.rfind("/")) != string::npos) {
  81 + context->stream = uri.substr(pos + 1);
  82 + context->tcUrl = uri = uri.substr(0, pos);
  83 + }
  84 + // schema
  85 + if ((pos = uri.find("rtmp://")) != string::npos) {
  86 + uri = uri.substr(pos + 7);
  87 + }
  88 + // host/vhost/port
  89 + if ((pos = uri.find(":")) != string::npos) {
  90 + context->vhost = context->host = uri.substr(0, pos);
  91 + uri = uri.substr(pos + 1);
  92 +
  93 + if ((pos = uri.find("/")) != string::npos) {
  94 + context->port = uri.substr(0, pos);
  95 + uri = uri.substr(pos + 1);
  96 + }
  97 + } else {
  98 + if ((pos = uri.find("/")) != string::npos) {
  99 + context->vhost = context->host = uri.substr(0, pos);
  100 + uri = uri.substr(pos + 1);
  101 + }
  102 + context->port = RTMP_DEFAULT_PORT;
  103 + }
  104 + // app
  105 + context->app = uri;
  106 + // query of app
  107 + if ((pos = uri.find("?")) != string::npos) {
  108 + context->app = uri.substr(0, pos);
  109 + string query = uri.substr(pos + 1);
  110 + if ((pos = query.find("vhost=")) != string::npos) {
  111 + context->vhost = query.substr(pos + 6);
  112 + if ((pos = context->vhost.find("&")) != string::npos) {
  113 + context->vhost = context->vhost.substr(pos);
  114 + }
  115 + }
  116 + }
  117 +
  118 + // create socket
  119 + srs_freep(context->skt);
  120 + context->skt = new SimpleSocketStream();
  121 +
  122 + if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) {
  123 + return ret;
  124 + }
  125 +
  126 + // connect to server:port
  127 + string server = srs_dns_resolve(context->host);
  128 + if (server.empty()) {
  129 + return -1;
  130 + }
  131 + if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) {
  132 + return ret;
  133 + }
  134 +
  135 + return ret;
  136 +}
  137 +
56 #ifdef __cplusplus 138 #ifdef __cplusplus
57 extern "C"{ 139 extern "C"{
58 #endif 140 #endif
59 141
60 -srs_rtmp_t srs_rtmp_create(const char* url){ 142 +srs_rtmp_t srs_rtmp_create(const char* url)
  143 +{
61 Context* context = new Context(); 144 Context* context = new Context();
62 context->url = url; 145 context->url = url;
63 return context; 146 return context;
64 } 147 }
65 148
66 -void srs_rtmp_destroy(srs_rtmp_t rtmp){ 149 +void srs_rtmp_destroy(srs_rtmp_t rtmp)
  150 +{
67 srs_assert(rtmp != NULL); 151 srs_assert(rtmp != NULL);
68 Context* context = (Context*)rtmp; 152 Context* context = (Context*)rtmp;
69 153
@@ -72,17 +156,29 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp){ @@ -72,17 +156,29 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp){
72 156
73 int srs_simple_handshake(srs_rtmp_t rtmp) 157 int srs_simple_handshake(srs_rtmp_t rtmp)
74 { 158 {
  159 + int ret = ERROR_SUCCESS;
  160 +
75 srs_assert(rtmp != NULL); 161 srs_assert(rtmp != NULL);
76 Context* context = (Context*)rtmp; 162 Context* context = (Context*)rtmp;
77 163
78 - srs_freep(context->skt);  
79 - context->skt = new SimpleSocketStream(); 164 + // parse uri, resolve host, connect to server:port
  165 + if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) {
  166 + return ret;
  167 + }
80 168
81 - return ERROR_SUCCESS; 169 + // simple handshake
  170 + srs_freep(context->rtmp);
  171 + context->rtmp = new SrsRtmpClient(context->skt);
  172 +
  173 + return ret;
82 } 174 }
83 175
84 int srs_complex_handshake(srs_rtmp_t rtmp) 176 int srs_complex_handshake(srs_rtmp_t rtmp)
85 { 177 {
  178 +#ifndef SRS_SSL
  179 + return ERROR_RTMP_HS_SSL_REQUIRE;
  180 +#endif
  181 +
86 return ERROR_SUCCESS; 182 return ERROR_SUCCESS;
87 } 183 }
88 184