|
18 | 18 | use std::collections::BTreeMap;
|
19 | 19 |
|
20 | 20 | use tokio::sync::{broadcast, mpsc};
|
21 |
| -use tracing::{debug, info, warn}; |
| 21 | +use tracing::{info, warn}; |
22 | 22 |
|
23 | 23 | use orion_configuration::config::{
|
24 | 24 | network_filters::http_connection_manager::RouteConfiguration, Listener as ListenerConfig,
|
@@ -122,19 +122,18 @@ impl ListenersManager {
|
122 | 122 | let listener_name = listener.get_name();
|
123 | 123 | let (addr, dev) = listener.get_socket();
|
124 | 124 | info!("Listener {} at {addr} (device bind:{})", listener_name, dev.is_some());
|
| 125 | + |
| 126 | + // Check if listener with same name already exists |
| 127 | + if self.listener_handles.contains_key(&listener_name) { |
| 128 | + warn!("Listener {listener_name} already exists, rejecting new listener to avoid breaking existing connections"); |
| 129 | + return Err(format!("Listener with name '{}' already exists", listener_name).into()); |
| 130 | + } |
| 131 | + |
125 | 132 | // spawn the task for this listener address, this will spawn additional task per connection
|
126 | 133 | let join_handle = tokio::spawn(async move {
|
127 | 134 | let error = listener.start().await;
|
128 | 135 | warn!("Listener {listener_name} exited: {error}");
|
129 | 136 | });
|
130 |
| - #[cfg(debug_assertions)] |
131 |
| - if self.listener_handles.contains_key(&listener_name) { |
132 |
| - debug!("Listener {listener_name} already exists, replacing it"); |
133 |
| - } |
134 |
| - // note: join handle gets overwritten here if it already exists. |
135 |
| - // handles are abort on drop so will be aborted, closing the socket |
136 |
| - // but the any tasks spawned within this task, which happens on a per-connection basis, |
137 |
| - // will survive past this point and only get dropped when their session ends |
138 | 137 | self.listener_handles.insert(listener_name, ListenerInfo::new(join_handle, listener_conf));
|
139 | 138 |
|
140 | 139 | Ok(())
|
@@ -186,17 +185,14 @@ mod tests {
|
186 | 185 | assert!(routeb_tx1.send(RouteConfigurationChange::Removed("n/a".into())).is_ok());
|
187 | 186 | tokio::task::yield_now().await;
|
188 | 187 |
|
189 |
| - let (routeb_tx2, routeb_rx) = broadcast::channel(chan); |
| 188 | + let (_routeb_tx2, routeb_rx) = broadcast::channel(chan); |
190 | 189 | let (_secb_tx2, secb_rx) = broadcast::channel(chan);
|
191 | 190 | let l2 = Listener::test_listener(name, routeb_rx, secb_rx);
|
192 | 191 | let l2_info = l1_info;
|
193 |
| - man.start_listener(l2, l2_info).unwrap(); |
194 |
| - assert!(routeb_tx2.send(RouteConfigurationChange::Removed("n/a".into())).is_ok()); |
195 |
| - tokio::task::yield_now().await; |
196 |
| - |
197 |
| - // This should fail because the old listener exited already dropping the rx |
198 |
| - assert!(routeb_tx1.send(RouteConfigurationChange::Removed("n/a".into())).is_err()); |
199 |
| - // Yield once more just in case more logs can be seen |
| 192 | + // Second start should fail because listener with same name already exists |
| 193 | + assert!(man.start_listener(l2, l2_info).is_err()); |
| 194 | + // The first listener should still be active |
| 195 | + assert!(routeb_tx1.send(RouteConfigurationChange::Removed("n/a".into())).is_ok()); |
200 | 196 | tokio::task::yield_now().await;
|
201 | 197 | }
|
202 | 198 |
|
|
0 commit comments