winlin

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

... ... @@ -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.
... ...
.PHONY: default clean
.PHONY: default clean help ssl nossl
default: srs_publish srs_play
default: help
help:
@echo "Usage: make <help>|<clean>|<srs_publish_nossl>|<srs_play_nossl>|<srs_publish_ssl>|<srs_play_ssl>"
@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 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_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_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_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
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
# alias for publish/play with/without ssl
ssl: srs_publish_ssl srs_play_ssl
nossl: srs_publish_nossl srs_play_nossl
... ...
... ... @@ -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;
}
... ...
... ... @@ -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");
... ...
... ... @@ -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
... ...
... ... @@ -28,6 +28,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
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;
}
... ...
... ... @@ -27,11 +27,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
#include <srs_lib_simple_socket.hpp>
*/
#include <srs_core.hpp>
#include <srs_protocol_io.hpp>
/**
* 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
... ...
... ... @@ -31,6 +31,15 @@ using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_protocol_rtmp.hpp>
#include <srs_lib_simple_socket.hpp>
#include <srs_kernel_log.hpp>
#include <srs_protocol_utility.hpp>
// 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;
}
... ...