Skip to content

C: unetsocket_send_reliable() never waits for delivery — returns success on AGREE (acceptance), not delivery #23

Description

@mchitre

Summary

In c/unet.c, unetsocket_send_reliable() does not implement reliable-delivery semantics. It returns 0 (success) as soon as the datagram is accepted (the request is AGREE'd), and never waits for a delivery confirmation. As a result it reports success even when delivery ultimately fails (e.g. an unreachable node).

Unlike the JS bug (#22, a too-short wait) this is a missing feature: there is no delivery wait at all.

Reference behavior

Per the Java/Groovy UnetSocket and Julia UnetSockets.jl, a reliable send returns success only once the datagram is delivered, and failure if the stack reports a delivery failure. The header documents this intent:

/// Transmits a datagram ... with reliability enabled.
/// @return  0 on success, -1 otherwise
int unetsocket_send_reliable(unetsocket_t sock, uint8_t* data, int len, int to, int protocol);

For a reliable send, "success" should mean delivered.

Where it diverges (C)

c/unet.c:

int unetsocket_send_reliable(unetsocket_t sock, uint8_t* data, int len, int to, int protocol) {
  ...
  fjage_msg_add_bool(msg, "reliability", true);
  rv = unetsocket_send_request(usock, msg);   // same path as the unreliable send
  return rv;
}

int unetsocket_send_request(unetsocket_t sock, fjage_msg_t req) {
  ...
  req = request(usock, req, TIMEOUT);
  if (req != NULL && fjage_msg_get_performative(req) == FJAGE_AGREE) {
    fjage_msg_destroy(req);
    return 0;                                  // <-- returns on AGREE (acceptance), not delivery
  }
  fjage_msg_destroy(req);
  return -1;
}

unetsocket_send_reliable() only adds reliability=true and then goes through the exact same code path as unetsocket_send(). Both return 0 the moment the provider AGREEs to the request. There is no wait for DatagramDeliveryNtf / DatagramFailureNtf.

Impact

  • Reliable send to a reachable node → returns 0. Happens to look correct, but 0 is returned on acceptance, before delivery is confirmed.
  • Reliable send to an unreachable node → returns 0 (wrong; the stack AGREEs to attempt reliable delivery, then emits DatagramFailureNtf after retries — the C API never observes this and reports success). The Java/Julia/(fixed) Python APIs return failure here.

So unetsocket_send_reliable() cannot distinguish delivered from failed — it degrades to the same "accepted for transmission" semantics as the unreliable unetsocket_send().

What's missing

After receiving the AGREE for a reliable request, the C implementation should block waiting for the completion notification matched by the request's message id (inReplyTo):

  • org.arl.unet.DatagramDeliveryNtf (or RemoteSuccessNtf) → return 0
  • org.arl.unet.DatagramFailureNtf (or RemoteFailureNtf) → return -1

The existing receive(usock, clazz, id, timeout) helper (wrapping fjage_receive by clazz/id) can wait on these keyed by the request id. Note the delivery wait must be effectively unbounded (reliable delivery can take seconds to tens of seconds); only the AGREE wait should use TIMEOUT. This should apply only when reliability=true (and/or in a blocking send mode), leaving the unreliable fast-path unchanged.

Suggested direction (for @notthetup to decide)

Assigning to @notthetup to decide scope — e.g. whether to add the delivery wait inside unetsocket_send_request gated on the request's reliability flag, or in unetsocket_send_reliable specifically, and how to surface the (currently absent) blocking/semi-blocking send-mode distinction that the other language bindings expose.

Refs: Python fix #21; JS issue #22; Java org.arl.unet.api.UnetSocket.send; UnetSockets.jl Fjage.send(::UnetSocket, ::Message).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions