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