1
//! Program configurations.
2

            
3
use std::env;
4

            
5
use clap::{
6
    builder::{BoolValueParser, RangedU64ValueParser},
7
    Arg, ArgMatches, Command,
8
};
9
use serde::Deserialize;
10

            
11
use sylvia_iot_corelib::constants::MqEngine;
12

            
13
/// Configuration file object.
14
#[derive(Default, Deserialize)]
15
pub struct Config {
16
    /// **sylvia-iot-auth** API base path with host. For example: `http://localhost:1080/auth`.
17
    pub auth: Option<String>,
18
    /// **sylvia-iot-broker** API base path with host. For example: `http://localhost:2080/broker`.
19
    pub broker: Option<String>,
20
    /// Message queue broker configurations.
21
    pub mq: Option<Mq>,
22
    #[serde(rename = "mqChannels")]
23
    pub mq_channels: Option<MqChannels>,
24
}
25

            
26
/// Message queue engine configurations.
27
#[derive(Default, Deserialize)]
28
pub struct Mq {
29
    /// Engine selections.
30
    pub engine: Option<Engine>,
31
    /// RabbitMQ configurations.
32
    pub rabbitmq: Option<RabbitMq>,
33
    /// EMQX configurations.
34
    pub emqx: Option<Emqx>,
35
    /// rumqttd configurations.
36
    pub rumqttd: Option<Rumqttd>,
37
}
38

            
39
/// Engine selections.
40
#[derive(Default, Deserialize)]
41
pub struct Engine {
42
    /// AMQP message broker. Now we only support `rabbitmq`.
43
    pub amqp: Option<String>,
44
    /// MQTT message broker. `emqx` and `rumqttd` are supported. Default is `emqx`.
45
    pub mqtt: Option<String>,
46
}
47

            
48
/// Configurations for RabbitMQ.
49
#[derive(Default, Deserialize)]
50
pub struct RabbitMq {
51
    /// Management user name. Default is **guest**.
52
    pub username: Option<String>,
53
    /// Management password. Default is **guest**.
54
    pub password: Option<String>,
55
    /// Message TTL in milliseconds. Default is **3600000**.
56
    pub ttl: Option<usize>,
57
    /// Queue length. Default is **10000**.
58
    pub length: Option<usize>,
59
    /// Available hosts. None or empty means unlimited.
60
    pub hosts: Option<Vec<MqHost>>,
61
}
62

            
63
/// Configurations for EMQX.
64
#[derive(Default, Deserialize)]
65
pub struct Emqx {
66
    /// Management API key.
67
    #[serde(rename = "apiKey")]
68
    pub api_key: Option<String>,
69
    /// Management password. Default is **public**.
70
    #[serde(rename = "apiSecret")]
71
    pub api_secret: Option<String>,
72
    /// Available hosts. None or empty means unlimited.
73
    pub hosts: Option<Vec<MqHost>>,
74
}
75

            
76
/// Configurations for rumqttd.
77
#[derive(Default, Deserialize)]
78
pub struct Rumqttd {
79
    /// MQTT listen port. Default is 1883.
80
    #[serde(rename = "mqttPort")]
81
    pub mqtt_port: Option<u16>,
82
    /// MQTTS listen port. Default is 8883. This must used with both `cert_file` and `key_file` in
83
    /// [`sylvia_iot_corelib::server_config::Config`].
84
    #[serde(rename = "mqttsPort")]
85
    pub mqtts_port: Option<u16>,
86
    /// Console listen port. Default is 18083.
87
    #[serde(rename = "consolePort")]
88
    pub console_port: Option<u16>,
89
}
90

            
91
#[derive(Clone, Default, Deserialize)]
92
pub struct MqHost {
93
    /// Display name.
94
    pub name: String,
95
    /// Internal host name or IP address of the message broker for sylvia-iot-broker to access.
96
    pub host: String,
97
    /// External host name or IP address of the message broker for developer to access.
98
    pub external: String,
99
    /// Is active broker in operation or to be stopped.
100
    pub active: bool,
101
}
102

            
103
/// Message channels configuration object.
104
#[derive(Default, Deserialize)]
105
pub struct MqChannels {
106
    pub data: Option<CoremgrData>,
107
}
108

            
109
/// Channel `coremgr.data` configuration object.
110
#[derive(Default, Deserialize)]
111
pub struct CoremgrData {
112
    /// Queue connection URL of the data channel.
113
    pub url: Option<String>,
114
    /// AMQP persistent.
115
    pub persistent: Option<bool>,
116
}
117

            
118
pub const DEF_AUTH: &'static str = "http://localhost:1080/auth";
119
pub const DEF_BROKER: &'static str = "http://localhost:2080/broker";
120
pub const DEF_ENGINE_AMQP: &'static str = MqEngine::RABBITMQ;
121
pub const DEF_ENGINE_MQTT: &'static str = MqEngine::EMQX;
122
pub const DEF_RABBITMQ_USERNAME: &'static str = "guest";
123
pub const DEF_RABBITMQ_PASSWORD: &'static str = "guest";
124
pub const DEF_EMQX_API_KEY: &'static str = "";
125
pub const DEF_EMQX_API_SECRET: &'static str = "";
126
pub const DEF_RUMQTTD_MQTT_PORT: u16 = 1883;
127
pub const DEF_RUMQTTD_MQTTS_PORT: u16 = 8883;
128
pub const DEF_RUMQTTD_CONSOLE_PORT: u16 = 18083;
129
pub const DEF_MQ_CHANNEL_URL: &'static str = "amqp://localhost";
130
pub const DEF_MQ_PERSISTENT: bool = false;
131

            
132
/// To register Clap arguments.
133
7
pub fn reg_args(cmd: Command) -> Command {
134
7
    cmd.arg(
135
7
        Arg::new("coremgr.auth")
136
7
            .long("coremgr.auth")
137
7
            .help("sylvia-iot-auth host (ex: http://localhost:1080/auth)")
138
7
            .num_args(1),
139
7
    )
140
7
    .arg(
141
7
        Arg::new("coremgr.broker")
142
7
            .long("coremgr.broker")
143
7
            .help("sylvia-iot-broker host (ex: http://localhost:2080/broker)")
144
7
            .num_args(1),
145
7
    )
146
7
    .arg(
147
7
        Arg::new("coremgr.mq.engine.amqp")
148
7
            .long("coremgr.mq.engine.amqp")
149
7
            .help("AMQP broker")
150
7
            .num_args(1)
151
7
            .value_parser([MqEngine::RABBITMQ]),
152
7
    )
153
7
    .arg(
154
7
        Arg::new("coremgr.mq.engine.mqtt")
155
7
            .long("coremgr.mq.engine.mqtt")
156
7
            .help("MQTT broker")
157
7
            .num_args(1)
158
7
            .value_parser([MqEngine::EMQX, MqEngine::RUMQTTD]),
159
7
    )
160
7
    .arg(
161
7
        Arg::new("coremgr.mq.rabbitmq.username")
162
7
            .long("coremgr.mq.rabbitmq.username")
163
7
            .help("RabbitMQ configurations: management user name")
164
7
            .num_args(1),
165
7
    )
166
7
    .arg(
167
7
        Arg::new("coremgr.mq.rabbitmq.password")
168
7
            .long("coremgr.mq.rabbitmq.password")
169
7
            .help("RabbitMQ configurations: management password")
170
7
            .num_args(1),
171
7
    )
172
7
    .arg(
173
7
        Arg::new("coremgr.mq.rabbitmq.ttl")
174
7
            .long("coremgr.mq.rabbitmq.ttl")
175
7
            .help("RabbitMQ configurations: message TTL in milliseconds")
176
7
            .num_args(1)
177
7
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
178
7
    )
179
7
    .arg(
180
7
        Arg::new("coremgr.mq.rabbitmq.length")
181
7
            .long("coremgr.mq.rabbitmq.length")
182
7
            .help("RabbitMQ configurations: queue length")
183
7
            .num_args(1)
184
7
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
185
7
    )
186
7
    .arg(
187
7
        Arg::new("coremgr.mq.rabbitmq.hosts")
188
7
            .long("coremgr.mq.rabbitmq.hosts")
189
7
            .help("RabbitMQ hosts")
190
7
            .num_args(1),
191
7
    )
192
7
    .arg(
193
7
        Arg::new("coremgr.mq.emqx.apikey")
194
7
            .long("coremgr.mq.emqx.apikey")
195
7
            .help("EMQX configurations: management API key")
196
7
            .num_args(1),
197
7
    )
198
7
    .arg(
199
7
        Arg::new("coremgr.mq.emqx.apisecret")
200
7
            .long("coremgr.mq.emqx.apisecret")
201
7
            .help("EMQX configurations: management API secret")
202
7
            .num_args(1),
203
7
    )
204
7
    .arg(
205
7
        Arg::new("coremgr.mq.emqx.hosts")
206
7
            .long("coremgr.mq.emqx.hosts")
207
7
            .help("EMQX hosts")
208
7
            .num_args(1),
209
7
    )
210
7
    .arg(
211
7
        Arg::new("coremgr.mq.rumqttd.mqtt-port")
212
7
            .long("coremgr.mq.rumqttd.mqtt-port")
213
7
            .help("rumqttd MQTT listen port")
214
7
            .num_args(1)
215
7
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
216
7
    )
217
7
    .arg(
218
7
        Arg::new("coremgr.mq.rumqttd.mqtts-port")
219
7
            .long("coremgr.mq.rumqttd.mqtts-port")
220
7
            .help("rumqttd MQTTS listen port")
221
7
            .num_args(1)
222
7
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
223
7
    )
224
7
    .arg(
225
7
        Arg::new("coremgr.mq.rumqttd.console-port")
226
7
            .long("coremgr.mq.rumqttd.console-port")
227
7
            .help("rumqttd console listen port")
228
7
            .num_args(1)
229
7
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
230
7
    )
231
7
    .arg(
232
7
        Arg::new("coremgr.mq-channels.data.url")
233
7
            .long("coremgr.mq-channels.data.url")
234
7
            .help("URL of `coremgr.data` channel")
235
7
            .num_args(1),
236
7
    )
237
7
    .arg(
238
7
        Arg::new("coremgr.mq-channels.data.persistent")
239
7
            .long("coremgr.mq-channels.data.persistent")
240
7
            .help("AMQP persistent for `coremgr.data` channel")
241
7
            .num_args(1)
242
7
            .value_parser(BoolValueParser::new()),
243
7
    )
244
7
}
245

            
246
/// To read input arguments from command-line arguments and environment variables.
247
///
248
/// This function will call [`apply_default()`] to fill missing values so you do not need call it
249
/// again.
250
8
pub fn read_args(args: &ArgMatches) -> Config {
251
8
    apply_default(&Config {
252
8
        auth: match args.get_one::<String>("coremgr.auth") {
253
6
            None => match env::var("COREMGR_AUTH") {
254
3
                Err(_) => None,
255
3
                Ok(v) => Some(v),
256
            },
257
2
            Some(v) => Some(v.clone()),
258
        },
259
8
        broker: match args.get_one::<String>("coremgr.broker") {
260
6
            None => match env::var("COREMGR_BROKER") {
261
3
                Err(_) => None,
262
3
                Ok(v) => Some(v),
263
            },
264
2
            Some(v) => Some(v.clone()),
265
        },
266
        mq: Some(Mq {
267
            engine: Some(Engine {
268
8
                amqp: match args.get_one::<String>("coremgr.mq.engine.amqp") {
269
6
                    None => match env::var("COREMGR_MQ_ENGINE_AMQP") {
270
3
                        Err(_) => None,
271
3
                        Ok(v) => Some(v),
272
                    },
273
2
                    Some(v) => Some(v.clone()),
274
                },
275
8
                mqtt: match args.get_one::<String>("coremgr.mq.engine.mqtt") {
276
6
                    None => match env::var("COREMGR_MQ_ENGINE_MQTT") {
277
3
                        Err(_) => None,
278
3
                        Ok(v) => Some(v),
279
                    },
280
2
                    Some(v) => Some(v.clone()),
281
                },
282
            }),
283
            rabbitmq: Some(RabbitMq {
284
8
                username: match args.get_one::<String>("coremgr.mq.rabbitmq.username") {
285
6
                    None => match env::var("COREMGR_MQ_RABBITMQ_USERNAME") {
286
3
                        Err(_) => None,
287
3
                        Ok(v) => Some(v),
288
                    },
289
2
                    Some(v) => Some(v.clone()),
290
                },
291
8
                password: match args.get_one::<String>("coremgr.mq.rabbitmq.password") {
292
6
                    None => match env::var("COREMGR_MQ_RABBITMQ_PASSWORD") {
293
3
                        Err(_) => None,
294
3
                        Ok(v) => Some(v),
295
                    },
296
2
                    Some(v) => Some(v.clone()),
297
                },
298
8
                ttl: match args.get_one::<u64>("coremgr.mq.rabbitmq.ttl") {
299
6
                    None => match env::var("COREMGR_MQ_RABBITMQ_TTL") {
300
3
                        Err(_) => None,
301
3
                        Ok(v) => match v.parse::<usize>() {
302
1
                            Err(_) => None,
303
2
                            Ok(v) => Some(v),
304
                        },
305
                    },
306
2
                    Some(v) => Some(*v as usize),
307
                },
308
8
                length: match args.get_one::<u64>("coremgr.mq.rabbitmq.length") {
309
6
                    None => match env::var("COREMGR_MQ_RABBITMQ_LENGTH") {
310
3
                        Err(_) => None,
311
3
                        Ok(v) => match v.parse::<usize>() {
312
1
                            Err(_) => None,
313
2
                            Ok(v) => Some(v),
314
                        },
315
                    },
316
2
                    Some(v) => Some(*v as usize),
317
                },
318
8
                hosts: match args.get_one::<String>("coremgr.mq.rabbitmq.hosts") {
319
4
                    None => match env::var("COREMGR_MQ_RABBITMQ_HOSTS") {
320
1
                        Err(_) => None,
321
3
                        Ok(v) => match v.len() {
322
1
                            0 => None,
323
2
                            _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
324
1
                                Err(_) => None,
325
1
                                Ok(v) => Some(v),
326
                            },
327
                        },
328
                    },
329
4
                    Some(v) => match v.len() {
330
1
                        0 => None,
331
3
                        _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
332
1
                            Err(_) => None,
333
2
                            Ok(v) => Some(v),
334
                        },
335
                    },
336
                },
337
            }),
338
            emqx: Some(Emqx {
339
8
                api_key: match args.get_one::<String>("coremgr.mq.emqx.apikey") {
340
6
                    None => match env::var("COREMGR_MQ_EMQX_APIKEY") {
341
3
                        Err(_) => None,
342
3
                        Ok(v) => Some(v),
343
                    },
344
2
                    Some(v) => Some(v.clone()),
345
                },
346
8
                api_secret: match args.get_one::<String>("coremgr.mq.emqx.apisecret") {
347
6
                    None => match env::var("COREMGR_MQ_EMQX_APISECRET") {
348
3
                        Err(_) => None,
349
3
                        Ok(v) => Some(v),
350
                    },
351
2
                    Some(v) => Some(v.clone()),
352
                },
353
8
                hosts: match args.get_one::<String>("coremgr.mq.emqx.hosts") {
354
4
                    None => match env::var("COREMGR_MQ_EMQX_HOSTS") {
355
1
                        Err(_) => None,
356
3
                        Ok(v) => match v.len() {
357
1
                            0 => None,
358
2
                            _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
359
1
                                Err(_) => None,
360
1
                                Ok(v) => Some(v),
361
                            },
362
                        },
363
                    },
364
4
                    Some(v) => match v.len() {
365
1
                        0 => None,
366
3
                        _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
367
1
                            Err(_) => None,
368
2
                            Ok(v) => Some(v),
369
                        },
370
                    },
371
                },
372
            }),
373
            rumqttd: Some(Rumqttd {
374
8
                mqtt_port: match args.get_one::<u64>("coremgr.mq.rumqttd.mqtt-port") {
375
6
                    None => match env::var("COREMGR_MQ_RUMQTTD_MQTT_PORT") {
376
3
                        Err(_) => None,
377
3
                        Ok(v) => match v.parse::<u16>() {
378
1
                            Err(_) => None,
379
2
                            Ok(v) => Some(v),
380
                        },
381
                    },
382
2
                    Some(v) => Some(*v as u16),
383
                },
384
8
                mqtts_port: match args.get_one::<u64>("coremgr.mq.rumqttd.mqtts-port") {
385
6
                    None => match env::var("COREMGR_MQ_RUMQTTD_MQTTS_PORT") {
386
3
                        Err(_) => None,
387
3
                        Ok(v) => match v.parse::<u16>() {
388
1
                            Err(_) => None,
389
2
                            Ok(v) => Some(v),
390
                        },
391
                    },
392
2
                    Some(v) => Some(*v as u16),
393
                },
394
8
                console_port: match args.get_one::<u64>("coremgr.mq.rumqttd.console-port") {
395
6
                    None => match env::var("COREMGR_MQ_RUMQTTD_CONSOLE_PORT") {
396
3
                        Err(_) => None,
397
3
                        Ok(v) => match v.parse::<u16>() {
398
1
                            Err(_) => None,
399
2
                            Ok(v) => Some(v),
400
                        },
401
                    },
402
2
                    Some(v) => Some(*v as u16),
403
                },
404
            }),
405
        }),
406
        mq_channels: Some(MqChannels {
407
            data: Some(CoremgrData {
408
8
                url: match args.get_one::<String>("coremgr.mq-channels.data.url") {
409
6
                    None => match env::var("COREMGR_MQCHANNELS_DATA_URL") {
410
3
                        Err(_) => None,
411
3
                        Ok(v) => Some(v),
412
                    },
413
2
                    Some(v) => Some(v.clone()),
414
                },
415
8
                persistent: match args.get_one::<bool>("coremgr.mq-channels.data.persistent") {
416
5
                    None => match env::var("COREMGR_MQCHANNELS_DATA_PERSISTENT") {
417
2
                        Err(_) => None,
418
3
                        Ok(v) => match v.parse::<bool>() {
419
1
                            Err(_) => None,
420
2
                            Ok(v) => Some(v),
421
                        },
422
                    },
423
3
                    Some(v) => Some(*v as bool),
424
                },
425
            }),
426
        }),
427
    })
428
8
}
429

            
430
/// Fill missing configuration with default values.
431
19
pub fn apply_default(config: &Config) -> Config {
432
19
    Config {
433
19
        auth: match config.auth.as_ref() {
434
8
            None => Some(DEF_AUTH.to_string()),
435
11
            Some(auth) => Some(auth.clone()),
436
        },
437
19
        broker: match config.broker.as_ref() {
438
8
            None => Some(DEF_BROKER.to_string()),
439
11
            Some(broker) => Some(broker.clone()),
440
        },
441
19
        mq: match config.mq.as_ref() {
442
2
            None => Some(Mq {
443
2
                engine: Some(Engine {
444
2
                    amqp: Some(DEF_ENGINE_AMQP.to_string()),
445
2
                    mqtt: Some(DEF_ENGINE_MQTT.to_string()),
446
2
                }),
447
2
                rabbitmq: Some(RabbitMq {
448
2
                    username: Some(DEF_RABBITMQ_USERNAME.to_string()),
449
2
                    password: Some(DEF_RABBITMQ_PASSWORD.to_string()),
450
2
                    ttl: None,
451
2
                    length: None,
452
2
                    hosts: None,
453
2
                }),
454
2
                emqx: Some(Emqx {
455
2
                    api_key: Some(DEF_EMQX_API_KEY.to_string()),
456
2
                    api_secret: Some(DEF_EMQX_API_SECRET.to_string()),
457
2
                    hosts: None,
458
2
                }),
459
2
                rumqttd: Some(Rumqttd {
460
2
                    mqtt_port: Some(DEF_RUMQTTD_MQTT_PORT),
461
2
                    mqtts_port: Some(DEF_RUMQTTD_MQTTS_PORT),
462
2
                    console_port: Some(DEF_RUMQTTD_CONSOLE_PORT),
463
2
                }),
464
2
            }),
465
17
            Some(mq) => Some(Mq {
466
17
                engine: match mq.engine.as_ref() {
467
1
                    None => Some(Engine {
468
1
                        amqp: Some(DEF_ENGINE_AMQP.to_string()),
469
1
                        mqtt: Some(DEF_ENGINE_MQTT.to_string()),
470
1
                    }),
471
16
                    Some(engine) => Some(Engine {
472
16
                        amqp: match engine.amqp.as_ref() {
473
4
                            None => Some(DEF_ENGINE_AMQP.to_string()),
474
12
                            Some(amqp) => match amqp.as_str() {
475
12
                                MqEngine::RABBITMQ => Some(MqEngine::RABBITMQ.to_string()),
476
3
                                _ => Some(DEF_ENGINE_AMQP.to_string()),
477
                            },
478
                        },
479
16
                        mqtt: match engine.mqtt.as_ref() {
480
4
                            None => Some(DEF_ENGINE_MQTT.to_string()),
481
12
                            Some(mqtt) => match mqtt.as_str() {
482
12
                                MqEngine::EMQX => Some(MqEngine::EMQX.to_string()),
483
7
                                MqEngine::RUMQTTD => Some(MqEngine::RUMQTTD.to_string()),
484
2
                                _ => Some(DEF_ENGINE_MQTT.to_string()),
485
                            },
486
                        },
487
                    }),
488
                },
489
17
                rabbitmq: match mq.rabbitmq.as_ref() {
490
1
                    None => Some(RabbitMq {
491
1
                        username: Some(DEF_RABBITMQ_USERNAME.to_string()),
492
1
                        password: Some(DEF_RABBITMQ_PASSWORD.to_string()),
493
1
                        ttl: None,
494
1
                        length: None,
495
1
                        hosts: None,
496
1
                    }),
497
16
                    Some(rabbitmq) => Some(RabbitMq {
498
16
                        username: match rabbitmq.username.as_ref() {
499
5
                            None => Some(DEF_RABBITMQ_USERNAME.to_string()),
500
11
                            Some(username) => Some(username.clone()),
501
                        },
502
16
                        password: match rabbitmq.password.as_ref() {
503
5
                            None => Some(DEF_RABBITMQ_PASSWORD.to_string()),
504
11
                            Some(password) => Some(password.clone()),
505
                        },
506
16
                        ttl: rabbitmq.ttl,
507
16
                        length: rabbitmq.length,
508
16
                        hosts: match rabbitmq.hosts.as_ref() {
509
12
                            None => None,
510
4
                            Some(hosts) => Some(hosts.clone()),
511
                        },
512
                    }),
513
                },
514
17
                emqx: match mq.emqx.as_ref() {
515
1
                    None => Some(Emqx {
516
1
                        api_key: Some(DEF_EMQX_API_KEY.to_string()),
517
1
                        api_secret: Some(DEF_EMQX_API_SECRET.to_string()),
518
1
                        hosts: None,
519
1
                    }),
520
16
                    Some(emqx) => Some(Emqx {
521
16
                        api_key: match emqx.api_key.as_ref() {
522
5
                            None => Some(DEF_EMQX_API_KEY.to_string()),
523
11
                            Some(api_key) => Some(api_key.clone()),
524
                        },
525
16
                        api_secret: match emqx.api_secret.as_ref() {
526
5
                            None => Some(DEF_EMQX_API_SECRET.to_string()),
527
11
                            Some(api_secret) => Some(api_secret.clone()),
528
                        },
529
16
                        hosts: match emqx.hosts.as_ref() {
530
12
                            None => None,
531
4
                            Some(hosts) => Some(hosts.clone()),
532
                        },
533
                    }),
534
                },
535
17
                rumqttd: match mq.rumqttd.as_ref() {
536
1
                    None => Some(Rumqttd {
537
1
                        mqtt_port: Some(DEF_RUMQTTD_MQTT_PORT),
538
1
                        mqtts_port: Some(DEF_RUMQTTD_MQTTS_PORT),
539
1
                        console_port: Some(DEF_RUMQTTD_CONSOLE_PORT),
540
1
                    }),
541
16
                    Some(rumqttd) => Some(Rumqttd {
542
16
                        mqtt_port: match rumqttd.mqtt_port {
543
6
                            None => Some(DEF_RUMQTTD_MQTT_PORT),
544
10
                            Some(port) => Some(port),
545
                        },
546
16
                        mqtts_port: match rumqttd.mqtts_port {
547
6
                            None => Some(DEF_RUMQTTD_MQTTS_PORT),
548
10
                            Some(port) => Some(port),
549
                        },
550
16
                        console_port: match rumqttd.console_port {
551
6
                            None => Some(DEF_RUMQTTD_CONSOLE_PORT),
552
10
                            Some(port) => Some(port),
553
                        },
554
                    }),
555
                },
556
            }),
557
        },
558
19
        mq_channels: match config.mq_channels.as_ref() {
559
5
            None => Some(MqChannels { data: None }),
560
14
            Some(mq_channels) => Some(MqChannels {
561
14
                data: match mq_channels.data.as_ref() {
562
1
                    None => None,
563
13
                    Some(channel) => Some(CoremgrData {
564
13
                        url: match channel.url.as_ref() {
565
4
                            None => None,
566
9
                            Some(url) => Some(url.to_string()),
567
                        },
568
13
                        persistent: match channel.persistent {
569
7
                            None => Some(DEF_MQ_PERSISTENT),
570
6
                            Some(persistent) => Some(persistent),
571
                        },
572
                    }),
573
                },
574
            }),
575
        },
576
    }
577
19
}