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
14
pub fn reg_args(cmd: Command) -> Command {
134
14
    cmd.arg(
135
14
        Arg::new("coremgr.auth")
136
14
            .long("coremgr.auth")
137
14
            .help("sylvia-iot-auth host (ex: http://localhost:1080/auth)")
138
14
            .num_args(1),
139
14
    )
140
14
    .arg(
141
14
        Arg::new("coremgr.broker")
142
14
            .long("coremgr.broker")
143
14
            .help("sylvia-iot-broker host (ex: http://localhost:2080/broker)")
144
14
            .num_args(1),
145
14
    )
146
14
    .arg(
147
14
        Arg::new("coremgr.mq.engine.amqp")
148
14
            .long("coremgr.mq.engine.amqp")
149
14
            .help("AMQP broker")
150
14
            .num_args(1)
151
14
            .value_parser([MqEngine::RABBITMQ]),
152
14
    )
153
14
    .arg(
154
14
        Arg::new("coremgr.mq.engine.mqtt")
155
14
            .long("coremgr.mq.engine.mqtt")
156
14
            .help("MQTT broker")
157
14
            .num_args(1)
158
14
            .value_parser([MqEngine::EMQX, MqEngine::RUMQTTD]),
159
14
    )
160
14
    .arg(
161
14
        Arg::new("coremgr.mq.rabbitmq.username")
162
14
            .long("coremgr.mq.rabbitmq.username")
163
14
            .help("RabbitMQ configurations: management user name")
164
14
            .num_args(1),
165
14
    )
166
14
    .arg(
167
14
        Arg::new("coremgr.mq.rabbitmq.password")
168
14
            .long("coremgr.mq.rabbitmq.password")
169
14
            .help("RabbitMQ configurations: management password")
170
14
            .num_args(1),
171
14
    )
172
14
    .arg(
173
14
        Arg::new("coremgr.mq.rabbitmq.ttl")
174
14
            .long("coremgr.mq.rabbitmq.ttl")
175
14
            .help("RabbitMQ configurations: message TTL in milliseconds")
176
14
            .num_args(1)
177
14
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
178
14
    )
179
14
    .arg(
180
14
        Arg::new("coremgr.mq.rabbitmq.length")
181
14
            .long("coremgr.mq.rabbitmq.length")
182
14
            .help("RabbitMQ configurations: queue length")
183
14
            .num_args(1)
184
14
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=usize::MAX as u64)),
185
14
    )
186
14
    .arg(
187
14
        Arg::new("coremgr.mq.rabbitmq.hosts")
188
14
            .long("coremgr.mq.rabbitmq.hosts")
189
14
            .help("RabbitMQ hosts")
190
14
            .num_args(1),
191
14
    )
192
14
    .arg(
193
14
        Arg::new("coremgr.mq.emqx.apikey")
194
14
            .long("coremgr.mq.emqx.apikey")
195
14
            .help("EMQX configurations: management API key")
196
14
            .num_args(1),
197
14
    )
198
14
    .arg(
199
14
        Arg::new("coremgr.mq.emqx.apisecret")
200
14
            .long("coremgr.mq.emqx.apisecret")
201
14
            .help("EMQX configurations: management API secret")
202
14
            .num_args(1),
203
14
    )
204
14
    .arg(
205
14
        Arg::new("coremgr.mq.emqx.hosts")
206
14
            .long("coremgr.mq.emqx.hosts")
207
14
            .help("EMQX hosts")
208
14
            .num_args(1),
209
14
    )
210
14
    .arg(
211
14
        Arg::new("coremgr.mq.rumqttd.mqtt-port")
212
14
            .long("coremgr.mq.rumqttd.mqtt-port")
213
14
            .help("rumqttd MQTT listen port")
214
14
            .num_args(1)
215
14
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
216
14
    )
217
14
    .arg(
218
14
        Arg::new("coremgr.mq.rumqttd.mqtts-port")
219
14
            .long("coremgr.mq.rumqttd.mqtts-port")
220
14
            .help("rumqttd MQTTS listen port")
221
14
            .num_args(1)
222
14
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
223
14
    )
224
14
    .arg(
225
14
        Arg::new("coremgr.mq.rumqttd.console-port")
226
14
            .long("coremgr.mq.rumqttd.console-port")
227
14
            .help("rumqttd console listen port")
228
14
            .num_args(1)
229
14
            .value_parser(RangedU64ValueParser::<u64>::new().range(1..=65535)),
230
14
    )
231
14
    .arg(
232
14
        Arg::new("coremgr.mq-channels.data.url")
233
14
            .long("coremgr.mq-channels.data.url")
234
14
            .help("URL of `coremgr.data` channel")
235
14
            .num_args(1),
236
14
    )
237
14
    .arg(
238
14
        Arg::new("coremgr.mq-channels.data.persistent")
239
14
            .long("coremgr.mq-channels.data.persistent")
240
14
            .help("AMQP persistent for `coremgr.data` channel")
241
14
            .num_args(1)
242
14
            .value_parser(BoolValueParser::new()),
243
14
    )
244
14
}
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
16
pub fn read_args(args: &ArgMatches) -> Config {
251
16
    apply_default(&Config {
252
16
        auth: match args.get_one::<String>("coremgr.auth") {
253
12
            None => match env::var("COREMGR_AUTH") {
254
6
                Err(_) => None,
255
6
                Ok(v) => Some(v),
256
            },
257
4
            Some(v) => Some(v.clone()),
258
        },
259
16
        broker: match args.get_one::<String>("coremgr.broker") {
260
12
            None => match env::var("COREMGR_BROKER") {
261
6
                Err(_) => None,
262
6
                Ok(v) => Some(v),
263
            },
264
4
            Some(v) => Some(v.clone()),
265
        },
266
        mq: Some(Mq {
267
            engine: Some(Engine {
268
16
                amqp: match args.get_one::<String>("coremgr.mq.engine.amqp") {
269
12
                    None => match env::var("COREMGR_MQ_ENGINE_AMQP") {
270
6
                        Err(_) => None,
271
6
                        Ok(v) => Some(v),
272
                    },
273
4
                    Some(v) => Some(v.clone()),
274
                },
275
16
                mqtt: match args.get_one::<String>("coremgr.mq.engine.mqtt") {
276
12
                    None => match env::var("COREMGR_MQ_ENGINE_MQTT") {
277
6
                        Err(_) => None,
278
6
                        Ok(v) => Some(v),
279
                    },
280
4
                    Some(v) => Some(v.clone()),
281
                },
282
            }),
283
            rabbitmq: Some(RabbitMq {
284
16
                username: match args.get_one::<String>("coremgr.mq.rabbitmq.username") {
285
12
                    None => match env::var("COREMGR_MQ_RABBITMQ_USERNAME") {
286
6
                        Err(_) => None,
287
6
                        Ok(v) => Some(v),
288
                    },
289
4
                    Some(v) => Some(v.clone()),
290
                },
291
16
                password: match args.get_one::<String>("coremgr.mq.rabbitmq.password") {
292
12
                    None => match env::var("COREMGR_MQ_RABBITMQ_PASSWORD") {
293
6
                        Err(_) => None,
294
6
                        Ok(v) => Some(v),
295
                    },
296
4
                    Some(v) => Some(v.clone()),
297
                },
298
16
                ttl: match args.get_one::<u64>("coremgr.mq.rabbitmq.ttl") {
299
12
                    None => match env::var("COREMGR_MQ_RABBITMQ_TTL") {
300
6
                        Err(_) => None,
301
6
                        Ok(v) => match v.parse::<usize>() {
302
2
                            Err(_) => None,
303
4
                            Ok(v) => Some(v),
304
                        },
305
                    },
306
4
                    Some(v) => Some(*v as usize),
307
                },
308
16
                length: match args.get_one::<u64>("coremgr.mq.rabbitmq.length") {
309
12
                    None => match env::var("COREMGR_MQ_RABBITMQ_LENGTH") {
310
6
                        Err(_) => None,
311
6
                        Ok(v) => match v.parse::<usize>() {
312
2
                            Err(_) => None,
313
4
                            Ok(v) => Some(v),
314
                        },
315
                    },
316
4
                    Some(v) => Some(*v as usize),
317
                },
318
16
                hosts: match args.get_one::<String>("coremgr.mq.rabbitmq.hosts") {
319
8
                    None => match env::var("COREMGR_MQ_RABBITMQ_HOSTS") {
320
2
                        Err(_) => None,
321
6
                        Ok(v) => match v.len() {
322
2
                            0 => None,
323
4
                            _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
324
2
                                Err(_) => None,
325
2
                                Ok(v) => Some(v),
326
                            },
327
                        },
328
                    },
329
8
                    Some(v) => match v.len() {
330
2
                        0 => None,
331
6
                        _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
332
2
                            Err(_) => None,
333
4
                            Ok(v) => Some(v),
334
                        },
335
                    },
336
                },
337
            }),
338
            emqx: Some(Emqx {
339
16
                api_key: match args.get_one::<String>("coremgr.mq.emqx.apikey") {
340
12
                    None => match env::var("COREMGR_MQ_EMQX_APIKEY") {
341
6
                        Err(_) => None,
342
6
                        Ok(v) => Some(v),
343
                    },
344
4
                    Some(v) => Some(v.clone()),
345
                },
346
16
                api_secret: match args.get_one::<String>("coremgr.mq.emqx.apisecret") {
347
12
                    None => match env::var("COREMGR_MQ_EMQX_APISECRET") {
348
6
                        Err(_) => None,
349
6
                        Ok(v) => Some(v),
350
                    },
351
4
                    Some(v) => Some(v.clone()),
352
                },
353
16
                hosts: match args.get_one::<String>("coremgr.mq.emqx.hosts") {
354
8
                    None => match env::var("COREMGR_MQ_EMQX_HOSTS") {
355
2
                        Err(_) => None,
356
6
                        Ok(v) => match v.len() {
357
2
                            0 => None,
358
4
                            _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
359
2
                                Err(_) => None,
360
2
                                Ok(v) => Some(v),
361
                            },
362
                        },
363
                    },
364
8
                    Some(v) => match v.len() {
365
2
                        0 => None,
366
6
                        _ => match serde_json::from_str::<Vec<MqHost>>(v.as_str()) {
367
2
                            Err(_) => None,
368
4
                            Ok(v) => Some(v),
369
                        },
370
                    },
371
                },
372
            }),
373
            rumqttd: Some(Rumqttd {
374
16
                mqtt_port: match args.get_one::<u64>("coremgr.mq.rumqttd.mqtt-port") {
375
12
                    None => match env::var("COREMGR_MQ_RUMQTTD_MQTT_PORT") {
376
6
                        Err(_) => None,
377
6
                        Ok(v) => match v.parse::<u16>() {
378
2
                            Err(_) => None,
379
4
                            Ok(v) => Some(v),
380
                        },
381
                    },
382
4
                    Some(v) => Some(*v as u16),
383
                },
384
16
                mqtts_port: match args.get_one::<u64>("coremgr.mq.rumqttd.mqtts-port") {
385
12
                    None => match env::var("COREMGR_MQ_RUMQTTD_MQTTS_PORT") {
386
6
                        Err(_) => None,
387
6
                        Ok(v) => match v.parse::<u16>() {
388
2
                            Err(_) => None,
389
4
                            Ok(v) => Some(v),
390
                        },
391
                    },
392
4
                    Some(v) => Some(*v as u16),
393
                },
394
16
                console_port: match args.get_one::<u64>("coremgr.mq.rumqttd.console-port") {
395
12
                    None => match env::var("COREMGR_MQ_RUMQTTD_CONSOLE_PORT") {
396
6
                        Err(_) => None,
397
6
                        Ok(v) => match v.parse::<u16>() {
398
2
                            Err(_) => None,
399
4
                            Ok(v) => Some(v),
400
                        },
401
                    },
402
4
                    Some(v) => Some(*v as u16),
403
                },
404
            }),
405
        }),
406
        mq_channels: Some(MqChannels {
407
            data: Some(CoremgrData {
408
16
                url: match args.get_one::<String>("coremgr.mq-channels.data.url") {
409
12
                    None => match env::var("COREMGR_MQCHANNELS_DATA_URL") {
410
6
                        Err(_) => None,
411
6
                        Ok(v) => Some(v),
412
                    },
413
4
                    Some(v) => Some(v.clone()),
414
                },
415
16
                persistent: match args.get_one::<bool>("coremgr.mq-channels.data.persistent") {
416
10
                    None => match env::var("COREMGR_MQCHANNELS_DATA_PERSISTENT") {
417
4
                        Err(_) => None,
418
6
                        Ok(v) => match v.parse::<bool>() {
419
2
                            Err(_) => None,
420
4
                            Ok(v) => Some(v),
421
                        },
422
                    },
423
6
                    Some(v) => Some(*v as bool),
424
                },
425
            }),
426
        }),
427
    })
428
16
}
429

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