在cRtmpServer的入口处,有三个函数比较重要:
一,main()函数,这是整个cRtmpServer服务的入口函数;检查命令行参数及启动其它两个函数;
int main(int argc, char **argv)
{
SRAND();
InitNetworking();
//1. Pick up the startup parameters and hold them inside the running status
if (argc < 2) {
cout << "Invalid command line. Use --help" << endl;
return -1;
}
//命令行参数检查;
if (!Variant::DeserializeFromCmdLineArgs(argc, argv, gRs.commandLine))
{
PrintHelp();
return -1;
}
string configFile = argv[argc - 1];
if (configFile.find("--") == 0)
configFile = "";
NormalizeCommandLine(configFile);
if ((bool)gRs.commandLine["arguments"]["--help"])
{
PrintHelp();
return 0;
}
if ((bool)gRs.commandLine["arguments"]["--version"])
{
PrintVersion();
return 0;
}
do
{
//2. Reset the run flag
gRs.run = false;
//3. Initialize the running status
if (Initialize())
{ //初始化整个流媒体服务器;
Run(); //处理各种事件;
} else
{
gRs.run = false;
}
//5. Cleanup
Cleanup(); //关闭服务器的各项功能,并清空;
} while (gRs.run);
//6. We are done
return 0;
}
二,Initialize函数;
bool Initialize() {
Logger::Init();
if ((bool)gRs.commandLine["arguments"]["--use-implicit-console-appender"]) {
Variant dummy;
dummy[CONF_LOG_APPENDER_NAME] = "implicit console appender";
dummy[CONF_LOG_APPENDER_TYPE] = CONF_LOG_APPENDER_TYPE_CONSOLE;
dummy[CONF_LOG_APPENDER_COLORED] = (bool)true;
dummy[CONF_LOG_APPENDER_LEVEL] = (uint32_t) 6;
ConsoleLogLocation * pLogLocation = new ConsoleLogLocation(dummy);
pLogLocation->SetLevel(_FINEST_);
Logger::AddLogLocation(pLogLocation);
}
INFO("Reading configuration from %s", STR(gRs.commandLine["arguments"]["configFile"]));
#ifdef COMPILE_STATIC
gRs.pConfigFile = new ConfigFile(SpawnApplication, SpawnFactory);
#else
gRs.pConfigFile = new ConfigFile(NULL, NULL);
#endif
string configFilePath = gRs.commandLine["arguments"]["configFile"];
string fileName;
string extension;
splitFileName(configFilePath, fileName, extension);
if (lowerCase(extension) == "xml") {
if (!gRs.pConfigFile->LoadXmlFile(configFilePath,
(bool)gRs.commandLine["arguments"]["--daemon"])) {
FATAL("Unable to load file %s", STR(configFilePath));
return false;
}
} else if (lowerCase(extension) == "lua") {
#ifdef HAS_LUA
if (!gRs.pConfigFile->LoadLuaFile(configFilePath,
(bool)gRs.commandLine["arguments"]["--daemon"])) {
FATAL("Unable to load file %s", STR(configFilePath));
return false;
}
#else
cout << "Lua is not supported by the current build of the server" << endl;
ASSERT("Lua is not supported by the current build of the server");
return false;
#endif /* HAS_LUA */
} else {
FATAL("Invalid file format: %s", STR(configFilePath));
return false;
}
#ifndef WIN32
if (gRs.pConfigFile->IsDaemon()) {
if (!gRs.daemon) {
INFO("Daemonize...");
pid_t pid = fork();
if (pid < 0) {
FATAL("Unable to start daemonize. fork() failed");
return false;
}
if (pid > 0) {
if (gRs.commandLine["arguments"].HasKey("--pid"))
WritePidFile(pid);
return false;
}
FINEST("Create a new SID for the daemon");
pid_t sid = setsid();
if (sid < 0) {
FATAL("Unable to start daemonize. setsid() failed");
return false;
}
gRs.daemon = true;
Logger::SignalFork();
}
}
#endif /* WIN32 */
INFO("Configure logger");
if (!gRs.pConfigFile->ConfigLogAppenders()) { //配置流媒体服务器日志模块;
FATAL("Unable to configure log appenders");
return false;
}
INFO("Initialize I/O handlers manager: %s", NETWORK_REACTOR);
IOHandlerManager::Initialize(); //初始化类IOHandlerManager的成员变量;
INFO("Configure modules");
if (!gRs.pConfigFile->ConfigModules()) { //加载各个模块的动态库;
FATAL("Unable to configure modules");
return false;
}
INFO("Plug in the default protocol factory");
gRs.pProtocolFactory = new DefaultProtocolFactory(); //创建类DefaultProtocolFactory的对象;
if (!ProtocolFactoryManager::RegisterProtocolFactory(gRs.pProtocolFactory)) { //初始化协议工厂类的对象的成员变量;
FATAL("Unable to register default protocols factory");
return false;
}
INFO("Configure factories");
if (!gRs.pConfigFile->ConfigFactories()) { //将加载了动态库的模块注册到协议工厂的成员变量中去;
FATAL("Unable to configure factories");
return false;
}
INFO("Configure acceptors");
if (!gRs.pConfigFile->ConfigAcceptors()) { //区分是UDP还是TCP,对所有要处理协议对应的端口进行socket绑定;并初始化每个协议事件响应函数;
FATAL("Unable to configure acceptors");
return false;
}
INFO("Configure instances");
if (!gRs.pConfigFile->ConfigInstances()) { //创建server的实例;
FATAL("Unable to configure instances");
return false;
}
INFO("Start I/O handlers manager: %s", NETWORK_REACTOR);
IOHandlerManager::Start(); //;
INFO("Configure applications");
if (!gRs.pConfigFile->ConfigApplications()) { //初始化各种应用;
FATAL("Unable to configure applications");
return false;
}
INFO("Install the quit signal");
installQuitSignal(QuitSignalHandler); //依据不同的平台, 如linux ,windows, android等安装不同的信号处理机;
return true;
}
三,Run函数;
void Run()
{
if (!ApplyUIDGID())
{
FATAL("Unable to apply user id");
exit(-1);
}
//打印显示流媒体服务器所有开启的应用,以及对应的端口;
INFO("\n%s", STR(gRs.pConfigFile->GetServicesInfo()));
//显示流媒体服务器的进程ID;
INFO("GO! GO! GO! (%u)", (uint32_t) getpid());
//调用网络等待事件发生;当对应端口的事件发生时,就调用事件处理函数进行处理;
while (IOHandlerManager::Pulse())
{
IOHandlerManager::DeleteDeadHandlers();
ProtocolManager::CleanupDeadProtocols();
}
}