33 using System.Collections;
34 using System.Collections.Generic;
35 using System.Reflection;
36 using System.Threading;
42 using OpenSim.Framework;
44 using OpenSim.Framework.Capabilities;
45 using OpenSim.Framework.Servers;
46 using OpenSim.Framework.Servers.HttpServer;
47 using OpenSim.Region.Framework.Interfaces;
48 using OpenSim.Region.Framework.Scenes;
53 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"VivoxVoiceModule")]
58 public const int CHAN_DIST_NONE = 0;
59 public const int CHAN_DIST_INVERSE = 1;
60 public const int CHAN_DIST_LINEAR = 2;
61 public const int CHAN_DIST_EXPONENT = 3;
62 public const int CHAN_DIST_DEFAULT = CHAN_DIST_LINEAR;
65 public static readonly
string CHAN_TYPE_POSITIONAL =
"positional";
66 public static readonly
string CHAN_TYPE_CHANNEL =
"channel";
67 public static readonly
string CHAN_TYPE_DEFAULT = CHAN_TYPE_POSITIONAL;
70 public static readonly
string CHAN_MODE_OPEN =
"open";
71 public static readonly
string CHAN_MODE_LECTURE =
"lecture";
72 public static readonly
string CHAN_MODE_PRESENTATION =
"presentation";
73 public static readonly
string CHAN_MODE_AUDITORIUM =
"auditorium";
74 public static readonly
string CHAN_MODE_DEFAULT = CHAN_MODE_OPEN;
77 public const double CHAN_ROLL_OFF_DEFAULT = 2.0;
78 public const double CHAN_ROLL_OFF_MIN = 1.0;
79 public const double CHAN_ROLL_OFF_MAX = 4.0;
80 public const int CHAN_MAX_RANGE_DEFAULT = 80;
81 public const int CHAN_MAX_RANGE_MIN = 0;
82 public const int CHAN_MAX_RANGE_MAX = 160;
83 public const int CHAN_CLAMPING_DISTANCE_DEFAULT = 10;
84 public const int CHAN_CLAMPING_DISTANCE_MIN = 0;
85 public const int CHAN_CLAMPING_DISTANCE_MAX = 160;
88 private static readonly ILog m_log =
89 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
93 private static readonly
string m_parcelVoiceInfoRequestPath =
"0107/";
94 private static readonly
string m_provisionVoiceAccountRequestPath =
"0108/";
98 private static bool m_pluginEnabled =
false;
99 private static bool m_adminConnected =
false;
101 private static string m_vivoxServer;
102 private static string m_vivoxSipUri;
103 private static string m_vivoxVoiceAccountApi;
104 private static string m_vivoxAdminUser;
105 private static string m_vivoxAdminPassword;
106 private static string m_authToken = String.Empty;
108 private static int m_vivoxChannelDistanceModel;
109 private static double m_vivoxChannelRollOff;
110 private static int m_vivoxChannelMaximumRange;
111 private static string m_vivoxChannelMode;
112 private static string m_vivoxChannelType;
113 private static int m_vivoxChannelClampingDistance;
115 private static Dictionary<string,string> m_parents =
new Dictionary<string,string>();
116 private static bool m_dumpXml;
118 private IConfig m_config;
120 private object m_Lock;
124 MainConsole.Instance.Commands.AddCommand(
"vivox",
false,
"vivox debug",
"vivox debug <on>|<off>",
"Set vivox debugging", HandleDebug);
126 m_config = config.Configs[
"VivoxVoice"];
128 if (null == m_config)
131 if (!m_config.GetBoolean(
"enabled",
false))
134 m_Lock =
new object();
139 m_vivoxServer = m_config.GetString(
"vivox_server", String.Empty);
140 m_vivoxSipUri = m_config.GetString(
"vivox_sip_uri", String.Empty);
141 m_vivoxAdminUser = m_config.GetString(
"vivox_admin_user", String.Empty);
142 m_vivoxAdminPassword = m_config.GetString(
"vivox_admin_password", String.Empty);
144 m_vivoxChannelDistanceModel = m_config.GetInt(
"vivox_channel_distance_model", CHAN_DIST_DEFAULT);
145 m_vivoxChannelRollOff = m_config.GetDouble(
"vivox_channel_roll_off", CHAN_ROLL_OFF_DEFAULT);
146 m_vivoxChannelMaximumRange = m_config.GetInt(
"vivox_channel_max_range", CHAN_MAX_RANGE_DEFAULT);
147 m_vivoxChannelMode = m_config.GetString(
"vivox_channel_mode", CHAN_MODE_DEFAULT).ToLower();
148 m_vivoxChannelType = m_config.GetString(
"vivox_channel_type", CHAN_TYPE_DEFAULT).ToLower();
149 m_vivoxChannelClampingDistance = m_config.GetInt(
"vivox_channel_clamping_distance",
150 CHAN_CLAMPING_DISTANCE_DEFAULT);
151 m_dumpXml = m_config.GetBoolean(
"dump_xml",
false);
154 if (m_vivoxChannelRollOff < CHAN_ROLL_OFF_MIN || m_vivoxChannelRollOff > CHAN_ROLL_OFF_MAX)
156 m_log.WarnFormat(
"[VivoxVoice] Invalid value for roll off ({0}), reset to {1}.",
157 m_vivoxChannelRollOff, CHAN_ROLL_OFF_DEFAULT);
158 m_vivoxChannelRollOff = CHAN_ROLL_OFF_DEFAULT;
161 if (m_vivoxChannelMaximumRange < CHAN_MAX_RANGE_MIN || m_vivoxChannelMaximumRange > CHAN_MAX_RANGE_MAX)
163 m_log.WarnFormat(
"[VivoxVoice] Invalid value for maximum range ({0}), reset to {1}.",
164 m_vivoxChannelMaximumRange, CHAN_MAX_RANGE_DEFAULT);
165 m_vivoxChannelMaximumRange = CHAN_MAX_RANGE_DEFAULT;
168 if (m_vivoxChannelClampingDistance < CHAN_CLAMPING_DISTANCE_MIN ||
169 m_vivoxChannelClampingDistance > CHAN_CLAMPING_DISTANCE_MAX)
171 m_log.WarnFormat(
"[VivoxVoice] Invalid value for clamping distance ({0}), reset to {1}.",
172 m_vivoxChannelClampingDistance, CHAN_CLAMPING_DISTANCE_DEFAULT);
173 m_vivoxChannelClampingDistance = CHAN_CLAMPING_DISTANCE_DEFAULT;
176 switch (m_vivoxChannelMode)
179 case "lecture" :
break;
180 case "presentation" :
break;
181 case "auditorium" :
break;
183 m_log.WarnFormat(
"[VivoxVoice] Invalid value for channel mode ({0}), reset to {1}.",
184 m_vivoxChannelMode, CHAN_MODE_DEFAULT);
185 m_vivoxChannelMode = CHAN_MODE_DEFAULT;
189 switch (m_vivoxChannelType)
191 case "positional" :
break;
192 case "channel" :
break;
194 m_log.WarnFormat(
"[VivoxVoice] Invalid value for channel type ({0}), reset to {1}.",
195 m_vivoxChannelType, CHAN_TYPE_DEFAULT);
196 m_vivoxChannelType = CHAN_TYPE_DEFAULT;
200 m_vivoxVoiceAccountApi = String.Format(
"http://{0}/api2", m_vivoxServer);
203 if (
String.IsNullOrEmpty(m_vivoxServer) ||
204 String.IsNullOrEmpty(m_vivoxSipUri) ||
205 String.IsNullOrEmpty(m_vivoxAdminUser) ||
206 String.IsNullOrEmpty(m_vivoxAdminPassword))
208 m_log.Error(
"[VivoxVoice] plugin mis-configured");
209 m_log.Info(
"[VivoxVoice] plugin disabled: incomplete configuration");
213 m_log.InfoFormat(
"[VivoxVoice] using vivox server {0}", m_vivoxServer);
219 m_pluginEnabled =
true;
221 m_log.Info(
"[VivoxVoice] plugin enabled");
225 m_log.ErrorFormat(
"[VivoxVoice] plugin initialization failed: {0}", e.Message);
226 m_log.DebugFormat(
"[VivoxVoice] plugin initialization failed: {0}", e.ToString());
239 string sceneUUID = scene.RegionInfo.RegionID.ToString();
240 string sceneName = scene.RegionInfo.RegionName;
248 if (VivoxTryGetDirectory(sceneUUID +
"D", out channelId))
250 m_log.DebugFormat(
"[VivoxVoice]: region {0}: uuid {1}: located directory id {2}",
251 sceneName, sceneUUID, channelId);
253 XmlElement children = VivoxListChildren(channelId);
256 if (XmlFind(children,
"response.level0.channel-search.count", out count))
258 int cnum = Convert.ToInt32(count);
259 for (
int i = 0; i < cnum; i++)
262 if (XmlFind(children,
"response.level0.channel-search.channels.channels.level4.id", i, out
id))
264 if (!IsOK(VivoxDeleteChannel(channelId,
id)))
265 m_log.WarnFormat(
"[VivoxVoice] Channel delete failed {0}:{1}:{2}", i, channelId,
id);
272 if (!VivoxTryCreateDirectory(sceneUUID +
"D", sceneName, out channelId))
274 m_log.WarnFormat(
"[VivoxVoice] Create failed <{0}:{1}:{2}>",
275 "*", sceneUUID, sceneName);
276 channelId = String.Empty;
286 if (m_parents.ContainsKey(sceneUUID))
289 m_parents.Add(sceneUUID, channelId);
293 m_parents.Add(sceneUUID, channelId);
300 scene.EventManager.OnRegisterCaps += delegate(
UUID agentID,
Caps caps)
302 OnRegisterCaps(scene, agentID, caps);
320 string sceneUUID = scene.RegionInfo.RegionID.ToString();
321 string sceneName = scene.RegionInfo.RegionName;
328 if (VivoxTryGetDirectory(sceneUUID +
"D", out channelId))
330 m_log.DebugFormat(
"[VivoxVoice]: region {0}: uuid {1}: located directory id {2}",
331 sceneName, sceneUUID, channelId);
333 XmlElement children = VivoxListChildren(channelId);
336 if (XmlFind(children,
"response.level0.channel-search.count", out count))
338 int cnum = Convert.ToInt32(count);
339 for (
int i = 0; i < cnum; i++)
342 if (XmlFind(children,
"response.level0.channel-search.channels.channels.level4.id", i, out
id))
344 if (!IsOK(VivoxDeleteChannel(channelId,
id)))
345 m_log.WarnFormat(
"[VivoxVoice] Channel delete failed {0}:{1}:{2}", i, channelId,
id);
351 if (!IsOK(VivoxDeleteChannel(null, channelId)))
352 m_log.WarnFormat(
"[VivoxVoice] Parent channel delete failed {0}:{1}:{2}", sceneName, sceneUUID, channelId);
358 if (m_parents.ContainsKey(sceneUUID))
360 m_parents.Remove(sceneUUID);
378 public Type ReplaceableInterface
385 get {
return "VivoxVoiceModule"; }
388 public bool IsSharedModule
413 m_log.DebugFormat(
"[VivoxVoice] OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
415 string capsBase =
"/CAPS/" + caps.CapsObjectPath;
417 caps.RegisterHandler(
418 "ProvisionVoiceAccountRequest",
421 capsBase + m_provisionVoiceAccountRequestPath,
422 (request, path, param, httpRequest, httpResponse)
423 => ProvisionVoiceAccountRequest(scene, request, path, param, agentID, caps),
424 "ProvisionVoiceAccountRequest",
425 agentID.ToString()));
427 caps.RegisterHandler(
428 "ParcelVoiceInfoRequest",
431 capsBase + m_parcelVoiceInfoRequestPath,
432 (request, path, param, httpRequest, httpResponse)
433 => ParcelVoiceInfoRequest(scene, request, path, param, agentID, caps),
434 "ParcelVoiceInfoRequest",
435 agentID.ToString()));
459 UUID agentID,
Caps caps)
464 string avatarName = null;
467 throw new Exception(
"[VivoxVoice][PROVISIONVOICE]: Invalid scene");
469 avatar = scene.GetScenePresence(agentID);
470 while (avatar == null)
473 avatar = scene.GetScenePresence(agentID);
476 avatarName = avatar.Name;
478 m_log.DebugFormat(
"[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID);
484 string agentname =
"x" + Convert.ToBase64String(agentID.GetBytes());
485 string password =
new UUID(Guid.NewGuid()).ToString().Replace(
'-',
'Z').Substring(0,16);
486 string code = String.Empty;
488 agentname = agentname.Replace(
'+',
'-').Replace(
'/',
'_');
492 resp = VivoxGetAccountInfo(agentname);
494 if (XmlFind(resp,
"response.level0.status", out code))
498 if (XmlFind(resp,
"response.level0.body.code", out code))
504 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Get account information failed : expired credentials",
506 m_adminConnected =
false;
507 retry = DoAdminLogin();
511 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Get account information failed : missing credentials",
516 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Get account information failed : not authorized",
521 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Get account information failed : parameter missing",
526 resp = VivoxCreateAccount(agentname,password);
528 if (XmlFind(resp,
"response.level0.status", out code))
533 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Create account information failed : expired credentials",
535 m_adminConnected =
false;
536 retry = DoAdminLogin();
540 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Create account information failed : missing credentials",
545 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Create account information failed : not authorized",
550 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Create account information failed : parameter missing",
555 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Create account information failed : create failed",
563 m_log.ErrorFormat(
"[VivoxVoice]: avatar \"{0}\": Get account information failed : retrieve failed");
575 m_log.DebugFormat(
"[VivoxVoice][PROVISIONVOICE]: Get Account Request failed for \"{0}\"", avatarName);
576 throw new Exception(
"Unable to execute request");
580 VivoxPassword(agentname, password);
585 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
593 m_log.ErrorFormat(
"[VivoxVoice][PROVISIONVOICE]: : {0}, retry later", e.Message);
594 m_log.DebugFormat(
"[VivoxVoice][PROVISIONVOICE]: : {0} failed", e.ToString());
595 return "<llsd><undef /></llsd>";
610 UUID agentID,
Caps caps)
613 string avatarName = avatar.Name;
626 throw new Exception(
String.Format(
"region \"{0}\": avatar \"{1}\": land data not yet available",
633 LandData land = scene.GetLandData(avatar.AbsolutePosition);
636 return "<llsd><undef /></llsd>";
649 channel_uri = String.Empty;
652 if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0)
656 channel_uri = String.Empty;
660 channel_uri = RegionGetOrCreateChannel(scene, land);
664 Hashtable creds =
new Hashtable();
665 creds[
"channel_uri"] = channel_uri;
668 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
676 m_log.ErrorFormat(
"[VivoxVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2}, retry later",
677 scene.RegionInfo.RegionName, avatarName, e.Message);
678 m_log.DebugFormat(
"[VivoxVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2} failed",
679 scene.RegionInfo.RegionName, avatarName, e.ToString());
681 return "<llsd><undef /></llsd>";
696 UUID agentID,
Caps caps)
703 return "<llsd>true</llsd>";
706 private string RegionGetOrCreateChannel(
Scene scene,
LandData land)
708 string channelUri = null;
709 string channelId = null;
716 parentId = m_parents[scene.
RegionInfo.RegionID.ToString()];
720 if (land.LocalID != 1 && (land.Flags & (uint)ParcelFlags.UseEstateVoiceChan) == 0)
722 landName = String.Format(
"{0}:{1}", scene.RegionInfo.RegionName, land.Name);
723 landUUID = land.GlobalID.ToString();
724 m_log.DebugFormat(
"[VivoxVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}",
725 landName, land.LocalID, landUUID);
729 landName = String.Format(
"{0}:{1}", scene.RegionInfo.RegionName, scene.RegionInfo.RegionName);
730 landUUID = scene.RegionInfo.RegionID.ToString();
731 m_log.DebugFormat(
"[VivoxVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}",
732 landName, land.LocalID, landUUID);
738 if (VivoxTryGetChannel(parentId, landUUID, out channelId, out channelUri))
739 m_log.DebugFormat(
"[VivoxVoice] Found existing channel at " + channelUri);
740 else if (VivoxTryCreateChannel(parentId, landUUID, landName, out channelUri))
741 m_log.DebugFormat(
"[VivoxVoice] Created new channel at " + channelUri);
743 throw new Exception(
"vivox channel uri not available");
745 m_log.DebugFormat(
"[VivoxVoice]: Region:Parcel \"{0}\": parent channel id {1}: retrieved parcel channel_uri {2} ",
746 landName, parentId, channelUri);
752 private static readonly
string m_vivoxLoginPath =
"http://{0}/api2/viv_signin.php?userid={1}&pwd={2}";
758 private XmlElement VivoxLogin(
string name,
string password)
760 string requrl = String.Format(m_vivoxLoginPath, m_vivoxServer, name, password);
761 return VivoxCall(requrl,
false);
764 private static readonly
string m_vivoxLogoutPath =
"http://{0}/api2/viv_signout.php?auth_token={1}";
769 private XmlElement VivoxLogout()
771 string requrl = String.Format(m_vivoxLogoutPath, m_vivoxServer, m_authToken);
772 return VivoxCall(requrl,
false);
776 private static readonly
string m_vivoxGetAccountPath =
"http://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}";
782 private XmlElement VivoxGetAccountInfo(
string user)
784 string requrl = String.Format(m_vivoxGetAccountPath, m_vivoxServer, m_authToken, user);
785 return VivoxCall(requrl,
true);
789 private static readonly
string m_vivoxNewAccountPath =
"http://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}";
797 private XmlElement VivoxCreateAccount(
string user,
string password)
799 string requrl = String.Format(m_vivoxNewAccountPath, m_vivoxServer, user, password, m_authToken);
800 return VivoxCall(requrl,
true);
804 private static readonly
string m_vivoxPasswordPath =
"http://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}";
809 private XmlElement VivoxPassword(
string user,
string password)
811 string requrl = String.Format(m_vivoxPasswordPath, m_vivoxServer, user, password, m_authToken);
812 return VivoxCall(requrl,
true);
816 private static readonly
string m_vivoxChannelPath =
"http://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}";
830 private bool VivoxTryCreateChannel(
string parent,
string channelId,
string description, out
string channelUri)
832 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer,
"create", channelId, m_authToken);
834 if (!
string.IsNullOrEmpty(parent))
836 requrl = String.Format(
"{0}&chan_parent={1}", requrl, parent);
838 if (!
string.IsNullOrEmpty(description))
840 requrl = String.Format(
"{0}&chan_desc={1}", requrl, description);
843 requrl = String.Format(
"{0}&chan_type={1}", requrl, m_vivoxChannelType);
844 requrl = String.Format(
"{0}&chan_mode={1}", requrl, m_vivoxChannelMode);
845 requrl = String.Format(
"{0}&chan_roll_off={1}", requrl, m_vivoxChannelRollOff);
846 requrl = String.Format(
"{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel);
847 requrl = String.Format(
"{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange);
848 requrl = String.Format(
"{0}&chan_clamping_distance={1}", requrl, m_vivoxChannelClampingDistance);
850 XmlElement resp = VivoxCall(requrl,
true);
851 if (XmlFind(resp,
"response.level0.body.chan_uri", out channelUri))
854 channelUri = String.Empty;
865 private bool VivoxTryCreateDirectory(
string dirId,
string description, out
string channelId)
867 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer,
"create", dirId, m_authToken);
874 if (!
string.IsNullOrEmpty(description))
876 requrl = String.Format(
"{0}&chan_desc={1}", requrl, description);
878 requrl = String.Format(
"{0}&chan_type={1}", requrl,
"dir");
880 XmlElement resp = VivoxCall(requrl,
true);
881 if (IsOK(resp) && XmlFind(resp,
"response.level0.body.chan_id", out channelId))
884 channelId = String.Empty;
888 private static readonly
string m_vivoxChannelSearchPath =
"http://{0}/api2/viv_chan_search.php?cond_channame={1}&auth_token={2}";
901 private bool VivoxTryGetChannel(
string channelParent,
string channelName,
902 out
string channelId, out
string channelUri)
906 string requrl = String.Format(m_vivoxChannelSearchPath, m_vivoxServer, channelName, m_authToken);
907 XmlElement resp = VivoxCall(requrl,
true);
909 if (XmlFind(resp,
"response.level0.channel-search.count", out count))
911 int channels = Convert.ToInt32(count);
917 for (
int j=0;j<100;j++)
920 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.id", j, out tmpId))
927 for (
int i = 0; i < channels; i++)
936 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.type", i, out type) ||
937 (type !=
"channel" && type !=
"positional_M"))
939 m_log.Debug(
"[VivoxVoice] Skipping Channel " + i +
" as it's not a channel.");
944 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.name", i, out name) ||
947 m_log.Debug(
"[VivoxVoice] Skipping Channel " + i +
" as it has no name.");
952 if (channelParent != null && !XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.parent", i, out parent))
954 m_log.Debug(
"[VivoxVoice] Skipping Channel " + i +
"/" + name +
" as it's parent doesnt match");
959 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.id", i, out
id))
961 m_log.Debug(
"[VivoxVoice] Skipping Channel " + i +
"/" + name +
" as it has no channel ID");
966 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.uri", i, out uri))
968 m_log.Debug(
"[VivoxVoice] Skipping Channel " + i +
"/" + name +
" as it has no channel URI");
980 m_log.Debug(
"[VivoxVoice] No count element?");
983 channelId = String.Empty;
984 channelUri = String.Empty;
992 private bool VivoxTryGetDirectory(
string directoryName, out
string directoryId)
996 string requrl = String.Format(m_vivoxChannelSearchPath, m_vivoxServer, directoryName, m_authToken);
997 XmlElement resp = VivoxCall(requrl,
true);
999 if (XmlFind(resp,
"response.level0.channel-search.count", out count))
1001 int channels = Convert.ToInt32(count);
1002 for (
int i = 0; i < channels; i++)
1009 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.type", i, out type) ||
1014 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.name", i, out name) ||
1015 name != directoryName)
1019 if (!XmlFind(resp,
"response.level0.channel-search.channels.channels.level4.id", i, out
id))
1027 directoryId = String.Empty;
1043 private static readonly
string m_vivoxChannelDel =
"http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}";
1057 private XmlElement VivoxDeleteChannel(
string parent,
string channelid)
1059 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer,
"delete", channelid, m_authToken);
1060 if (!
string.IsNullOrEmpty(parent))
1062 requrl = String.Format(
"{0}&chan_parent={1}", requrl, parent);
1064 return VivoxCall(requrl,
true);
1067 private static readonly
string m_vivoxChannelSearch =
"http://{0}/api2/viv_chan_search.php?&cond_chanparent={1}&auth_token={2}";
1073 private XmlElement VivoxListChildren(
string channelid)
1075 string requrl = String.Format(m_vivoxChannelSearch, m_vivoxServer, channelid, m_authToken);
1076 return VivoxCall(requrl,
true);
1117 private XmlElement VivoxCall(
string requrl,
bool admin)
1120 XmlDocument doc = null;
1124 if (admin && !m_adminConnected && !DoAdminLogin())
1127 doc =
new XmlDocument();
1140 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl);
1143 req.ContentLength = 0;
1146 using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse())
1147 using (Stream s = rsp.GetResponseStream())
1148 using (XmlTextReader rdr =
new XmlTextReader(s))
1153 m_log.ErrorFormat(
"[VivoxVoice] Error in admin call : {0}", e.Message);
1159 if (m_dumpXml) XmlScanl(doc.DocumentElement,0);
1161 return doc.DocumentElement;
1167 private bool IsOK(XmlElement resp)
1170 XmlFind(resp,
"response.level0.status", out status);
1171 return (status ==
"OK");
1179 private bool DoAdminLogin()
1181 m_log.Debug(
"[VivoxVoice] Establishing admin connection");
1185 if (!m_adminConnected)
1187 string status =
"Unknown";
1188 XmlElement resp = null;
1190 resp = VivoxLogin(m_vivoxAdminUser, m_vivoxAdminPassword);
1192 if (XmlFind(resp,
"response.level0.body.status", out status))
1196 m_log.Info(
"[VivoxVoice] Admin connection established");
1197 if (XmlFind(resp,
"response.level0.body.auth_token", out m_authToken))
1199 if (m_dumpXml) m_log.DebugFormat(
"[VivoxVoice] Auth Token <{0}>",
1201 m_adminConnected =
true;
1206 m_log.WarnFormat(
"[VivoxVoice] Admin connection failed, status = {0}",
1213 return m_adminConnected;
1223 private void XmlScanl(XmlElement e,
int index)
1225 if (e.HasChildNodes)
1227 m_log.DebugFormat(
"<{0}>".PadLeft(index+5), e.Name);
1228 XmlNodeList children = e.ChildNodes;
1229 foreach (XmlNode node
in children)
1230 switch (node.NodeType)
1232 case XmlNodeType.Element :
1233 XmlScanl((XmlElement)node, index+1);
1235 case XmlNodeType.Text :
1236 m_log.DebugFormat(
"\"{0}\"".PadLeft(index+5), node.Value);
1241 m_log.DebugFormat(
"</{0}>".PadLeft(index+6), e.Name);
1245 m_log.DebugFormat(
"<{0}/>".PadLeft(index+6), e.Name);
1249 private static readonly
char[] C_POINT = {
'.'};
1262 private bool XmlFind(XmlElement root,
string tag,
int nth, out
string result)
1264 if (root == null || tag == null || tag ==
String.Empty)
1266 result = String.Empty;
1269 return XmlSearch(root,tag.Split(C_POINT),0, ref nth, out result);
1272 private bool XmlFind(XmlElement root,
string tag, out
string result)
1275 if (root == null || tag == null || tag ==
String.Empty)
1277 result = String.Empty;
1280 return XmlSearch(root,tag.Split(C_POINT),0, ref nth, out result);
1294 private bool XmlSearch(XmlElement e,
string[] tags,
int index, ref
int nth, out
string result)
1296 if (index == tags.Length || e.Name != tags[index])
1298 result = String.Empty;
1302 if (tags.Length-index == 1)
1306 result = e.InnerText;
1312 result = String.Empty;
1317 if (e.HasChildNodes)
1319 XmlNodeList children = e.ChildNodes;
1320 foreach (XmlNode node
in children)
1322 switch (node.NodeType)
1324 case XmlNodeType.Element :
1325 if (XmlSearch((XmlElement)node, tags, index+1, ref nth, out result))
1335 result = String.Empty;
1339 private void HandleDebug(
string module,
string[] cmd)
1343 MainConsole.Instance.Output(
"Error: missing on/off flag");
1349 else if (cmd[2] ==
"off")
1352 MainConsole.Instance.Output(
"Error: only on and off are supported");
EstateSettings EstateSettings
string ParcelVoiceInfoRequest(Scene scene, string request, string path, string param, UUID agentID, Caps caps)
Callback for a client request for ParcelVoiceInfo
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
string ChatSessionRequest(Scene scene, string request, string path, string param, UUID agentID, Caps caps)
Callback for a client request for a private chat channel
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
OpenSim.Framework.Capabilities.Caps Caps
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Details of a Parcel of land
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
Interactive OpenSim region server
void OnRegisterCaps(Scene scene, UUID agentID, Caps caps)
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
virtual RegionInfo RegionInfo
string ProvisionVoiceAccountRequest(Scene scene, string request, string path, string param, UUID agentID, Caps caps)
Callback for a client request for Voice Account Details
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...