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

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

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

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

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

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

@ -1,173 +1,173 @@
/* /*
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2013 winlin Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include <srs_core_pithy_print.hpp> #include <srs_core_pithy_print.hpp>
#include <stdlib.h> #include <stdlib.h>
#include <map> #include <map>
#include <srs_core_log.hpp> #include <srs_core_log.hpp>
#include <srs_core_config.hpp> #include <srs_core_config.hpp>
#include <srs_core_reload.hpp> #include <srs_core_reload.hpp>
#include <srs_core_error.hpp> #include <srs_core_error.hpp>
#define SRS_STAGE_DEFAULT_INTERVAL_MS 1200 #define SRS_STAGE_DEFAULT_INTERVAL_MS 1200
#define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300 #define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300
#define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100 #define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100
#define SRS_STAGE_FORWARDER_INTERVAL_MS 2000 #define SRS_STAGE_FORWARDER_INTERVAL_MS 2000
struct SrsStageInfo : public SrsReloadHandler struct SrsStageInfo : public SrsReloadHandler
{ {
int stage_id; int stage_id;
int pithy_print_time_ms; int pithy_print_time_ms;
int nb_clients; int nb_clients;
SrsStageInfo(int _stage_id) SrsStageInfo(int _stage_id)
{ {
stage_id = _stage_id; stage_id = _stage_id;
nb_clients = 0; nb_clients = 0;
update_print_time(); update_print_time();
config->subscribe(this); config->subscribe(this);
} }
virtual ~SrsStageInfo() virtual ~SrsStageInfo()
{ {
config->unsubscribe(this); config->unsubscribe(this);
} }
void update_print_time() void update_print_time()
{ {
switch (stage_id) { switch (stage_id) {
case SRS_STAGE_PLAY_USER: { case SRS_STAGE_PLAY_USER: {
pithy_print_time_ms = SRS_STAGE_PLAY_USER_INTERVAL_MS; pithy_print_time_ms = SRS_STAGE_PLAY_USER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_play(); SrsConfDirective* conf = config->get_pithy_print_play();
if (conf && !conf->arg0().empty()) { if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str()); pithy_print_time_ms = ::atoi(conf->arg0().c_str());
} }
break; break;
} }
case SRS_STAGE_PUBLISH_USER: { case SRS_STAGE_PUBLISH_USER: {
pithy_print_time_ms = SRS_STAGE_PUBLISH_USER_INTERVAL_MS; pithy_print_time_ms = SRS_STAGE_PUBLISH_USER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_publish(); SrsConfDirective* conf = config->get_pithy_print_publish();
if (conf && !conf->arg0().empty()) { if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str()); pithy_print_time_ms = ::atoi(conf->arg0().c_str());
} }
break; break;
} }
case SRS_STAGE_FORWARDER: { case SRS_STAGE_FORWARDER: {
pithy_print_time_ms = SRS_STAGE_FORWARDER_INTERVAL_MS; pithy_print_time_ms = SRS_STAGE_FORWARDER_INTERVAL_MS;
SrsConfDirective* conf = config->get_pithy_print_forwarder(); SrsConfDirective* conf = config->get_pithy_print_forwarder();
if (conf && !conf->arg0().empty()) { if (conf && !conf->arg0().empty()) {
pithy_print_time_ms = ::atoi(conf->arg0().c_str()); pithy_print_time_ms = ::atoi(conf->arg0().c_str());
} }
break; break;
} }
default: { default: {
pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS; pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS;
break; break;
} }
} }
} }
public: public:
virtual int on_reload_pithy_print() virtual int on_reload_pithy_print()
{ {
update_print_time(); update_print_time();
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
}; };
static std::map<int, SrsStageInfo*> _srs_stages; static std::map<int, SrsStageInfo*> _srs_stages;
SrsPithyPrint::SrsPithyPrint(int _stage_id) SrsPithyPrint::SrsPithyPrint(int _stage_id)
{ {
stage_id = _stage_id; stage_id = _stage_id;
client_id = enter_stage(); client_id = enter_stage();
printed_age = age = 0; printed_age = age = 0;
} }
SrsPithyPrint::~SrsPithyPrint() SrsPithyPrint::~SrsPithyPrint()
{ {
leave_stage(); leave_stage();
} }
int SrsPithyPrint::enter_stage() int SrsPithyPrint::enter_stage()
{ {
SrsStageInfo* stage = NULL; SrsStageInfo* stage = NULL;
std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id); std::map<int, SrsStageInfo*>::iterator it = _srs_stages.find(stage_id);
if (it == _srs_stages.end()) { if (it == _srs_stages.end()) {
stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id); stage = _srs_stages[stage_id] = new SrsStageInfo(stage_id);
} else { } else {
stage = it->second; stage = it->second;
} }
srs_assert(stage != NULL); srs_assert(stage != NULL);
client_id = stage->nb_clients++; client_id = stage->nb_clients++;
srs_verbose("enter stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", 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); stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
return client_id; return client_id;
} }
void SrsPithyPrint::leave_stage() void SrsPithyPrint::leave_stage()
{ {
SrsStageInfo* stage = _srs_stages[stage_id]; SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL); srs_assert(stage != NULL);
stage->nb_clients--; stage->nb_clients--;
srs_verbose("leave stage, stage_id=%d, client_id=%d, nb_clients=%d, time_ms=%d", 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); stage->stage_id, client_id, stage->nb_clients, stage->pithy_print_time_ms);
} }
void SrsPithyPrint::elapse(int64_t time_ms) void SrsPithyPrint::elapse(int64_t time_ms)
{ {
age += time_ms; age += time_ms;
} }
bool SrsPithyPrint::can_print() bool SrsPithyPrint::can_print()
{ {
SrsStageInfo* stage = _srs_stages[stage_id]; SrsStageInfo* stage = _srs_stages[stage_id];
srs_assert(stage != NULL); srs_assert(stage != NULL);
int64_t alive_age = age - printed_age; int64_t alive_age = age - printed_age;
int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms; int64_t can_print_age = stage->nb_clients * stage->pithy_print_time_ms;
bool can_print = alive_age >= can_print_age; bool can_print = alive_age >= can_print_age;
if (can_print) { if (can_print) {
printed_age = age; printed_age = age;
} }
return can_print; return can_print;
} }
int64_t SrsPithyPrint::get_age() int64_t SrsPithyPrint::get_age()
{ {
return age; return age;
} }
void SrsPithyPrint::set_age(int64_t _age) void SrsPithyPrint::set_age(int64_t _age)
{ {
age = _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) The MIT License (MIT)
Copyright (c) 2013 winlin Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#ifndef SRS_CORE_PITHY_PRINT_HPP #ifndef SRS_CORE_PITHY_PRINT_HPP
#define SRS_CORE_PITHY_PRINT_HPP #define SRS_CORE_PITHY_PRINT_HPP
/* /*
#include <srs_core_pithy_print.hpp> #include <srs_core_pithy_print.hpp>
*/ */
#include <srs_core.hpp> #include <srs_core.hpp>
// the pithy stage for all play clients. // the pithy stage for all play clients.
#define SRS_STAGE_PLAY_USER 1 #define SRS_STAGE_PLAY_USER 1
// the pithy stage for all publish clients. // the pithy stage for all publish clients.
#define SRS_STAGE_PUBLISH_USER 2 #define SRS_STAGE_PUBLISH_USER 2
// the pithy stage for all forward clients. // the pithy stage for all forward clients.
#define SRS_STAGE_FORWARDER 3 #define SRS_STAGE_FORWARDER 3
/** /**
* the stage is used for a collection of object to do print, * the stage is used for a collection of object to do print,
* the print time in a stage is constant and not changed. * the print time in a stage is constant and not changed.
* for example, stage #1 for all play clients, print time is 3s, * for example, stage #1 for all play clients, print time is 3s,
* if there is 10clients, then all clients should print in 10*3s. * if there is 10clients, then all clients should print in 10*3s.
*/ */
class SrsPithyPrint class SrsPithyPrint
{ {
private: private:
int client_id; int client_id;
int stage_id; int stage_id;
int64_t age; int64_t age;
int64_t printed_age; int64_t printed_age;
public: public:
/** /**
* @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER. * @param _stage_id defined in SRS_STAGE_xxx, eg. SRS_STAGE_PLAY_USER.
*/ */
SrsPithyPrint(int _stage_id); SrsPithyPrint(int _stage_id);
virtual ~SrsPithyPrint(); virtual ~SrsPithyPrint();
private: private:
/** /**
* enter the specified stage, return the client id. * enter the specified stage, return the client id.
*/ */
virtual int enter_stage(); virtual int enter_stage();
/** /**
* leave the specified stage, release the client id. * leave the specified stage, release the client id.
*/ */
virtual void leave_stage(); virtual void leave_stage();
public: public:
/** /**
* specified client elapse some time. * specified client elapse some time.
*/ */
virtual void elapse(int64_t time_ms); virtual void elapse(int64_t time_ms);
/** /**
* whether current client can print. * whether current client can print.
*/ */
virtual bool can_print(); virtual bool can_print();
/** /**
* get the elapsed time in ms. * get the elapsed time in ms.
*/ */
virtual int64_t get_age(); virtual int64_t get_age();
virtual void set_age(int64_t _age); virtual void set_age(int64_t _age);
}; };
#endif #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) The MIT License (MIT)
Copyright (c) 2013 winlin Copyright (c) 2013 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#ifndef SRS_CORE_RTMP_HPP #ifndef SRS_CORE_RTMP_HPP
#define SRS_CORE_RTMP_HPP #define SRS_CORE_RTMP_HPP
/* /*
#include <srs_core_rtmp.hpp> #include <srs_core_rtmp.hpp>
*/ */
#include <srs_core.hpp> #include <srs_core.hpp>
#include <string> #include <string>
#include <st.h> #include <st.h>
class SrsProtocol; class SrsProtocol;
class ISrsMessage; class ISrsMessage;
class SrsCommonMessage; class SrsCommonMessage;
class SrsCreateStreamPacket; class SrsCreateStreamPacket;
class SrsFMLEStartPacket; class SrsFMLEStartPacket;
class SrsPublishPacket; class SrsPublishPacket;
class SrsSharedPtrMessage; class SrsSharedPtrMessage;
class SrsOnMetaDataPacket; class SrsOnMetaDataPacket;
/** /**
* the original request from client. * the original request from client.
*/ */
struct SrsRequest struct SrsRequest
{ {
std::string tcUrl; std::string tcUrl;
std::string pageUrl; std::string pageUrl;
std::string swfUrl; std::string swfUrl;
double objectEncoding; double objectEncoding;
std::string schema; std::string schema;
std::string vhost; std::string vhost;
std::string port; std::string port;
std::string app; std::string app;
std::string stream; std::string stream;
SrsRequest(); SrsRequest();
virtual ~SrsRequest(); virtual ~SrsRequest();
/** /**
* disconvery vhost/app from tcUrl. * disconvery vhost/app from tcUrl.
*/ */
virtual int discovery_app(); virtual int discovery_app();
virtual std::string get_stream_url(); virtual std::string get_stream_url();
virtual void strip(); virtual void strip();
private: private:
std::string& trim(std::string& str, std::string chs); std::string& trim(std::string& str, std::string chs);
}; };
/** /**
* the response to client. * the response to client.
*/ */
struct SrsResponse struct SrsResponse
{ {
int stream_id; int stream_id;
SrsResponse(); SrsResponse();
virtual ~SrsResponse(); virtual ~SrsResponse();
}; };
/** /**
* the rtmp client type. * the rtmp client type.
*/ */
enum SrsClientType enum SrsClientType
{ {
SrsClientUnknown, SrsClientUnknown,
SrsClientPlay, SrsClientPlay,
SrsClientFMLEPublish, SrsClientFMLEPublish,
SrsClientFlashPublish, SrsClientFlashPublish,
}; };
/** /**
* implements the client role protocol. * implements the client role protocol.
*/ */
class SrsRtmpClient class SrsRtmpClient
{ {
private: private:
SrsProtocol* protocol; SrsProtocol* protocol;
st_netfd_t stfd; st_netfd_t stfd;
public: public:
SrsRtmpClient(st_netfd_t _stfd); SrsRtmpClient(st_netfd_t _stfd);
virtual ~SrsRtmpClient(); virtual ~SrsRtmpClient();
public: public:
virtual void set_recv_timeout(int64_t timeout_us); virtual void set_recv_timeout(int64_t timeout_us);
virtual void set_send_timeout(int64_t timeout_us); virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes(); virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes(); virtual int64_t get_send_bytes();
virtual int get_recv_kbps(); virtual int get_recv_kbps();
virtual int get_send_kbps(); virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg); virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg); virtual int send_message(ISrsMessage* msg);
public: public:
virtual int handshake(); virtual int handshake();
virtual int connect_app(std::string app, std::string tc_url); virtual int connect_app(std::string app, std::string tc_url);
virtual int create_stream(int& stream_id); virtual int create_stream(int& stream_id);
virtual int play(std::string stream, int stream_id); virtual int play(std::string stream, int stream_id);
virtual int publish(std::string stream, int stream_id); virtual int publish(std::string stream, int stream_id);
}; };
/** /**
* the rtmp provices rtmp-command-protocol services, * the rtmp provices rtmp-command-protocol services,
* a high level protocol, media stream oriented services, * a high level protocol, media stream oriented services,
* such as connect to vhost/app, play stream, get audio/video data. * such as connect to vhost/app, play stream, get audio/video data.
*/ */
class SrsRtmp class SrsRtmp
{ {
private: private:
SrsProtocol* protocol; SrsProtocol* protocol;
st_netfd_t stfd; st_netfd_t stfd;
public: public:
SrsRtmp(st_netfd_t client_stfd); SrsRtmp(st_netfd_t client_stfd);
virtual ~SrsRtmp(); virtual ~SrsRtmp();
public: public:
virtual SrsProtocol* get_protocol(); virtual SrsProtocol* get_protocol();
virtual void set_recv_timeout(int64_t timeout_us); virtual void set_recv_timeout(int64_t timeout_us);
virtual int64_t get_recv_timeout(); virtual int64_t get_recv_timeout();
virtual void set_send_timeout(int64_t timeout_us); virtual void set_send_timeout(int64_t timeout_us);
virtual int64_t get_recv_bytes(); virtual int64_t get_recv_bytes();
virtual int64_t get_send_bytes(); virtual int64_t get_send_bytes();
virtual int get_recv_kbps(); virtual int get_recv_kbps();
virtual int get_send_kbps(); virtual int get_send_kbps();
virtual int recv_message(SrsCommonMessage** pmsg); virtual int recv_message(SrsCommonMessage** pmsg);
virtual int send_message(ISrsMessage* msg); virtual int send_message(ISrsMessage* msg);
public: public:
virtual int handshake(); virtual int handshake();
virtual int connect_app(SrsRequest* req); virtual int connect_app(SrsRequest* req);
virtual int set_window_ack_size(int ack_size); virtual int set_window_ack_size(int ack_size);
/** /**
* @type: The sender can mark this message hard (0), soft (1), or dynamic (2) * @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
* using the Limit type field. * using the Limit type field.
*/ */
virtual int set_peer_bandwidth(int bandwidth, int type); virtual int set_peer_bandwidth(int bandwidth, int type);
virtual int response_connect_app(SrsRequest* req); virtual int response_connect_app(SrsRequest* req);
virtual int on_bw_done(); virtual int on_bw_done();
/** /**
* recv some message to identify the client. * recv some message to identify the client.
* @stream_id, client will createStream to play or publish by flash, * @stream_id, client will createStream to play or publish by flash,
* the stream_id used to response the createStream request. * the stream_id used to response the createStream request.
* @type, output the client type. * @type, output the client type.
*/ */
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name); virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
/** /**
* set the chunk size when client type identified. * set the chunk size when client type identified.
*/ */
virtual int set_chunk_size(int chunk_size); virtual int set_chunk_size(int chunk_size);
/** /**
* when client type is play, response with packets: * when client type is play, response with packets:
* StreamBegin, * StreamBegin,
* onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start)., * onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
* |RtmpSampleAccess(false, false), * |RtmpSampleAccess(false, false),
* onStatus(NetStream.Data.Start). * onStatus(NetStream.Data.Start).
*/ */
virtual int start_play(int stream_id); virtual int start_play(int stream_id);
/** /**
* when client(type is play) send pause message, * when client(type is play) send pause message,
* if is_pause, response the following packets: * if is_pause, response the following packets:
* onStatus(NetStream.Pause.Notify) * onStatus(NetStream.Pause.Notify)
* StreamEOF * StreamEOF
* if not is_pause, response the following packets: * if not is_pause, response the following packets:
* onStatus(NetStream.Unpause.Notify) * onStatus(NetStream.Unpause.Notify)
* StreamBegin * StreamBegin
*/ */
virtual int on_play_client_pause(int stream_id, bool is_pause); virtual int on_play_client_pause(int stream_id, bool is_pause);
/** /**
* when client type is publish, response with packets: * when client type is publish, response with packets:
* releaseStream response * releaseStream response
* FCPublish * FCPublish
* FCPublish response * FCPublish response
* createStream response * createStream response
* onFCPublish(NetStream.Publish.Start) * onFCPublish(NetStream.Publish.Start)
* onStatus(NetStream.Publish.Start) * onStatus(NetStream.Publish.Start)
*/ */
virtual int start_fmle_publish(int stream_id); virtual int start_fmle_publish(int stream_id);
/** /**
* process the FMLE unpublish event. * process the FMLE unpublish event.
* @unpublish_tid the unpublish request transaction id. * @unpublish_tid the unpublish request transaction id.
*/ */
virtual int fmle_unpublish(int stream_id, double unpublish_tid); virtual int fmle_unpublish(int stream_id, double unpublish_tid);
/** /**
* when client type is publish, response with packets: * when client type is publish, response with packets:
* onStatus(NetStream.Publish.Start) * onStatus(NetStream.Publish.Start)
*/ */
virtual int start_flash_publish(int stream_id); virtual int start_flash_publish(int stream_id);
private: private:
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name); 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_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); virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
}; };
#endif #endif

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