From f24f27deb92963c6277a8c4e1de000624acffbe7 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 2 Mar 2014 11:31:31 +0800 Subject: [PATCH] srs-librtmp: add make ssl/nossl support for sample --- trunk/configure | 9 +- trunk/research/librtmp/Makefile | 49 +++++++++-- trunk/research/librtmp/srs_play.c | 5 +- trunk/research/librtmp/srs_publish.c | 2 +- trunk/src/kernel/srs_kernel_error.hpp | 4 + trunk/src/libs/srs_lib_simple_socket.cpp | 96 +++++++++++++++++++- trunk/src/libs/srs_lib_simple_socket.hpp | 31 ++++++- trunk/src/libs/srs_librtmp.cpp | 106 +++++++++++++++++++++-- 8 files changed, 282 insertions(+), 20 deletions(-) mode change 100755 => 100644 trunk/configure mode change 100644 => 100755 trunk/research/librtmp/Makefile diff --git a/trunk/configure b/trunk/configure old mode 100755 new mode 100644 index 18ffd732c..51621703f --- a/trunk/configure +++ b/trunk/configure @@ -39,6 +39,13 @@ echo "" >> $SRS_AUTO_HEADERS_H ##################################################################################### ##################################################################################### +# srs-librtmp sample entry +SrsLibrtmpSampleEntry="nossl" +if [ $SRS_SSL = YES ]; then + SrsLibrtmpSampleEntry="ssl" +fi + +# makefile echo "generate Makefile" SRS_MAKEFILE="Makefile" cat << END > ${SRS_MAKEFILE} @@ -86,7 +93,7 @@ librtmp: _prepare_dir librtmp-sample: @echo "build the srs-librtmp sample" - (cd research/librtmp; make) + (cd research/librtmp; make ${SrsLibrtmpSampleEntry}) @echo "srs-librtmp sample build success" # the ./configure will generate it. diff --git a/trunk/research/librtmp/Makefile b/trunk/research/librtmp/Makefile old mode 100644 new mode 100755 index 5f3b08ced..50571ef8f --- a/trunk/research/librtmp/Makefile +++ b/trunk/research/librtmp/Makefile @@ -1,12 +1,47 @@ -.PHONY: default clean +.PHONY: default clean help ssl nossl -default: srs_publish srs_play +default: help + +help: + @echo "Usage: make |||||" + @echo " help display this help" + @echo " clean cleanup build" + @echo " ssl srs_publish_ssl, srs_play_ssl" + @echo " nossl srs_publish_nossl, srs_play_nossl" + @echo " srs_publish_nossl publish program using srs-librtmp, without ssl(simple handshake)" + @echo " srs_play_nossl play program using srs-librtmp, without ssl(simple handshake)" + @echo " srs_publish_ssl publish program using srs-librtmp, with ssl(complex handshake)" + @echo " srs_play_ssl play program using srs-librtmp, with ssl(complex handshake)" + @echo "Remark: about simple/complex handshake, see: http://blog.csdn.net/win_lin/article/details/13006803" + @echo "Remark: srs Makefile will auto invoke this by --with/without-ssl, " + @echo " that is, if user specified ssl(by --with-ssl), srs will make this by 'make ssl'" + @echo " that is, if user not use ssl(by --without-ssl), use 'make nossl'" + @echo " see: https://github.com/winlinvip/simple-rtmp-server/wiki/Build" + @echo "Remark: before make this sample, user must make the srs, with/without ssl" clean: - @rm -f srs_publish srs_play + @rm -f srs_publish_nossl srs_play_nossl srs_publish_ssl srs_play_ssl -srs_publish: srs_publish.c Makefile ../../objs/include/srs_librtmp.h ../../objs/lib/srs_librtmp.a - gcc srs_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_publish +# srs library root +SRS_OBJS = ../../objs +# srs-librtmp for publish/play, built by srs. +SRS_LIBRTMP_I = $(SRS_OBJS)/include/srs_librtmp.h +SRS_LIBRTMP_L = $(SRS_OBJS)/lib/srs_librtmp.a +# openssl for complex handshake, built by srs. +SRS_LIBSSL_L = $(SRS_OBJS)/openssl/lib/libssl.a $(SRS_OBJS)/openssl/lib/libcrypto.a -srs_play: srs_play.c Makefile ../../objs/include/srs_librtmp.h ../../objs/lib/srs_librtmp.a - gcc srs_play.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_play +srs_publish_nossl: srs_publish.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) + gcc srs_publish.c $(SRS_LIBRTMP_L) -g -O0 -lstdc++ -o srs_publish_nossl + +srs_play_nossl: srs_play.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) + gcc srs_play.c $(SRS_LIBRTMP_L) -g -O0 -lstdc++ -o srs_play_nossl + +srs_publish_ssl: srs_publish.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) + gcc srs_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) -g -O0 -ldl -lstdc++ -o srs_publish_ssl + +srs_play_ssl: srs_play.c Makefile $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) + gcc srs_play.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) -g -O0 -ldl -lstdc++ -o srs_play_ssl + +# alias for publish/play with/without ssl +ssl: srs_publish_ssl srs_play_ssl +nossl: srs_publish_nossl srs_play_nossl diff --git a/trunk/research/librtmp/srs_play.c b/trunk/research/librtmp/srs_play.c index b1e4b3386..aa1e3787e 100644 --- a/trunk/research/librtmp/srs_play.c +++ b/trunk/research/librtmp/srs_play.c @@ -35,9 +35,10 @@ int main(int argc, char** argv) printf("srs(simple-rtmp-server) client librtmp library.\n"); printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); - rtmp = srs_rtmp_create("rtmp://127.0.0.1/live/livestream"); + rtmp = srs_rtmp_create("rtmp://127.0.0.1:1935/live/show?vhost=__defaultVhost__/livestream"); - if (srs_simple_handshake(rtmp) != 0) { + //if (srs_simple_handshake(rtmp) != 0) { + if (srs_complex_handshake(rtmp) != 0) { printf("simple handshake failed.\n"); goto rtmp_destroy; } diff --git a/trunk/research/librtmp/srs_publish.c b/trunk/research/librtmp/srs_publish.c index c61221b97..f85e8fb3d 100644 --- a/trunk/research/librtmp/srs_publish.c +++ b/trunk/research/librtmp/srs_publish.c @@ -35,7 +35,7 @@ int main(int argc, char** argv) printf("srs(simple-rtmp-server) client librtmp library.\n"); printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); - rtmp = srs_rtmp_create("rtmp://127.0.0.1/live/livestream"); + rtmp = srs_rtmp_create("rtmp://127.0.0.1:1936/live/livestream"); if (srs_simple_handshake(rtmp) != 0) { printf("simple handshake failed.\n"); diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index e8c424f06..27564c5dc 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -71,6 +71,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_RTMP_ACCESS_DENIED 315 #define ERROR_RTMP_HANDSHAKE 316 #define ERROR_RTMP_NO_REQUEST 317 +// if user use complex handshake, but without ssl, +// 1. srs is ok, ignore and turn to simple handshake. +// 2. srs-librtmp return error, to terminate the program. +#define ERROR_RTMP_HS_SSL_REQUIRE 318 #define ERROR_SYSTEM_STREAM_INIT 400 #define ERROR_SYSTEM_PACKET_INVALID 401 diff --git a/trunk/src/libs/srs_lib_simple_socket.cpp b/trunk/src/libs/srs_lib_simple_socket.cpp index 5d53d0a8d..7f513469d 100644 --- a/trunk/src/libs/srs_lib_simple_socket.cpp +++ b/trunk/src/libs/srs_lib_simple_socket.cpp @@ -28,6 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include +#include SimpleSocketStream::SimpleSocketStream() { @@ -44,11 +46,101 @@ SimpleSocketStream::~SimpleSocketStream() int SimpleSocketStream::create_socket() { - fd = ::socket(AF_INET, SOCK_STREAM, 0); - if(fd == -1){ + if((fd = ::socket(AF_INET, SOCK_STREAM, 0)) < 0){ return -1; } return ERROR_SUCCESS; } +int SimpleSocketStream::connect(const char* server_ip, int port) +{ + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(server_ip); + + if(::connect(fd, (const struct sockaddr*)&addr, sizeof(sockaddr_in)) < 0){ + return -1; + } + + return ERROR_SUCCESS; +} + +// ISrsBufferReader +int SimpleSocketStream::read(const void* buf, size_t size, ssize_t* nread) +{ + int ret = ERROR_SUCCESS; + return ret; +} + +// ISrsProtocolReader +void SimpleSocketStream::set_recv_timeout(int64_t timeout_us) +{ +} + +int64_t SimpleSocketStream::get_recv_timeout() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int64_t SimpleSocketStream::get_recv_bytes() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int SimpleSocketStream::get_recv_kbps() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +// ISrsProtocolWriter +void SimpleSocketStream::set_send_timeout(int64_t timeout_us) +{ +} + +int64_t SimpleSocketStream::get_send_timeout() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int64_t SimpleSocketStream::get_send_bytes() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int SimpleSocketStream::get_send_kbps() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int SimpleSocketStream::writev(const iovec *iov, int iov_size, ssize_t* nwrite) +{ + int ret = ERROR_SUCCESS; + return ret; +} + +// ISrsProtocolReaderWriter +bool SimpleSocketStream::is_never_timeout(int64_t timeout_us) +{ + return true; +} + +int SimpleSocketStream::read_fully(const void* buf, size_t size, ssize_t* nread) +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int SimpleSocketStream::write(const void* buf, size_t size, ssize_t* nwrite) +{ + int ret = ERROR_SUCCESS; + return ret; +} + diff --git a/trunk/src/libs/srs_lib_simple_socket.hpp b/trunk/src/libs/srs_lib_simple_socket.hpp index dd4ac73e8..99034e49d 100644 --- a/trunk/src/libs/srs_lib_simple_socket.hpp +++ b/trunk/src/libs/srs_lib_simple_socket.hpp @@ -27,11 +27,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* #include */ + +#include + +#include /** -* the stream over epoll: never wait for data coming, that is async mode. +* simple socket stream, +* use tcp socket, sync block mode, for client like srs-librtmp. */ -class SimpleSocketStream +class SimpleSocketStream : public ISrsProtocolReaderWriter { private: int fd; @@ -40,6 +45,28 @@ public: virtual ~SimpleSocketStream(); public: virtual int create_socket(); + virtual int connect(const char* server, int port); +// ISrsBufferReader +public: + virtual int read(const void* buf, size_t size, ssize_t* nread); +// ISrsProtocolReader +public: + virtual void set_recv_timeout(int64_t timeout_us); + virtual int64_t get_recv_timeout(); + virtual int64_t get_recv_bytes(); + virtual int get_recv_kbps(); +// ISrsProtocolWriter +public: + virtual void set_send_timeout(int64_t timeout_us); + virtual int64_t get_send_timeout(); + virtual int64_t get_send_bytes(); + virtual int get_send_kbps(); + virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite); +// ISrsProtocolReaderWriter +public: + virtual bool is_never_timeout(int64_t timeout_us); + virtual int read_fully(const void* buf, size_t size, ssize_t* nread); + virtual int write(const void* buf, size_t size, ssize_t* nwrite); }; #endif diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index 2b3651e71..5b30c617d 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -31,6 +31,15 @@ using namespace std; #include #include #include +#include +#include + +// if user want to define log, define the folowing macro. +#ifndef SRS_RTMP_USER_DEFINED_LOG + // kernel module. + ISrsLog* _srs_log = new ISrsLog(); + ISrsThreadContext* _srs_context = new ISrsThreadContext(); +#endif /** * export runtime context. @@ -38,6 +47,13 @@ using namespace std; struct Context { std::string url; + std::string tcUrl; + std::string host; + std::string port; + std::string vhost; + std::string app; + std::string stream; + SrsRtmpClient* rtmp; SimpleSocketStream* skt; int stream_id; @@ -53,17 +69,85 @@ struct Context } }; +int srs_librtmp_context_connect(Context* context) +{ + int ret = ERROR_SUCCESS; + + // parse uri + size_t pos = string::npos; + string uri = context->url; + // tcUrl, stream + if ((pos = uri.rfind("/")) != string::npos) { + context->stream = uri.substr(pos + 1); + context->tcUrl = uri = uri.substr(0, pos); + } + // schema + if ((pos = uri.find("rtmp://")) != string::npos) { + uri = uri.substr(pos + 7); + } + // host/vhost/port + if ((pos = uri.find(":")) != string::npos) { + context->vhost = context->host = uri.substr(0, pos); + uri = uri.substr(pos + 1); + + if ((pos = uri.find("/")) != string::npos) { + context->port = uri.substr(0, pos); + uri = uri.substr(pos + 1); + } + } else { + if ((pos = uri.find("/")) != string::npos) { + context->vhost = context->host = uri.substr(0, pos); + uri = uri.substr(pos + 1); + } + context->port = RTMP_DEFAULT_PORT; + } + // app + context->app = uri; + // query of app + if ((pos = uri.find("?")) != string::npos) { + context->app = uri.substr(0, pos); + string query = uri.substr(pos + 1); + if ((pos = query.find("vhost=")) != string::npos) { + context->vhost = query.substr(pos + 6); + if ((pos = context->vhost.find("&")) != string::npos) { + context->vhost = context->vhost.substr(pos); + } + } + } + + // create socket + srs_freep(context->skt); + context->skt = new SimpleSocketStream(); + + if ((ret = context->skt->create_socket()) != ERROR_SUCCESS) { + return ret; + } + + // connect to server:port + string server = srs_dns_resolve(context->host); + if (server.empty()) { + return -1; + } + if ((ret = context->skt->connect(server.c_str(), ::atoi(context->port.c_str()))) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + #ifdef __cplusplus extern "C"{ #endif -srs_rtmp_t srs_rtmp_create(const char* url){ +srs_rtmp_t srs_rtmp_create(const char* url) +{ Context* context = new Context(); context->url = url; return context; } -void srs_rtmp_destroy(srs_rtmp_t rtmp){ +void srs_rtmp_destroy(srs_rtmp_t rtmp) +{ srs_assert(rtmp != NULL); Context* context = (Context*)rtmp; @@ -72,17 +156,29 @@ void srs_rtmp_destroy(srs_rtmp_t rtmp){ int srs_simple_handshake(srs_rtmp_t rtmp) { + int ret = ERROR_SUCCESS; + srs_assert(rtmp != NULL); Context* context = (Context*)rtmp; - srs_freep(context->skt); - context->skt = new SimpleSocketStream(); + // parse uri, resolve host, connect to server:port + if ((ret = srs_librtmp_context_connect(context)) != ERROR_SUCCESS) { + return ret; + } - return ERROR_SUCCESS; + // simple handshake + srs_freep(context->rtmp); + context->rtmp = new SrsRtmpClient(context->skt); + + return ret; } int srs_complex_handshake(srs_rtmp_t rtmp) { +#ifndef SRS_SSL + return ERROR_RTMP_HS_SSL_REQUIRE; +#endif + return ERROR_SUCCESS; }