예제 #1
0
        /// <summary>
        ///     <para>Creates a new instance of <see cref="Consumer"/> for the specified <paramref name="topic"/> and
        ///     <paramref name="channel"/>, using the specified <paramref name="logger"/> and <paramref name="config"/>.</para>
        /// </summary>
        /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="topic"/> or
        ///     <paramref name="channel"/> exceed the maximum length or contain invalid characters. Topic and channel names
        ///     must be greater than 0 and less than or equal to 64 characters longer and must match the pattern "^[\.a-zA-Z0-
        ///     9_-]+(#ephemeral)?$".
        /// </exception>
        /// <param name="topic">The topic name.</param>
        /// <param name="channel">The channel name.</param>
        /// <param name="logger">The <see cref="ILogger"/> instance.</param>
        /// <param name="config">The <see cref="Config"/> settings. After config is passed in the values are no longer mutable
        ///     (they are copied).
        /// </param>
        public Consumer(string topic, string channel, ILogger logger, Config config)
        {
            if (string.IsNullOrEmpty(topic))
                throw new ArgumentNullException("topic");
            if (string.IsNullOrEmpty(channel))
                throw new ArgumentNullException("channel");
            if (config == null)
                throw new ArgumentNullException("config");
            if (logger == null)
                throw new ArgumentNullException("logger");

            config.Validate();

            if (!Protocol.IsValidTopicName(topic))
            {
                throw new ArgumentException("invalid topic name", "topic");
            }

            if (!Protocol.IsValidChannelName(channel))
            {
                throw new ArgumentException("invalid channel name", "channel");
            }

            _id = Interlocked.Increment(ref _instCount);

            _topic = topic;
            _channel = channel;
            _config = config.Clone();
            _logger = logger;

            _maxInFlight = config.MaxInFlight;

            _incomingMessages = new Chan<Message>();

            _rdyRetryTimers = new Dictionary<string, Timer>();
            _pendingConnections = new Dictionary<string, Conn>();
            _connections = new Dictionary<string, Conn>();

            _lookupdRecheckChan = new Chan<int>(bufferSize: 1);

            _rng = new RNGCryptoServiceProvider();

            _stopChan = new Chan<int>();
            _exitChan = new Chan<int>();

            _wg.Add(1);

            GoFunc.Run(rdyLoop, string.Format("rdyLoop: {0}/{1}", _topic, _channel));
        }
예제 #2
0
 public void Validate(Config c)
 {
     // no op
 }
예제 #3
0
 /// <summary>
 ///     <para>Creates a new instance of <see cref="Consumer"/> for the specified <paramref name="topic"/> and
 ///     <paramref name="channel"/>, using the specified <paramref name="config"/>.</para>
 ///     <para>Uses <see cref="ConsoleLogger"/> with log level <see cref="F:LogLevel.Info"/>.</para>
 /// </summary>
 /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception>
 /// <exception cref="ArgumentException">Thrown when the <paramref name="topic"/> or <paramref name="channel"/>
 ///     exceed the maximum length or contain invalid characters. Topic and channel names must be greater than 0 and
 ///     less than or equal to 64 characters longer and must match the pattern "^[\.a-zA-Z0-9_-]+(#ephemeral)?$".
 /// </exception>
 /// <remarks>Uses <see cref="ConsoleLogger"/> with <see cref="F:LogLevel.Info"/> to log messages.</remarks>
 /// <param name="topic">The topic name.</param>
 /// <param name="channel">The channel name.</param>
 /// <param name="config">The <see cref="Config"/> settings. After config is passed in the values are no longer mutable
 ///     (they are copied).
 /// </param>
 public Consumer(string topic, string channel, Config config)
     : this(topic, channel, new ConsoleLogger(LogLevel.Info), config)
 {
 }
예제 #4
0
 public bool HandlesOption(Config c, string option)
 {
     switch (option)
     {
         case "tls_min_version":
         case "tls_check_certificate_revocation":
         case "tls_insecure_skip_verify":
             return true;
     }
     return false;
 }
예제 #5
0
            public void Set(Config c, string option, object value)
            {
                var tlsConfig = c.TlsConfig != null
                                    ? c.TlsConfig.Clone()
                                    : new TlsConfig();

                switch (option)
                {
                    case "tls_min_version":
                        var version = (string)value;
                        switch (version)
                        {
                            case "ssl3.0":
                                tlsConfig.MinVersion = SslProtocols.Ssl3;
                                break;
                            case "tls1.0":
                                tlsConfig.MinVersion = SslProtocols.Tls;
                                break;
                #if !NETFX_3_5 && !NETFX_4_0
                            case "tls1.1":
                                tlsConfig.MinVersion = SslProtocols.Tls11;
                                break;
                            case "tls1.2":
                                tlsConfig.MinVersion = SslProtocols.Tls12;
                                break;
                #endif
                            default:
                                throw new Exception(string.Format("ERROR: {0} is not a tls version", value));
                        }
                        break;
                    case "tls_check_certificate_revocation":
                        bool checkCertificationRevocation = value.Coerce<bool>();
                        tlsConfig.CheckCertificateRevocation = checkCertificationRevocation;
                        break;
                    case "tls_insecure_skip_verify":
                        bool insecureSkipVerify = value.Coerce<bool>();
                        tlsConfig.InsecureSkipVerify = insecureSkipVerify;
                        break;
                    default:
                        throw new Exception(string.Format("unknown option {0}", option));
                }

                c.TlsConfig = tlsConfig;
            }
예제 #6
0
            public void SetDefaults(Config c)
            {
                Type typ = c.GetType();
                foreach (var field in typ.GetProperties())
                {
                    var opt = field.Get<OptAttribute>();
                    var defaultValue = field.Get<DefaultAttribute>();
                    if (opt == null || defaultValue == null)
                        continue;

                    c.Set(opt.Name, defaultValue.Value);
                }

                string hostname = OS.Hostname();

                c.ClientID = hostname.Split(new[] { '.' })[0];
                c.Hostname = hostname;
                c.UserAgent = string.Format("{0}/{1}", ClientInfo.ClientName, ClientInfo.Version);
            }
예제 #7
0
            public void Validate(Config c)
            {
                var typ = c.GetType();
                foreach (var field in typ.GetProperties())
                {
                    MinAttribute min = field.Get<MinAttribute>();
                    MaxAttribute max = field.Get<MaxAttribute>();

                    if (min == null && max == null)
                        continue;

                    object value = field.GetValue(c, index: null);

                    var opt = field.Get<OptAttribute>();
                    if (min != null)
                    {
                        var coercedMinVal = (IComparable)opt.Coerce(min.Value, field.PropertyType);
                        if (coercedMinVal.CompareTo(value) == 1)
                            throw new Exception(string.Format("invalid {0} ! {1} < {2}", opt.Name, value, coercedMinVal));
                    }
                    if (max != null)
                    {
                        var coercedMaxVal = (IComparable)opt.Coerce(max.Value, field.PropertyType);
                        if (coercedMaxVal.CompareTo(value) == -1)
                            throw new Exception(string.Format("invalid {0} ! {1} > {2}", opt.Name, value, coercedMaxVal));
                    }
                }

                if (c.HeartbeatInterval > c.ReadTimeout)
                {
                    throw new Exception(string.Format("HeartbeatInterval {0} must be less than ReadTimeout {1}",
                        c.HeartbeatInterval, c.ReadTimeout));
                }

                // TODO: PR go-nsq: this check was removed, seems still valid since the value can be set through code
                // https://github.com/bitly/go-nsq/commit/dd8e5fc4ad80922d884ece51f5574af3fa4f14d3#diff-b4bda758a2aef091432646c354b4dc59L376
                if (c.BackoffStrategy == null)
                    throw new Exception(string.Format("BackoffStrategy cannot be null"));
            }
예제 #8
0
            public void Set(Config c, string option, object value)
            {
                var typ = c.GetType();
                foreach (var field in typ.GetProperties())
                {
                    var opt = field.Get<OptAttribute>();
                    if (opt == null || opt.Name != option)
                        continue;

                    var min = field.Get<MinAttribute>();
                    var max = field.Get<MaxAttribute>();

                    var coercedVal = opt.Coerce(value, field.PropertyType);

                    if (min != null)
                    {
                        var coercedMinVal = (IComparable)opt.Coerce(min.Value, field.PropertyType);
                        if (coercedMinVal.CompareTo(coercedVal) == 1)
                            throw new Exception(string.Format("invalid {0} ! {1} < {2}", opt.Name, coercedVal, coercedMinVal));
                    }

                    if (max != null)
                    {
                        var coercedMaxVal = (IComparable)opt.Coerce(max.Value, field.PropertyType);
                        if (coercedMaxVal.CompareTo(coercedVal) == -1)
                            throw new Exception(string.Format("invalid {0} ! {1} > {2}", opt.Name, coercedVal, coercedMaxVal));
                    }

                    field.SetValue(c, coercedVal, index: null);
                    return;
                }

                throw new Exception(string.Format("unknown option {0}", option));
            }
예제 #9
0
            public bool HandlesOption(Config c, string option)
            {
                var typ = c.GetType();
                foreach (var field in typ.GetProperties())
                {
                    var opt = field.Get<OptAttribute>();
                    if (opt != null && opt.Name == option)
                    {
                        return true;
                    }
                }

                return false;
            }
예제 #10
0
        /// <summary>Clones (makes a copy) of this instance.</summary>
        /// <returns>A copy of this object.</returns>
        public Config Clone()
        {
            var newConfig = new Config();

            newConfig.BackoffStrategy = BackoffStrategy;

            var typ = GetType();
            foreach (var field in typ.GetProperties())
            {
                var opt = field.Get<OptAttribute>();
                if (opt != null)
                {
                    newConfig.Set(opt.Name, field.GetValue(this, index: null));
                }
            }

            return newConfig;
        }
예제 #11
0
            public void Set(Config c, string option, object value)
            {
                if (c.TlsConfig == null)
                {
                    c.TlsConfig = new TlsConfig
                    {
                        MinVersion = SslProtocols.Tls,
                #if NETFX_3_5 || NETFX_4_0
                        MaxVersion = SslProtocols.Tls
                #else
                        MaxVersion = SslProtocols.Tls12
                #endif
                    };
                }

                switch (option)
                {
                    case "tls_cert":
                    case "tls_key":
                        // TODO: Test
                        if (option == "tls_cert")
                            certFile = (string)value;
                        else
                            keyFile = (string)value;

                        if (!string.IsNullOrEmpty(certFile) && !string.IsNullOrEmpty(keyFile) &&
                            c.TlsConfig.Certificates.Count == 0)
                        {
                            c.TlsConfig.Certificates.Import(certFile);
                            c.TlsConfig.Certificates.Import(keyFile);
                        }
                        return;

                    case "tls_root_ca_file":
                        // TODO: Test
                        string path = (string)value;
                        var certificates = PEM(File.ReadAllText(path));
                        c.TlsConfig.RootCAs = certificates;
                        return;

                    case "tls_insecure_skip_verify":
                        bool coercedVal = value.Coerce<bool>();
                        c.TlsConfig.InsecureSkipVerify = coercedVal;
                        return;

                    case "tls_min_version":
                        var version = (string)value;
                        switch (version)
                        {
                            case "ssl3.0":
                                c.TlsConfig.MinVersion = SslProtocols.Ssl3;
                                break;
                            case "tls1.0":
                                c.TlsConfig.MinVersion = SslProtocols.Tls;
                                break;
                #if !NETFX_3_5 && !NETFX_4_0
                            case "tls1.1":
                                c.TlsConfig.MinVersion = SslProtocols.Tls11;
                                return;
                            case "tls1.2":
                                c.TlsConfig.MinVersion = SslProtocols.Tls12;
                                return;
                #endif
                            default:
                                throw new Exception(string.Format("ERROR: {0} is not a tls version", value));
                        }
                        return;
                }

                throw new Exception(string.Format("unknown option {0}", option));
            }

            public void Validate(Config c)
            {
                // no op
            }
예제 #12
0
 public bool HandlesOption(Config c, string option)
 {
     switch (option)
     {
         case "tls_root_ca_file":
         case "tls_insecure_skip_verify":
         case "tls_cert":
         case "tls_key":
         case "tls_min_version":
             return true;
     }
     return false;
 }