lstngrp

Check-in Differences
Login

Check-in Differences

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Difference From lstngrp-0.0.4 To lstngrp-0.0.5

2024-10-02
18:36
Release maintenance. Leaf check-in: 641db927fd user: jan tags: lstngrp-0.0.5, trunk
18:32
Fixed renamed type name. check-in: d2e1fea4d3 user: jan tags: trunk
15:49
Update change log. check-in: 77a8709ec0 user: jan tags: trunk
2024-09-20
13:04
Fix docs. check-in: 328cbfb7c7 user: jan tags: lstngrp-0.0.4, trunk
12:56
Update idbag to 0.2.0. check-in: 45e048243f user: jan tags: trunk

Changes to Cargo.toml.

1
2
3
4
5
6
7
8
9
10
[package]
name = "lstngrp"
version = "0.0.4"
edition = "2021"
license = "0BSD"
# https://crates.io/category_slugs
categories = [ "network-programming", "asynchronous" ]
keywords = [ "network", "server", "listen", "protwrap" ]
repository = "https://repos.qrnch.tech/pub/lstngrp"
description = "Groups listeners and connections with common data/logic."


|







1
2
3
4
5
6
7
8
9
10
[package]
name = "lstngrp"
version = "0.0.5"
edition = "2021"
license = "0BSD"
# https://crates.io/category_slugs
categories = [ "network-programming", "asynchronous" ]
keywords = [ "network", "server", "listen", "protwrap" ]
repository = "https://repos.qrnch.tech/pub/lstngrp"
description = "Groups listeners and connections with common data/logic."
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
]

# https://doc.rust-lang.org/cargo/reference/manifest.html#the-badges-section
[badges]
maintenance = { status = "experimental" }

[dependencies]
hashbrown = { version = "0.14.5" }
idbag = { version = "0.2.0" }
killswitch = { version = "0.4.2" }
parking_lot = { version = "0.12.3" }
protwrap = { version = "0.3.0", features = [
  "tls", "tokio"
] }
tokio = { version = "1.40.0", features = [
  "macros", "net", "rt", "sync"







|
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
]

# https://doc.rust-lang.org/cargo/reference/manifest.html#the-badges-section
[badges]
maintenance = { status = "experimental" }

[dependencies]
hashbrown = { version = "0.15.0" }
idbag = { version = "0.2.1" }
killswitch = { version = "0.4.2" }
parking_lot = { version = "0.12.3" }
protwrap = { version = "0.3.0", features = [
  "tls", "tokio"
] }
tokio = { version = "1.40.0", features = [
  "macros", "net", "rt", "sync"

Changes to README.md.

1
2
3
4
5
# lstngrp

`ListenerGroup` is meant to collect a group of network listeners into a single
entity, and help track connections made against those listeners.



|


1
2
3
4
5
# lstngrp

`ListenGroup` is meant to collect a group of network listeners into a single
entity, and help track connections made against those listeners.

Changes to examples/per_listener_ctx.rs.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use std::{str::FromStr, sync::Arc};

use parking_lot::Mutex;

use hashbrown::HashMap;

use lstngrp::{
  async_trait, ArcId, ConnHandler, ConnInfo, GroupHandler, ListenGroup,
  Listener, ListenerSpec, SockAddr, Stream
};

struct ListenCtx {
  name: String
}








|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use std::{str::FromStr, sync::Arc};

use parking_lot::Mutex;

use hashbrown::HashMap;

use lstngrp::{
  async_trait, ArcIdUsize, ConnHandler, ConnInfo, GroupHandler, ListenGroup,
  Listener, ListenerSpec, SockAddr, Stream
};

struct ListenCtx {
  name: String
}

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
    }
  }
}


struct MyConnHandler {
  listen_id: i64,
  conn_id: ArcId
}

#[async_trait]
impl ConnHandler for MyConnHandler {
  async fn run(&self, _conn: Stream) {
    println!(
      "Run connection {} from listener={}",







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
    }
  }
}


struct MyConnHandler {
  listen_id: i64,
  conn_id: ArcIdUsize
}

#[async_trait]
impl ConnHandler for MyConnHandler {
  async fn run(&self, _conn: Stream) {
    println!(
      "Run connection {} from listener={}",

Changes to examples/simple.rs.

1
2
3
4
5
6
7
8
9
10
11
use std::str::FromStr;

use lstngrp::{
  async_trait, ArcId, ConnHandler, ConnInfo, GroupHandler, ListenGroup,
  Listener, ListenerSpec, SockAddr, Stream
};

struct MyHandler {}

#[async_trait]
impl GroupHandler for MyHandler {



|







1
2
3
4
5
6
7
8
9
10
11
use std::str::FromStr;

use lstngrp::{
  async_trait, ArcIdUsize, ConnHandler, ConnInfo, GroupHandler, ListenGroup,
  Listener, ListenerSpec, SockAddr, Stream
};

struct MyHandler {}

#[async_trait]
impl GroupHandler for MyHandler {
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    }
  }
}


struct MyConnHandler {
  listen_id: i64,
  conn_id: ArcId
}

#[async_trait]
impl ConnHandler for MyConnHandler {
  async fn run(&self, _conn: Stream) {
    println!(
      "Run connection {} from listener={}",







|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    }
  }
}


struct MyConnHandler {
  listen_id: i64,
  conn_id: ArcIdUsize
}

#[async_trait]
impl ConnHandler for MyConnHandler {
  async fn run(&self, _conn: Stream) {
    println!(
      "Run connection {} from listener={}",

Changes to src/lib.rs.

55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use hashbrown::HashMap;

pub use protwrap::tokio::server::{
  listener::{async_trait, Listener, SockAddr},
  Stream
};

pub use idbag::ArcIdUsize as ArcId;

use idbag::IdBagUsize as IdBag;

use conn::ConnectionData;

use listener::{ListenData, ListenTaskParams};


/// Internal alias for a `GroupHandler` with a generic listener identifier and
/// connection handler.
type LCHandler<LI, CC> =
  dyn GroupHandler<ListenIdent = LI, ConnHandler = CC> + Send + Sync + 'static;


/// Context passed to [`GroupHandler::connected()`] used to pass connection
/// (metadata) information.
#[derive(Clone)]
pub struct ConnInfo {
  /// The connecting client's address.
  pub sa: Arc<SockAddr>,

  /// The unique client connection id.
  pub id: ArcId
}


/// Group listener handler.
#[async_trait]
pub trait GroupHandler {
  /// Unique listener identifier type.







|
>
|




















|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use hashbrown::HashMap;

pub use protwrap::tokio::server::{
  listener::{async_trait, Listener, SockAddr},
  Stream
};

pub use idbag::ArcIdUsize;

use idbag::IdBagUsize;

use conn::ConnectionData;

use listener::{ListenData, ListenTaskParams};


/// Internal alias for a `GroupHandler` with a generic listener identifier and
/// connection handler.
type LCHandler<LI, CC> =
  dyn GroupHandler<ListenIdent = LI, ConnHandler = CC> + Send + Sync + 'static;


/// Context passed to [`GroupHandler::connected()`] used to pass connection
/// (metadata) information.
#[derive(Clone)]
pub struct ConnInfo {
  /// The connecting client's address.
  pub sa: Arc<SockAddr>,

  /// The unique client connection id.
  pub id: ArcIdUsize
}


/// Group listener handler.
#[async_trait]
pub trait GroupHandler {
  /// Unique listener identifier type.
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  LI: Hash + Eq
{
  /// Keep track of all listeners, identified by `LI` and all their active
  /// connections, identified by an `ArcId`, with their connection context,
  /// identified by `CC`.
  lmap: Arc<Mutex<HashMap<LI, ListenData>>>,

  cmap: Arc<Mutex<HashMap<ArcId, ConnectionData<LI, CC>>>>,

  /// Connection handler used by all the listeners within this group.
  lhandler: Arc<LCHandler<LI, CC>>,

  idbag: Arc<IdBag>,

  shutdown: Arc<AtomicBool>
}


impl<LI, CC> ListenGroup<LI, CC>
where
  LI: Hash + Eq + Send + Sync + Clone + 'static,
  CC: ConnHandler + Send + Sync + 'static
{
  /// Create a new listener group.
  pub fn new(
    handler: impl GroupHandler<ListenIdent = LI, ConnHandler = CC>
      + Send
      + Sync
      + 'static
  ) -> Self {
    // ToDo: Allow this to be passed in from the application
    let idbag = Arc::new(IdBag::new());

    Self {
      lmap: Arc::new(Mutex::new(HashMap::new())),
      lhandler: Arc::new(handler),
      cmap: Arc::new(Mutex::new(HashMap::new())),
      idbag,
      shutdown: Arc::new(AtomicBool::new(false))







|




|


















|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  LI: Hash + Eq
{
  /// Keep track of all listeners, identified by `LI` and all their active
  /// connections, identified by an `ArcId`, with their connection context,
  /// identified by `CC`.
  lmap: Arc<Mutex<HashMap<LI, ListenData>>>,

  cmap: Arc<Mutex<HashMap<ArcIdUsize, ConnectionData<LI, CC>>>>,

  /// Connection handler used by all the listeners within this group.
  lhandler: Arc<LCHandler<LI, CC>>,

  idbag: Arc<IdBagUsize>,

  shutdown: Arc<AtomicBool>
}


impl<LI, CC> ListenGroup<LI, CC>
where
  LI: Hash + Eq + Send + Sync + Clone + 'static,
  CC: ConnHandler + Send + Sync + 'static
{
  /// Create a new listener group.
  pub fn new(
    handler: impl GroupHandler<ListenIdent = LI, ConnHandler = CC>
      + Send
      + Sync
      + 'static
  ) -> Self {
    // ToDo: Allow this to be passed in from the application
    let idbag = Arc::new(IdBagUsize::new());

    Self {
      lmap: Arc::new(Mutex::new(HashMap::new())),
      lhandler: Arc::new(handler),
      cmap: Arc::new(Mutex::new(HashMap::new())),
      idbag,
      shutdown: Arc::new(AtomicBool::new(false))
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
    }
  }

  /// Terminate a connection given a connection identifier.
  ///
  /// This function will not return until the background connection task has
  /// terminated.
  pub async fn kill_connection(&self, cid: ArcId) {
    // Extraction of join handle placed in a scope so that clippy doesn't think
    // the lock is held over an await point.
    let mut jh = {
      let mut cmap = self.cmap.lock();
      let Some(cdata) = cmap.get_mut(&cid) else {
        // No such id found
        return;







|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
    }
  }

  /// Terminate a connection given a connection identifier.
  ///
  /// This function will not return until the background connection task has
  /// terminated.
  pub async fn kill_connection(&self, cid: ArcIdUsize) {
    // Extraction of join handle placed in a scope so that clippy doesn't think
    // the lock is held over an await point.
    let mut jh = {
      let mut cmap = self.cmap.lock();
      let Some(cdata) = cmap.get_mut(&cid) else {
        // No such id found
        return;
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  pub conns: Vec<CInfo<CC>>
}

/// Information returned about a connection when a listen group's current state
/// is inspected.
pub struct CInfo<CC> {
  /// The client connection's internal identifier.
  pub id: ArcId,

  /// The client connection handler.
  pub chandler: Arc<CC>
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :







|






446
447
448
449
450
451
452
453
454
455
456
457
458
459
  pub conns: Vec<CInfo<CC>>
}

/// Information returned about a connection when a listen group's current state
/// is inspected.
pub struct CInfo<CC> {
  /// The client connection's internal identifier.
  pub id: ArcIdUsize,

  /// The client connection handler.
  pub chandler: Arc<CC>
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :

Changes to www/changelog.md.

1
2
3
4
5
6












7











8
9
10
11
12
13
14
# Change Log

⚠️  indicates a breaking change.

## [Unreleased]













[Details](/vdiff?from=lstngrp-0.0.3&to=trunk)












### Added

- Support automatically closing connections when a listener is removed.

### Changed







>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Change Log

⚠️  indicates a breaking change.

## [Unreleased]

[Details](/vdiff?from=lstngrp-0.0.5&to=trunk)

### Added

### Changed

### Removed

---

## [0.0.5] - 2024-10-02

[Details](/vdiff?from=lstngrp-0.0.4&to=lstngrp-0.0.5)

### Changed

- No longer rename `ArcIdUsize` to `ArcId` for the export, because it turned
  out to cause confusion.

---

## [0.0.4] - 2024-09-20

[Details](/vdiff?from=lstngrp-0.0.3&to=lstngrp-0.0.4)

### Added

- Support automatically closing connections when a listener is removed.

### Changed

Changes to www/index.md.

1
2
3
4
5
6
7
8
9
10
# lstngrp

`ListenerGroup` is meant to collect a group of network listeners into a single
entity, and help track connections made against those listeners.


## Change log

The details of changes can always be found in the timeline, but for a
high-level view of changes between released versions there's a manually


|







1
2
3
4
5
6
7
8
9
10
# lstngrp

`ListenGroup` is meant to collect a group of network listeners into a single
entity, and help track connections made against those listeners.


## Change log

The details of changes can always be found in the timeline, but for a
high-level view of changes between released versions there's a manually