示例#1
0
        public void FlightRecorder_PassThru_SysLogProvider()
        {
            // Verify that the ISysLogProvider implementation works.

            Queue <FlightEvent> queue       = new Queue <FlightEvent>();
            ISysLogProvider     orgProvider = SysLog.LogProvider;

            try
            {
                FlightEvent flightEvent;

                using (var recorder = new FlightRecorder(evt => queue.Enqueue(evt)))
                {
                    SysLog.LogProvider = recorder;

                    SysLog.LogError("Test Error");
                    SysLog.LogWarning("Test Warning");
                    SysLog.LogInformation("Test Information");
                    SysLog.Flush();

                    Assert.AreEqual(3, queue.Count);

                    flightEvent = queue.Dequeue();
                    Assert.AreEqual("SysLog:Error", flightEvent.Operation);
                    Assert.IsTrue(flightEvent.Details.Contains("Test Error"));
                    Assert.IsTrue(flightEvent.IsError);

                    flightEvent = queue.Dequeue();
                    Assert.AreEqual("SysLog:Warning", flightEvent.Operation);
                    Assert.IsTrue(flightEvent.Details.Contains("Test Warning"));
                    Assert.IsFalse(flightEvent.IsError);

                    flightEvent = queue.Dequeue();
                    Assert.AreEqual("SysLog:Information", flightEvent.Operation);
                    Assert.IsTrue(flightEvent.Details.Contains("Test Information"));
                    Assert.IsFalse(flightEvent.IsError);

                    // Verify that system events actually serialize exception
                    // and stack trace related information.

                    try
                    {
                        throw new AssertException();
                    }
                    catch (Exception e)
                    {
                        SysLog.LogException(e);
                        SysLog.Flush();

                        flightEvent = queue.Dequeue();
                        Assert.AreEqual("SysLog:Exception", flightEvent.Operation);
                        Assert.IsTrue(flightEvent.Details.Contains("AssertException"));
                    }
                }
            }
            finally
            {
                SysLog.LogProvider = orgProvider;
            }
        }
示例#2
0
        private static int              refCount = 0;   // Start() reference count

        /// <summary>
        /// Used by services and applications to start the <see cref="ChannelHost" />,
        /// using the result of <see cref="Assembly" />.<see cref="Assembly.GetEntryAssembly" /> 
        /// to determine the location of the application configuration file.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Calls to this method may be nested.  A reference count is maintained and only
        /// the first call will actually perform any initialization.
        /// </para>
        /// <note>
        /// All successful calls to <see cref="Start()" /> must eventually be matched with
        /// a call to <see cref="Stop" /> global state including the underlying LillTek
        /// <see cref="MsgRouter" /> will be released properly.
        /// </note>
        /// </remarks>
        public static void Start()
        {
            using (TimedLock.Lock(SyncRoot))
            {
                if (refCount == 0)
                {
                    if (!Helper.IsInitialized)
                    {
                        Assembly entryAssembly = Assembly.GetEntryAssembly();

                        if (entryAssembly == null)
                        {
                            SysLog.LogWarning("Unable obtain the entry assembly via Assembly.GetEntryAssembly().  " +
                                              "The application's LillTek configuration settings will not be available.  " +
                                              "You may call LillTek.ServiceModel.ChannelHost.Start(Assembly) with a valid " +
                                              "assembly during application initialization to correct this.");

                            entryAssembly = Assembly.GetExecutingAssembly();    // Use the current assembly instead
                        }

                        Helper.InitializeApp(entryAssembly);
                    }

                    RegisterMsgTypes();
                    MsgRouter.StartGlobal();
                }

                refCount++;
            }
        }
示例#3
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="packet">The switch packet.</param>
        internal SwitchEventReceivedArgs(SwitchPacket packet)
        {
            ArgCollection properties;
            ArgCollection variables;
            string        eventName;

            this.TimeUtc = packet.Headers.Get("Event-Date-GMT", DateTime.MinValue);

            if (packet.Headers.TryGetValue("Event-Name", out eventName))
            {
                this.EventName = eventName;
                this.EventCode = SwitchHelper.ParseEventCode(eventName);
            }
            else
            {
                // I don't think this should ever happen.

                SysLog.LogWarning("SwitchConnection received an event without an [Event-Name] property.");

                this.EventName = string.Empty;
                this.EventCode = default(SwitchEventCode);
            }

            SwitchHelper.ProcessEventProperties(packet.Headers, out properties, out variables);

            this.Properties  = properties;
            this.Variables   = variables;
            this.ContentType = packet.ContentType;
            this.Content     = packet.Content;
            this.ContentText = packet.ContentText;
        }
示例#4
0
        /// <summary>
        /// Reflects an assembly looking for public classes that implement <see cref="ISwitchSubcommand" />
        /// and registers any found with the switch command dispatch subsystem.
        /// </summary>
        /// <param name="assembly">The source assembly.</param>
        /// <remarks>
        /// <note>
        /// The application may call this method <b>only</b> when executing within its
        /// <see cref="SwitchApp.Main" /> method.
        /// </note>
        /// <para>
        /// This method registers the name of the class without the namespace and
        /// also stripping the "Command" suffix if present as the name of the
        /// subcommand.
        /// </para>
        /// <note>
        /// Registered subcommands are case insensitive.
        /// </note>
        /// </remarks>
        public static void RegisterAssemblySubcommands(Assembly assembly)
        {
            if (!SwitchApp.InMain)
            {
                throw new InvalidOperationException("[RegisterAssemblySubcommands] may be called only from within the SwitchApp.Main() method.");
            }

            foreach (var type in assembly.GetTypes())
            {
                if (!type.IsPublic || !typeof(ISwitchSubcommand).IsAssignableFrom(type))
                {
                    continue;
                }

                string subcommand = type.Name.ToLowerInvariant();
                Type   existing;

                if (subcommand.EndsWith("command"))
                {
                    subcommand = subcommand.Substring(0, subcommand.Length - "command".Length);
                }

                if (subcommandHandlers.TryGetValue(subcommand, out existing))
                {
                    SysLog.LogWarning("NeonSwitch subcommand conflict. Subcommand class [{0}] conflicts with [{1}].  [{1}] will be used.", type.FullName, existing.FullName);
                    continue;
                }

                subcommandHandlers.Add(subcommand, type);
            }
        }
示例#5
0
        /// <summary>
        /// Verifies that a <see cref="ChannelState" /> code passed is one of the known states.
        /// </summary>
        /// <param name="channelState">The channel state code being tested.</param>
        /// <returns>
        /// The same state code if it is known to the current implementation,
        /// <see cref="ChannelState.None" /> otherwise.
        /// </returns>
        /// <remarks>
        /// A warning will be logged if the state code is not known.
        /// </remarks>
        public static ChannelState ValidateChannelState(ChannelState channelState)
        {
            switch (channelState)
            {
            case ChannelState.New:
            case ChannelState.Initialized:
            case ChannelState.Routing:
            case ChannelState.SoftExecute:
            case ChannelState.Execute:
            case ChannelState.ExchangingMedia:
            case ChannelState.Park:
            case ChannelState.ConsumingMedia:
            case ChannelState.Hibernate:
            case ChannelState.Reset:
            case ChannelState.Hangup:
            case ChannelState.Reporting:
            case ChannelState.Destroy:
            case ChannelState.None:

                return(channelState);

            default:

                SysLog.LogWarning("Unexpected channel state [{0}].", channelState);
                return(ChannelState.None);
            }
        }
示例#6
0
        /// <summary>
        /// Removes the performance counters from the system if present.
        /// </summary>
        /// <remarks>
        /// <note>
        /// The calling process must have sufficient rights to perform this operation.  If
        /// this is not the case, then this method will fail silently.
        /// </note>
        /// </remarks>
        public void Uninstall()
        {
            foreach (var counter in counters.Values)
            {
                counter.Close();
            }

            if (!PerfCounter.ProcessLocalOnly && PerformanceCounterCategory.Exists(categoryName))
            {
                try
                {
                    PerformanceCounterCategory.Delete(categoryName);
                }
                catch (SecurityException)
                {
                    SysLog.LogWarning("Process does not have sufficient rights to uninstall performance counters.");
                    return;
                }
                catch (UnauthorizedAccessException)
                {
                    SysLog.LogWarning("Process does not have sufficient rights to uninstall performance counters.");
                    return;
                }
                catch (Exception e)
                {
                    SysLog.LogException(e, "Process was not able to uninstall performance counters.");
                    return;
                }
            }

            installed = false;
        }
示例#7
0
        /// <summary>
        /// Opens the topology instance in server mode.
        /// </summary>
        /// <param name="router">The message router to be used by the cluster.</param>
        /// <param name="dynamicScope">The dynamic scope name.</param>
        /// <param name="target">The target object whose dynamic message handlers are to be registered (or <c>null</c>).</param>
        /// <param name="clusterEP">The cluster's logical endpoint.</param>
        /// <param name="args">Topology implementation specific parameters (ignored for this implementation).</param>
        /// <remarks>
        /// <para>
        /// This method also registers the dynamic message handlers that case-insensitvely
        /// match the dynamicScope parameter passed that are found within the
        /// target object passed with the router's message dispatcher, after performing
        /// any necessary munging of their message endpoints.  This is done by
        /// matching the dynamicScope parameter passed against the <see cref="MsgHandler.DynamicScope" />
        /// property in the <see cref="MsgHandler" /> attribute tagging the message handler.
        /// </para>
        /// <para>
        /// The matching message handler endpoints will be set to clusterEP.
        /// </para>
        /// </remarks>
        public virtual void OpenServer(MsgRouter router, string dynamicScope, MsgEP clusterEP, object target, ArgCollection args)
        {
            if (!clusterEP.IsLogical)
            {
                throw new ArgumentException(TopologyHelper.ClusterEPNotLogicalMsg);
            }

            if (!router.EnableP2P)
            {
                SysLog.LogWarning(NoP2PMsg);
            }

            this.router      = router;
            this.instanceID  = Helper.NewGuid();
            this.clusterEP   = clusterEP;
            this.broadcastEP = new MsgEP(clusterEP, "*");
            this.instanceEP  = new MsgEP(clusterEP, Helper.NewGuid().ToString());
            this.isClient    = false;

            if (target != null)
            {
                router.Dispatcher.AddTarget(target, dynamicScope, this, null);
            }

            OnLogicalChange();      // Forces the initial load of the instance EPs
        }
示例#8
0
        /// <summary>
        /// Opens the topology instance in client mode.
        /// </summary>
        /// <param name="router">The message router to be used by the cluster.</param>
        /// <param name="clusterEP">The cluster's logical endpoint.</param>
        /// <param name="args">Topology implementation specific parameters (ignored for this implementation).</param>
        /// <remarks>
        /// </remarks>
        public virtual void OpenClient(MsgRouter router, MsgEP clusterEP, ArgCollection args)
        {
            if (!clusterEP.IsLogical)
            {
                throw new ArgumentException(TopologyHelper.ClusterEPNotLogicalMsg);
            }

            if (!router.EnableP2P)
            {
                SysLog.LogWarning(NoP2PMsg);
            }

            this.router      = router;
            this.instanceID  = Helper.NewGuid();
            this.clusterEP   = clusterEP;
            this.broadcastEP = new MsgEP(clusterEP, "*");
            this.instanceEP  = null;
            this.isClient    = true;

            ArgCollection argsCopy;

            argsCopy = args.Clone();
            argsCopy["topology-type"] = TopologyHelper.SerializeType(this.GetType());
            serialized = argsCopy.ToString();

            OnLogicalChange();      // Forces the initial load of the instance EPs
        }
示例#9
0
        public void OnMsg(AuthControlMsg msg)
        {
            try
            {
                using (TimedLock.Lock(this))
                {
                    if (!isOpen)
                    {
                        return;
                    }

                    switch (msg.Command)
                    {
                    case "auth-key-update":

                        publicKey = null;           // This will force the retrieval of a new key
                        break;                      // on the next auth request

                    case "cache-clear":

                        if (cache != null)
                        {
                            cache.Clear();
                        }

                        break;

                    case "cache-remove-realm":

                        if (cache != null)
                        {
                            CacheRemove(msg.Get("realm", string.Empty) + "\t");
                        }

                        break;

                    case "lock-account":
                    case "cache-remove-account":

                        if (cache != null)
                        {
                            CacheRemove(msg.Get("realm", string.Empty) + "\t" + msg.Get("account", string.Empty) + "\t");
                        }

                        break;

                    default:

                        SysLog.LogWarning("Unexpected authentication control command [{0}].", msg.Command);
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                SysLog.LogException(e);
            }
        }
示例#10
0
        /// <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();
        }
示例#11
0
        /// <summary>
        /// Installs the set of performance counters to the system if necessary.
        /// </summary>
        /// <remarks>
        /// <note>
        /// The calling process must have sufficient rights to perform this operation.  If
        /// this is not the case, then this method will fail silently.
        /// </note>
        /// </remarks>
        public void Install()
        {
            if (!enabled || installed)
            {
                return;
            }

            // Install the counters as necessary.

            if (!PerfCounter.ProcessLocalOnly && !PerformanceCounterCategory.Exists(categoryName))
            {
                var creationData = new CounterCreationDataCollection();

                foreach (var counter in counters.Values.OrderBy(c => c.Name.ToLowerInvariant()))
                {
                    creationData.Add(new CounterCreationData(counter.Name, counter.Help, counter.Type));
                }

                try
                {
                    PerformanceCounterCategory.Create(categoryName, categoryHelp,
                                                      multiInstance ? PerformanceCounterCategoryType.MultiInstance : PerformanceCounterCategoryType.SingleInstance,
                                                      creationData);
                }
                catch (InvalidOperationException e)
                {
                    // We can see this error sometimes when multiple processes attempt
                    // to create the performance counters at the same time and one
                    // attempt failes because the counters already exist.  We're going
                    // log and ignore this.

                    SysLog.LogException(e, "This can happen if more than one process or thread is trying to register performance counters at the same time.  This is probably not a problem.");
                }
                catch (SecurityException)
                {
                    SysLog.LogWarning("Process does not have sufficient rights to install performance counters.  Falling back to simulated local performance counters.");

                    installFailed = true;
                }
                catch (UnauthorizedAccessException)
                {
                    SysLog.LogWarning("Process does not have sufficient rights to install performance counters.  Falling back to simulated local performance counters.");

                    installFailed = true;
                }
                catch (Exception e)
                {
                    SysLog.LogException(e, "Process was unable to install performance counters.  Falling back to simulated local performance counters.");

                    installFailed = true;
                }
            }

            // Mark the set as installed.

            installed = true;
        }
示例#12
0
        /// <summary>
        /// Loads the requested environment variable, logging a warning if the variable is not set.
        /// </summary>
        /// <param name="name">The variable name.</param>
        /// <returns>The variable's value or the empty string.</returns>
        private static string GetVar(string name)
        {
            var value = System.Environment.GetEnvironmentVariable(name);

            if (string.IsNullOrWhiteSpace(value))
            {
                SysLog.LogWarning("AzureHelper.Initialize: Environment variable [{0}] is not set.", name);
            }

            return(value);
        }
示例#13
0
        /// <summary>
        /// Returns the low-level FreeSWITCH string corresponding to a <see cref="SwitchEventCode" />.
        /// </summary>
        /// <param name="switchEvent">The switch event code.</param>
        /// <returns>The corresponding string or <b>SWITCH_EVENT_CUSTOM</b> if the code is unknown.</returns>
        public static string GetEventCodeString(SwitchEventCode switchEvent)
        {
            string eventString;

            if (!switchEventToString.TryGetValue(switchEvent, out eventString))
            {
                SysLog.LogWarning("Unexpected switch event code [{0}].", switchEvent);
                eventString = switchEventToString[SwitchEventCode.Custom];
            }

            return(eventString);
        }
示例#14
0
        /// <summary>
        /// Returns the low-level FreeSWITCH string corresponding to a <see cref="SwitchLogLevel" />.
        /// </summary>
        /// <param name="logLevel">The log level.</param>
        /// <returns>The corresponding string or <b>NONE</b> if the code is unknown.</returns>
        public static string GetSwitchLogLevelString(SwitchLogLevel logLevel)
        {
            string logLevelString;

            if (!switchLogLevelToString.TryGetValue(logLevel, out logLevelString))
            {
                SysLog.LogWarning("Unexpected channel log level [{0}].", logLevel);
                logLevelString = switchLogLevelToString[SwitchLogLevel.None];
            }

            return(logLevelString);
        }
示例#15
0
        /// <summary>
        /// Parses the low-level FreeSWITCH log level string into a <see cref="SwitchLogLevel" /> value.
        /// </summary>
        /// <param name="value">The FreeSWITCH channel state string.</param>
        /// <returns>The parsed <see cref="SwitchLogLevel" /> or <see cref="SwitchLogLevel.None" />
        /// if the value could not be parsed.
        /// </returns>
        public static SwitchLogLevel ParseSwitchLogLevel(string value)
        {
            SwitchLogLevel logLevel;

            if (!stringToSwitchLogLevel.TryGetValue(value, out logLevel))
            {
                SysLog.LogWarning("Unexpected FreeSWITCH log level [{0}].", value);
                logLevel = SwitchLogLevel.None;
            }

            return(logLevel);
        }
示例#16
0
        /// <summary>
        /// Returns the low-level FreeSWITCH string corresponding to a <see cref="ChannelState" />.
        /// </summary>
        /// <param name="channelState">The channel state code.</param>
        /// <returns>The corresponding string or <b>NONE</b> if the code is unknown.</returns>
        public static string GetChannelStateString(ChannelState channelState)
        {
            string stateString;

            if (!channelStateToString.TryGetValue(channelState, out stateString))
            {
                SysLog.LogWarning("Unexpected channel state code [{0}].", channelState);
                stateString = channelStateToString[ChannelState.None];
            }

            return(stateString);
        }
示例#17
0
        /// <summary>
        /// Returns the low-level FreeSWITCH string corresponding to a <see cref="CallDirection" />.
        /// </summary>
        /// <param name="direction">The direction code.</param>
        /// <returns>The corresponding string or <see cref="Empty" /> if the code is unknown.</returns>
        public static string GetSwitchHangupReasonString(CallDirection direction)
        {
            string directionString;

            if (!callDirectionToString.TryGetValue(direction, out directionString))
            {
                SysLog.LogWarning("Unexpected call direction code [{0}].", direction);
                directionString = string.Empty;
            }

            return(directionString);
        }
示例#18
0
        /// <summary>
        /// Parses the low-level FreeSWITCH call direction string to a <see cref="CallDirection" /> value.
        /// </summary>
        /// <param name="directionString">The FreeSWITCH direction string.</param>
        /// <returns>
        /// The parsed <see cref="CallDirection" /> or <see cref="CallDirection.Unknown" />
        /// if the value could not be parsed.
        /// </returns>
        public static CallDirection ParseCallDirection(string directionString)
        {
            CallDirection direction;

            if (!stringToCallDirection.TryGetValue(directionString, out direction))
            {
                SysLog.LogWarning("Unexpected FreeSWITCH call direction [{0}].", directionString);
                direction = CallDirection.Unknown;
            }

            return(direction);
        }
示例#19
0
        /// <summary>
        /// Returns the low-level FreeSWITCH string corresponding to a <see cref="SwitchHangupReason" />.
        /// </summary>
        /// <param name="reason">The hangup reason code.</param>
        /// <returns>The corresponding string or <b>NONE</b> if the code is unknown.</returns>
        public static string GetSwitchHangupReasonString(SwitchHangupReason reason)
        {
            string reasonString;

            if (!switchHangupReasonToString.TryGetValue(reason, out reasonString))
            {
                SysLog.LogWarning("Unexpected switch hangup reason code [{0}].", reason);
                reasonString = switchHangupReasonToString[SwitchHangupReason.None];
            }

            return(reasonString);
        }
示例#20
0
        /// <summary>
        /// Parses the low-level FreeSWITCH hangup reason <see cref="SwitchHangupReason" /> value.
        /// </summary>
        /// <param name="reasonString">The FreeSWITCH hangup reason.</param>
        /// <returns>
        /// The parsed <see cref="SwitchHangupReason" /> or <see cref="SwitchHangupReason.None" />
        /// if the value could not be parsed.
        /// </returns>
        public static SwitchHangupReason ParseHangupReason(string reasonString)
        {
            SwitchHangupReason reason;

            if (!stringToSwitchHangupReason.TryGetValue(reasonString, out reason))
            {
                SysLog.LogWarning("Unexpected FreeSWITCH hangup reason [{0}].", reasonString);
                reason = SwitchHangupReason.None;
            }

            return(reason);
        }
示例#21
0
        /// <summary>
        /// Parses the low-level FreeSWITCH event name passed into a <see cref="SwitchEventCode" /> value.
        /// </summary>
        /// <param name="value">The FreeSWITCH event name.</param>
        /// <returns>
        /// The parsed <see cref="SwitchEventCode" /> or <see cref="SwitchEventCode.Custom" />
        /// if the value could not be parsed.
        /// </returns>
        public static SwitchEventCode ParseEventCode(string value)
        {
            SwitchEventCode switchEvent;

            if (!stringToSwitchEvent.TryGetValue(value, out switchEvent))
            {
                SysLog.LogWarning("Unexpected FreeSWITCH event [{0}].", value);
                switchEvent = SwitchEventCode.Custom;
            }

            return(switchEvent);
        }
示例#22
0
        /// <summary>
        /// Parses the low-level FreeSWITCH channel state string into a <see cref="ChannelState" /> value.
        /// </summary>
        /// <param name="value">The FreeSWITCH channel state string.</param>
        /// <returns>The parsed <see cref="ChannelState" /> or <see cref="ChannelState.None" />
        /// if the value could not be parsed.
        /// </returns>
        public static ChannelState ParseChannelState(string value)
        {
            ChannelState channelState;

            if (!stringToChannelState.TryGetValue(value, out channelState))
            {
                SysLog.LogWarning("Unexpected FreeSWITCH channel state [{0}].", value);
                channelState = ChannelState.None;
            }

            return(channelState);
        }
示例#23
0
        /// <summary>
        /// Performs a best efforts recovery of orphaned transactions.
        /// </summary>
        private void Recover()
        {
            var        orphans = log.GetOrphanTransactions();
            var        context = new UpdateContext(this, true, false, false, Guid.Empty);
            IOperation operation;

            SysLog.LogWarning("Recovering [{0}] transactions for [{1}].", orphans.Count, resource.Name);

            Trace(0, "Begin Recovery", null);
            resource.BeginRecovery(context);

            for (int i = 0; i < orphans.Count; i++)
            {
                IOperationLog opLog = log.OpenOperationLog(orphans[i]);

                context.TransactionID = opLog.TransactionID;
                if (opLog.Mode == OperationLogMode.Redo)
                {
                    if (resource.BeginRedo(context))
                    {
                        foreach (ILogPosition pos in opLog.GetPositions(false))
                        {
                            operation = opLog.Read(resource, pos);
                            Trace(0, "Redo: " + operation.Description, "ID=" + context.TransactionID.ToString());
                            resource.Redo(context, operation);
                        }
                    }

                    resource.EndRedo(context);
                }
                else
                {
                    if (resource.BeginUndo(context))
                    {
                        foreach (ILogPosition pos in opLog.GetPositions(true))
                        {
                            operation = opLog.Read(resource, pos);
                            Trace(0, "Undo: " + operation.Description, "ID=" + context.TransactionID.ToString());
                            resource.Undo(context, opLog.Read(resource, pos));
                        }
                    }

                    resource.EndUndo(context);
                }

                log.CloseOperationLog(opLog);
            }

            context.TransactionID = Guid.Empty;
            resource.EndRecovery(context);
            Trace(0, "End Recovery", null);
        }
示例#24
0
        /// <summary>
        /// Starts the gateway and the associated <see cref="SipCore" /> if it has not
        /// already been started.
        /// </summary>
        /// <remarks>
        /// <note><see cref="SipMssGateway" /> instances cannot be restarted.</note>
        /// </remarks>
        public void Start()
        {
            using (TimedLock.Lock(core))
            {
                if (isRunning)
                {
                    throw new InvalidOperationException("MSS Gateway is already running.");
                }

                if (isUsed)
                {
                    throw new InvalidOperationException("Cannot restart a MSS Gateway.");
                }

                isRunning = true;
                isUsed    = true;
            }

            Helper.GetNetworkInfo(out localAddress, out localSubnet);

            b2bua = new SipB2BUserAgent <object>(core);
            b2bua.InviteRequestReceived  += new SipB2BUAEventDelegate <object>(OnInviteRequestReceived);
            b2bua.InviteResponseReceived += new SipB2BUAEventDelegate <object>(OnInviteResponseReceived);
            b2bua.SessionConfirmed       += new SipB2BUAEventDelegate <object>(OnSessionConfirmed);
            b2bua.SessionClosing         += new SipB2BUAEventDelegate <object>(OnSessionClosing);
            b2bua.ClientRequestReceived  += new SipB2BUAEventDelegate <object>(OnClientRequestReceived);
            b2bua.ServerRequestReceived  += new SipB2BUAEventDelegate <object>(OnServerRequestReceived);
            b2bua.ClientResponseReceived += new SipB2BUAEventDelegate <object>(OnClientResponseReceived);
            b2bua.ServerResponseReceived += new SipB2BUAEventDelegate <object>(OnServerResponseReceived);

            if (!core.IsRunning)
            {
                core.Start();
            }

            b2bua.Start();

            if (settings.Register.Length > 1)
            {
                SysLog.LogWarning("MSS Gateway currently supports only one registration URI.  Only the first URI will be registered.");
            }

            if (settings.Register.Length > 0)
            {
                core.StartAutoRegistration((string)settings.TrunkUri, (string)settings.Register[0]);
            }
        }
示例#25
0
        /// <summary>
        /// Attempts to return the server side transaction ID from the message.  This is
        /// the <b>branch</b> parameter from the top-most <b>Via</b> header.
        /// </summary>
        /// <param name="transactionID">Returns as the transaction ID on success.</param>
        /// <returns><b><c>true</c> if the transaction ID was returned.</b></returns>
        /// <remarks>
        /// <para>
        /// Transaction IDs are formed from the "branch" parameter of the
        /// topmost "Via" header, plus the "sent-by" parameter on the "Via" (if present)
        /// plus the method as upper case (except for the ACK method which maps to INVITE)
        /// </para>
        /// <para>
        /// This method also implements the alternative RFC 2543 compatible procedure
        /// if the Via branch parameter doesn't start with the magic cookie (not
        /// implemented yet).
        /// </para>
        /// <para>
        /// See RFC 3261 17.2.3 on page 138 for more information.
        /// </para>
        /// </remarks>
        public bool TryGetTransactionID(out string transactionID)
        {
            SipHeader   via;
            SipViaValue viaValue;
            string      branch;
            string      sentBy;

            transactionID = null;

            via = base[SipHeader.Via];
            if (via == null)
            {
                return(false);
            }

            viaValue = new SipViaValue(via.Text);
            branch   = viaValue.Branch;

            if (branch == null || !branch.StartsWith("z9hG4bK"))
            {
                SysLog.LogWarning("SIP Request received with non-compliant Via branch parameter.");
                return(false);
            }

            transactionID = branch + ":";

            sentBy = viaValue.SentBy;
            if (sentBy != null)
            {
                transactionID += sentBy;
            }

            transactionID += ":";

            if (method == SipMethod.Ack)
            {
                transactionID += "INVITE";
            }
            else
            {
                transactionID += methodText.ToUpper();
            }

            return(true);
        }
示例#26
0
        /// <summary>
        /// Starts the transaction manager.
        /// </summary>
        /// <param name="resource">The <see cref="ITransactedResource" /> to be managed.</param>
        /// <param name="log">The unopened <see cref="ITransactionLog" /> implementation to be used.</param>
        /// <param name="recoverCorrupt">Pass as <c>true</c> if recovery of corrupt transaction logs should be attempted.</param>
        public void Start(ITransactedResource resource, ITransactionLog log, bool recoverCorrupt)
        {
            using (TimedLock.Lock(this))
            {
                if (running)
                {
                    throw new TransactionException("Transaction manager has already started for [{0}].", resource.Name);
                }

                switch (log.Open(this))
                {
                case LogStatus.Ready:

                    break;

                case LogStatus.Recover:

                    this.resource = resource;
                    this.log      = log;

                    Recover();
                    break;

                case LogStatus.Corrupt:

                    if (!recoverCorrupt)
                    {
                        throw new TransactionException("Transaction log for [{0]] is corrupt.", resource.Name);
                    }

                    SysLog.LogWarning("Corrupt transaction log detected for [{0}]. Best efforts are being taken to recover.", resource.Name);
                    Recover();
                    break;
                }

                this.running        = true;
                this.resource       = resource;
                this.log            = log;
                this.transactions   = new Dictionary <Guid, BaseTransaction>();
                this.threadTransMap = new Dictionary <int, BaseTransaction>();
            }
        }
示例#27
0
        /// <summary>
        /// Queues an email message for deliver,
        /// </summary>
        /// <param name="message">The outbound message.</param>
        /// <remarks>
        /// <note>
        /// This message will do nothing but log a warning if the agent was started
        /// with a <b>Any</b> network binding.
        /// </note>
        /// </remarks>
        public void Enqueue(MailMessage message)
        {
            // Generate a unique file name that will sort roughly in the order
            // that the messages were added to the queue so that messages were
            // are delivered to the relay server in rougly the order that the
            // were queued.

            string fileName = string.Format("{0}-{1}.msg", Helper.ToIsoDate(DateTime.UtcNow).Replace(':', '-'), Guid.NewGuid());

            if (smtpServer.IsAny)
            {
                // Email transmission is disabled

                SysLog.LogWarning("Email transmission is disabled.");
                return;
            }

            using (var output = new EnhancedFileStream(Path.Combine(queueFolder, fileName), FileMode.Create, FileAccess.ReadWrite))
                MailHelper.WriteMessage(output, message);
        }
示例#28
0
        private CallStack createdAt;                            // The stack at the time the context was created
#endif

        /// <summary>
        /// Initializes the context with the connection string passed.
        /// </summary>
        /// <param name="connectionString">The connection string.</param>
        /// <remarks>
        /// See the .NET Framework documentation for information on the format
        /// of this parameter.
        /// </remarks>
        public SqlContext(string connectionString)
        {
            this.conString     = connectionString;
            this.sqlCon        = null;
            this.sqlTrans      = null;
            this.transactions  = new Stack();
            this.nextSavePoint = 0;
            this.onStdError    = null;
            this.retrying      = false;
            this.isSqlAzure    = null;
#if TRACK
            this.lastCommand = string.Empty;
            this.createdAt   = new CallStack(1, true);

            if (!traceWarning)
            {
                SysLog.LogWarning("LillTek.Data.SqlContext TRACE enabled.");
                traceWarning = true;
            }
#endif
        }
示例#29
0
        /// <summary>
        /// Reads the operation from the specified position in the log.
        /// </summary>
        /// <param name="resource">The parent <see cref="ITransactedResource" /> responsible for deserializing the operation.</param>
        /// <param name="position">See the <see cref="ILogPosition" />.</param>
        /// <returns>The <see cref="IOperation" /> read from the log.</returns>
        public IOperation Read(ITransactedResource resource, ILogPosition position)
        {
            int        cb;
            long       recEndPos;
            string     description;
            IOperation operation;

            using (TimedLock.Lock(this))
            {
                if (file == null)
                {
                    throw new TransactionException(ClosedMsg);
                }

                file.Position = ((FileLogPosition)position).Position;

                if (file.ReadInt32() != Magic)
                {
                    throw new TransactionException(CorruptMsg);
                }

                cb = file.ReadInt32();
                if (cb <= 0 || cb + file.Position > file.Length)
                {
                    throw new TransactionException(CorruptMsg);
                }

                recEndPos   = file.Position + cb;
                description = file.ReadString32();
                operation   = resource.ReadOperation(file);

                if (file.Position != recEndPos)
                {
                    SysLog.LogWarning("ITransactedResource.ReadOperation() returned with an unexpected stream position.");
                    file.Position = recEndPos;
                }

                return(operation);
            }
        }
示例#30
0
        /// <summary>
        /// Initializes the instance.
        /// </summary>
        /// <param name="name">The logical counter name.</param>
        /// <param name="help">Counter description.</param>
        /// <param name="type">The performance counter type.</param>
        public PerfCounter(string name, string help, PerformanceCounterType type)
            : this()
        {
            this.name     = name;
            this.category = string.Empty;
            this.help     = help;
            this.type     = type;

            switch (type)
            {
            case PerformanceCounterType.NumberOfItems32:
            case PerformanceCounterType.NumberOfItems64:
            case PerformanceCounterType.RateOfCountsPerSecond32:
            case PerformanceCounterType.RateOfCountsPerSecond64:

                break;

            default:

                SysLog.LogWarning("Performance counter type [{0}] for counter [{1}] is not supported for process local counters.  [NextValue()] will always return zero.", type, name);
                break;
            }
        }