Determine total CoAP message size

295 views Asked by At

I have both a CoAP Server and Client I wrote in Java with the Californium library. I can get resources from the server both through the client or with Firefox with the Copper(Cu) extension. I want to get the total size of the response i get from the server. I can get the size of the payload already, but I want the total message size. It doesn't matter if I accomplish this through code or with a tool. So far i have been unable to find on Google a way to accomplish this.

1

There are 1 answers

0
eugene-nikolaev On

It depends on what you want to get.

1) If you just want to discover some footprints.

I'd recommend to use wireshark, capture and analyze the packets:

https://www.wireshark.org

2) If you want to use the lengths programatically

As far as I know there is no clean and direct way to achieve this.

There is some workarounds.

Connector

You may wrap a Connector and explicitly set an endpoint to the client (and server as well, but I'm showing a client version):

CoapClient client = new CoapClient(new URI(uri));
client.setEndpoint(
    new CoapEndpoint(
        new InterceptingUDPConnector(
            new UDPConnector(
                new InetSocketAddress(
                    portNumber
                )
            )
        ),
        NetworkConfig.getStandard()
    )
)

Here is the connector wrapper:

public class InterceptingUDPConnector implements Connector {
    private final Connector origin;

    public InterceptingUDPConnector(Connector origin) {
        this.origin = origin;
    }

    @Override
    public void send(RawData msg) {
        System.out.println("Length:" + msg.getSize());
        origin.send(msg);
    }

    @Override
    public void setRawDataReceiver(RawDataChannel messageHandler) {
        RawDataChannel decodingChannel = raw -> {
            System.out.println("Length: " + raw.getSize())
            messageHandler.receiveData(raw);
        };
        origin.setRawDataReceiver(decodingChannel);
    }

    @Override
    public void start() throws IOException {
        origin.start();
    }

    @Override
    public void stop() { origin.stop();
    }

    @Override
    public void destroy() { origin.destroy();
    }

    @Override
    public InetSocketAddress getAddress() {
        return origin.getAddress();
    }
}

However, it is hard to associate these lengths and responses.

I use the following class to parse the RawData:

import org.eclipse.californium.core.coap.Message;
import org.eclipse.californium.core.network.serialization.DataParser;
import org.eclipse.californium.elements.RawData;

public class ParsedPacket {
    private final RawData packet;

    public ParsedPacket(RawData packet) {
        this.packet = packet;
    }

    @Override
    public String toString() {
        Message msg = null;
        DataParser parser = new DataParser(packet.getBytes());
        if (parser.isEmpty()) {
            msg = parser.parseEmptyMessage();
        } else if (parser.isRequest()) {
            msg = parser.parseRequest();
        } else if (parser.isResponse()) {
            msg = parser.parseResponse();
        }
        return (msg == null) ? "" : msg.toString();
    }
}

With that, you may associate a particular response and the overall length using, for example MID and token.

A pitfall here is that you have to use some global storage for that.

I don't recommend using it for production. Except some rare cases e.g. print some packet info + length. Which also maybe covered by enabling some appropriate Californium logger level as well.

So, it is a bad practice, literally.

MessageTracer and serializing Messages

You may implement a org.eclipse.californium.core.network.interceptors.MessageInterceptor interface, say, with a class MessageLengthTracer.

client.setEndpoint(...);
client.endpoint().setMessageTracer(new MessageLengthTracer());

There you can serialize messages using org.eclipse.californium.core.network.serialization.DataSerializer with technique similar to the previous workaround and get their lengths.

Though, it is a workaround too and there is two pitfalls - possible length inaccuracy and double serialization work.

P.S. I will be glad if someone says I am wrong and point me to a clean way to do that.