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...