예제 #1
0
        public void EndpointDispatcherAddTest7()
        {
            var                 uri      = CreateAvailableUri("http://localhost:37564");
            ServiceHost         h        = new ServiceHost(typeof(TestContract), uri);
            var                 binding  = new BasicHttpBinding();
            var                 listener = new MyChannelListener <IReplyChannel> (uri);
            MyChannelDispatcher d        = new MyChannelDispatcher(listener);
            var                 ed       = new EndpointDispatcher(new EndpointAddress(uri), "", "");

            d.Endpoints.Add(ed);

            ed.DispatchRuntime.Type = typeof(TestContract);

            d.MessageVersion = MessageVersion.Default;

            // add service endpoint to open the host (unlike all tests above).
            h.AddServiceEndpoint(typeof(TestContract),
                                 new BasicHttpBinding(), uri.ToString());
            h.ChannelDispatchers.Clear();

            h.ChannelDispatchers.Add(d);
            d.Open();              // At this state, it does *not* call AcceptChannel() yet.

            // This rejects already-opened ChannelDispatcher.
            h.Open(TimeSpan.FromSeconds(10));
            // should not reach here, but in case it didn't, it must be closed.
            h.Close(TimeSpan.FromSeconds(10));
        }
예제 #2
0
        // FIXME: this test itself indeed passes, but some weird conflict that blocks correspoding port happens between this and somewhere (probably above)
//		[Test]
        public void EndpointDispatcherAddTest9()          // test singleton service
        {
            var         uri = CreateAvailableUri("http://localhost:37564");
            ServiceHost h   = new ServiceHost(new TestContract(), uri);

            h.Description.Behaviors.Find <ServiceBehaviorAttribute> ().InstanceContextMode = InstanceContextMode.Single;
            var listener          = new MyChannelListener <IReplyChannel> (uri);
            MyChannelDispatcher d = new MyChannelDispatcher(listener);
            var ed = new EndpointDispatcher(new EndpointAddress(uri), "", "");

            d.Endpoints.Add(ed);
            ed.DispatchRuntime.Type = typeof(TestContract);
            d.MessageVersion        = MessageVersion.Default;
            h.AddServiceEndpoint(typeof(TestContract), new BasicHttpBinding(), uri.ToString());
            h.ChannelDispatchers.Clear();
            Assert.IsNull(ed.DispatchRuntime.SingletonInstanceContext, "#1");
            h.ChannelDispatchers.Add(d);
            Assert.IsNull(ed.DispatchRuntime.SingletonInstanceContext, "#2");
            try {
                h.Open(TimeSpan.FromSeconds(10));
                Assert.IsNull(ed.DispatchRuntime.InstanceProvider, "#4");
                Assert.IsNotNull(ed.DispatchRuntime.InstanceContextProvider, "#5");                  // it was set after ServiceHost.Open().
                Assert.IsNotNull(ed.DispatchRuntime.SingletonInstanceContext, "#6");
            } finally {
                h.Close(TimeSpan.FromSeconds(10));
                h.Abort();
            }
        }
예제 #3
0
        public void EndpointDispatcherAddTest6()
        {
            var                 uri      = CreateAvailableUri("http://localhost:37564");
            ServiceHost         h        = new ServiceHost(typeof(TestContract), uri);
            var                 binding  = new BasicHttpBinding();
            var                 listener = new MyChannelListener <IReplyChannel> (uri);
            MyChannelDispatcher d        = new MyChannelDispatcher(listener);
            var                 ed       = new EndpointDispatcher(new EndpointAddress(uri), "", "");

            d.Endpoints.Add(ed);
            Assert.IsFalse(d.Attached, "#x1");

            ed.DispatchRuntime.Type = typeof(TestContract);

            d.MessageVersion = MessageVersion.Default;
            h.ChannelDispatchers.Add(d);
            Assert.IsTrue(d.Attached, "#x2");
            d.Open();              // At this state, it does *not* call AcceptChannel() yet.
            Assert.IsFalse(listener.AcceptChannelTried, "#1");
            Assert.IsFalse(listener.WaitForChannelTried, "#2");

            Assert.IsNotNull(ed.DispatchRuntime, "#3");
            Assert.IsNull(ed.DispatchRuntime.InstanceProvider, "#4");
            Assert.IsNull(ed.DispatchRuntime.InstanceContextProvider, "#5");              // it is not still set after ChannelDispatcher.Open().
            Assert.IsNull(ed.DispatchRuntime.InstanceProvider, "#5.2");
            Assert.IsNull(ed.DispatchRuntime.SingletonInstanceContext, "#6");

            d.Close();              // we don't have to even close it.
        }
예제 #4
0
        [ExpectedException(typeof(InvalidOperationException))]           // i.e. it is thrown synchronously in current thread.
        public void EndpointDispatcherAddTest4()
        {
            var                 uri      = CreateAvailableUri("http://localhost:37564");
            ServiceHost         h        = new ServiceHost(typeof(TestContract), uri);
            var                 listener = new MyChannelListener(uri);
            MyChannelDispatcher d        = new MyChannelDispatcher(listener);
            var                 ed       = new EndpointDispatcher(new EndpointAddress(uri), "", "");

            Assert.IsNotNull(ed.DispatchRuntime, "#1");
            Assert.IsNull(ed.DispatchRuntime.InstanceProvider, "#2");
            Assert.IsNull(ed.DispatchRuntime.InstanceContextProvider, "#3");
            Assert.IsNull(ed.DispatchRuntime.InstanceProvider, "#3.2");
            Assert.IsNull(ed.DispatchRuntime.SingletonInstanceContext, "#4");
            d.Endpoints.Add(ed);
            d.MessageVersion = MessageVersion.Default;
            h.ChannelDispatchers.Add(d);
            // it misses DispatchRuntime.Type, which seems set
            // automatically when the dispatcher is created in
            // ordinal process but need to be set manually in this case.
            try {
                d.Open();
                try {
                    // should not reach here, but in case it didn't, it must be closed.
                    d.Close(TimeSpan.FromSeconds(10));
                } catch {
                }
            } finally {
                Assert.AreEqual(CommunicationState.Opened, listener.State, "#5");
            }
        }
예제 #5
0
        // Validating duplicate listen URI causes this regression.
        // Since it is niche, I rather fixed ServiceHostBase to introduce validation.
        // It is probably because this code doesn't use ServiceEndpoint to build IChannelListener i.e. built without Binding.
        // We can add an extra field to ChannelDispatcher to indicate that it is from ServiceEndpoint (i.e. with Binding),
        // but it makes little sense especially for checking duplicate listen URIs. Duplicate listen URIs should be rejected anyways.
        public void EndpointDispatcherAddTest8()
        {
            var                 uri      = CreateAvailableUri("http://localhost:37564");
            ServiceHost         h        = new ServiceHost(typeof(TestContract), uri);
            var                 listener = new MyChannelListener <IReplyChannel> (uri);
            MyChannelDispatcher d        = new MyChannelDispatcher(listener);
            var                 ed       = new EndpointDispatcher(new EndpointAddress(uri), "", "");

            d.Endpoints.Add(ed);

            ed.DispatchRuntime.Type = typeof(TestContract);

            d.MessageVersion = MessageVersion.Default;

            // add service endpoint to open the host (unlike all tests above).
            h.AddServiceEndpoint(typeof(TestContract),
                                 new BasicHttpBinding(), uri.ToString());
            h.ChannelDispatchers.Clear();

            h.ChannelDispatchers.Add(d);

            Assert.AreEqual(h, d.Host, "#0");

            try
            {
                h.Open(TimeSpan.FromSeconds(10));
                Assert.AreEqual(3, h.ChannelDispatchers.Count, "#0");  // TestContract, d, mex
                Assert.IsTrue(listener.BeginAcceptChannelTried, "#1"); // while it throws NIE ...
                Assert.IsFalse(listener.WaitForChannelTried, "#2");
                Assert.IsNotNull(ed.DispatchRuntime, "#3");
                Assert.IsNull(ed.DispatchRuntime.InstanceProvider, "#4");
                Assert.IsNotNull(ed.DispatchRuntime.InstanceContextProvider, "#5"); // it was set after ServiceHost.Open().
                Assert.IsNull(ed.DispatchRuntime.SingletonInstanceContext, "#6");

                /*
                 * var l = new HttpListener ();
                 * l.Prefixes.Add (uri.ToString ());
                 * l.Start ();
                 * l.Stop ();
                 */
            }
            finally
            {
                h.Close(TimeSpan.FromSeconds(10));
                h.Abort();
            }
        }
예제 #6
0
        [ExpectedException(typeof(InvalidOperationException))]           // i.e. it is thrown synchronously in current thread.
        public void EndpointDispatcherAddTest5()
        {
            var                 uri      = CreateAvailableUri("http://localhost:37564");
            ServiceHost         h        = new ServiceHost(typeof(TestContract), uri);
            var                 binding  = new BasicHttpBinding();
            var                 listener = new MyChannelListener(uri);
            MyChannelDispatcher d        = new MyChannelDispatcher(listener);
            var                 ed       = new EndpointDispatcher(new EndpointAddress(uri), "", "");

            d.Endpoints.Add(ed);

            ed.DispatchRuntime.Type = typeof(TestContract);              // different from Test4

            d.MessageVersion = MessageVersion.Default;
            h.ChannelDispatchers.Add(d);
            // It rejects "unrecognized type" of the channel listener.
            // Test6 uses IChannelListener<IReplyChannel> and works.
            d.Open();
            // should not reach here, but in case it didn't, it must be closed.
            d.Close(TimeSpan.FromSeconds(10));
        }
예제 #7
0
        static int Main(string[] args)
        {
            Log(DriverMessage);
            Log("Driver version " + DriverVersion);
            Log("Using opendnp3 version 3.1.1");

            if (args.Length > 0) // first argument in number of the driver instance
            {
                int  num;
                bool res = int.TryParse(args[0], out num);
                if (res)
                {
                    ProtocolDriverInstanceNumber = num;
                }
            }
            if (args.Length > 1) // second argument is logLevel
            {
                int  num;
                bool res = int.TryParse(args[1], out num);
                if (res)
                {
                    LogLevel = num;
                }
            }
            string fname = JsonConfigFilePath;

            if (args.Length > 2) // third argument is config file name
            {
                if (File.Exists(args[2]))
                {
                    fname = args[2];
                }
            }
            if (!File.Exists(fname))
            {
                fname = JsonConfigFilePathAlt;
            }
            if (!File.Exists(fname))
            {
                Log("Missing config file " + JsonConfigFilePath);
                Environment.Exit(-1);
            }

            Log("Reading config file " + fname);
            string json = File.ReadAllText(fname);

            JSConfig = JsonSerializer.Deserialize <JSONSCADAConfig>(json);
            if (
                JSConfig.mongoConnectionString == "" ||
                JSConfig.mongoConnectionString == null
                )
            {
                Log("Missing MongoDB connection string in JSON config file " +
                    fname);
                Environment.Exit(-1);
            }
            if (
                JSConfig.mongoDatabaseName == "" ||
                JSConfig.mongoDatabaseName == null
                )
            {
                Log("Missing MongoDB database name in JSON config file " +
                    fname);
                Environment.Exit(-1);
            }
            Log("MongoDB database name: " + JSConfig.mongoDatabaseName);
            if (JSConfig.nodeName == "" || JSConfig.nodeName == null)
            {
                Log("Missing nodeName parameter in JSON config file " +
                    fname);
                Environment.Exit(-1);
            }
            Log("Node name: " + JSConfig.nodeName);

            var Client = ConnectMongoClient(JSConfig);
            var DB     = Client.GetDatabase(JSConfig.mongoDatabaseName);

            // read and process instances configuration
            var collinsts =
                DB
                .GetCollection
                <protocolDriverInstancesClass
                >(ProtocolDriverInstancesCollectionName);
            var instances =
                collinsts
                .Find(inst =>
                      inst.protocolDriver == ProtocolDriverName &&
                      inst.protocolDriverInstanceNumber ==
                      ProtocolDriverInstanceNumber &&
                      inst.enabled == true)
                .ToList();
            var foundInstance = false;

            foreach (protocolDriverInstancesClass inst in instances)
            {
                if (
                    ProtocolDriverName == inst.protocolDriver &&
                    ProtocolDriverInstanceNumber ==
                    inst.protocolDriverInstanceNumber
                    )
                {
                    foundInstance = true;
                    if (!inst.enabled)
                    {
                        Log("Driver instance [" +
                            ProtocolDriverInstanceNumber.ToString() +
                            "] disabled!");
                        Environment.Exit(-1);
                    }
                    Log("Instance: " +
                        inst.protocolDriverInstanceNumber.ToString());
                    var nodefound = false;
                    foreach (var name in inst.nodeNames)
                    {
                        if (JSConfig.nodeName == name)
                        {
                            nodefound = true;
                        }
                    }
                    if (!nodefound)
                    {
                        Log("Node '" +
                            JSConfig.nodeName +
                            "' not found in instances configuration!");
                        Environment.Exit(-1);
                    }
                    DriverInstance = inst;
                    break;
                }
                break; // process just first result
            }
            if (!foundInstance)
            {
                Log("Driver instance [" +
                    ProtocolDriverInstanceNumber +
                    "] not found in configuration!");
                Environment.Exit(-1);
            }

            // read and process connections configuration for this driver instance
            var collconns =
                DB
                .GetCollection
                <DNP3_connection>(ProtocolConnectionsCollectionName);
            var conns =
                collconns
                .Find(conn =>
                      conn.protocolDriver == ProtocolDriverName &&
                      conn.protocolDriverInstanceNumber ==
                      ProtocolDriverInstanceNumber &&
                      conn.enabled == true)
                .ToList();

            foreach (DNP3_connection isrv in conns)
            {
                if (isrv.ipAddresses.Length < 1 && isrv.portName.Trim() == "")
                {
                    Log("No ipAddresses or port name defined on conenction! " + isrv.name);
                    Environment.Exit(-1);
                }
                DNP3conns.Add(isrv);
                Log(isrv.name.ToString() + " - New Connection");
            }
            if (DNP3conns.Count == 0)
            {
                Log("No connections found!");
                Environment.Exit(-1);
            }

            // start thread to process redundancy control
            Thread thrMongoRedundacy =
                new Thread(() =>
                           ProcessRedundancyMongo(JSConfig));

            thrMongoRedundacy.Start();

            // start thread to update acquired data to database
            Thread thrMongo =
                new Thread(() =>
                           ProcessMongo(JSConfig));

            thrMongo.Start();

            // start thread to watch for commands in the database using a change stream
            Thread thrMongoCmd =
                new Thread(() =>
                           ProcessMongoCmd(JSConfig));

            thrMongoCmd.Start();

            Log("Setting up connections & ASDU handlers...");
            mgr = DNP3ManagerFactory.CreateManager(2 * Environment.ProcessorCount, new PrintingLogAdapter());
            foreach (DNP3_connection srv in DNP3conns)
            {
                uint logLevel = LogLevels.NONE;
                if (LogLevel >= LogLevelBasic)
                {
                    logLevel = LogLevels.NORMAL;
                }
                if (LogLevel >= LogLevelDetailed)
                {
                    logLevel = LogLevels.NORMAL | LogLevels.APP_COMMS;
                }
                if (LogLevel >= LogLevelDebug)
                {
                    logLevel = LogLevels.ALL;
                }

                MyChannelListener chlistener = new MyChannelListener();
                chlistener.dnp3conn = srv;

                IChannel channel = null;        // can be tcp, udp, tls, or serial
                if (srv.ipAddresses.Length > 0) // TCP, TLS or UDP
                {
                    if (srv.ipAddressLocalBind.Trim() != "")
                    { // UDP
                        // look for the same channel config already created (multi-drop case)
                        // if found, just reuse
                        foreach (DNP3_connection conn in DNP3conns)
                        {
                            if (!(conn.channel is null))
                            {
                                if (conn.ipAddressLocalBind.Trim() != "" &&
                                    srv.ipAddressLocalBind.Trim() == conn.ipAddressLocalBind.Trim() &&
                                    srv.ipAddresses[0] == conn.ipAddresses[0])
                                {
                                    channel = conn.channel;
                                    break;
                                }
                            }
                        }
                        if (!(channel is null))
                        {
                            Log(srv.name + " - Reusing channel...");
                        }
                        else
                        {
                            Log(srv.name + " - Creating UDP channel...");
                            ushort   localUdpPort    = 20000;
                            string[] localIpAddrPort = srv.ipAddressLocalBind.Split(':');
                            if (localIpAddrPort.Length > 1)
                            {
                                if (int.TryParse(localIpAddrPort[1], out _))
                                {
                                    localUdpPort = System.Convert.ToUInt16(localIpAddrPort[1]);
                                }
                            }
                            ushort   remoteUdpPort    = 20000;
                            string[] remoteIpAddrPort = srv.ipAddresses[0].Split(':');
                            if (remoteIpAddrPort.Length > 1)
                            {
                                if (int.TryParse(remoteIpAddrPort[1], out _))
                                {
                                    remoteUdpPort = System.Convert.ToUInt16(remoteIpAddrPort[1]);
                                }
                            }
                            channel = mgr.AddUDPChannel(
                                "UDP:" + srv.name,
                                logLevel,
                                new ChannelRetry(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(5)),
                                new IPEndpoint(localIpAddrPort[0], localUdpPort),
                                new IPEndpoint(remoteIpAddrPort[0], remoteUdpPort),
                                chlistener
                                );
                        }
                    }
                    else
                    { // TCP or TLS
                        ushort   tcpPort    = 20000;
                        string[] ipAddrPort = srv.ipAddresses[0].Split(':');
                        if (ipAddrPort.Length > 1)
                        {
                            if (int.TryParse(ipAddrPort[1], out _))
                            {
                                tcpPort = System.Convert.ToUInt16(ipAddrPort[1]);
                            }
                        }

                        // look for the same channel config already created (multi-drop case)
                        // if found, just reuse
                        foreach (DNP3_connection conn in DNP3conns)
                        {
                            if (!(conn.channel is null))
                            {
                                if (srv.ipAddresses.SequenceEqual(conn.ipAddresses))
                                {
                                    channel = conn.channel;
                                    break;
                                }
                            }
                        }
                        if (!(channel is null))
                        {
                            Log(srv.name + " - Reusing channel...");
                        }