/// <summary> /// The application worker thread. /// </summary> private void AppThread() { // All NeonSwitch applications (except for the core service) need to wait for // the core to be initialized before the application can be started. We're // going to spin here until the core indicates that it's ready. var warningTimer = new PolledTimer(TimeSpan.FromSeconds(60)); if (!SwitchApp.IsCore) { while (true) { if (String.Compare(Switch.GetGlobal(SwitchGlobal.NeonSwitchReady), "true", true) == 0) { break; } if (warningTimer.HasFired) { warningTimer.Disable(); SysLog.LogWarning("NeonSwitch application [{0}] has waited [{1}] for the core NeonSwitch service to start.", SwitchApp.Name, warningTimer.Interval); } Thread.Sleep(TimeSpan.FromSeconds(1)); } } // Continue performing wwitch initialization. We needed to wait until after // the NeonSwitch core service started before calling this. Switch.Initialize(); // Call the application entry point so it can initalize itself. try { InMain = true; Main(); InMain = false; mainCalled = true; } catch (Exception e) { SysLog.LogException(e, "The NeonSwitch application's Main() method threw an exception."); throw; } finally { InMain = false; } // NeonSwitch handles the event dispatching. Switch.EventLoop(); }
/// <summary> /// Continues the application load process by scanning the loaded assemblies /// for the class definition that derives from <see cref="SwitchApp" /> /// and then constructing an instance. /// </summary> /// <param name="appName">Name to be used for the module.</param> /// <param name="appPath">Path to the application folder.</param> /// <param name="loaderDllName">Name of the NeonSwitch application loader DLL file.</param> /// <param name="appClassName">The optional application class name or <c>null</c>.</param> /// <exception cref="TypeLoadException">Thrown if a single derived <see cref="SwitchApp" /> type could not be found or instantiated.</exception> /// <exception cref="NotSupportedException">Thrown if the application is not running on a NeonSwitch enabled build of FreeSWITCH.</exception> /// <remarks> /// <note> /// If <paramref name="appClassName" /> is passed as <c>null</c> then only one type /// deriving from <see cref="SwitchApp" /> may be defined across all of the loaded /// assemblies. A <see cref="TypeLoadException" /> will be thrown if more than one /// definitions are located. /// </note> /// </remarks> public void Load(string loaderDllName, string appName, string appPath, string appClassName) { var thisAssembly = Assembly.GetExecutingAssembly(); var appRefs = new List <AppRef>(); var NeonSwitchValue = Switch.GetGlobal("NeonSwitch"); bool isNeonSwitch; // Verify that we're actually running on a NeonSwitch enabled version of FreeSwitch // by looking for the [NeonSwitch] global variable. if (NeonSwitchValue == null || !bool.TryParse(NeonSwitchValue, out isNeonSwitch) || !isNeonSwitch) { throw new NotSupportedException("NeonSwitch applications require a NeonSwitch enabled FreeSWITCH build. Load terminated."); } // Continue the loading process. foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in assembly.GetTypes()) { if (type.IsDerivedFrom(typeof(SwitchApp))) { appRefs.Add(new AppRef(assembly, type.FullName)); } } } // Attempt to construct a specific type if one was specified. if (!string.IsNullOrWhiteSpace(appClassName)) { foreach (var appRef in appRefs) { if (appClassName == appRef.TypeName) { app = (SwitchApp)appRef.Assembly.CreateInstance(appClassName); app.Load(appName, loaderDllName, appPath); return; } } throw new TypeLoadException(string.Format("Could not locate application class [{0}] in the loaded assemblies.", appClassName)); } // Remove any references to test applications in this assembly. var delList = new List <AppRef>(); foreach (var appRef in appRefs) { if (appRef.Assembly == thisAssembly) { delList.Add(appRef); } } foreach (var appRef in delList) { appRefs.Remove(appRef); } // Make sure we found a single entry class in the assemblies. if (appRefs.Count == 0) { throw new TypeLoadException("Could not find a NeonSwitch application class that derives from [LillTek.Telephony.NeonSwitch.SwitchApp]."); } else if (appRefs.Count > 1) { var sb = new StringBuilder(); sb.AppendLine("Multiple NeonSwitch application classes defined:"); sb.AppendLine(); foreach (var appRef in appRefs) { sb.AppendFormatLine("[{0}] in [{1}]", appRef.TypeName, appRef.Assembly.Location); } throw new TypeLoadException(sb.ToString()); } // Instantiate the application's entry point class. Note that the base // SwitchApp class will take over the remainder of the NeonSwitch // platform initialization. app = (SwitchApp)appRefs[0].Assembly.CreateInstance(appRefs[0].TypeName); app.Load(appName, loaderDllName, appPath); }