ibm-security-innovation / crosscoap

CoAP-to-HTTP translator proxy
https://developer.ibm.com/open/crosscoap/
Apache License 2.0
66 stars 22 forks source link

Does not send content-format when it's text/plain #5

Closed james-awelina closed 6 years ago

james-awelina commented 6 years ago

I have been testing with the ETSI plug-fest suite at http://coap.me Messages fail the interop tests, in particular COAP_CORE01(GET) when the http response has Content-Type:text/plain whereas they work fine with other COAP supported types such as application/xml.

The value of content-format is 0 in the case of text/plain (41 for application/xml etc) and should be sent but it's not sent when the value is zero. This has also been verified using tcpdump to capture outgoing coap traffic from server and I am sure that it's not a bug in the ETSI suite. I believe there is a bug in function 'encodeInt' in message.go (imported from /dustin/go-coap) which returns nil when the byte value is zero. Suspect code snippet here:

func encodeInt(v uint32) []byte { switch { case v == 0: return nil case v < 256: return []byte{byte(v)} case v < 65536: rv := []byte{0, 0} binary.BigEndian.PutUint16(rv, uint16(v)) return rv ...

Use of this case v == 0 is not appropriate for option MediaType, but is used here:

func (o option) toBytes() []byte { var v uint32 switch i := o.Value.(type) { case string: return []byte(i) case []byte: return i case MediaType: v = uint32(i) case int: v = uint32(i) case int32: ... return encodeInt(v)

Whether the fix should be in go-coap or by trapping it in crosscoap I do not know. I am assured by one of the authors of RFC 7252 that the value should be sent. He says "To me it looks like crosscoap instead believes the default is 0 and they can leave out the option if its value would be zero. Can you check that in the code? Please file a bug report if this hypothesis is corroborated."

cabo commented 6 years ago

... and here is the text from RFC 7252 I was citing:

5.10.3.  Content-Format

   The Content-Format Option indicates the representation format of the
   message payload.  The representation format is given as a numeric
   Content-Format identifier that is defined in the "CoAP Content-
   Formats" registry (Section 12.3).  In the absence of the option, no
   default value is assumed, i.e., the representation format of any
   representation message payload is indeterminate (Section 5.5).
james-awelina commented 6 years ago

I've fixed it. I was wrong about where the problem was - it's not in the encodeInt function in go-coap but in the file translate.go within crosscoap.

The map from coap to html works fine, but a function 'invertMap' was used to create the inverse map. Clever idea, but it seems not to work reliably. I deleted it and just wrote the inverse map in full as the variable called httpcontentTypeContentFormat = map[string]coap.MediaType{ "text/plain": coap.TextPlain, "application/link-format": coap.AppLinkFormat, etc, etc } Once this was done crosscoap returns the correct MediaTypes from the http ContentTypes.

dubek commented 6 years ago

Thanks @james-awelina for reporting and analyzing. I fixed the invertMap function to ignore everything after the ; character, exactly as done in translateContentType. See 9278cca5d848e8d76d80caa8da9f2cccce10c1a1 .