diff --git a/veilid-cli/src/command_processor.rs b/veilid-cli/src/command_processor.rs index c6ab46c7..6225d5d2 100644 --- a/veilid-cli/src/command_processor.rs +++ b/veilid-cli/src/command_processor.rs @@ -482,15 +482,26 @@ reply reply to an AppCall not handled directly by } } + let (message, truncated) = if message.len() > 64 { + (&message[0..64], true) + } else { + (&message[..], false) + }; + let strmsg = if printable { - String::from_utf8_lossy(&message).to_string() + format!("\"{}\"", String::from_utf8_lossy(&message).to_string()) } else { hex::encode(message) }; self.inner().ui_sender.add_node_event( Level::Info, - format!("AppMessage ({:?}): {}", msg["sender"], strmsg), + format!( + "AppMessage ({:?}): {}{}", + msg["sender"], + strmsg, + if truncated { "..." } else { "" } + ), ); } @@ -505,10 +516,16 @@ reply reply to an AppCall not handled directly by } } - let strmsg = if printable { - String::from_utf8_lossy(&message).to_string() + let (message, truncated) = if message.len() > 64 { + (&message[0..64], true) } else { - format!("#{}", hex::encode(&message)) + (&message[..], false) + }; + + let strmsg = if printable { + format!("\"{}\"", String::from_utf8_lossy(&message).to_string()) + } else { + hex::encode(message) }; let id = json_str_u64(&call["call_id"]); @@ -516,8 +533,11 @@ reply reply to an AppCall not handled directly by self.inner().ui_sender.add_node_event( Level::Info, format!( - "AppCall ({:?}) id = {:016x} : {}", - call["sender"], id, strmsg + "AppCall ({:?}) id = {:016x} : {}{}", + call["sender"], + id, + strmsg, + if truncated { "..." } else { "" } ), ); diff --git a/veilid-core/src/rpc_processor/rpc_app_call.rs b/veilid-core/src/rpc_processor/rpc_app_call.rs index f3de4828..6e0a3e43 100644 --- a/veilid-core/src/rpc_processor/rpc_app_call.rs +++ b/veilid-core/src/rpc_processor/rpc_app_call.rs @@ -3,7 +3,7 @@ use super::*; impl RPCProcessor { // Sends a high level app request and wait for response // Can be sent via all methods including relays and routes - #[instrument(level = "trace", skip(self), ret, err)] + #[instrument(level = "trace", skip(self, message), ret, err)] pub async fn rpc_call_app_call( self, dest: Destination, diff --git a/veilid-core/src/rpc_processor/rpc_app_message.rs b/veilid-core/src/rpc_processor/rpc_app_message.rs index 726515a4..d6040e26 100644 --- a/veilid-core/src/rpc_processor/rpc_app_message.rs +++ b/veilid-core/src/rpc_processor/rpc_app_message.rs @@ -3,7 +3,7 @@ use super::*; impl RPCProcessor { // Sends a high level app message // Can be sent via all methods including relays and routes - #[instrument(level = "trace", skip(self), ret, err)] + #[instrument(level = "trace", skip(self, message), ret, err)] pub async fn rpc_call_app_message( self, dest: Destination, diff --git a/veilid-python/tests/test_routing_context.py b/veilid-python/tests/test_routing_context.py index bf20d77c..931fa89c 100644 --- a/veilid-python/tests/test_routing_context.py +++ b/veilid-python/tests/test_routing_context.py @@ -1,6 +1,7 @@ # Routing context veilid tests import asyncio +import random import pytest import veilid @@ -109,3 +110,46 @@ async def test_routing_context_app_call_loopback(): # now we should get the reply from the call result = await app_call_task assert result == reply + + +@pytest.mark.asyncio +async def test_routing_context_app_message_loopback_big_packets(): + + app_message_queue: asyncio.Queue = asyncio.Queue() + + async def app_message_queue_update_callback(update: veilid.VeilidUpdate): + if update.kind == veilid.VeilidUpdateKind.APP_MESSAGE: + await app_message_queue.put(update) + + hostname, port = server_info() + api = await veilid.json_api_connect( + hostname, port, app_message_queue_update_callback + ) + async with api: + # purge routes to ensure we start fresh + await api.debug("purge routes") + + # make a routing context that uses a safety route + rc = await (await api.new_routing_context()).with_privacy() + async with rc: + + # make a new local private route + prl, blob = await api.new_private_route() + + # import it as a remote route as well so we can send to it + prr = await api.import_remote_private_route(blob) + + # do this test 10 times + for _ in range(10): + + # send a random sized random app message to our own private route + message = random.randbytes(random.randint(0,32768)) + await rc.app_message(prr, message) + + # we should get the same message back + update: veilid.VeilidUpdate = await asyncio.wait_for( + app_message_queue.get(), timeout=10 + ) + + assert isinstance(update.detail, veilid.VeilidAppMessage) + assert update.detail.message == message diff --git a/veilid-server/src/cmdline.rs b/veilid-server/src/cmdline.rs index cdc4158a..bd74babc 100644 --- a/veilid-server/src/cmdline.rs +++ b/veilid-server/src/cmdline.rs @@ -287,8 +287,10 @@ pub fn process_command_line() -> EyreResult<(Settings, ArgMatches)> { let mut out: Vec = Vec::new(); for x in x.split(',') { let x = x.trim().to_string(); - println!(" {}", x); - out.push(x); + if !x.is_empty() { + println!(" {}", x); + out.push(x); + } } out }