diff options
6 files changed, 435 insertions, 77 deletions
diff --git a/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs b/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs index 07bafc8..150df45 100644 --- a/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs +++ b/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerConnector.cs | |||
@@ -26,18 +26,25 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | ||
30 | using System.Web; | ||
31 | using System.Reflection; | ||
29 | using Nini.Config; | 32 | using Nini.Config; |
30 | using OpenSim.Server.Base; | 33 | using OpenSim.Server.Base; |
31 | using OpenSim.Services.Interfaces; | 34 | using OpenSim.Services.Interfaces; |
32 | using OpenSim.Framework.Servers.HttpServer; | 35 | using OpenSim.Framework.Servers.HttpServer; |
33 | using OpenSim.Server.Handlers.Base; | 36 | using OpenSim.Server.Handlers.Base; |
37 | using log4net; | ||
34 | 38 | ||
35 | namespace OpenSim.Server.Handlers.Freeswitch | 39 | namespace OpenSim.Server.Handlers.Freeswitch |
36 | { | 40 | { |
37 | public class FreeswitchServerConnector : ServiceConnector | 41 | public class FreeswitchServerConnector : ServiceConnector |
38 | { | 42 | { |
43 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
44 | |||
39 | private IFreeswitchService m_FreeswitchService; | 45 | private IFreeswitchService m_FreeswitchService; |
40 | private string m_ConfigName = "FreeswitchService"; | 46 | private string m_ConfigName = "FreeswitchService"; |
47 | protected readonly string m_freeSwitchAPIPrefix = "/fsapi"; | ||
41 | 48 | ||
42 | public FreeswitchServerConnector(IConfigSource config, IHttpServer server, string configName) : | 49 | public FreeswitchServerConnector(IConfigSource config, IHttpServer server, string configName) : |
43 | base(config, server, configName) | 50 | base(config, server, configName) |
@@ -59,7 +66,44 @@ namespace OpenSim.Server.Handlers.Freeswitch | |||
59 | m_FreeswitchService = | 66 | m_FreeswitchService = |
60 | ServerUtils.LoadPlugin<IFreeswitchService>(freeswitchService, args); | 67 | ServerUtils.LoadPlugin<IFreeswitchService>(freeswitchService, args); |
61 | 68 | ||
62 | server.AddStreamHandler(new FreeswitchServerGetHandler(m_FreeswitchService)); | 69 | server.AddHTTPHandler(String.Format("{0}/freeswitch-config", m_freeSwitchAPIPrefix), FreeSwitchConfigHTTPHandler); |
70 | } | ||
71 | |||
72 | public Hashtable FreeSwitchConfigHTTPHandler(Hashtable request) | ||
73 | { | ||
74 | Hashtable response = new Hashtable(); | ||
75 | response["str_response_string"] = string.Empty; | ||
76 | |||
77 | Hashtable requestBody = ParseRequestBody((string) request["body"]); | ||
78 | |||
79 | string section = (string) requestBody["section"]; | ||
80 | |||
81 | if (section == "directory") | ||
82 | response = m_FreeswitchService.HandleDirectoryRequest(requestBody); | ||
83 | else if (section == "dialplan") | ||
84 | response = m_FreeswitchService.HandleDialplanRequest(requestBody); | ||
85 | else | ||
86 | m_log.WarnFormat("[FreeSwitchVoice]: section was {0}", section); | ||
87 | |||
88 | return response; | ||
89 | } | ||
90 | |||
91 | private Hashtable ParseRequestBody(string body) | ||
92 | { | ||
93 | Hashtable bodyParams = new Hashtable(); | ||
94 | // split string | ||
95 | string [] nvps = body.Split(new Char [] {'&'}); | ||
96 | |||
97 | foreach (string s in nvps) | ||
98 | { | ||
99 | if (s.Trim() != "") | ||
100 | { | ||
101 | string [] nvp = s.Split(new Char [] {'='}); | ||
102 | bodyParams.Add(HttpUtility.UrlDecode(nvp[0]), HttpUtility.UrlDecode(nvp[1])); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | return bodyParams; | ||
63 | } | 107 | } |
64 | } | 108 | } |
65 | } | 109 | } |
diff --git a/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerGetHandler.cs b/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerGetHandler.cs deleted file mode 100644 index 8b41742..0000000 --- a/OpenSim/Server/Handlers/Freeswitch/FreeswitchServerGetHandler.cs +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using Nini.Config; | ||
29 | using log4net; | ||
30 | using System; | ||
31 | using System.IO; | ||
32 | using System.Reflection; | ||
33 | using System.Net; | ||
34 | using System.Text; | ||
35 | using System.Text.RegularExpressions; | ||
36 | using System.Xml; | ||
37 | using System.Xml.Serialization; | ||
38 | using OpenSim.Server.Base; | ||
39 | using OpenSim.Services.Interfaces; | ||
40 | using OpenSim.Framework; | ||
41 | using OpenSim.Framework.Servers.HttpServer; | ||
42 | |||
43 | namespace OpenSim.Server.Handlers.Freeswitch | ||
44 | { | ||
45 | public class FreeswitchServerGetHandler : BaseStreamHandler | ||
46 | { | ||
47 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
48 | |||
49 | //private IFreeswitchService m_FreeswitchService; | ||
50 | |||
51 | public FreeswitchServerGetHandler(IFreeswitchService service) : | ||
52 | base("GET", "/api") | ||
53 | { | ||
54 | //m_FreeswitchService = service; | ||
55 | } | ||
56 | |||
57 | public override byte[] Handle(string path, Stream request, | ||
58 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
59 | { | ||
60 | byte[] result = new byte[0]; | ||
61 | |||
62 | string[] p = SplitParams(path); | ||
63 | |||
64 | if (p.Length == 0) | ||
65 | return result; | ||
66 | |||
67 | // Process web request | ||
68 | |||
69 | return result; | ||
70 | } | ||
71 | } | ||
72 | } | ||
diff --git a/OpenSim/Services/FreeswitchService/FreeswitchService.cs b/OpenSim/Services/FreeswitchService/FreeswitchService.cs index 0a38300..b62a65a 100644 --- a/OpenSim/Services/FreeswitchService/FreeswitchService.cs +++ b/OpenSim/Services/FreeswitchService/FreeswitchService.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Text; | ||
29 | using System.Reflection; | 30 | using System.Reflection; |
30 | using Nini.Config; | 31 | using Nini.Config; |
31 | using log4net; | 32 | using log4net; |
@@ -33,19 +34,355 @@ using OpenSim.Framework; | |||
33 | using OpenSim.Data; | 34 | using OpenSim.Data; |
34 | using OpenSim.Services.Interfaces; | 35 | using OpenSim.Services.Interfaces; |
35 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using System.Collections; | ||
36 | 38 | ||
37 | namespace OpenSim.Services.FreeswitchService | 39 | namespace OpenSim.Services.FreeswitchService |
38 | { | 40 | { |
39 | public class FreeswitchService : FreeswitchServiceBase, IFreeswitchService | 41 | public class FreeswitchService : FreeswitchServiceBase, IFreeswitchService |
40 | { | 42 | { |
41 | //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 43 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
42 | 44 | ||
43 | public FreeswitchService(IConfigSource config) : base(config) | 45 | public FreeswitchService(IConfigSource config) : base(config) |
44 | { | 46 | { |
45 | // Perform initilialization here | 47 | // Perform initilialization here |
46 | } | 48 | } |
47 | 49 | ||
50 | public Hashtable HandleDialplanRequest(Hashtable request) | ||
51 | { | ||
52 | m_log.DebugFormat("[FreeSwitchVoice] HandleDialplanRequest called with {0}",request.ToString()); | ||
53 | |||
54 | Hashtable response = new Hashtable(); | ||
55 | |||
56 | foreach (DictionaryEntry item in request) | ||
57 | { | ||
58 | m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}",item.Key, item.Value); | ||
59 | } | ||
60 | |||
61 | string requestcontext = (string) request["Hunt-Context"]; | ||
62 | response["content_type"] = "text/xml"; | ||
63 | response["keepalive"] = false; | ||
64 | response["int_response_code"] = 200; | ||
65 | |||
66 | if (m_freeSwitchContext != String.Empty && m_freeSwitchContext != requestcontext) | ||
67 | { | ||
68 | m_log.Debug("[FreeSwitchDirectory] returning empty as it's for another context"); | ||
69 | response["str_response_string"] = ""; | ||
70 | } | ||
71 | else | ||
72 | { | ||
73 | response["str_response_string"] = String.Format(@"<?xml version=""1.0"" encoding=""utf-8""?> | ||
74 | <document type=""freeswitch/xml""> | ||
75 | <section name=""dialplan""> | ||
76 | <context name=""{0}"">" + | ||
77 | |||
78 | /* <!-- dial via SIP uri --> | ||
79 | <extension name=""sip_uri""> | ||
80 | <condition field=""destination_number"" expression=""^sip:(.*)$""> | ||
81 | <action application=""bridge"" data=""sofia/${use_profile}/$1""/> | ||
82 | <!--<action application=""bridge"" data=""$1""/>--> | ||
83 | </condition> | ||
84 | </extension>*/ | ||
85 | |||
86 | @"<extension name=""opensim_conferences""> | ||
87 | <condition field=""destination_number"" expression=""^confctl-(.*)$""> | ||
88 | <action application=""answer""/> | ||
89 | <action application=""conference"" data=""$1-{1}@{0}""/> | ||
90 | </condition> | ||
91 | </extension> | ||
48 | 92 | ||
49 | // Implement IFreeswitchService here | 93 | <extension name=""opensim_conf""> |
94 | <condition field=""destination_number"" expression=""^conf-(.*)$""> | ||
95 | <action application=""answer""/> | ||
96 | <action application=""conference"" data=""$1-{1}@{0}""/> | ||
97 | </condition> | ||
98 | </extension> | ||
99 | |||
100 | <extension name=""avatar""> | ||
101 | <condition field=""destination_number"" expression=""^(x.*)$""> | ||
102 | <action application=""bridge"" data=""user/$1""/> | ||
103 | </condition> | ||
104 | </extension> | ||
105 | |||
106 | </context> | ||
107 | </section> | ||
108 | </document>", m_freeSwitchContext, m_freeSwitchRealm); | ||
109 | } | ||
110 | |||
111 | return response; | ||
112 | } | ||
113 | |||
114 | public Hashtable HandleDirectoryRequest(Hashtable request) | ||
115 | { | ||
116 | Hashtable response = new Hashtable(); | ||
117 | string domain = (string) request["domain"]; | ||
118 | if (domain != m_freeSwitchRealm) { | ||
119 | response["content_type"] = "text/xml"; | ||
120 | response["keepalive"] = false; | ||
121 | response["int_response_code"] = 200; | ||
122 | response["str_response_string"] = ""; | ||
123 | } else { | ||
124 | m_log.DebugFormat("[FreeSwitchDirectory] HandleDirectoryRequest called with {0}",request.ToString()); | ||
125 | |||
126 | // information in the request we might be interested in | ||
127 | |||
128 | // Request 1 sip_auth for users account | ||
129 | |||
130 | //Event-Calling-Function=sofia_reg_parse_auth | ||
131 | //Event-Calling-Line-Number=1494 | ||
132 | //action=sip_auth | ||
133 | //sip_user_agent=Vivox-SDK-2.1.3010.6151-Mac%20(Feb-11-2009/16%3A42%3A41) | ||
134 | //sip_auth_username=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==) | ||
135 | //sip_auth_realm=9.20.151.43 | ||
136 | //sip_contact_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==) | ||
137 | //sip_contact_host=192.168.0.3 // this shouldnt really be a local IP, investigate STUN servers | ||
138 | //sip_to_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D | ||
139 | //sip_to_host=9.20.151.43 | ||
140 | //sip_auth_method=REGISTER | ||
141 | //user=xhZuXKmRpECyr2AARJYyGgg%3D%3D | ||
142 | //domain=9.20.151.43 | ||
143 | //ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup | ||
144 | |||
145 | foreach (DictionaryEntry item in request) | ||
146 | { | ||
147 | m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}", item.Key, item.Value); | ||
148 | } | ||
149 | |||
150 | string eventCallingFunction = (string) request["Event-Calling-Function"]; | ||
151 | if (eventCallingFunction == null) | ||
152 | { | ||
153 | eventCallingFunction = "sofia_reg_parse_auth"; | ||
154 | } | ||
155 | |||
156 | if (eventCallingFunction.Length == 0) | ||
157 | { | ||
158 | eventCallingFunction = "sofia_reg_parse_auth"; | ||
159 | } | ||
160 | |||
161 | if (eventCallingFunction == "sofia_reg_parse_auth") | ||
162 | { | ||
163 | string sipAuthMethod = (string)request["sip_auth_method"]; | ||
164 | |||
165 | if (sipAuthMethod == "REGISTER") | ||
166 | { | ||
167 | response = HandleRegister(m_freeSwitchContext, m_freeSwitchRealm, request); | ||
168 | } | ||
169 | else if (sipAuthMethod == "INVITE") | ||
170 | { | ||
171 | response = HandleInvite(m_freeSwitchContext, m_freeSwitchRealm, request); | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod); | ||
176 | response["int_response_code"] = 404; | ||
177 | response["content_type"] = "text/xml"; | ||
178 | response["str_response_string"] = ""; | ||
179 | } | ||
180 | } | ||
181 | else if (eventCallingFunction == "switch_xml_locate_user") | ||
182 | { | ||
183 | response = HandleLocateUser(m_freeSwitchRealm, request); | ||
184 | } | ||
185 | else if (eventCallingFunction == "user_data_function") // gets called when an avatar to avatar call is made | ||
186 | { | ||
187 | response = HandleLocateUser(m_freeSwitchRealm, request); | ||
188 | } | ||
189 | else if (eventCallingFunction == "user_outgoing_channel") | ||
190 | { | ||
191 | response = HandleRegister(m_freeSwitchContext, m_freeSwitchRealm, request); | ||
192 | } | ||
193 | else if (eventCallingFunction == "config_sofia") // happens once on freeswitch startup | ||
194 | { | ||
195 | response = HandleConfigSofia(m_freeSwitchContext, m_freeSwitchRealm, request); | ||
196 | } | ||
197 | else if (eventCallingFunction == "switch_load_network_lists") | ||
198 | { | ||
199 | //response = HandleLoadNetworkLists(request); | ||
200 | response["int_response_code"] = 404; | ||
201 | response["keepalive"] = false; | ||
202 | response["content_type"] = "text/xml"; | ||
203 | response["str_response_string"] = ""; | ||
204 | } | ||
205 | else | ||
206 | { | ||
207 | m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction); | ||
208 | response["int_response_code"] = 404; | ||
209 | response["keepalive"] = false; | ||
210 | response["content_type"] = "text/xml"; | ||
211 | response["str_response_string"] = ""; | ||
212 | } | ||
213 | } | ||
214 | return response; | ||
215 | } | ||
216 | |||
217 | private Hashtable HandleRegister(string Context, string Realm, Hashtable request) | ||
218 | { | ||
219 | m_log.Info("[FreeSwitchDirectory] HandleRegister called"); | ||
220 | |||
221 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
222 | string password = "1234"; | ||
223 | string domain = (string) request["domain"]; | ||
224 | string user = (string) request["user"]; | ||
225 | |||
226 | Hashtable response = new Hashtable(); | ||
227 | response["content_type"] = "text/xml"; | ||
228 | response["keepalive"] = false; | ||
229 | response["int_response_code"] = 200; | ||
230 | |||
231 | response["str_response_string"] = String.Format( | ||
232 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
233 | "<document type=\"freeswitch/xml\">\r\n" + | ||
234 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
235 | "<domain name=\"{0}\">\r\n" + | ||
236 | "<user id=\"{1}\">\r\n" + | ||
237 | "<params>\r\n" + | ||
238 | "<param name=\"password\" value=\"{2}\" />\r\n" + | ||
239 | "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" + | ||
240 | "</params>\r\n" + | ||
241 | "<variables>\r\n" + | ||
242 | "<variable name=\"user_context\" value=\"{3}\" />\r\n" + | ||
243 | "<variable name=\"presence_id\" value=\"{1}@{0}\"/>"+ | ||
244 | "</variables>\r\n" + | ||
245 | "</user>\r\n" + | ||
246 | "</domain>\r\n" + | ||
247 | "</section>\r\n" + | ||
248 | "</document>\r\n", | ||
249 | domain , user, password, Context); | ||
250 | |||
251 | return response; | ||
252 | } | ||
253 | |||
254 | private Hashtable HandleInvite(string Context, string Realm, Hashtable request) | ||
255 | { | ||
256 | m_log.Info("[FreeSwitchDirectory] HandleInvite called"); | ||
257 | |||
258 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
259 | string password = "1234"; | ||
260 | string domain = (string) request["domain"]; | ||
261 | string user = (string) request["user"]; | ||
262 | string sipRequestUser = (string) request["sip_request_user"]; | ||
263 | |||
264 | Hashtable response = new Hashtable(); | ||
265 | response["content_type"] = "text/xml"; | ||
266 | response["keepalive"] = false; | ||
267 | response["int_response_code"] = 200; | ||
268 | response["str_response_string"] = String.Format( | ||
269 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
270 | "<document type=\"freeswitch/xml\">\r\n" + | ||
271 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
272 | "<domain name=\"{0}\">\r\n" + | ||
273 | "<user id=\"{1}\">\r\n" + | ||
274 | "<params>\r\n" + | ||
275 | "<param name=\"password\" value=\"{2}\" />\r\n" + | ||
276 | "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${1}@${{dialed_domain}}}}${{sofia_contact(${1}@${{dialed_domain}})}}\"/>\r\n" + | ||
277 | "</params>\r\n" + | ||
278 | "<variables>\r\n" + | ||
279 | "<variable name=\"user_context\" value=\"{4}\" />\r\n" + | ||
280 | "<variable name=\"presence_id\" value=\"{1}@$${{domain}}\"/>"+ | ||
281 | "</variables>\r\n" + | ||
282 | "</user>\r\n" + | ||
283 | "<user id=\"{3}\">\r\n" + | ||
284 | "<params>\r\n" + | ||
285 | "<param name=\"password\" value=\"{2}\" />\r\n" + | ||
286 | "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${3}@${{dialed_domain}}}}${{sofia_contact(${3}@${{dialed_domain}})}}\"/>\r\n" + | ||
287 | "</params>\r\n" + | ||
288 | "<variables>\r\n" + | ||
289 | "<variable name=\"user_context\" value=\"{4}\" />\r\n" + | ||
290 | "<variable name=\"presence_id\" value=\"{3}@$${{domain}}\"/>"+ | ||
291 | "</variables>\r\n" + | ||
292 | "</user>\r\n" + | ||
293 | "</domain>\r\n" + | ||
294 | "</section>\r\n" + | ||
295 | "</document>\r\n", | ||
296 | domain , user, password,sipRequestUser, Context); | ||
297 | |||
298 | return response; | ||
299 | } | ||
300 | |||
301 | private Hashtable HandleLocateUser(String Realm, Hashtable request) | ||
302 | { | ||
303 | m_log.Info("[FreeSwitchDirectory] HandleLocateUser called"); | ||
304 | |||
305 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
306 | string domain = (string) request["domain"]; | ||
307 | string user = (string) request["user"]; | ||
308 | |||
309 | Hashtable response = new Hashtable(); | ||
310 | response["content_type"] = "text/xml"; | ||
311 | response["keepalive"] = false; | ||
312 | response["int_response_code"] = 200; | ||
313 | response["str_response_string"] = String.Format( | ||
314 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
315 | "<document type=\"freeswitch/xml\">\r\n" + | ||
316 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
317 | "<domain name=\"{0}\">\r\n" + | ||
318 | "<params>\r\n" + | ||
319 | "<param name=\"dial-string\" value=\"{{sip_contact_user=${{dialed_user}}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" + | ||
320 | "</params>\r\n" + | ||
321 | "<user id=\"{1}\">\r\n" + | ||
322 | "<variables>\r\n"+ | ||
323 | "<variable name=\"default_gateway\" value=\"$${{default_provider}}\"/>\r\n"+ | ||
324 | "<variable name=\"presence_id\" value=\"{1}@$${{domain}}\"/>"+ | ||
325 | "</variables>\r\n"+ | ||
326 | "</user>\r\n" + | ||
327 | "</domain>\r\n" + | ||
328 | "</section>\r\n" + | ||
329 | "</document>\r\n", | ||
330 | domain , user); | ||
331 | |||
332 | return response; | ||
333 | } | ||
334 | |||
335 | private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request) | ||
336 | { | ||
337 | m_log.Info("[FreeSwitchDirectory] HandleConfigSofia called"); | ||
338 | |||
339 | // TODO the password we return needs to match that sent in the request, this is hard coded for now | ||
340 | string domain = (string) request["domain"]; | ||
341 | |||
342 | Hashtable response = new Hashtable(); | ||
343 | response["content_type"] = "text/xml"; | ||
344 | response["keepalive"] = false; | ||
345 | response["int_response_code"] = 200; | ||
346 | response["str_response_string"] = String.Format( | ||
347 | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + | ||
348 | "<document type=\"freeswitch/xml\">\r\n" + | ||
349 | "<section name=\"directory\" description=\"User Directory\">\r\n" + | ||
350 | "<domain name=\"{0}\">\r\n" + | ||
351 | "<params>\r\n" + | ||
352 | "<param name=\"dial-string\" value=\"{{sip_contact_user=${{dialed_user}}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" + | ||
353 | "</params>\r\n" + | ||
354 | "<groups name=\"default\">\r\n"+ | ||
355 | "<users>\r\n"+ | ||
356 | "<user id=\"$${{default_provider}}\">\r\n"+ | ||
357 | "<gateways>\r\n"+ | ||
358 | "<gateway name=\"$${{default_provider}}\">\r\n"+ | ||
359 | "<param name=\"username\" value=\"$${{default_provider_username}}\"/>\r\n"+ | ||
360 | "<param name=\"password\" value=\"$${{default_provider_password}}\"/>\r\n"+ | ||
361 | "<param name=\"from-user\" value=\"$${{default_provider_username}}\"/>\r\n"+ | ||
362 | "<param name=\"from-domain\" value=\"$${{default_provider_from_domain}}\"/>\r\n"+ | ||
363 | "<param name=\"expire-seconds\" value=\"600\"/>\r\n"+ | ||
364 | "<param name=\"register\" value=\"$${{default_provider_register}}\"/>\r\n"+ | ||
365 | "<param name=\"retry-seconds\" value=\"30\"/>\r\n"+ | ||
366 | "<param name=\"extension\" value=\"$${{default_provider_contact}}\"/>\r\n"+ | ||
367 | "<param name=\"contact-params\" value=\"domain_name=$${{domain}}\"/>\r\n"+ | ||
368 | "<param name=\"context\" value=\"{1}\"/>\r\n"+ | ||
369 | "</gateway>\r\n"+ | ||
370 | "</gateways>\r\n"+ | ||
371 | "<params>\r\n"+ | ||
372 | "<param name=\"password\" value=\"$${{default_provider_password}}\"/>\r\n"+ | ||
373 | "</params>\r\n"+ | ||
374 | "</user>\r\n"+ | ||
375 | "</users>"+ | ||
376 | "</groups>\r\n" + | ||
377 | "<variables>\r\n"+ | ||
378 | "<variable name=\"default_gateway\" value=\"$${{default_provider}}\"/>\r\n"+ | ||
379 | "</variables>\r\n"+ | ||
380 | "</domain>\r\n" + | ||
381 | "</section>\r\n" + | ||
382 | "</document>\r\n", | ||
383 | domain, Context); | ||
384 | |||
385 | return response; | ||
386 | } | ||
50 | } | 387 | } |
51 | } | 388 | } |
diff --git a/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs b/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs index 83fecef..ebbb1b0 100644 --- a/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs +++ b/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs | |||
@@ -31,11 +31,28 @@ using Nini.Config; | |||
31 | using OpenSim.Framework; | 31 | using OpenSim.Framework; |
32 | using OpenSim.Services.Interfaces; | 32 | using OpenSim.Services.Interfaces; |
33 | using OpenSim.Services.Base; | 33 | using OpenSim.Services.Base; |
34 | using log4net; | ||
34 | 35 | ||
35 | namespace OpenSim.Services.FreeswitchService | 36 | namespace OpenSim.Services.FreeswitchService |
36 | { | 37 | { |
37 | public class FreeswitchServiceBase : ServiceBase | 38 | public class FreeswitchServiceBase : ServiceBase |
38 | { | 39 | { |
40 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
41 | |||
42 | protected string m_freeSwitchRealm; | ||
43 | protected string m_freeSwitchSIPProxy; | ||
44 | protected bool m_freeSwitchAttemptUseSTUN = false; | ||
45 | protected string m_freeSwitchEchoServer; | ||
46 | protected int m_freeSwitchEchoPort = 50505; | ||
47 | protected string m_freeSwitchDefaultWellKnownIP; | ||
48 | protected int m_freeSwitchDefaultTimeout = 5000; | ||
49 | protected string m_freeSwitchContext = "default"; | ||
50 | protected string m_freeSwitchServerUser = "freeswitch"; | ||
51 | protected string m_freeSwitchServerPass = "password"; | ||
52 | protected readonly string m_freeSwitchAPIPrefix = "/fsapi"; | ||
53 | |||
54 | protected bool m_Enabled = false; | ||
55 | |||
39 | public FreeswitchServiceBase(IConfigSource config) : base(config) | 56 | public FreeswitchServiceBase(IConfigSource config) : base(config) |
40 | { | 57 | { |
41 | // | 58 | // |
@@ -44,7 +61,24 @@ namespace OpenSim.Services.FreeswitchService | |||
44 | IConfig freeswitchConfig = config.Configs["FreeswitchService"]; | 61 | IConfig freeswitchConfig = config.Configs["FreeswitchService"]; |
45 | if (freeswitchConfig != null) | 62 | if (freeswitchConfig != null) |
46 | { | 63 | { |
47 | // Read config here !! | 64 | m_freeSwitchDefaultWellKnownIP = freeswitchConfig.GetString("ServerAddress", String.Empty); |
65 | if (m_freeSwitchDefaultWellKnownIP == String.Empty) | ||
66 | { | ||
67 | m_log.Error("[FREESWITCH]: No FreeswitchServerAddress given, can't continue"); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | m_freeSwitchRealm = freeswitchConfig.GetString("Realm", m_freeSwitchDefaultWellKnownIP); | ||
72 | m_freeSwitchSIPProxy = freeswitchConfig.GetString("SIPProxy", m_freeSwitchDefaultWellKnownIP + ":5060"); | ||
73 | m_freeSwitchEchoServer = freeswitchConfig.GetString("EchoServer", m_freeSwitchDefaultWellKnownIP); | ||
74 | m_freeSwitchEchoPort = freeswitchConfig.GetInt("EchoPort", m_freeSwitchEchoPort); | ||
75 | m_freeSwitchAttemptUseSTUN = freeswitchConfig.GetBoolean("AttemptSTUN", false); // This may not work | ||
76 | m_freeSwitchDefaultTimeout = freeswitchConfig.GetInt("DefaultTimeout", m_freeSwitchDefaultTimeout); | ||
77 | m_freeSwitchContext = freeswitchConfig.GetString("Context", m_freeSwitchContext); | ||
78 | m_freeSwitchServerUser = freeswitchConfig.GetString("UserName", m_freeSwitchServerUser); | ||
79 | m_freeSwitchServerPass = freeswitchConfig.GetString("Password", m_freeSwitchServerPass); | ||
80 | |||
81 | m_Enabled = true; | ||
48 | } | 82 | } |
49 | } | 83 | } |
50 | } | 84 | } |
diff --git a/OpenSim/Services/Interfaces/IFreeswitchService.cs b/OpenSim/Services/Interfaces/IFreeswitchService.cs index d1f635b..2b3ffeb 100644 --- a/OpenSim/Services/Interfaces/IFreeswitchService.cs +++ b/OpenSim/Services/Interfaces/IFreeswitchService.cs | |||
@@ -27,11 +27,13 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using OpenSim.Framework; | 29 | using OpenSim.Framework; |
30 | using System.Collections; | ||
30 | 31 | ||
31 | namespace OpenSim.Services.Interfaces | 32 | namespace OpenSim.Services.Interfaces |
32 | { | 33 | { |
33 | public interface IFreeswitchService | 34 | public interface IFreeswitchService |
34 | { | 35 | { |
35 | // Place anything the connector eeds to access here! | 36 | Hashtable HandleDirectoryRequest(Hashtable requestBody); |
37 | Hashtable HandleDialplanRequest(Hashtable requestBody); | ||
36 | } | 38 | } |
37 | } | 39 | } |
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index bc87ac2..14998d4 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example | |||
@@ -69,6 +69,19 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 | |||
69 | ; * This is the configuration for the freeswitch server in grid mode | 69 | ; * This is the configuration for the freeswitch server in grid mode |
70 | [FreeswitchService] | 70 | [FreeswitchService] |
71 | LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" | 71 | LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" |
72 | ;; IP of your FS server | ||
73 | ; FreeswitchService = 127.0.0.1 | ||
74 | |||
75 | ;; All other options are - well - optional | ||
76 | ; Realm = 1"27.0.0.1" | ||
77 | ; SIPProxy = 1"27.0.0.1:5060" | ||
78 | ; EchoServer = "127.0.0.1" | ||
79 | ; EchoPort = 50505 | ||
80 | ; AttemptSTUN = "false" | ||
81 | ; DefaultTimeout = 5000 | ||
82 | ; Context = "default" | ||
83 | ; UserName = "freeswitch" | ||
84 | ; Password = "password" | ||
72 | 85 | ||
73 | ; * This is the new style authentication service. Currently, only MySQL | 86 | ; * This is the new style authentication service. Currently, only MySQL |
74 | ; * is implemented. "Realm" is the table that is used for user lookup. | 87 | ; * is implemented. "Realm" is the table that is used for user lookup. |