1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-14 20:31:56 +00:00

convert to unix format

This commit is contained in:
winlin 2013-11-29 22:21:31 +08:00
parent db405b7e0e
commit 5d69236bff
10 changed files with 3516 additions and 3516 deletions

1048
trunk/src/core/srs_core_client.cpp Executable file → Normal file

File diff suppressed because it is too large Load diff

1664
trunk/src/core/srs_core_config.cpp Executable file → Normal file

File diff suppressed because it is too large Load diff

288
trunk/src/core/srs_core_config.hpp Executable file → Normal file
View file

@ -1,145 +1,145 @@
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_CONIFG_HPP
#define SRS_CORE_CONIFG_HPP
/*
#include <srs_core_config.hpp>
*/
#include <srs_core.hpp>
#include <vector>
#include <string>
#include <srs_core_reload.hpp>
// default vhost for rtmp
#define RTMP_VHOST_DEFAULT "__defaultVhost__"
#define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
#define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
#define SRS_CONF_DEFAULT_HLS_WINDOW 60
// in ms, for HLS aac sync time.
#define SRS_CONF_DEFAULT_AAC_SYNC 100
// in ms, for HLS aac flush the audio
#define SRS_CONF_DEFAULT_AAC_DELAY 300
class SrsFileBuffer
{
public:
int fd;
int line;
// start of buffer.
char* start;
// end of buffer.
char* end;
// current consumed position.
char* pos;
// last available position.
char* last;
SrsFileBuffer();
virtual ~SrsFileBuffer();
virtual int open(const char* filename);
};
class SrsConfDirective
{
public:
int conf_line;
std::string name;
std::vector<std::string> args;
std::vector<SrsConfDirective*> directives;
public:
SrsConfDirective();
virtual ~SrsConfDirective();
std::string arg0();
std::string arg1();
std::string arg2();
SrsConfDirective* at(int index);
SrsConfDirective* get(std::string _name);
public:
virtual int parse(const char* filename);
public:
enum SrsDirectiveType{parse_file, parse_block};
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
virtual int refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s_quoted, int startline, char*& pstart);
};
/**
* the config parser.
* for the config supports reload, so never keep the reference cross st-thread,
* that is, never save the SrsConfDirective* get by any api of config,
* for it maybe free in the reload st-thread cycle.
* you can keep it before st-thread switch, or simply never keep it.
*/
class SrsConfig
{
private:
bool show_help;
bool show_version;
std::string config_file;
SrsConfDirective* root;
std::vector<SrsReloadHandler*> subscribes;
public:
SrsConfig();
virtual ~SrsConfig();
public:
virtual int reload();
virtual void subscribe(SrsReloadHandler* handler);
virtual void unsubscribe(SrsReloadHandler* handler);
public:
virtual int parse_options(int argc, char** argv);
virtual SrsConfDirective* get_vhost(std::string vhost);
virtual SrsConfDirective* get_vhost_enabled(std::string vhost);
virtual SrsConfDirective* get_gop_cache(std::string vhost);
virtual SrsConfDirective* get_forward(std::string vhost);
virtual SrsConfDirective* get_hls(std::string vhost);
virtual SrsConfDirective* get_hls_path(std::string vhost);
virtual SrsConfDirective* get_hls_fragment(std::string vhost);
virtual SrsConfDirective* get_hls_window(std::string vhost);
virtual SrsConfDirective* get_refer(std::string vhost);
virtual SrsConfDirective* get_refer_play(std::string vhost);
virtual SrsConfDirective* get_refer_publish(std::string vhost);
virtual SrsConfDirective* get_listen();
virtual SrsConfDirective* get_chunk_size();
virtual SrsConfDirective* get_pithy_print_publish();
virtual SrsConfDirective* get_pithy_print_forwarder();
virtual SrsConfDirective* get_pithy_print_play();
private:
virtual int parse_file(const char* filename);
virtual int parse_argv(int& i, char** argv);
virtual void print_help(char** argv);
};
/**
* deep compare directive.
*/
bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b);
// global config
extern SrsConfig* config;
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_CONIFG_HPP
#define SRS_CORE_CONIFG_HPP
/*
#include <srs_core_config.hpp>
*/
#include <srs_core.hpp>
#include <vector>
#include <string>
#include <srs_core_reload.hpp>
// default vhost for rtmp
#define RTMP_VHOST_DEFAULT "__defaultVhost__"
#define SRS_CONF_DEFAULT_HLS_PATH "./objs/nginx/html"
#define SRS_CONF_DEFAULT_HLS_FRAGMENT 10
#define SRS_CONF_DEFAULT_HLS_WINDOW 60
// in ms, for HLS aac sync time.
#define SRS_CONF_DEFAULT_AAC_SYNC 100
// in ms, for HLS aac flush the audio
#define SRS_CONF_DEFAULT_AAC_DELAY 300
class SrsFileBuffer
{
public:
int fd;
int line;
// start of buffer.
char* start;
// end of buffer.
char* end;
// current consumed position.
char* pos;
// last available position.
char* last;
SrsFileBuffer();
virtual ~SrsFileBuffer();
virtual int open(const char* filename);
};
class SrsConfDirective
{
public:
int conf_line;
std::string name;
std::vector<std::string> args;
std::vector<SrsConfDirective*> directives;
public:
SrsConfDirective();
virtual ~SrsConfDirective();
std::string arg0();
std::string arg1();
std::string arg2();
SrsConfDirective* at(int index);
SrsConfDirective* get(std::string _name);
public:
virtual int parse(const char* filename);
public:
enum SrsDirectiveType{parse_file, parse_block};
virtual int parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type);
virtual int read_token(SrsFileBuffer* buffer, std::vector<std::string>& args);
virtual int refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s_quoted, int startline, char*& pstart);
};
/**
* the config parser.
* for the config supports reload, so never keep the reference cross st-thread,
* that is, never save the SrsConfDirective* get by any api of config,
* for it maybe free in the reload st-thread cycle.
* you can keep it before st-thread switch, or simply never keep it.
*/
class SrsConfig
{
private:
bool show_help;
bool show_version;
std::string config_file;
SrsConfDirective* root;
std::vector<SrsReloadHandler*> subscribes;
public:
SrsConfig();
virtual ~SrsConfig();
public:
virtual int reload();
virtual void subscribe(SrsReloadHandler* handler);
virtual void unsubscribe(SrsReloadHandler* handler);
public:
virtual int parse_options(int argc, char** argv);
virtual SrsConfDirective* get_vhost(std::string vhost);
virtual SrsConfDirective* get_vhost_enabled(std::string vhost);
virtual SrsConfDirective* get_gop_cache(std::string vhost);
virtual SrsConfDirective* get_forward(std::string vhost);
virtual SrsConfDirective* get_hls(std::string vhost);
virtual SrsConfDirective* get_hls_path(std::string vhost);
virtual SrsConfDirective* get_hls_fragment(std::string vhost);
virtual SrsConfDirective* get_hls_window(std::string vhost);
virtual SrsConfDirective* get_refer(std::string vhost);
virtual SrsConfDirective* get_refer_play(std::string vhost);
virtual SrsConfDirective* get_refer_publish(std::string vhost);
virtual SrsConfDirective* get_listen();
virtual SrsConfDirective* get_chunk_size();
virtual SrsConfDirective* get_pithy_print_publish();
virtual SrsConfDirective* get_pithy_print_forwarder();
virtual SrsConfDirective* get_pithy_print_play();
private:
virtual int parse_file(const char* filename);
virtual int parse_argv(int& i, char** argv);
virtual void print_help(char** argv);
};
/**
* deep compare directive.
*/
bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b);
// global config
extern SrsConfig* config;
#endif

700
trunk/src/core/srs_core_forward.cpp Executable file → Normal file
View file

@ -1,350 +1,350 @@
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_core_forward.hpp>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <srs_core_error.hpp>
#include <srs_core_rtmp.hpp>
#include <srs_core_log.hpp>
#include <srs_core_protocol.hpp>
#include <srs_core_pithy_print.hpp>
#define SRS_PULSE_TIMEOUT_MS 100
#define SRS_FORWARDER_SLEEP_MS 2000
#define SRS_SEND_TIMEOUT_US 3000000L
#define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US
SrsForwarder::SrsForwarder()
{
client = NULL;
tid = NULL;
stfd = NULL;
loop = false;
stream_id = 0;
}
SrsForwarder::~SrsForwarder()
{
on_unpublish();
std::vector<SrsSharedPtrMessage*>::iterator it;
for (it = msgs.begin(); it != msgs.end(); ++it) {
SrsSharedPtrMessage* msg = *it;
srs_freep(msg);
}
msgs.clear();
}
int SrsForwarder::on_publish(std::string vhost, std::string _app, std::string stream, std::string forward_server)
{
int ret = ERROR_SUCCESS;
app = _app;
tc_url = "rtmp://";
tc_url += vhost;
tc_url += "/";
tc_url += app;
stream_name = stream;
server = forward_server;
port = 1935;
size_t pos = forward_server.find(":");
if (pos != std::string::npos) {
port = ::atoi(forward_server.substr(pos + 1).c_str());
server = forward_server.substr(0, pos);
}
if ((ret = open_socket()) != ERROR_SUCCESS) {
return ret;
}
srs_assert(!tid);
if((tid = st_thread_create(forward_thread, this, 1, 0)) == NULL){
ret = ERROR_ST_CREATE_FORWARD_THREAD;
srs_error("st_thread_create failed. ret=%d", ret);
return ret;
}
return ret;
}
void SrsForwarder::on_unpublish()
{
if (tid) {
loop = false;
st_thread_interrupt(tid);
st_thread_join(tid, NULL);
tid = NULL;
}
if (stfd) {
int fd = st_netfd_fileno(stfd);
st_netfd_close(stfd);
stfd = NULL;
// st does not close it sometimes,
// close it manually.
close(fd);
}
srs_freep(client);
}
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata)
{
int ret = ERROR_SUCCESS;
msgs.push_back(metadata);
return ret;
}
int SrsForwarder::on_audio(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
msgs.push_back(msg);
return ret;
}
int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
msgs.push_back(msg);
return ret;
}
int SrsForwarder::open_socket()
{
int ret = ERROR_SUCCESS;
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){
ret = ERROR_SOCKET_CREATE;
srs_error("create socket error. ret=%d", ret);
return ret;
}
stfd = st_netfd_open_socket(sock);
if(stfd == NULL){
ret = ERROR_ST_OPEN_SOCKET;
srs_error("st_netfd_open_socket failed. ret=%d", ret);
return ret;
}
srs_freep(client);
client = new SrsRtmpClient(stfd);
return ret;
}
int SrsForwarder::connect_server()
{
int ret = ERROR_SUCCESS;
std::string ip = parse_server(server);
if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
ret = ERROR_ST_CONNECT;
srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret);
return ret;
}
srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
return ret;
}
std::string SrsForwarder::parse_server(std::string host)
{
if (inet_addr(host.c_str()) != INADDR_NONE) {
return host;
}
hostent* answer = gethostbyname(host.c_str());
if (answer == NULL) {
srs_error("dns resolve host %s error.", host.c_str());
return "";
}
char ipv4[16];
memset(ipv4, 0, sizeof(ipv4));
for (int i = 0; i < answer->h_length; i++) {
inet_ntop(AF_INET, answer->h_addr_list[i], ipv4, sizeof(ipv4));
srs_info("dns resolve host %s to %s.", host.c_str(), ipv4);
break;
}
return ipv4;
}
int SrsForwarder::forward_cycle_imp()
{
int ret = ERROR_SUCCESS;
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
if ((ret = connect_server()) != ERROR_SUCCESS) {
return ret;
}
srs_assert(client);
if ((ret = client->handshake()) != ERROR_SUCCESS) {
srs_error("handshake with server failed. ret=%d", ret);
return ret;
}
if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
return ret;
}
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
return ret;
}
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
stream_name.c_str(), stream_id, ret);
return ret;
}
if ((ret = forward()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsForwarder::forward()
{
int ret = ERROR_SUCCESS;
client->set_recv_timeout(SRS_PULSE_TIMEOUT_MS * 1000);
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
while (loop) {
pithy_print.elapse(SRS_PULSE_TIMEOUT_MS);
// switch to other st-threads.
st_usleep(0);
// read from client.
if (true) {
SrsCommonMessage* msg = NULL;
ret = client->recv_message(&msg);
srs_verbose("play loop recv message. ret=%d", ret);
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
srs_error("recv server control message failed. ret=%d", ret);
return ret;
}
}
int count = (int)msgs.size();
// reportable
if (pithy_print.can_print()) {
srs_trace("-> clock=%u, time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
(int)(srs_get_system_time_ms()/1000), pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
}
// all msgs to forward.
for (int i = 0; i < count; i++) {
SrsSharedPtrMessage* msg = msgs[i];
msgs[i] = NULL;
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
srs_error("forwarder send message to server failed. ret=%d", ret);
return ret;
}
}
msgs.clear();
}
return ret;
}
void SrsForwarder::forward_cycle()
{
int ret = ERROR_SUCCESS;
log_context->generate_id();
srs_trace("forward cycle start");
while (loop) {
if ((ret = forward_cycle_imp()) != ERROR_SUCCESS) {
srs_warn("forward cycle failed, ignored and retry, ret=%d", ret);
} else {
srs_info("forward cycle success, retry");
}
if (!loop) {
break;
}
st_usleep(SRS_FORWARDER_SLEEP_MS * 1000);
if ((ret = open_socket()) != ERROR_SUCCESS) {
srs_warn("forward cycle reopen failed, ignored and retry, ret=%d", ret);
} else {
srs_info("forward cycle reopen success");
}
}
srs_trace("forward cycle finished");
}
void* SrsForwarder::forward_thread(void* arg)
{
SrsForwarder* obj = (SrsForwarder*)arg;
srs_assert(obj != NULL);
obj->loop = true;
obj->forward_cycle();
return NULL;
}
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_core_forward.hpp>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <srs_core_error.hpp>
#include <srs_core_rtmp.hpp>
#include <srs_core_log.hpp>
#include <srs_core_protocol.hpp>
#include <srs_core_pithy_print.hpp>
#define SRS_PULSE_TIMEOUT_MS 100
#define SRS_FORWARDER_SLEEP_MS 2000
#define SRS_SEND_TIMEOUT_US 3000000L
#define SRS_RECV_TIMEOUT_US SRS_SEND_TIMEOUT_US
SrsForwarder::SrsForwarder()
{
client = NULL;
tid = NULL;
stfd = NULL;
loop = false;
stream_id = 0;
}
SrsForwarder::~SrsForwarder()
{
on_unpublish();
std::vector<SrsSharedPtrMessage*>::iterator it;
for (it = msgs.begin(); it != msgs.end(); ++it) {
SrsSharedPtrMessage* msg = *it;
srs_freep(msg);
}
msgs.clear();
}
int SrsForwarder::on_publish(std::string vhost, std::string _app, std::string stream, std::string forward_server)
{
int ret = ERROR_SUCCESS;
app = _app;
tc_url = "rtmp://";
tc_url += vhost;
tc_url += "/";
tc_url += app;
stream_name = stream;
server = forward_server;
port = 1935;
size_t pos = forward_server.find(":");
if (pos != std::string::npos) {
port = ::atoi(forward_server.substr(pos + 1).c_str());
server = forward_server.substr(0, pos);
}
if ((ret = open_socket()) != ERROR_SUCCESS) {
return ret;
}
srs_assert(!tid);
if((tid = st_thread_create(forward_thread, this, 1, 0)) == NULL){
ret = ERROR_ST_CREATE_FORWARD_THREAD;
srs_error("st_thread_create failed. ret=%d", ret);
return ret;
}
return ret;
}
void SrsForwarder::on_unpublish()
{
if (tid) {
loop = false;
st_thread_interrupt(tid);
st_thread_join(tid, NULL);
tid = NULL;
}
if (stfd) {
int fd = st_netfd_fileno(stfd);
st_netfd_close(stfd);
stfd = NULL;
// st does not close it sometimes,
// close it manually.
close(fd);
}
srs_freep(client);
}
int SrsForwarder::on_meta_data(SrsSharedPtrMessage* metadata)
{
int ret = ERROR_SUCCESS;
msgs.push_back(metadata);
return ret;
}
int SrsForwarder::on_audio(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
msgs.push_back(msg);
return ret;
}
int SrsForwarder::on_video(SrsSharedPtrMessage* msg)
{
int ret = ERROR_SUCCESS;
msgs.push_back(msg);
return ret;
}
int SrsForwarder::open_socket()
{
int ret = ERROR_SUCCESS;
srs_trace("forward stream=%s, tcUrl=%s to server=%s, port=%d",
stream_name.c_str(), tc_url.c_str(), server.c_str(), port);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1){
ret = ERROR_SOCKET_CREATE;
srs_error("create socket error. ret=%d", ret);
return ret;
}
stfd = st_netfd_open_socket(sock);
if(stfd == NULL){
ret = ERROR_ST_OPEN_SOCKET;
srs_error("st_netfd_open_socket failed. ret=%d", ret);
return ret;
}
srs_freep(client);
client = new SrsRtmpClient(stfd);
return ret;
}
int SrsForwarder::connect_server()
{
int ret = ERROR_SUCCESS;
std::string ip = parse_server(server);
if (ip.empty()) {
ret = ERROR_SYSTEM_IP_INVALID;
srs_error("dns resolve server error, ip empty. ret=%d", ret);
return ret;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip.c_str());
if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
ret = ERROR_ST_CONNECT;
srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), port, ret);
return ret;
}
srs_trace("connect to server success. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
return ret;
}
std::string SrsForwarder::parse_server(std::string host)
{
if (inet_addr(host.c_str()) != INADDR_NONE) {
return host;
}
hostent* answer = gethostbyname(host.c_str());
if (answer == NULL) {
srs_error("dns resolve host %s error.", host.c_str());
return "";
}
char ipv4[16];
memset(ipv4, 0, sizeof(ipv4));
for (int i = 0; i < answer->h_length; i++) {
inet_ntop(AF_INET, answer->h_addr_list[i], ipv4, sizeof(ipv4));
srs_info("dns resolve host %s to %s.", host.c_str(), ipv4);
break;
}
return ipv4;
}
int SrsForwarder::forward_cycle_imp()
{
int ret = ERROR_SUCCESS;
client->set_recv_timeout(SRS_RECV_TIMEOUT_US);
client->set_send_timeout(SRS_SEND_TIMEOUT_US);
if ((ret = connect_server()) != ERROR_SUCCESS) {
return ret;
}
srs_assert(client);
if ((ret = client->handshake()) != ERROR_SUCCESS) {
srs_error("handshake with server failed. ret=%d", ret);
return ret;
}
if ((ret = client->connect_app(app, tc_url)) != ERROR_SUCCESS) {
srs_error("connect with server failed, tcUrl=%s. ret=%d", tc_url.c_str(), ret);
return ret;
}
if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
return ret;
}
if ((ret = client->publish(stream_name, stream_id)) != ERROR_SUCCESS) {
srs_error("connect with server failed, stream_name=%s, stream_id=%d. ret=%d",
stream_name.c_str(), stream_id, ret);
return ret;
}
if ((ret = forward()) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsForwarder::forward()
{
int ret = ERROR_SUCCESS;
client->set_recv_timeout(SRS_PULSE_TIMEOUT_MS * 1000);
SrsPithyPrint pithy_print(SRS_STAGE_FORWARDER);
while (loop) {
pithy_print.elapse(SRS_PULSE_TIMEOUT_MS);
// switch to other st-threads.
st_usleep(0);
// read from client.
if (true) {
SrsCommonMessage* msg = NULL;
ret = client->recv_message(&msg);
srs_verbose("play loop recv message. ret=%d", ret);
if (ret != ERROR_SUCCESS && ret != ERROR_SOCKET_TIMEOUT) {
srs_error("recv server control message failed. ret=%d", ret);
return ret;
}
}
int count = (int)msgs.size();
// reportable
if (pithy_print.can_print()) {
srs_trace("-> clock=%u, time=%"PRId64", msgs=%d, obytes=%"PRId64", ibytes=%"PRId64", okbps=%d, ikbps=%d",
(int)(srs_get_system_time_ms()/1000), pithy_print.get_age(), count, client->get_send_bytes(), client->get_recv_bytes(), client->get_send_kbps(), client->get_recv_kbps());
}
// all msgs to forward.
for (int i = 0; i < count; i++) {
SrsSharedPtrMessage* msg = msgs[i];
msgs[i] = NULL;
if ((ret = client->send_message(msg)) != ERROR_SUCCESS) {
srs_error("forwarder send message to server failed. ret=%d", ret);
return ret;
}
}
msgs.clear();
}
return ret;
}
void SrsForwarder::forward_cycle()
{
int ret = ERROR_SUCCESS;
log_context->generate_id();
srs_trace("forward cycle start");
while (loop) {
if ((ret = forward_cycle_imp()) != ERROR_SUCCESS) {
srs_warn("forward cycle failed, ignored and retry, ret=%d", ret);
} else {
srs_info("forward cycle success, retry");
}
if (!loop) {
break;
}
st_usleep(SRS_FORWARDER_SLEEP_MS * 1000);
if ((ret = open_socket()) != ERROR_SUCCESS) {
srs_warn("forward cycle reopen failed, ignored and retry, ret=%d", ret);
} else {
srs_info("forward cycle reopen success");
}
}
srs_trace("forward cycle finished");
}
void* SrsForwarder::forward_thread(void* arg)
{
SrsForwarder* obj = (SrsForwarder*)arg;
srs_assert(obj != NULL);
obj->loop = true;
obj->forward_cycle();
return NULL;
}

160
trunk/src/core/srs_core_forward.hpp Executable file → Normal file
View file

@ -1,80 +1,80 @@
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_FORWARD_HPP
#define SRS_CORE_FORWARD_HPP
/*
#include <srs_core_forward.hpp>
*/
#include <srs_core.hpp>
#include <string>
#include <vector>
#include <st.h>
class SrsSharedPtrMessage;
class SrsOnMetaDataPacket;
class SrsRtmpClient;
/**
* forward the stream to other servers.
*/
class SrsForwarder
{
private:
std::string app;
std::string tc_url;
std::string stream_name;
int stream_id;
std::string server;
int port;
private:
st_netfd_t stfd;
st_thread_t tid;
bool loop;
private:
SrsRtmpClient* client;
std::vector<SrsSharedPtrMessage*> msgs;
public:
SrsForwarder();
virtual ~SrsForwarder();
public:
virtual int on_publish(std::string vhost, std::string app, std::string stream, std::string forward_server);
virtual void on_unpublish();
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
virtual int on_audio(SrsSharedPtrMessage* msg);
virtual int on_video(SrsSharedPtrMessage* msg);
private:
virtual int open_socket();
virtual int connect_server();
std::string parse_server(std::string host);
private:
virtual int forward_cycle_imp();
virtual int forward();
virtual void forward_cycle();
static void* forward_thread(void* arg);
};
#endif
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_FORWARD_HPP
#define SRS_CORE_FORWARD_HPP
/*
#include <srs_core_forward.hpp>
*/
#include <srs_core.hpp>
#include <string>
#include <vector>
#include <st.h>
class SrsSharedPtrMessage;
class SrsOnMetaDataPacket;
class SrsRtmpClient;
/**
* forward the stream to other servers.
*/
class SrsForwarder
{
private:
std::string app;
std::string tc_url;
std::string stream_name;
int stream_id;
std::string server;
int port;
private:
st_netfd_t stfd;
st_thread_t tid;
bool loop;
private:
SrsRtmpClient* client;
std::vector<SrsSharedPtrMessage*> msgs;
public:
SrsForwarder();
virtual ~SrsForwarder();
public:
virtual int on_publish(std::string vhost, std::string app, std::string stream, std::string forward_server);
virtual void on_unpublish();
virtual int on_meta_data(SrsSharedPtrMessage* metadata);
virtual int on_audio(SrsSharedPtrMessage* msg);
virtual int on_video(SrsSharedPtrMessage* msg);
private:
virtual int open_socket();
virtual int connect_server();
std::string parse_server(std::string host);
private:
virtual int forward_cycle_imp();
virtual int forward();
virtual void forward_cycle();
static void* forward_thread(void* arg);
};
#endif

346
trunk/src/core/srs_core_pithy_print.cpp Executable file → Normal file
View file

@ -1,173 +1,173 @@
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_core_pithy_print.hpp>
#include <stdlib.h>
#include <map>
#include <srs_core_log.hpp>
#include <srs_core_config.hpp>
#include <srs_core_reload.hpp>
#include <srs_core_error.hpp>
#define SRS_STAGE_DEFAULT_INTERVAL_MS 1200
#define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300
#define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100
#define SRS_STAGE_FORWARDER_INTERVAL_MS 2000
struct SrsStageInfo : public SrsReloadHandler
{
int stage_id;
int pithy_print_time_ms;
int nb_clients;
SrsStageInfo(int _stage_id)
{
stage_id = _stage_id;
nb_clients = 0;
update_print_time();
config->subscribe(this);
}
virtual ~SrsStageInfo()
{
config->unsubscribe(this);
}
void update_print_time()
{
switch (stage_id) {
case SRS_STAGE_PLAY_USER: {
pithy_print_time_ms = SRS_STAGE_PLAY_USER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_play();
if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str());
}
break;
}
case SRS_STAGE_PUBLISH_USER: {
pithy_print_time_ms = SRS_STAGE_PUBLISH_USER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_publish();
if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str());
}
break;
}
case SRS_STAGE_FORWARDER: {
pithy_print_time_ms = SRS_STAGE_FORWARDER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_forwarder();
if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str());
}
break;
}
default: {
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
break;
}
}
}
public:
virtual int on_reload_pithy_print()
{
update_print_time();
return ERROR_SUCCESS;
}
};
static std::map<int, SrsStageInfo*> _srs_stages;
SrsPithyPrint::SrsPithyPrint(int _stage_id)
{
stage_id = _stage_id;
client_id = enter_stage();
printed_age = age = 0;
}
SrsPithyPrint::~SrsPithyPrint()
{
leave_stage();
}
int SrsPithyPrint::enter_stage()
{
SrsStageInfo* stage = NULL;
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
if (it == _srs_stages.end()) {
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
} else {
stage = it->second;
}
srs_assert(stage != NULL);
client_id = stage->nb_clients++;
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
return client_id;
}
void SrsPithyPrint::leave_stage()
{
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
stage->nb_clients--;
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
}
void SrsPithyPrint::elapse(int64_t time_ms)
{
age += time_ms;
}
bool SrsPithyPrint::can_print()
{
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
int64_t alive_age = age - printed_age;
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
bool can_print = alive_age >= can_print_age;
if (can_print) {
printed_age = age;
}
return can_print;
}
int64_t SrsPithyPrint::get_age()
{
return age;
}
void SrsPithyPrint::set_age(int64_t _age)
{
age = _age;
}
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_core_pithy_print.hpp>
#include <stdlib.h>
#include <map>
#include <srs_core_log.hpp>
#include <srs_core_config.hpp>
#include <srs_core_reload.hpp>
#include <srs_core_error.hpp>
#define SRS_STAGE_DEFAULT_INTERVAL_MS 1200
#define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300
#define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100
#define SRS_STAGE_FORWARDER_INTERVAL_MS 2000
struct SrsStageInfo : public SrsReloadHandler
{
int stage_id;
int pithy_print_time_ms;
int nb_clients;
SrsStageInfo(int _stage_id)
{
stage_id = _stage_id;
nb_clients = 0;
update_print_time();
config->subscribe(this);
}
virtual ~SrsStageInfo()
{
config->unsubscribe(this);
}
void update_print_time()
{
switch (stage_id) {
case SRS_STAGE_PLAY_USER: {
pithy_print_time_ms = SRS_STAGE_PLAY_USER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_play();
if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str());
}
break;
}
case SRS_STAGE_PUBLISH_USER: {
pithy_print_time_ms = SRS_STAGE_PUBLISH_USER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_publish();
if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str());
}
break;
}
case SRS_STAGE_FORWARDER: {
pithy_print_time_ms = SRS_STAGE_FORWARDER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_forwarder();
if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str());
}
break;
}
default: {
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
break;
}
}
}
public:
virtual int on_reload_pithy_print()
{
update_print_time();
return ERROR_SUCCESS;
}
};
static std::map<int, SrsStageInfo*> _srs_stages;
SrsPithyPrint::SrsPithyPrint(int _stage_id)
{
stage_id = _stage_id;
client_id = enter_stage();
printed_age = age = 0;
}
SrsPithyPrint::~SrsPithyPrint()
{
leave_stage();
}
int SrsPithyPrint::enter_stage()
{
SrsStageInfo* stage = NULL;
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
if (it == _srs_stages.end()) {
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
} else {
stage = it->second;
}
srs_assert(stage != NULL);
client_id = stage->nb_clients++;
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
return client_id;
}
void SrsPithyPrint::leave_stage()
{
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
stage->nb_clients--;
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d",
stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
}
void SrsPithyPrint::elapse(int64_t time_ms)
{
age += time_ms;
}
bool SrsPithyPrint::can_print()
{
SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL);
int64_t alive_age = age - printed_age;
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
bool can_print = alive_age >= can_print_age;
if (can_print) {
printed_age = age;
}
return can_print;
}
int64_t SrsPithyPrint::get_age()
{
return age;
}
void SrsPithyPrint::set_age(int64_t _age)
{
age = _age;
}

166
trunk/src/core/srs_core_pithy_print.hpp Executable file → Normal file
View file

@ -1,84 +1,84 @@
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_PITHY_PRINT_HPP
#define SRS_CORE_PITHY_PRINT_HPP
/*
#include <srs_core_pithy_print.hpp>
*/
#include <srs_core.hpp>
// the pithy stage for all play clients.
#define SRS_STAGE_PLAY_USER 1
// the pithy stage for all publish clients.
#define SRS_STAGE_PUBLISH_USER 2
// the pithy stage for all forward clients.
#define SRS_STAGE_FORWARDER 3
/**
* the stage is used for a collection of object to do print,
* the print time in a stage is constant and not changed.
* for example, stage #1 for all play clients, print time is 3s,
* if there is 10clients, then all clients should print in 10*3s.
*/
class SrsPithyPrint
{
private:
int client_id;
int stage_id;
int64_t age;
int64_t printed_age;
public:
/**
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
*/
SrsPithyPrint(int _stage_id);
virtual ~SrsPithyPrint();
private:
/**
* enter the specified stage, return the client id.
*/
virtual int enter_stage();
/**
* leave the specified stage, release the client id.
*/
virtual void leave_stage();
public:
/**
* specified client elapse some time.
*/
virtual void elapse(int64_t time_ms);
/**
* whether current client can print.
*/
virtual bool can_print();
/**
* get the elapsed time in ms.
*/
virtual int64_t get_age();
virtual void set_age(int64_t _age);
};
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_PITHY_PRINT_HPP
#define SRS_CORE_PITHY_PRINT_HPP
/*
#include <srs_core_pithy_print.hpp>
*/
#include <srs_core.hpp>
// the pithy stage for all play clients.
#define SRS_STAGE_PLAY_USER 1
// the pithy stage for all publish clients.
#define SRS_STAGE_PUBLISH_USER 2
// the pithy stage for all forward clients.
#define SRS_STAGE_FORWARDER 3
/**
* the stage is used for a collection of object to do print,
* the print time in a stage is constant and not changed.
* for example, stage #1 for all play clients, print time is 3s,
* if there is 10clients, then all clients should print in 10*3s.
*/
class SrsPithyPrint
{
private:
int client_id;
int stage_id;
int64_t age;
int64_t printed_age;
public:
/**
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
*/
SrsPithyPrint(int _stage_id);
virtual ~SrsPithyPrint();
private:
/**
* enter the specified stage, return the client id.
*/
virtual int enter_stage();
/**
* leave the specified stage, release the client id.
*/
virtual void leave_stage();
public:
/**
* specified client elapse some time.
*/
virtual void elapse(int64_t time_ms);
/**
* whether current client can print.
*/
virtual bool can_print();
/**
* get the elapsed time in ms.
*/
virtual int64_t get_age();
virtual void set_age(int64_t _age);
};
#endif

2232
trunk/src/core/srs_core_rtmp.cpp Executable file → Normal file

File diff suppressed because it is too large Load diff

428
trunk/src/core/srs_core_rtmp.hpp Executable file → Normal file
View file

@ -1,215 +1,215 @@
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_RTMP_HPP
#define SRS_CORE_RTMP_HPP
/*
#include <srs_core_rtmp.hpp>
*/
#include <srs_core.hpp>
#include <string>
#include <st.h>
class SrsProtocol;
class ISrsMessage;
class SrsCommonMessage;
class SrsCreateStreamPacket;
class SrsFMLEStartPacket;
class SrsPublishPacket;
class SrsSharedPtrMessage;
class SrsOnMetaDataPacket;
/**
* the original request from client.
*/
struct SrsRequest
{
std::string tcUrl;
std::string pageUrl;
std::string swfUrl;
double objectEncoding;
std::string schema;
std::string vhost;
std::string port;
std::string app;
std::string stream;
SrsRequest();
virtual ~SrsRequest();
/**
* disconvery vhost/app from tcUrl.
*/
virtual int discovery_app();
virtual std::string get_stream_url();
virtual void strip();
private:
std::string& trim(std::string& str, std::string chs);
};
/**
* the response to client.
*/
struct SrsResponse
{
int stream_id;
SrsResponse();
virtual ~SrsResponse();
};
/**
* the rtmp client type.
*/
enum SrsClientType
{
SrsClientUnknown,
SrsClientPlay,
SrsClientFMLEPublish,
SrsClientFlashPublish,
};
/**
* implements the client role protocol.
*/
class SrsRtmpClient
{
private:
SrsProtocol* protocol;
st_netfd_t stfd;
public:
SrsRtmpClient(st_netfd_t _stfd);
virtual ~SrsRtmpClient();
public:
virtual void set_recv_timeout(int64_t timeout_us);
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
public:
virtual int handshake();
virtual int connect_app(std::string app, std::string tc_url);
virtual int create_stream(int& stream_id);
virtual int play(std::string stream, int stream_id);
virtual int publish(std::string stream, int stream_id);
};
/**
* the rtmp provices rtmp-command-protocol services,
* a high level protocol, media stream oriented services,
* such as connect to vhost/app, play stream, get audio/video data.
*/
class SrsRtmp
{
private:
SrsProtocol* protocol;
st_netfd_t stfd;
public:
SrsRtmp(st_netfd_t client_stfd);
virtual ~SrsRtmp();
public:
virtual SrsProtocol* get_protocol();
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
public:
virtual int handshake();
virtual int connect_app(SrsRequest* req);
virtual int set_window_ack_size(int ack_size);
/**
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
* using the Limit type field.
*/
virtual int set_peer_bandwidth(int bandwidth, int type);
virtual int response_connect_app(SrsRequest* req);
virtual int on_bw_done();
/**
* recv some message to identify the client.
* @stream_id, client will createStream to play or publish by flash,
* the stream_id used to response the createStream request.
* @type, output the client type.
*/
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
/**
* set the chunk size when client type identified.
*/
virtual int set_chunk_size(int chunk_size);
/**
* when client type is play, response with packets:
* StreamBegin,
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
* |RtmpSampleAccess(false, false),
* onStatus(NetStream.Data.Start).
*/
virtual int start_play(int stream_id);
/**
* when client(type is play) send pause message,
* if is_pause, response the following packets:
* onStatus(NetStream.Pause.Notify)
* StreamEOF
* if not is_pause, response the following packets:
* onStatus(NetStream.Unpause.Notify)
* StreamBegin
*/
virtual int on_play_client_pause(int stream_id, bool is_pause);
/**
* when client type is publish, response with packets:
* releaseStream response
* FCPublish
* FCPublish response
* createStream response
* onFCPublish(NetStream.Publish.Start)
* onStatus(NetStream.Publish.Start)
*/
virtual int start_fmle_publish(int stream_id);
/**
* process the FMLE unpublish event.
* @unpublish_tid the unpublish request transaction id.
*/
virtual int fmle_unpublish(int stream_id, double unpublish_tid);
/**
* when client type is publish, response with packets:
* onStatus(NetStream.Publish.Start)
*/
virtual int start_flash_publish(int stream_id);
private:
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
};
/*
The MIT License (MIT)
Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_RTMP_HPP
#define SRS_CORE_RTMP_HPP
/*
#include <srs_core_rtmp.hpp>
*/
#include <srs_core.hpp>
#include <string>
#include <st.h>
class SrsProtocol;
class ISrsMessage;
class SrsCommonMessage;
class SrsCreateStreamPacket;
class SrsFMLEStartPacket;
class SrsPublishPacket;
class SrsSharedPtrMessage;
class SrsOnMetaDataPacket;
/**
* the original request from client.
*/
struct SrsRequest
{
std::string tcUrl;
std::string pageUrl;
std::string swfUrl;
double objectEncoding;
std::string schema;
std::string vhost;
std::string port;
std::string app;
std::string stream;
SrsRequest();
virtual ~SrsRequest();
/**
* disconvery vhost/app from tcUrl.
*/
virtual int discovery_app();
virtual std::string get_stream_url();
virtual void strip();
private:
std::string& trim(std::string& str, std::string chs);
};
/**
* the response to client.
*/
struct SrsResponse
{
int stream_id;
SrsResponse();
virtual ~SrsResponse();
};
/**
* the rtmp client type.
*/
enum SrsClientType
{
SrsClientUnknown,
SrsClientPlay,
SrsClientFMLEPublish,
SrsClientFlashPublish,
};
/**
* implements the client role protocol.
*/
class SrsRtmpClient
{
private:
SrsProtocol* protocol;
st_netfd_t stfd;
public:
SrsRtmpClient(st_netfd_t _stfd);
virtual ~SrsRtmpClient();
public:
virtual void set_recv_timeout(int64_t timeout_us);
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
public:
virtual int handshake();
virtual int connect_app(std::string app, std::string tc_url);
virtual int create_stream(int& stream_id);
virtual int play(std::string stream, int stream_id);
virtual int publish(std::string stream, int stream_id);
};
/**
* the rtmp provices rtmp-command-protocol services,
* a high level protocol, media stream oriented services,
* such as connect to vhost/app, play stream, get audio/video data.
*/
class SrsRtmp
{
private:
SrsProtocol* protocol;
st_netfd_t stfd;
public:
SrsRtmp(st_netfd_t client_stfd);
virtual ~SrsRtmp();
public:
virtual SrsProtocol* get_protocol();
virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes();
virtual int get_recv_kbps();
virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg);
public:
virtual int handshake();
virtual int connect_app(SrsRequest* req);
virtual int set_window_ack_size(int ack_size);
/**
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
* using the Limit type field.
*/
virtual int set_peer_bandwidth(int bandwidth, int type);
virtual int response_connect_app(SrsRequest* req);
virtual int on_bw_done();
/**
* recv some message to identify the client.
* @stream_id, client will createStream to play or publish by flash,
* the stream_id used to response the createStream request.
* @type, output the client type.
*/
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
/**
* set the chunk size when client type identified.
*/
virtual int set_chunk_size(int chunk_size);
/**
* when client type is play, response with packets:
* StreamBegin,
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
* |RtmpSampleAccess(false, false),
* onStatus(NetStream.Data.Start).
*/
virtual int start_play(int stream_id);
/**
* when client(type is play) send pause message,
* if is_pause, response the following packets:
* onStatus(NetStream.Pause.Notify)
* StreamEOF
* if not is_pause, response the following packets:
* onStatus(NetStream.Unpause.Notify)
* StreamBegin
*/
virtual int on_play_client_pause(int stream_id, bool is_pause);
/**
* when client type is publish, response with packets:
* releaseStream response
* FCPublish
* FCPublish response
* createStream response
* onFCPublish(NetStream.Publish.Start)
* onStatus(NetStream.Publish.Start)
*/
virtual int start_fmle_publish(int stream_id);
/**
* process the FMLE unpublish event.
* @unpublish_tid the unpublish request transaction id.
*/
virtual int fmle_unpublish(int stream_id, double unpublish_tid);
/**
* when client type is publish, response with packets:
* onStatus(NetStream.Publish.Start)
*/
virtual int start_flash_publish(int stream_id);
private:
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
};
#endif

0
trunk/src/srs/srs.upp Executable file → Normal file
View file