1# zoap23A WiP [CoAP][rfc 7252] implementation for bare-metal [constrained devices][rfc 7228] in [Zig][zig web].45## Status67Presently, the majority of the CoAP standard is not implemented.8However, creating a very basic CoAP server which sends and receives9non-confirmable messages is possible and already done as part of my10[zig-riscv-embedded][zig-riscv github] project. Since the code focus11on constrained bare-metal targets, it is optimized for a small memory12footprint and uses statically allocated fixed-size buffers instead of13performing dynamic memory allocation. Furthermore, it does not use any14OS-specific code from the Zig standard library (e.g. Sockets).1516The code is known to compile with Zig `0.13.0`.1718## Usage1920As noted above, this library targets freestanding constrained devices.21For this reason, all memory is statically allocated. To implement a CoAP22server with zoap, the central data structure is the Dispatcher. This23Dispatcher takes a list of Resources and forwards incoming requests to24them if the URI in the request matches one of the available resources.25Both, the dispatcher and the resources need to be statically allocated,26e.g. as global variables:2728 const resources = &[_]zoap.Resource{29 .{ .path = "hello", .handler = helloHandler },30 .{ .path = "about", .handler = aboutHandler },31 };32 var dispatcher = zoap.Dispatcher{33 .resources = resources,34 };3536The code above allocates a dispatcher with two resources: `/hello` and37`/about`. An incoming CoAP request for either of those resources invokes38the associated handler function. The `helloHandler` implementation may39looks as follows:4041 pub fn helloHandler(resp: *zoap.Response, req: *zoap.Request) codes.Code {42 if (!req.header.code.equal(codes.GET))43 return codes.BAD_METHOD;4445 const w = resp.payloadWriter();46 w.writeAll("Hello, World!") catch {47 return codes.INTERNAL_ERR;48 };4950 return codes.CONTENT;51 }5253The function takes two parameters: The resulting CoAP response and the54incoming CoAP request. The handler returns the CoAP response code for55the incoming request. The implementation above first checks the request56method, if it doesn't match the expected method a response with a57Method Not Allowed status code is returned. Otherwise, the58`helloHandler` writes `Hello, World!` to the response body and, unless an59error occurs, it responses with a successful content response code.6061In order to invoke these handlers, incoming CoAP requests need to be62forwarded to the Dispatcher via the `Dispatcher.dispatch` method which63takes an incoming CoAP request as a parameter and forwards it to the64matching resource (if any). The method returns the appropriate CoAP65response. Since this library attempts to be OS-independent, the code for66retrieving incoming requests and sending responses to these requests67depends on your environment. For example, CoAP request may be read from68a UDP socket in a POSIX environment.6970For or a more detailed and complete usage example refer to71[zig-riscv-embedded][zig-riscv github] which reads incoming requests72from a [SLIP][rfc 1055] serial interface.7374## Test vectors7576For parsing code, test vectors are created using the existing77[go-coap][go-coap github] implementation written in [Go][go website].78Test vectors are generated using `./src/testvectors/generate.go` and79available as `./src/testvectors/*.bin` files. These files are tracked80in the Git repositories and thus Go is not necessarily needed to run81existing tests.8283Each Zig test case embeds this file via [`@embedFile`][zig embedFile].84All existing Zig parser test cases can be run using:8586 $ zig test src/packet.zig8788New test cases can be added by modifying `./src/testvectors/generate.go` and89`./src/packet.zig`. Afterwards, the test case files need to be regenerated90using:9192 $ cd ./src/testvectors && go build -trimpath && ./testvectors9394New test vectors must be committed to the Git repository.9596## License9798This program is free software: you can redistribute it and/or modify it99under the terms of the GNU Affero General Public License as published by100the Free Software Foundation, either version 3 of the License, or (at101your option) any later version.102103This program is distributed in the hope that it will be useful, but104WITHOUT ANY WARRANTY; without even the implied warranty of105MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero106General Public License for more details.107108You should have received a copy of the GNU Affero General Public License109along with this program. If not, see <https://www.gnu.org/licenses/>.110111[rfc 7252]: https://datatracker.ietf.org/doc/rfc7252/112[rfc 7228]: https://datatracker.ietf.org/doc/rfc7228/113[rfc 1055]: https://datatracker.ietf.org/doc/rfc1055/114[zig web]: https://ziglang.org/115[zig-riscv github]: https://github.com/nmeum/zig-riscv-embedded116[go-coap github]: https://github.com/plgd-dev/go-coap117[go website]: https://golang.org118[zig embedFile]: https://ziglang.org/documentation/0.9.1/#embedFile119[zig import]: https://ziglang.org/documentation/0.9.1/#import120[git submodules]: https://git-scm.com/book/en/v2/Git-Tools-Submodules121[gyro github]: https://github.com/mattnite/gyro