eclipse-californium / californium

CoAP/DTLS Java Implementation
https://www.eclipse.org/californium/
Other
729 stars 367 forks source link

Does the Californium project only support ACK messages? #807

Closed yuuuuuy closed 5 years ago

yuuuuuy commented 5 years ago

Does Californium not support COAP NON messages?

I used a NB development board and developed a LWM2M Server based on a third-party library. When the server receives the NON data sent by the device, the server sends the RST message to cancel the subscription. I find the specific code as follows.

package org.eclipse.californium.core.network;
...

private void receiveResponse(final Response response) {

            /* 
             * Logging here causes significant performance loss.
             * If necessary, add an interceptor that logs the messages,
             * e.g., the MessageTracer.
             */
            for (MessageInterceptor interceptor : interceptors) {
                interceptor.receiveResponse(response);
            }

            // MessageInterceptor might have canceled
            if (!response.isCanceled()) {
                Exchange exchange = matcher.receiveResponse(response);
                if (exchange != null) {
                    exchangeExecutor.execute(new StripedExchangeJob(exchange) {

                        @Override
                        public void runStriped() {
                            // entered striped execution.
                            // recheck, if the response still match the exchange
                            // and the exchange is not changed in the meantime
                            if (exchange.checkCurrentResponse(response)) {
                                exchange.setEndpoint(CoapEndpoint.this);
                                response.setRTT(exchange.calculateRTT());
                                coapstack.receiveResponse(exchange, response);
                            } else if (!response.isDuplicate() && response.getType() != Type.ACK) {
                                LOGGER.debug("rejecting not longer matchable response from {}",
                                        response.getSourceContext());
                            //  reject(response);
                            } else {
                                LOGGER.debug("not longer matched response {}", response);
                            }
                        }
                    });
                } else if (response.getType() != Type.ACK && response.hasMID()) {
                    // reject only messages with MID, ignore for TCP
                    LOGGER.debug("rejecting unmatchable response from {}", response.getSourceContext());
                    reject(response);
                }
            }
        }
...
boaks commented 5 years ago

I would guess, you use a LWM2M Data Reporting. That is mapped to observe/notify, where the notifies are sent as NON. If that is the case, the RST mainly indicates, that the LWM2M server can't map your notify to the observe request. That is mainly caused by either NAT (or/and) DTLS issues.

Check issue #719, if the situation and solution fits you case. Or in addition issue #772, if DTLS is used.

The solution there (RELAXED matching) for plain CoAP introduces certain security risks. If you use DTLS with a NAT, you first must fix the DTLS connections by a "(resumption) Handshake", but that must be initiated by your client.

@sbernard31 wrote a very good summary of that topic https://github.com/eclipse/leshan/wiki/LWM2M-Observe

And finally, though that OMA specification of the data reporting interface seems to be really a failure hot spot, please report your troubles to https://github.com/OpenMobileAlliance/OMA_LwM2M_for_Developers

boaks commented 5 years ago
Exchange exchange = matcher.receiveResponse(response);
    if (exchange != null) {
...
    } else if (response.getType() != Type.ACK && response.hasMID()) {
        // reject only messages with MID, ignore for TCP
        LOGGER.debug("rejecting unmatchable response from {}", response.getSourceContext());
        reject(response);
    }

the "else" branch, which rejects all but ACK, is only taken, if the response could not be matched with a request (in your case the request with an observe option). That standard matching rest upon the presented ip-address:port (which may differ from the used ip-address:port, if a NAT is in between). Therefore, the NAT changed ip-address:port inhibit the matching, so the "else" is taken and the NON gets answered by RST.

yuuuuuy commented 5 years ago

yes, I did use NAT. Now I try again with a server with a public IP address.

boaks commented 5 years ago

You assume, the one NAT you know, is the only one :-). If you're wrong, using a public IP address solves only the "last" NAT, but your issue will remain. May be you consider to follow the recommended similar issues above.

boaks commented 5 years ago

Don't hesitate to add a new comment or open a new issue, when you have new information for us.