2013-11-23 03:36:07 +00:00
|
|
|
/*
|
|
|
|
The MIT License (MIT)
|
|
|
|
|
2014-01-01 02:37:12 +00:00
|
|
|
Copyright (c) 2013-2014 winlin
|
2013-11-23 03:36:07 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2014-03-02 13:49:09 +00:00
|
|
|
#include <srs_app_server.hpp>
|
2013-11-23 03:36:07 +00:00
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <signal.h>
|
2014-03-21 07:45:34 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
2013-11-23 03:36:07 +00:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2014-03-01 02:42:55 +00:00
|
|
|
#include <srs_kernel_log.hpp>
|
2014-03-01 02:30:16 +00:00
|
|
|
#include <srs_kernel_error.hpp>
|
2014-03-27 04:14:04 +00:00
|
|
|
#include <srs_app_rtmp_conn.hpp>
|
2014-03-02 13:49:09 +00:00
|
|
|
#include <srs_app_config.hpp>
|
2014-03-21 09:56:27 +00:00
|
|
|
#include <srs_kernel_utility.hpp>
|
2014-03-27 05:25:08 +00:00
|
|
|
#include <srs_app_http_api.hpp>
|
|
|
|
#include <srs_app_http_conn.hpp>
|
2014-04-02 10:07:34 +00:00
|
|
|
#include <srs_app_http.hpp>
|
2014-04-07 01:07:12 +00:00
|
|
|
#include <srs_app_ingest.hpp>
|
2014-05-03 14:59:21 +00:00
|
|
|
#include <srs_app_source.hpp>
|
2014-05-17 06:53:04 +00:00
|
|
|
#include <srs_app_utility.hpp>
|
2014-05-19 09:39:01 +00:00
|
|
|
#include <srs_app_heartbeat.hpp>
|
2014-06-19 07:28:05 +00:00
|
|
|
#include <srs_app_kbps.hpp>
|
2013-11-23 03:36:07 +00:00
|
|
|
|
2014-06-08 05:03:03 +00:00
|
|
|
// signal defines.
|
|
|
|
#define SIGNAL_RELOAD SIGHUP
|
|
|
|
|
2014-01-01 12:14:46 +00:00
|
|
|
#define SERVER_LISTEN_BACKLOG 512
|
2014-04-19 13:23:34 +00:00
|
|
|
|
|
|
|
// system interval
|
2014-04-19 16:15:26 +00:00
|
|
|
// all resolution times should be times togother,
|
|
|
|
// for example, system-time is 3(300ms),
|
|
|
|
// then rusage can be 3*x, for instance, 3*10=30(3s),
|
|
|
|
// the meminfo canbe 30*x, for instance, 30*2=60(6s)
|
2014-04-19 13:23:34 +00:00
|
|
|
#define SRS_SYS_CYCLE_INTERVAL 100
|
|
|
|
|
|
|
|
// update time interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_TIME_RESOLUTION_MS_TIMES
|
2014-06-27 05:35:28 +00:00
|
|
|
// @see SYS_TIME_RESOLUTION_US
|
2014-04-19 13:23:34 +00:00
|
|
|
#define SRS_SYS_TIME_RESOLUTION_MS_TIMES 3
|
|
|
|
|
|
|
|
// update rusage interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_RUSAGE_RESOLUTION_TIMES
|
2014-04-19 15:18:00 +00:00
|
|
|
#define SRS_SYS_RUSAGE_RESOLUTION_TIMES 30
|
2014-04-19 13:23:34 +00:00
|
|
|
|
2014-08-02 01:54:21 +00:00
|
|
|
// update network devices info interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES
|
|
|
|
#define SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES 30
|
|
|
|
|
2014-04-19 13:23:34 +00:00
|
|
|
// update rusage interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_CPU_STAT_RESOLUTION_TIMES
|
2014-04-19 15:18:00 +00:00
|
|
|
#define SRS_SYS_CPU_STAT_RESOLUTION_TIMES 30
|
2013-11-23 03:36:07 +00:00
|
|
|
|
2014-07-27 06:04:22 +00:00
|
|
|
// update the disk iops interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_DISK_STAT_RESOLUTION_TIMES
|
|
|
|
#define SRS_SYS_DISK_STAT_RESOLUTION_TIMES 60
|
|
|
|
|
2014-04-19 16:15:26 +00:00
|
|
|
// update rusage interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_MEMINFO_RESOLUTION_TIMES
|
|
|
|
#define SRS_SYS_MEMINFO_RESOLUTION_TIMES 60
|
|
|
|
|
2014-05-08 07:45:51 +00:00
|
|
|
// update platform info interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES
|
2014-05-19 09:39:01 +00:00
|
|
|
#define SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES 90
|
2014-05-08 07:45:51 +00:00
|
|
|
|
2014-06-18 08:13:02 +00:00
|
|
|
// update network devices info interval:
|
|
|
|
// SRS_SYS_CYCLE_INTERVAL * SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES
|
|
|
|
#define SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES 90
|
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
SrsListener::SrsListener(SrsServer* server, SrsListenerType type)
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
fd = -1;
|
|
|
|
stfd = NULL;
|
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
_port = 0;
|
|
|
|
_server = server;
|
|
|
|
_type = type;
|
2013-12-14 06:06:32 +00:00
|
|
|
|
2014-05-23 09:23:33 +00:00
|
|
|
pthread = new SrsThread(this, 0, true);
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SrsListener::~SrsListener()
|
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
srs_close_stfd(stfd);
|
|
|
|
|
|
|
|
pthread->stop();
|
|
|
|
srs_freep(pthread);
|
|
|
|
|
|
|
|
// st does not close it sometimes,
|
|
|
|
// close it manually.
|
|
|
|
close(fd);
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
SrsListenerType SrsListener::type()
|
|
|
|
{
|
|
|
|
return _type;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsListener::listen(int port)
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
_port = port;
|
2014-03-18 03:32:58 +00:00
|
|
|
|
|
|
|
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
2013-11-23 03:36:07 +00:00
|
|
|
ret = ERROR_SOCKET_CREATE;
|
|
|
|
srs_error("create linux socket error. ret=%d", ret);
|
|
|
|
return ret;
|
2014-03-18 03:32:58 +00:00
|
|
|
}
|
|
|
|
srs_verbose("create linux socket success. fd=%d", fd);
|
2013-11-23 03:36:07 +00:00
|
|
|
|
|
|
|
int reuse_socket = 1;
|
|
|
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int)) == -1) {
|
|
|
|
ret = ERROR_SOCKET_SETREUSE;
|
|
|
|
srs_error("setsockopt reuse-addr error. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("setsockopt reuse-addr success. fd=%d", fd);
|
|
|
|
|
|
|
|
sockaddr_in addr;
|
|
|
|
addr.sin_family = AF_INET;
|
2014-04-12 14:16:39 +00:00
|
|
|
addr.sin_port = htons(_port);
|
2013-11-23 03:36:07 +00:00
|
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
if (bind(fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
|
|
|
ret = ERROR_SOCKET_BIND;
|
|
|
|
srs_error("bind socket error. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("bind socket success. fd=%d", fd);
|
|
|
|
|
|
|
|
if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) {
|
|
|
|
ret = ERROR_SOCKET_LISTEN;
|
|
|
|
srs_error("listen socket error. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("listen socket success. fd=%d", fd);
|
|
|
|
|
|
|
|
if ((stfd = st_netfd_open_socket(fd)) == NULL){
|
|
|
|
ret = ERROR_ST_OPEN_SOCKET;
|
|
|
|
srs_error("st_netfd_open_socket open socket failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("st open socket success. fd=%d", fd);
|
|
|
|
|
2013-12-14 06:06:32 +00:00
|
|
|
if ((ret = pthread->start()) != ERROR_SUCCESS) {
|
2013-11-23 03:36:07 +00:00
|
|
|
srs_error("st_thread_create listen thread error. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("create st listen thread success.");
|
|
|
|
|
2014-04-16 08:58:54 +00:00
|
|
|
srs_trace("listen thread cid=%d, current_cid=%d, "
|
|
|
|
"listen at port=%d, type=%d, fd=%d started success",
|
|
|
|
pthread->cid(), _srs_context->get_id(), _port, _type, fd);
|
2014-03-18 03:32:58 +00:00
|
|
|
|
|
|
|
return ret;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2014-04-04 04:18:05 +00:00
|
|
|
void SrsListener::on_thread_start()
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2014-04-12 14:16:39 +00:00
|
|
|
srs_trace("listen cycle start, port=%d, type=%d, fd=%d", _port, _type, fd);
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2013-12-14 06:06:32 +00:00
|
|
|
int SrsListener::cycle()
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2013-12-14 06:06:32 +00:00
|
|
|
st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
|
|
|
|
|
|
|
|
if(client_stfd == NULL){
|
|
|
|
// ignore error.
|
2014-05-27 11:18:31 +00:00
|
|
|
srs_error("ignore accept thread stoppped for accept client error");
|
2013-12-14 06:06:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
|
2014-03-18 03:32:58 +00:00
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
if ((ret = _server->accept_client(_type, client_stfd)) != ERROR_SUCCESS) {
|
2014-03-18 03:32:58 +00:00
|
|
|
srs_warn("accept client error. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 03:26:32 +00:00
|
|
|
SrsSignalManager* SrsSignalManager::instance = NULL;
|
|
|
|
|
|
|
|
SrsSignalManager::SrsSignalManager(SrsServer* server)
|
|
|
|
{
|
|
|
|
SrsSignalManager::instance = this;
|
|
|
|
|
|
|
|
_server = server;
|
|
|
|
sig_pipe[0] = sig_pipe[1] = -1;
|
2014-05-23 09:23:33 +00:00
|
|
|
pthread = new SrsThread(this, 0, true);
|
2014-04-30 03:26:32 +00:00
|
|
|
signal_read_stfd = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
SrsSignalManager::~SrsSignalManager()
|
|
|
|
{
|
|
|
|
pthread->stop();
|
|
|
|
srs_freep(pthread);
|
|
|
|
|
|
|
|
srs_close_stfd(signal_read_stfd);
|
|
|
|
|
|
|
|
if (sig_pipe[0] > 0) {
|
|
|
|
::close(sig_pipe[0]);
|
|
|
|
}
|
|
|
|
if (sig_pipe[1] > 0) {
|
|
|
|
::close(sig_pipe[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsSignalManager::initialize()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsSignalManager::start()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Note that if multiple processes are used (see below),
|
|
|
|
* the signal pipe should be initialized after the fork(2) call
|
|
|
|
* so that each process has its own private pipe.
|
|
|
|
*/
|
|
|
|
struct sigaction sa;
|
|
|
|
|
|
|
|
/* Create signal pipe */
|
|
|
|
if (pipe(sig_pipe) < 0) {
|
|
|
|
ret = ERROR_SYSTEM_CREATE_PIPE;
|
|
|
|
srs_error("create signal manager pipe failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Install sig_catcher() as a signal handler */
|
|
|
|
sa.sa_handler = SrsSignalManager::sig_catcher;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = 0;
|
|
|
|
sigaction(SIGNAL_RELOAD, &sa, NULL);
|
|
|
|
|
|
|
|
sa.sa_handler = SrsSignalManager::sig_catcher;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = 0;
|
|
|
|
sigaction(SIGTERM, &sa, NULL);
|
|
|
|
|
|
|
|
sa.sa_handler = SrsSignalManager::sig_catcher;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = 0;
|
|
|
|
sigaction(SIGINT, &sa, NULL);
|
|
|
|
|
2014-05-03 14:59:21 +00:00
|
|
|
sa.sa_handler = SrsSignalManager::sig_catcher;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sa.sa_flags = 0;
|
|
|
|
sigaction(SIGUSR2, &sa, NULL);
|
|
|
|
|
|
|
|
srs_trace("signal installed");
|
|
|
|
|
2014-04-30 03:26:32 +00:00
|
|
|
return pthread->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsSignalManager::cycle()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
if (signal_read_stfd == NULL) {
|
|
|
|
signal_read_stfd = st_netfd_open(sig_pipe[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
int signo;
|
|
|
|
|
|
|
|
/* Read the next signal from the pipe */
|
|
|
|
st_read(signal_read_stfd, &signo, sizeof(int), ST_UTIME_NO_TIMEOUT);
|
|
|
|
|
|
|
|
/* Process signal synchronously */
|
|
|
|
_server->on_signal(signo);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsSignalManager::sig_catcher(int signo)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Save errno to restore it after the write() */
|
|
|
|
err = errno;
|
|
|
|
|
|
|
|
/* write() is reentrant/async-safe */
|
|
|
|
int fd = SrsSignalManager::instance->sig_pipe[1];
|
|
|
|
write(fd, &signo, sizeof(int));
|
|
|
|
|
|
|
|
errno = err;
|
|
|
|
}
|
|
|
|
|
2013-11-23 03:36:07 +00:00
|
|
|
SrsServer::SrsServer()
|
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
signal_reload = false;
|
|
|
|
signal_gmc_stop = false;
|
2014-04-12 12:46:32 +00:00
|
|
|
pid_fd = -1;
|
2014-03-18 03:32:58 +00:00
|
|
|
|
2014-06-19 07:28:05 +00:00
|
|
|
signal_manager = NULL;
|
|
|
|
kbps = NULL;
|
2014-04-30 03:26:32 +00:00
|
|
|
|
2014-04-08 07:28:34 +00:00
|
|
|
// donot new object in constructor,
|
|
|
|
// for some global instance is not ready now,
|
|
|
|
// new these objects in initialize instead.
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-07 06:20:03 +00:00
|
|
|
http_api_handler = NULL;
|
2014-04-02 10:07:34 +00:00
|
|
|
#endif
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-07 06:20:03 +00:00
|
|
|
http_stream_handler = NULL;
|
2014-04-02 10:07:34 +00:00
|
|
|
#endif
|
2014-05-19 09:39:01 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_PARSER
|
|
|
|
http_heartbeat = NULL;
|
|
|
|
#endif
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_INGEST
|
2014-04-07 06:20:03 +00:00
|
|
|
ingester = NULL;
|
2014-04-07 01:27:30 +00:00
|
|
|
#endif
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SrsServer::~SrsServer()
|
2014-05-02 06:08:48 +00:00
|
|
|
{
|
|
|
|
destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsServer::destroy()
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2014-05-03 14:59:21 +00:00
|
|
|
srs_warn("start destroy server");
|
2014-03-18 03:32:58 +00:00
|
|
|
|
2014-05-03 14:59:21 +00:00
|
|
|
_srs_config->unsubscribe(this);
|
2014-03-18 03:32:58 +00:00
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
close_listeners(SrsListenerRtmpStream);
|
|
|
|
close_listeners(SrsListenerHttpApi);
|
|
|
|
close_listeners(SrsListenerHttpStream);
|
2014-05-03 14:59:21 +00:00
|
|
|
|
|
|
|
#ifdef SRS_AUTO_INGEST
|
|
|
|
ingester->stop();
|
|
|
|
#endif
|
2014-04-30 03:26:32 +00:00
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-02 10:07:34 +00:00
|
|
|
srs_freep(http_api_handler);
|
|
|
|
#endif
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-02 10:07:34 +00:00
|
|
|
srs_freep(http_stream_handler);
|
|
|
|
#endif
|
2014-05-19 09:39:01 +00:00
|
|
|
|
|
|
|
#ifdef SRS_AUTO_HTTP_PARSER
|
|
|
|
srs_freep(http_heartbeat);
|
|
|
|
#endif
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_INGEST
|
2014-04-07 01:27:30 +00:00
|
|
|
srs_freep(ingester);
|
|
|
|
#endif
|
2014-05-03 14:59:21 +00:00
|
|
|
|
|
|
|
if (pid_fd > 0) {
|
|
|
|
::close(pid_fd);
|
|
|
|
pid_fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
srs_freep(signal_manager);
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_freep(kbps);
|
2014-05-03 14:59:21 +00:00
|
|
|
|
|
|
|
for (std::vector<SrsConnection*>::iterator it = conns.begin(); it != conns.end();) {
|
|
|
|
SrsConnection* conn = *it;
|
|
|
|
|
|
|
|
// remove the connection, then free it,
|
|
|
|
// for the free will remove itself from server,
|
|
|
|
// when erased here, the remove of server will ignore.
|
|
|
|
it = conns.erase(it);
|
|
|
|
|
|
|
|
srs_freep(conn);
|
|
|
|
}
|
|
|
|
conns.clear();
|
|
|
|
|
|
|
|
SrsSource::destroy();
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::initialize()
|
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
2014-04-02 10:07:34 +00:00
|
|
|
|
2014-06-27 05:35:28 +00:00
|
|
|
// ensure the time is ok.
|
|
|
|
srs_update_system_time_ms();
|
|
|
|
|
2014-04-12 12:37:16 +00:00
|
|
|
// for the main objects(server, config, log, context),
|
2014-04-12 12:35:40 +00:00
|
|
|
// never subscribe handler in constructor,
|
|
|
|
// instead, subscribe handler in initialize method.
|
|
|
|
srs_assert(_srs_config);
|
|
|
|
_srs_config->subscribe(this);
|
|
|
|
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_assert(!signal_manager);
|
|
|
|
signal_manager = new SrsSignalManager(this);
|
|
|
|
|
|
|
|
srs_assert(!kbps);
|
|
|
|
kbps = new SrsKbps();
|
|
|
|
kbps->set_io(NULL, NULL);
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-07 06:20:03 +00:00
|
|
|
srs_assert(!http_api_handler);
|
|
|
|
http_api_handler = SrsHttpHandler::create_http_api();
|
|
|
|
#endif
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-07 06:20:03 +00:00
|
|
|
srs_assert(!http_stream_handler);
|
|
|
|
http_stream_handler = SrsHttpHandler::create_http_stream();
|
|
|
|
#endif
|
2014-05-19 09:39:01 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_PARSER
|
|
|
|
srs_assert(!http_heartbeat);
|
|
|
|
http_heartbeat = new SrsHttpHeartbeat();
|
|
|
|
#endif
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_INGEST
|
2014-04-07 06:20:03 +00:00
|
|
|
srs_assert(!ingester);
|
|
|
|
ingester = new SrsIngester();
|
|
|
|
#endif
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-02 10:07:34 +00:00
|
|
|
if ((ret = http_api_handler->initialize()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-02 10:07:34 +00:00
|
|
|
if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-03-18 03:32:58 +00:00
|
|
|
return ret;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 03:26:32 +00:00
|
|
|
int SrsServer::initialize_signal()
|
|
|
|
{
|
|
|
|
return signal_manager->initialize();
|
|
|
|
}
|
|
|
|
|
2014-03-21 07:45:34 +00:00
|
|
|
int SrsServer::acquire_pid_file()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
std::string pid_file = _srs_config->get_pid_file();
|
|
|
|
|
|
|
|
// -rw-r--r--
|
|
|
|
// 644
|
|
|
|
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
|
|
|
|
|
|
|
int fd;
|
|
|
|
// open pid file
|
|
|
|
if ((fd = ::open(pid_file.c_str(), O_WRONLY | O_CREAT, mode)) < 0) {
|
|
|
|
ret = ERROR_SYSTEM_PID_ACQUIRE;
|
|
|
|
srs_error("open pid file %s error, ret=%#x", pid_file.c_str(), ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// require write lock
|
2014-07-27 11:32:12 +00:00
|
|
|
struct flock lock;
|
2014-03-21 07:45:34 +00:00
|
|
|
|
|
|
|
lock.l_type = F_WRLCK; // F_RDLCK, F_WRLCK, F_UNLCK
|
|
|
|
lock.l_start = 0; // type offset, relative to l_whence
|
|
|
|
lock.l_whence = SEEK_SET; // SEEK_SET, SEEK_CUR, SEEK_END
|
|
|
|
lock.l_len = 0;
|
|
|
|
|
|
|
|
if (fcntl(fd, F_SETLK, &lock) < 0) {
|
|
|
|
if(errno == EACCES || errno == EAGAIN) {
|
|
|
|
ret = ERROR_SYSTEM_PID_ALREADY_RUNNING;
|
|
|
|
srs_error("srs is already running! ret=%#x", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ERROR_SYSTEM_PID_LOCK;
|
|
|
|
srs_error("require lock for file %s error! ret=%#x", pid_file.c_str(), ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// truncate file
|
|
|
|
if (ftruncate(fd, 0) < 0) {
|
|
|
|
ret = ERROR_SYSTEM_PID_TRUNCATE_FILE;
|
|
|
|
srs_error("truncate pid file %s error! ret=%#x", pid_file.c_str(), ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pid = (int)getpid();
|
|
|
|
|
|
|
|
// write the pid
|
|
|
|
char buf[512];
|
|
|
|
snprintf(buf, sizeof(buf), "%d", pid);
|
|
|
|
if (write(fd, buf, strlen(buf)) != (int)strlen(buf)) {
|
|
|
|
ret = ERROR_SYSTEM_PID_WRITE_FILE;
|
|
|
|
srs_error("write our pid error! pid=%d file=%s ret=%#x", pid, pid_file.c_str(), ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// auto close when fork child process.
|
|
|
|
int val;
|
|
|
|
if ((val = fcntl(fd, F_GETFD, 0)) < 0) {
|
|
|
|
ret = ERROR_SYSTEM_PID_GET_FILE_INFO;
|
|
|
|
srs_error("fnctl F_GETFD error! file=%s ret=%#x", pid_file.c_str(), ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
val |= FD_CLOEXEC;
|
|
|
|
if (fcntl(fd, F_SETFD, val) < 0) {
|
|
|
|
ret = ERROR_SYSTEM_PID_SET_FILE_INFO;
|
|
|
|
srs_error("fcntl F_SETFD error! file=%s ret=%#x", pid_file.c_str(), ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
srs_trace("write pid=%d to %s success!", pid, pid_file.c_str());
|
2014-04-12 12:46:32 +00:00
|
|
|
pid_fd = fd;
|
2014-03-21 07:45:34 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-23 06:40:55 +00:00
|
|
|
int SrsServer::initialize_st()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
// use linux epoll.
|
|
|
|
if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
|
|
|
|
ret = ERROR_ST_SET_EPOLL;
|
|
|
|
srs_error("st_set_eventsys use linux epoll failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("st_set_eventsys use linux epoll success");
|
|
|
|
|
|
|
|
if(st_init() != 0){
|
|
|
|
ret = ERROR_ST_INITIALIZE;
|
|
|
|
srs_error("st_init failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_verbose("st_init success");
|
|
|
|
|
|
|
|
// set current log id.
|
|
|
|
_srs_context->generate_id();
|
2014-04-16 08:58:54 +00:00
|
|
|
srs_trace("server main cid=%d", _srs_context->get_id());
|
2014-03-23 06:40:55 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-11-23 03:36:07 +00:00
|
|
|
int SrsServer::listen()
|
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
if ((ret = listen_rtmp()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
2014-03-27 04:14:04 +00:00
|
|
|
}
|
2014-04-12 14:16:39 +00:00
|
|
|
|
|
|
|
if ((ret = listen_http_api()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
2014-03-27 04:14:04 +00:00
|
|
|
}
|
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
if ((ret = listen_http_stream()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
2014-03-18 03:32:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2014-04-30 03:26:32 +00:00
|
|
|
int SrsServer::register_signal()
|
|
|
|
{
|
|
|
|
// start signal process thread.
|
|
|
|
return signal_manager->start();
|
|
|
|
}
|
|
|
|
|
2014-04-07 05:13:57 +00:00
|
|
|
int SrsServer::ingest()
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_INGEST
|
2014-04-07 01:27:30 +00:00
|
|
|
if ((ret = ingester->start()) != ERROR_SUCCESS) {
|
|
|
|
srs_error("start ingest streams failed. ret=%d", ret);
|
2014-04-07 00:41:32 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2014-04-07 01:27:30 +00:00
|
|
|
#endif
|
2014-04-07 05:13:57 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::cycle()
|
2014-05-02 04:29:56 +00:00
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
ret = do_cycle();
|
|
|
|
|
2014-05-12 05:14:36 +00:00
|
|
|
#ifdef SRS_AUTO_GPERF_MC
|
2014-05-02 06:08:48 +00:00
|
|
|
destroy();
|
2014-05-02 04:29:56 +00:00
|
|
|
|
2014-05-03 14:59:21 +00:00
|
|
|
srs_warn("sleep a long time for system st-threads to cleanup.");
|
|
|
|
st_usleep(3 * 1000 * 1000);
|
|
|
|
srs_warn("system quit");
|
2014-05-12 05:14:36 +00:00
|
|
|
#else
|
|
|
|
srs_warn("main cycle terminated, system quit normally.");
|
|
|
|
exit(0);
|
2014-05-03 14:59:21 +00:00
|
|
|
#endif
|
|
|
|
|
2014-05-02 04:29:56 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsServer::remove(SrsConnection* conn)
|
|
|
|
{
|
|
|
|
std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
|
|
|
|
|
2014-05-03 14:59:21 +00:00
|
|
|
// removed by destroy, ignore.
|
|
|
|
if (it == conns.end()) {
|
|
|
|
srs_warn("server moved connection, ignore.");
|
|
|
|
return;
|
2014-05-02 04:29:56 +00:00
|
|
|
}
|
|
|
|
|
2014-05-03 14:59:21 +00:00
|
|
|
conns.erase(it);
|
|
|
|
|
2014-05-02 04:29:56 +00:00
|
|
|
srs_info("conn removed. conns=%d", (int)conns.size());
|
|
|
|
|
2014-06-19 07:28:05 +00:00
|
|
|
// resample the resource of specified connection.
|
|
|
|
resample_kbps(conn);
|
|
|
|
|
2014-05-02 04:29:56 +00:00
|
|
|
// all connections are created by server,
|
|
|
|
// so we free it here.
|
|
|
|
srs_freep(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsServer::on_signal(int signo)
|
|
|
|
{
|
|
|
|
if (signo == SIGNAL_RELOAD) {
|
|
|
|
signal_reload = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-03 14:59:21 +00:00
|
|
|
if (signo == SIGINT || signo == SIGUSR2) {
|
2014-05-02 04:29:56 +00:00
|
|
|
#ifdef SRS_AUTO_GPERF_MC
|
|
|
|
srs_trace("gmc is on, main cycle will terminate normally.");
|
|
|
|
signal_gmc_stop = true;
|
|
|
|
#else
|
|
|
|
srs_trace("user terminate program");
|
|
|
|
exit(0);
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (signo == SIGTERM) {
|
|
|
|
srs_trace("user terminate program");
|
|
|
|
exit(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::do_cycle()
|
2014-04-07 05:13:57 +00:00
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
2014-04-07 00:41:32 +00:00
|
|
|
|
2014-04-19 13:23:34 +00:00
|
|
|
// find the max loop
|
|
|
|
int max = srs_max(0, SRS_SYS_TIME_RESOLUTION_MS_TIMES);
|
|
|
|
max = srs_max(max, SRS_SYS_RUSAGE_RESOLUTION_TIMES);
|
|
|
|
max = srs_max(max, SRS_SYS_CPU_STAT_RESOLUTION_TIMES);
|
2014-07-27 06:04:22 +00:00
|
|
|
max = srs_max(max, SRS_SYS_DISK_STAT_RESOLUTION_TIMES);
|
2014-04-19 16:15:26 +00:00
|
|
|
max = srs_max(max, SRS_SYS_MEMINFO_RESOLUTION_TIMES);
|
2014-05-08 07:45:51 +00:00
|
|
|
max = srs_max(max, SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES);
|
2014-06-18 08:13:02 +00:00
|
|
|
max = srs_max(max, SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES);
|
2014-06-19 07:28:05 +00:00
|
|
|
max = srs_max(max, SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES);
|
2014-04-19 13:23:34 +00:00
|
|
|
|
2014-03-18 03:32:58 +00:00
|
|
|
// the deamon thread, update the time cache
|
|
|
|
while (true) {
|
2014-05-19 09:39:01 +00:00
|
|
|
// the interval in config.
|
2014-06-19 07:28:05 +00:00
|
|
|
int heartbeat_max_resolution = (int)(_srs_config->get_heartbeat_interval() / 100);
|
2014-05-19 09:39:01 +00:00
|
|
|
|
|
|
|
// dynamic fetch the max.
|
|
|
|
int __max = max;
|
|
|
|
__max = srs_max(__max, heartbeat_max_resolution);
|
|
|
|
|
2014-06-18 08:13:02 +00:00
|
|
|
for (int i = 0; i < __max; i++) {
|
2014-04-19 13:23:34 +00:00
|
|
|
st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000);
|
2014-03-18 03:32:58 +00:00
|
|
|
|
2014-03-06 10:12:19 +00:00
|
|
|
// for gperf heap checker,
|
|
|
|
// @see: research/gperftools/heap-checker/heap_checker.cc
|
|
|
|
// if user interrupt the program, exit to check mem leak.
|
2014-03-07 04:24:47 +00:00
|
|
|
// but, if gperf, use reload to ensure main return normally,
|
|
|
|
// because directly exit will cause core-dump.
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_GPERF_MC
|
2014-04-19 13:23:34 +00:00
|
|
|
if (signal_gmc_stop) {
|
2014-05-03 14:59:21 +00:00
|
|
|
srs_warn("gmc got singal to stop server.");
|
2014-05-02 04:29:56 +00:00
|
|
|
return ret;
|
2014-04-19 13:23:34 +00:00
|
|
|
}
|
2014-03-06 10:12:19 +00:00
|
|
|
#endif
|
2014-03-18 03:32:58 +00:00
|
|
|
|
2014-04-19 13:23:34 +00:00
|
|
|
if (signal_reload) {
|
|
|
|
signal_reload = false;
|
|
|
|
srs_info("get signal reload, to reload the config.");
|
|
|
|
|
|
|
|
if ((ret = _srs_config->reload()) != ERROR_SUCCESS) {
|
|
|
|
srs_error("reload config failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
srs_trace("reload config success.");
|
|
|
|
}
|
2014-03-18 03:32:58 +00:00
|
|
|
|
2014-04-19 13:23:34 +00:00
|
|
|
// update the cache time or rusage.
|
2014-04-19 16:15:26 +00:00
|
|
|
if ((i % SRS_SYS_TIME_RESOLUTION_MS_TIMES) == 0) {
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_info("update current time cache.");
|
2014-04-19 13:23:34 +00:00
|
|
|
srs_update_system_time_ms();
|
|
|
|
}
|
2014-04-19 16:15:26 +00:00
|
|
|
if ((i % SRS_SYS_RUSAGE_RESOLUTION_TIMES) == 0) {
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_info("update resource info, rss.");
|
2014-04-19 13:23:34 +00:00
|
|
|
srs_update_system_rusage();
|
|
|
|
}
|
2014-04-19 16:15:26 +00:00
|
|
|
if ((i % SRS_SYS_CPU_STAT_RESOLUTION_TIMES) == 0) {
|
2014-07-27 06:04:22 +00:00
|
|
|
srs_info("update cpu info, cpu usage.");
|
2014-04-19 13:43:13 +00:00
|
|
|
srs_update_proc_stat();
|
2014-03-18 03:32:58 +00:00
|
|
|
}
|
2014-07-27 06:04:22 +00:00
|
|
|
if ((i % SRS_SYS_DISK_STAT_RESOLUTION_TIMES) == 0) {
|
|
|
|
srs_info("update disk info, disk iops.");
|
|
|
|
srs_update_disk_stat();
|
|
|
|
}
|
2014-04-19 16:15:26 +00:00
|
|
|
if ((i % SRS_SYS_MEMINFO_RESOLUTION_TIMES) == 0) {
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_info("update memory info, usage/free.");
|
2014-04-19 16:15:26 +00:00
|
|
|
srs_update_meminfo();
|
|
|
|
}
|
2014-05-08 07:45:51 +00:00
|
|
|
if ((i % SRS_SYS_PLATFORM_INFO_RESOLUTION_TIMES) == 0) {
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_info("update platform info, uptime/load.");
|
2014-05-08 07:45:51 +00:00
|
|
|
srs_update_platform_info();
|
|
|
|
}
|
2014-06-18 08:13:02 +00:00
|
|
|
if ((i % SRS_SYS_NETWORK_DEVICE_RESOLUTION_TIMES) == 0) {
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_info("update network devices info.");
|
2014-06-18 08:13:02 +00:00
|
|
|
srs_update_network_devices();
|
|
|
|
}
|
2014-06-19 07:28:05 +00:00
|
|
|
if ((i % SRS_SYS_NETWORK_RTMP_SERVER_RESOLUTION_TIMES) == 0) {
|
|
|
|
srs_info("update network rtmp server info.");
|
|
|
|
resample_kbps(NULL);
|
2014-06-19 10:49:05 +00:00
|
|
|
srs_update_rtmp_server((int)conns.size(), kbps);
|
2014-06-19 07:28:05 +00:00
|
|
|
}
|
2014-05-19 09:39:01 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_PARSER
|
|
|
|
if (_srs_config->get_heartbeat_enabled()) {
|
|
|
|
if ((i % heartbeat_max_resolution) == 0) {
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_info("do http heartbeat, for internal server to report.");
|
2014-05-19 09:39:01 +00:00
|
|
|
http_heartbeat->heartbeat();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2014-06-19 07:28:05 +00:00
|
|
|
srs_info("server main thread loop");
|
2014-03-18 03:32:58 +00:00
|
|
|
}
|
|
|
|
}
|
2014-04-07 01:27:30 +00:00
|
|
|
|
2014-03-18 03:32:58 +00:00
|
|
|
return ret;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2014-04-12 14:16:39 +00:00
|
|
|
int SrsServer::listen_rtmp()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
// stream service port.
|
2014-07-18 02:21:34 +00:00
|
|
|
std::vector<std::string> ports = _srs_config->get_listen();
|
|
|
|
srs_assert((int)ports.size() > 0);
|
2014-04-12 14:16:39 +00:00
|
|
|
|
|
|
|
close_listeners(SrsListenerRtmpStream);
|
|
|
|
|
2014-07-18 02:21:34 +00:00
|
|
|
for (int i = 0; i < (int)ports.size(); i++) {
|
2014-04-12 14:16:39 +00:00
|
|
|
SrsListener* listener = new SrsListener(this, SrsListenerRtmpStream);
|
|
|
|
listeners.push_back(listener);
|
|
|
|
|
2014-07-18 02:21:34 +00:00
|
|
|
int port = ::atoi(ports[i].c_str());
|
2014-04-12 14:16:39 +00:00
|
|
|
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
|
|
|
|
srs_error("RTMP stream listen at port %d failed. ret=%d", port, ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::listen_http_api()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-12 14:16:39 +00:00
|
|
|
close_listeners(SrsListenerHttpApi);
|
|
|
|
if (_srs_config->get_http_api_enabled()) {
|
|
|
|
SrsListener* listener = new SrsListener(this, SrsListenerHttpApi);
|
|
|
|
listeners.push_back(listener);
|
|
|
|
|
|
|
|
int port = _srs_config->get_http_api_listen();
|
|
|
|
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
|
|
|
|
srs_error("HTTP api listen at port %d failed. ret=%d", port, ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::listen_http_stream()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-12 14:16:39 +00:00
|
|
|
close_listeners(SrsListenerHttpStream);
|
|
|
|
if (_srs_config->get_http_stream_enabled()) {
|
|
|
|
SrsListener* listener = new SrsListener(this, SrsListenerHttpStream);
|
|
|
|
listeners.push_back(listener);
|
|
|
|
|
|
|
|
int port = _srs_config->get_http_stream_listen();
|
|
|
|
if ((ret = listener->listen(port)) != ERROR_SUCCESS) {
|
|
|
|
srs_error("HTTP stream listen at port %d failed. ret=%d", port, ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsServer::close_listeners(SrsListenerType type)
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
std::vector<SrsListener*>::iterator it;
|
2014-04-12 14:16:39 +00:00
|
|
|
for (it = listeners.begin(); it != listeners.end();) {
|
2014-03-18 03:32:58 +00:00
|
|
|
SrsListener* listener = *it;
|
2014-04-12 14:16:39 +00:00
|
|
|
|
|
|
|
if (listener->type() != type) {
|
|
|
|
++it;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-03-18 03:32:58 +00:00
|
|
|
srs_freep(listener);
|
2014-04-12 14:16:39 +00:00
|
|
|
it = listeners.erase(it);
|
2014-03-18 03:32:58 +00:00
|
|
|
}
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2014-06-19 07:28:05 +00:00
|
|
|
void SrsServer::resample_kbps(SrsConnection* conn, bool do_resample)
|
|
|
|
{
|
|
|
|
// resample all when conn is NULL.
|
|
|
|
if (!conn) {
|
|
|
|
for (std::vector<SrsConnection*>::iterator it = conns.begin(); it != conns.end(); ++it) {
|
|
|
|
SrsConnection* client = *it;
|
|
|
|
srs_assert(client);
|
|
|
|
|
|
|
|
// only resample, do resample when all finished.
|
|
|
|
resample_kbps(client, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
kbps->sample();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// resample for connection.
|
|
|
|
conn->kbps_resample();
|
|
|
|
|
|
|
|
kbps->add_delta(conn);
|
|
|
|
|
2014-07-16 03:23:49 +00:00
|
|
|
// resample for server.
|
2014-06-19 07:28:05 +00:00
|
|
|
if (do_resample) {
|
|
|
|
kbps->sample();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-23 03:36:07 +00:00
|
|
|
int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
|
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
int max_connections = _srs_config->get_max_connections();
|
|
|
|
if ((int)conns.size() >= max_connections) {
|
|
|
|
int fd = st_netfd_fileno(client_stfd);
|
|
|
|
|
|
|
|
srs_error("exceed the max connections, drop client: "
|
|
|
|
"clients=%d, max=%d, fd=%d", (int)conns.size(), max_connections, fd);
|
|
|
|
|
|
|
|
srs_close_stfd(client_stfd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
SrsConnection* conn = NULL;
|
2014-03-27 04:27:47 +00:00
|
|
|
if (type == SrsListenerRtmpStream) {
|
|
|
|
conn = new SrsRtmpConn(this, client_stfd);
|
2014-03-27 04:14:04 +00:00
|
|
|
} else if (type == SrsListenerHttpApi) {
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-02 10:07:34 +00:00
|
|
|
conn = new SrsHttpApi(this, client_stfd, http_api_handler);
|
2014-04-01 08:06:32 +00:00
|
|
|
#else
|
|
|
|
srs_warn("close http client for server not support http-api");
|
|
|
|
srs_close_stfd(client_stfd);
|
|
|
|
return ret;
|
|
|
|
#endif
|
2014-03-27 04:14:04 +00:00
|
|
|
} else if (type == SrsListenerHttpStream) {
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-02 10:07:34 +00:00
|
|
|
conn = new SrsHttpConn(this, client_stfd, http_stream_handler);
|
2014-04-01 07:42:27 +00:00
|
|
|
#else
|
|
|
|
srs_warn("close http client for server not support http-server");
|
|
|
|
srs_close_stfd(client_stfd);
|
|
|
|
return ret;
|
|
|
|
#endif
|
2014-03-18 03:32:58 +00:00
|
|
|
} else {
|
2014-03-21 06:00:26 +00:00
|
|
|
// TODO: FIXME: handler others
|
2014-03-18 03:32:58 +00:00
|
|
|
}
|
|
|
|
srs_assert(conn);
|
|
|
|
|
|
|
|
// directly enqueue, the cycle thread will remove the client.
|
|
|
|
conns.push_back(conn);
|
2014-04-03 10:32:51 +00:00
|
|
|
srs_verbose("add conn to vector.");
|
2014-03-18 03:32:58 +00:00
|
|
|
|
|
|
|
// cycle will start process thread and when finished remove the client.
|
2014-06-28 03:16:45 +00:00
|
|
|
// @remark never use the conn, for it maybe destroyed.
|
2014-03-18 03:32:58 +00:00
|
|
|
if ((ret = conn->start()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
2014-06-28 02:57:58 +00:00
|
|
|
srs_verbose("conn started success.");
|
2014-04-03 10:32:51 +00:00
|
|
|
|
|
|
|
srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
|
2014-03-18 03:32:58 +00:00
|
|
|
|
|
|
|
return ret;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::on_reload_listen()
|
|
|
|
{
|
2014-03-18 03:32:58 +00:00
|
|
|
return listen();
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
2014-04-12 12:46:32 +00:00
|
|
|
|
|
|
|
int SrsServer::on_reload_pid()
|
|
|
|
{
|
|
|
|
if (pid_fd > 0) {
|
|
|
|
::close(pid_fd);
|
|
|
|
pid_fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return acquire_pid_file();
|
|
|
|
}
|
2014-04-13 05:08:10 +00:00
|
|
|
|
2014-04-13 05:27:51 +00:00
|
|
|
int SrsServer::on_reload_vhost_added(std::string vhost)
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-13 05:27:51 +00:00
|
|
|
if (!_srs_config->get_vhost_http_enabled(vhost)) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = on_reload_vhost_http_updated()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::on_reload_vhost_removed(std::string vhost)
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-13 05:27:51 +00:00
|
|
|
if ((ret = on_reload_vhost_http_updated()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::on_reload_vhost_http_updated()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-13 05:27:51 +00:00
|
|
|
srs_freep(http_stream_handler);
|
|
|
|
http_stream_handler = SrsHttpHandler::create_http_stream();
|
|
|
|
|
|
|
|
if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-04-13 05:08:10 +00:00
|
|
|
int SrsServer::on_reload_http_api_enabled()
|
|
|
|
{
|
2014-04-13 05:27:51 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-13 05:27:51 +00:00
|
|
|
ret = listen_http_api();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
2014-04-13 05:08:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::on_reload_http_api_disabled()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_API
|
2014-04-13 05:08:10 +00:00
|
|
|
close_listeners(SrsListenerHttpApi);
|
2014-04-13 05:27:51 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::on_reload_http_stream_enabled()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-13 05:27:51 +00:00
|
|
|
ret = listen_http_stream();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::on_reload_http_stream_disabled()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-13 05:27:51 +00:00
|
|
|
close_listeners(SrsListenerHttpStream);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SrsServer::on_reload_http_stream_updated()
|
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2014-04-15 06:01:57 +00:00
|
|
|
#ifdef SRS_AUTO_HTTP_SERVER
|
2014-04-13 05:27:51 +00:00
|
|
|
if ((ret = on_reload_http_stream_enabled()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = on_reload_vhost_http_updated()) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
2014-04-13 05:08:10 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2014-08-02 14:18:39 +00:00
|
|
|
|