1use std::{fmt, os::unix::net::UnixDatagram, path::{Path, PathBuf}};
15
16use crate::{common, error::SyRes, throw_error};
17
18#[cfg(feature = "build_sync")]
19pub(super) use crate::sync::socket::{SyslogTap, Tap};
20
21#[cfg(feature = "async_enabled")]
22pub use crate::a_sync::{AsyncTap, AsyncSyslogTap};
23
24#[cfg(feature = "build_sync")]
28pub trait SyslogDestination: fmt::Debug + fmt::Display + Send + Clone + SyslogDestMsg + 'static
29{
30 type SocketTap: SyslogTap<Self>;
32}
33
34#[cfg(feature = "async_enabled")]
38pub trait AsyncSyslogDestination: fmt::Debug + fmt::Display + Send + Clone + SyslogDestMsg + 'static
39{
40 type SocketTap: AsyncSyslogTap<Self>;
42}
43
44pub trait SyslogDestMsg: fmt::Debug + fmt::Display + Send + Clone + 'static
47{
48 fn get_max_msg_len(&self) -> usize;
50}
51
52
53#[derive(Debug, Clone)]
57pub struct SyslogLocal
58{
59 custom_remote_path: Option<PathBuf>,
61
62 use_alternative: bool,
64}
65
66
67impl fmt::Display for SyslogLocal
68{
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
70 {
71 write!(f, "custom_path: {:?}, alt: {}", self.custom_remote_path, self.use_alternative)
72 }
73}
74
75impl SyslogLocal
76{
77 fn new_internal(custom_path: Option<PathBuf>, use_alt_path: bool) -> SyRes<Self>
78 {
79 let remote_path: Option<PathBuf> =
80 if let Some(path) = custom_path
81 {
82 if use_alt_path == false
83 {
84 if path.exists() == false || path.is_file() == false
85 {
86 throw_error!("path either does not exists or not a file: '{}'", path.display());
87 }
88 }
89
90 Some(path.to_path_buf())
91 }
92 else
93 {
94 None
95 };
96
97 return Ok(
98 Self
99 {
100 custom_remote_path: remote_path,
101 use_alternative: use_alt_path,
102 }
103 );
104 }
105
106 pub
109 fn new() -> Self
110 {
111 return
112 Self::new_internal(None, false).unwrap();
113 }
114
115 pub
119 fn new_custom_path<P: Into<PathBuf>>(custom_path: P, use_alt_path: bool) -> SyRes<Self>
120 {
121 return
122 Self::new_internal(Some(custom_path.into()), use_alt_path);
123 }
124
125 #[inline]
126 pub
127 fn get_custom_remote_path(&self) -> Option<&Path>
128 {
129 return self.custom_remote_path.as_ref().map(|f| f.as_path());
130 }
131
132 #[inline]
133 pub
134 fn get_use_alternative(&self) -> bool
135 {
136 return self.use_alternative;
137 }
138}
139
140impl SyslogDestMsg for SyslogLocal
141{
142 fn get_max_msg_len(&self) -> usize
143 {
144 if *common::RFC5424_MAX_DGRAM >= common::MAXLINE
145 {
146 return common::MAXLINE;
147 }
148 else
149 {
150 return *common::RFC5424_MAX_DGRAM;
151 };
152 }
153}
154
155#[cfg(feature = "build_async_tokio")]
156impl AsyncSyslogDestination for SyslogLocal
157{
158 type SocketTap = AsyncTap::<tokio::net::UnixDatagram, Self>;
159
160}
161
162#[cfg(feature = "build_async_smol")]
163impl AsyncSyslogDestination for SyslogLocal
164{
165 type SocketTap = AsyncTap::<smol::net::unix::UnixDatagram, Self>;
166}
167
168#[cfg(feature = "build_sync")]
169impl SyslogDestination for SyslogLocal
170{
171 type SocketTap = Tap::<UnixDatagram, Self>;
172}
173
174#[cfg(feature = "build_ext_net")]
175pub mod imp_syslog_net
176{
177 use std::{fmt, net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream, UdpSocket}, time::Duration};
178
179 use crate::{common, error::SyRes, map_error, SyslogDestMsg};
180
181 use super::*;
182
183 #[derive(Debug, Clone)]
185 pub struct SyslogNetTcp
186 {
187 remote_addr: SocketAddr,
189
190 bind_addr: SocketAddr,
192
193 conn_timeout: Option<Duration>
195 }
196
197 impl fmt::Display for SyslogNetTcp
198 {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
200 {
201 write!(f, "remote_addr: {}, bind_addr: {}, conn_timeout: {:?}", self.remote_addr,
202 self.bind_addr, self.conn_timeout)
203 }
204 }
205
206 impl SyslogNetTcp
207 {
208 pub
220 fn new<P>(remote: P, local: Option<P>, conn_timeout: Option<Duration>) -> SyRes<Self>
221 where P: AsRef<str>
222 {
223 let remote_addr: SocketAddr =
224 remote
225 .as_ref()
226 .parse()
227 .map_err(|e|
228 map_error!("failed parsing remote addr '{}', error: '{}'", remote.as_ref(), e)
229 )?;
230
231 let bind_addr: SocketAddr =
232 if let Some(bind) = local
233 {
234 bind
235 .as_ref()
236 .parse()
237 .map_err(|e|
238 map_error!("failed parsing bind addr '{}', error: '{}'", remote.as_ref(), e)
239 )?
240 }
241 else
242 {
243 SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)
244 };
245
246 return Ok(
247 Self
248 {
249 remote_addr: remote_addr,
250 bind_addr: bind_addr,
251 conn_timeout: conn_timeout
252 }
253 );
254 }
255
256 #[inline]
257 pub
258 fn get_remote_addr(&self) -> &SocketAddr
259 {
260 return &self.remote_addr;
261 }
262
263 #[inline]
264 pub
265 fn get_bind_addr(&self) -> &SocketAddr
266 {
267 return &self.bind_addr;
268 }
269
270 #[inline]
271 pub
272 fn get_conn_timeout(&self) -> Option<Duration>
273 {
274 return self.conn_timeout;
275 }
276 }
277
278 impl SyslogDestMsg for SyslogNetTcp
279 {
280 fn get_max_msg_len(&self) -> usize
281 {
282 return common::RFC5424_TCP_MAX_PKT_LEN;
283 }
284 }
285
286 #[cfg(feature = "build_async_tokio")]
287 impl AsyncSyslogDestination for SyslogNetTcp
288 {
289 type SocketTap = AsyncTap::<tokio::net::TcpStream, Self>;
290 }
291
292 #[cfg(feature = "build_async_smol")]
293 impl AsyncSyslogDestination for SyslogNetTcp
294 {
295 type SocketTap = AsyncTap::<smol::net::TcpStream, Self>;
296 }
297
298 #[cfg(feature = "build_sync")]
299 impl SyslogDestination for SyslogNetTcp
300 {
301 type SocketTap = Tap::<TcpStream, Self>;
302 }
303
304
305 #[derive(Debug, Clone)]
307 pub struct SyslogNetUdp
308 {
309 remote_addr: SocketAddr,
310 bind_addr: SocketAddr
311 }
312
313 impl fmt::Display for SyslogNetUdp
314 {
315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
316 {
317 write!(f, "remote_addr: {}, bind_addr: {}", self.remote_addr,
318 self.bind_addr)
319 }
320 }
321
322 impl SyslogNetUdp
323 {
324 pub
333 fn new<P>(dest_addr: P, local: Option<P>) -> SyRes<Self>
334 where P: AsRef<str>
335 {
336 let remote_addr: SocketAddr =
337 dest_addr
338 .as_ref()
339 .parse()
340 .map_err(|e|
341 map_error!("failed parsing remote addr '{}', error: '{}'", dest_addr.as_ref(), e)
342 )?;
343
344 let bind_addr: SocketAddr =
345 if let Some(bind) = local
346 {
347 bind
348 .as_ref()
349 .parse()
350 .map_err(|e|
351 map_error!("failed parsing bind addr '{}', error: '{}'", dest_addr.as_ref(), e)
352 )?
353 }
354 else
355 {
356 SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)
357 };
358
359 return Ok(
360 Self
361 {
362 remote_addr: remote_addr,
363 bind_addr: bind_addr
364 }
365 );
366 }
367
368 #[inline]
369 pub
370 fn get_remote_addr(&self) -> &SocketAddr
371 {
372 return &self.remote_addr;
373 }
374
375 #[inline]
376 pub
377 fn get_bind_addr(&self) -> &SocketAddr
378 {
379 return &self.bind_addr;
380 }
381 }
382
383 impl SyslogDestMsg for SyslogNetUdp
384 {
385 fn get_max_msg_len(&self) -> usize
386 {
387 return common::RFC5424_UDP_MAX_PKT_LEN;
388 }
389 }
390
391 #[cfg(feature = "build_async_tokio")]
392 impl AsyncSyslogDestination for SyslogNetUdp
393 {
394 type SocketTap = AsyncTap::<tokio::net::UdpSocket, Self>;
395 }
396
397 #[cfg(feature = "build_async_smol")]
398 impl AsyncSyslogDestination for SyslogNetUdp
399 {
400 type SocketTap = AsyncTap::<smol::net::UdpSocket, Self>;
401 }
402
403 #[cfg(feature = "build_sync")]
404 impl SyslogDestination for SyslogNetUdp
405 {
406 type SocketTap = Tap::<UdpSocket, Self>;
407 }
408}
409
410#[cfg(feature = "build_ext_net")]
411pub use self::imp_syslog_net::SyslogNetTcp;
412
413#[cfg(feature = "build_ext_net")]
414pub use self::imp_syslog_net::SyslogNetUdp;
415
416#[cfg(feature = "build_ext_file")]
417pub mod imp_syslog_file
418{
419 use std::{fmt, fs::File, path::{Path, PathBuf}};
420
421 use crate::{common};
422
423 use super::*;
424
425 #[derive(Debug, Clone)]
427 pub struct SyslogFile
428 {
429 file_path: PathBuf
431 }
432
433 impl fmt::Display for SyslogFile
434 {
435 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
436 {
437 write!(f, "<file> path: {}", self.file_path.display())
438 }
439 }
440
441 impl SyslogFile
442 {
443 pub
445 fn new<P: Into<PathBuf>>(dest_path: P) -> Self
446 {
447 return
448 Self
449 {
450 file_path: dest_path.into()
451 };
452 }
453
454 #[inline]
455 pub
456 fn get_path(&self) -> &Path
457 {
458 return self.file_path.as_path();
459 }
460 }
461
462 impl SyslogDestMsg for SyslogFile
463 {
464 fn get_max_msg_len(&self) -> usize
465 {
466 if *common::RFC5424_MAX_DGRAM >= common::MAXLINE
467 {
468 return common::MAXLINE;
469 }
470 else
471 {
472 return *common::RFC5424_MAX_DGRAM;
473 };
474 }
475 }
476
477 #[cfg(feature = "build_async_tokio")]
478 impl AsyncSyslogDestination for SyslogFile
479 {
480 type SocketTap = AsyncTap::<tokio::fs::File, Self>;
481 }
482
483 #[cfg(feature = "build_async_smol")]
484 impl AsyncSyslogDestination for SyslogFile
485 {
486 type SocketTap = AsyncTap::<smol::fs::File, Self>;
487 }
488
489 #[cfg(feature = "build_sync")]
490 impl SyslogDestination for SyslogFile
491 {
492 type SocketTap = Tap::<File, Self>;
493 }
494}
495
496#[cfg(feature = "build_ext_file")]
497pub use self::imp_syslog_file::SyslogFile;
498
499#[cfg(feature = "build_ext_tls")]
500pub mod imp_syslog_tls
501{
502 use std::fmt;
503 use std::{net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream}, sync::Arc, time::Duration};
504
505 use rustls::{pki_types::{CertificateDer, ServerName}, ClientConfig, ClientConnection, RootCertStore, StreamOwned};
506
507 use crate::{common, error::SyRes, map_error};
508
509 use super::*;
510
511 #[derive(Debug, Clone)]
513 pub struct SyslogTls
514 {
515 remote_addr: SocketAddr,
517
518 bind_addr: SocketAddr,
520
521 serv_name: ServerName<'static>,
523
524 client_config: Arc<ClientConfig>,
526
527 conn_timeout: Option<Duration>,
529 }
530
531 impl fmt::Display for SyslogTls
532 {
533 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
534 {
535 write!(f, "remote: {}, bind: {}, serv_name: {:?}, client: {:?}, conn_timeout: {:?}", self.remote_addr,
536 self.bind_addr, self.serv_name, self.client_config, self.conn_timeout)
537 }
538 }
539
540 impl SyslogTls
541 {
542 pub
558 fn new<P>(remote: P, local: Option<P>, serv_name: impl Into<String>,
559 root_cert: Vec<u8>, conn_timeout: Option<Duration>) -> SyRes<Self>
560 where P: AsRef<str>
561 {
562 use rustls::pki_types::pem::PemObject;
563
564 let server_name = serv_name.into();
565
566 let remote_addr: SocketAddr =
567 remote
568 .as_ref()
569 .parse()
570 .map_err(|e|
571 map_error!("failed parsing remote addr '{}', error: '{}'", remote.as_ref(), e)
572 )?;
573
574 let cert =
575 CertificateDer::from_pem_slice(root_cert.as_slice())
576 .map_err(|e|
577 map_error!("certificate parse error: '{}'", e)
578 )?;
579
580 let mut root_store = RootCertStore::empty();
581 root_store
582 .add(cert)
583 .map_err(|e|
584 map_error!("can not add root ceritficate, error: '{}'", e)
585 )?;
586
587 let serv_name =
588 server_name
589 .try_into()
590 .map_err(|e|
591 map_error!("server name error: '{}'", e)
592 )?;
593
594 let client_config =
595 rustls::ClientConfig::builder()
596 .with_root_certificates(root_store)
597 .with_no_client_auth();
598
599 let bind_addr: SocketAddr =
600 if let Some(bind) = local
601 {
602 bind
603 .as_ref()
604 .parse()
605 .map_err(|e|
606 map_error!("failed parsing bind addr '{}', error: '{}'", remote.as_ref(), e)
607 )?
608 }
609 else
610 {
611 SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)
612 };
613
614 return Ok(
615 Self
616 {
617 remote_addr: remote_addr,
618 bind_addr: bind_addr,
619 serv_name: serv_name,
620 client_config: Arc::new(client_config),
621 conn_timeout: conn_timeout,
622 }
623 );
624 }
625
626 #[inline]
627 pub
628 fn get_remote_addr(&self) -> &SocketAddr
629 {
630 return &self.remote_addr;
631 }
632
633 #[inline]
634 pub
635 fn get_bind_addr(&self) -> &SocketAddr
636 {
637 return &self.bind_addr;
638 }
639
640 #[inline]
641 pub
642 fn get_serv_name(&self) -> ServerName<'static>
643 {
644 return self.serv_name.clone();
645 }
646
647 #[inline]
648 pub
649 fn get_client_config(&self) -> Arc<ClientConfig>
650 {
651 return self.client_config.clone();
652 }
653
654 #[inline]
655 pub
656 fn get_get_conn_timeout(&self) -> Option<Duration>
657 {
658 return self.conn_timeout.clone();
659 }
660 }
661
662 impl SyslogDestMsg for SyslogTls
663 {
664 fn get_max_msg_len(&self) -> usize
665 {
666 return common::RFC5424_TCP_MAX_PKT_LEN;
667 }
668 }
669
670 #[cfg(feature = "build_async_tokio")]
671 impl AsyncSyslogDestination for SyslogTls
672 {
673 type SocketTap = AsyncTap::<tokio_rustls::client::TlsStream<tokio::net::TcpStream>, Self>;
674 }
675
676 #[cfg(feature = "build_async_smol")]
677 impl AsyncSyslogDestination for SyslogTls
678 {
679 type SocketTap = AsyncTap::<futures_rustls::client::TlsStream<smol::net::TcpStream>, Self>;
680 }
681
682 #[cfg(feature = "build_sync")]
683 impl SyslogDestination for SyslogTls
684 {
685 type SocketTap = Tap::<StreamOwned<ClientConnection, TcpStream>, Self>;
686 }
687}
688
689#[cfg(feature = "build_ext_tls")]
690pub use self::imp_syslog_tls::SyslogTls;