1 /*
2 * Copyright (C) 2011 Raphael Coeffic
3 *
4 * This file is part of SEMS, a free SIP media server.
5 *
6 * SEMS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. This program is released under
10 * the GPL with the additional exemption that compiling, linking,
11 * and/or using OpenSSL is allowed.
12 *
13 * For a license to use the SEMS software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
16 * info@iptel.org
17 *
18 * SEMS is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28 #include "Rtmp.h"
29 #include "RtmpSession.h"
30 #include "RtmpConnection.h"
31 #include "AmConfigReader.h"
32 #include "AmEventDispatcher.h"
33 #include "ampi/SIPRegistrarClientAPI.h"
34
RtmpConfig()35 RtmpConfig::RtmpConfig()
36 : ListenAddress("0.0.0.0"),
37 ListenPort(DEFAULT_RTMP_PORT),
38 FromName("RTMP Gateway"),
39 FromDomain(),
40 AllowExternalRegister(false),
41 ImplicitRegistrar()
42 {
43 }
44
FACTORY_SESSION_EXPORT()45 extern "C" void* FACTORY_SESSION_EXPORT()
46 {
47 return RtmpFactory_impl::instance();
48 }
49
RtmpFactory()50 RtmpFactory::RtmpFactory()
51 : AmSessionFactory(MOD_NAME),
52 di_reg_client(NULL)
53 {
54 }
55
~RtmpFactory()56 RtmpFactory::~RtmpFactory()
57 {
58 }
59
onLoad()60 int RtmpFactory::onLoad()
61 {
62 AmConfigReader cfg_file;
63
64 if(cfg_file.loadPluginConf(MOD_NAME) < 0){
65 INFO("No config file for " MOD_NAME " plug-in: using defaults.\n");
66 }
67 else {
68
69 if(cfg_file.hasParameter("listen_address")){
70 cfg.ListenAddress = fixIface2IP(cfg_file.getParameter("listen_address"),false);
71 }
72
73 if(cfg_file.hasParameter("listen_port")){
74 string listen_port_str = cfg_file.getParameter("listen_port");
75 if(sscanf(listen_port_str.c_str(),"%u",
76 &(cfg.ListenPort)) != 1){
77 ERROR("listen_port: invalid RTMP port specified (%s), using default\n",
78 listen_port_str.c_str());
79 cfg.ListenPort = DEFAULT_RTMP_PORT;
80 }
81 }
82
83 if(cfg_file.hasParameter("from_name")){
84 cfg.FromName = cfg_file.getParameter("from_name");
85 }
86
87 if(cfg_file.hasParameter("from_domain")){
88 cfg.FromDomain = cfg_file.getParameter("from_domain");
89 }
90
91 if(cfg_file.hasParameter("allow_external_register")){
92 cfg.AllowExternalRegister =
93 cfg_file.getParameter("allow_external_register") == string("yes");
94 }
95
96 if(cfg_file.hasParameter("implicit_registrar")){
97 cfg.ImplicitRegistrar = cfg_file.getParameter("implicit_registrar");
98 }
99 }
100
101 RtmpServer* rtmp_server = RtmpServer::instance();
102
103 if(rtmp_server->listen(cfg.ListenAddress.c_str(),cfg.ListenPort) < 0) {
104 ERROR("could not start RTMP server at <%s:%u>\n",
105 cfg.ListenAddress.c_str(),cfg.ListenPort);
106 rtmp_server->dispose();
107 return -1;
108 }
109 rtmp_server->start();
110
111 AmDynInvokeFactory* di_reg_client_f = AmPlugIn::instance()->
112 getFactory4Di("registrar_client");
113 if(di_reg_client_f)
114 di_reg_client = di_reg_client_f->getInstance();
115
116 if(di_reg_client) {
117 // start the event processing
118 AmEventDispatcher::instance()->addEventQueue(FACTORY_Q_NAME,this);
119 start();
120 }
121 else {
122 INFO("'registrar_client' not found: registration disabled.\n");
123 }
124
125 return 0;
126 }
127
onInvite(const AmSipRequest & req,const string & app_name,const map<string,string> & app_params)128 AmSession* RtmpFactory::onInvite(const AmSipRequest& req,
129 const string& app_name,
130 const map<string,string>& app_params)
131 {
132 RtmpSession* sess=NULL;
133
134 m_connections.lock();
135 map<string,RtmpConnection*>::iterator it = connections.find(req.user);
136 if(it != connections.end()){
137 sess = new RtmpSession(it->second);
138 it->second->setSessionPtr(sess);
139 m_connections.unlock();
140 }
141 else {
142 m_connections.unlock();
143 AmSipDialog::reply_error(req,404,"Not found");
144 }
145
146 return sess;
147 }
148
addConnection(const string & ident,RtmpConnection * conn)149 int RtmpFactory::addConnection(const string& ident, RtmpConnection* conn)
150 {
151 int res = 0;
152
153 m_connections.lock();
154 if(ident.empty() || (connections.find(ident)!=connections.end())){
155 res = -1;
156 }
157 else {
158 connections[ident] = conn;
159 }
160 m_connections.unlock();
161
162 return res;
163 }
164
removeConnection(const string & ident)165 void RtmpFactory::removeConnection(const string& ident)
166 {
167 m_connections.lock();
168 connections.erase(ident);
169 m_connections.unlock();
170 }
171