DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
ntrip_caster.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file ntrip_caster.h
6 * @brief NTRIP caster protocol codec (DETWS_ENABLE_NTRIP_CASTER) - the pure, host-tested core.
7 *
8 * NTRIP (Networked Transport of RTCM via Internet Protocol) is how a GNSS base's RTCM corrections reach
9 * rovers over TCP. It is HTTP-shaped: a rover opens a connection and sends a request line
10 * `GET /<mountpoint> HTTP/1.x` with headers; the caster answers and then streams raw RTCM bytes.
11 *
12 * Two protocol revisions are in the field and this codec speaks both:
13 * - **NTRIP 1.0** - the request omits a version header; the caster replies with the bare status line
14 * `ICY 200 OK\r\n\r\n` and then streams, or `SOURCETABLE 200 OK` + the source table for a `GET /`.
15 * - **NTRIP 2.0** - the request carries `Ntrip-Version: Ntrip/2.0`; the caster replies with a real
16 * `HTTP/1.1 200 OK` and `Content-Type: gnss/data` (or `gnss/sourcetable`) before streaming.
17 *
18 * This file parses a rover request (mountpoint, version, optional HTTP Basic credentials) and builds the
19 * caster's responses - the stream-accept line, an error line, and the RTCM source table (one `STR;...`
20 * record per mountpoint per the NTRIP source-table format, terminated by `ENDSOURCETABLE`). It touches no
21 * sockets; the listener glue (ntrip_caster_listener.h) drives it and pumps bytes. Zero heap.
22 *
23 * @author Douglas Quigg (dstroy0)
24 * @date 2026
25 */
26
27#ifndef DETERMINISTICESPASYNCWEBSERVER_NTRIP_CASTER_H
28#define DETERMINISTICESPASYNCWEBSERVER_NTRIP_CASTER_H
29
30#include "ServerConfig.h"
31
32#if DETWS_ENABLE_NTRIP_CASTER
33
34#include <stddef.h>
35#include <stdint.h>
36
37/** @brief NTRIP protocol revision detected in / used for a request or response. */
38enum class NtripVersion : uint8_t
39{
40 NTRIP_V1 = 1, ///< legacy: ICY 200 OK / SOURCETABLE 200 OK
41 NTRIP_V2 = 2, ///< RFC-style: HTTP/1.1 200 OK, Content-Type: gnss/data
42};
43
44/** @brief A parsed NTRIP rover request. String spans point into the caller's request buffer. */
45struct NtripRequest
46{
47 bool complete; ///< the full request header block (up to a blank line) was present
48 bool is_get; ///< the request line was a GET
49 NtripVersion version; ///< NTRIP_V2 if an Ntrip-Version: Ntrip/2.0 header was present, else NTRIP_V1
50 char mountpoint[DETWS_NTRIP_MOUNT_MAX]; ///< requested mountpoint (empty = source-table request, "GET /")
51 bool want_sourcetable; ///< the request targets "/" (list the source table)
52 const char *auth_b64; ///< base64 of user:pass from an "Authorization: Basic" header, or null
53 uint16_t auth_b64_len; ///< length of @c auth_b64 (0 if none)
54};
55
56/**
57 * @brief Parse an NTRIP request from the bytes buffered so far.
58 *
59 * @return true once the request header block is complete (a `\r\n\r\n` or `\n\n` was seen) and @p out is
60 * filled; false if more bytes are still needed. A completed request with @c is_get false is a
61 * malformed / unsupported request the caller should reject.
62 */
63bool ntrip_request_parse(const char *buf, size_t len, NtripRequest *out);
64
65/**
66 * @brief Build the stream-accept response the caster sends before streaming RTCM to a rover.
67 * @return bytes written (excluding any NUL), or 0 on overflow. V1 = "ICY 200 OK\r\n\r\n";
68 * V2 = an HTTP/1.1 200 response with Content-Type: gnss/data.
69 */
70size_t ntrip_build_stream_response(char *out, size_t cap, NtripVersion version);
71
72/**
73 * @brief Build an error response for an unknown mountpoint / bad request.
74 * @return bytes written, or 0 on overflow. V1 = a bare "SOURCETABLE 200 OK" fallback is NOT used here;
75 * this emits a 404-style line ("HTTP/1.1 404 Not Found" for V2, "ERROR - Bad Request" for V1).
76 */
77size_t ntrip_build_error_response(char *out, size_t cap, NtripVersion version);
78
79/**
80 * @brief Build an unauthorized response for a mountpoint that requires (and did not get valid) HTTP
81 * Basic credentials. V2 = "HTTP/1.1 401 Unauthorized" with a WWW-Authenticate: Basic challenge;
82 * V1 = "ERROR - Bad Password". @return bytes written, or 0 on overflow.
83 */
84size_t ntrip_build_unauthorized_response(char *out, size_t cap, NtripVersion version);
85
86/** @brief One mountpoint's source-table (`STR;...`) description. Unset string fields default sensibly. */
87struct NtripMount
88{
89 const char *mountpoint; ///< e.g. "BASE1" (required)
90 const char *identifier; ///< source / place identifier, e.g. "Lab roof"
91 const char *format_details; ///< RTCM message list, e.g. "1005(1),1006(10)"
92 const char *nav_system; ///< e.g. "GPS" or "GPS+GLO"
93 const char *country; ///< 3-char code, e.g. "USA"
94 const char *generator; ///< producing hardware/software (null -> "DetWebServer")
95 double lat_deg; ///< approximate base latitude (source-table advertises 2 decimals)
96 double lon_deg; ///< approximate base longitude
97 bool nmea_required; ///< rover must send a GGA (1) or not (0); false for a single-base caster
98};
99
100/**
101 * @brief Build one NTRIP source-table `STR;...` record (no trailing CRLF) for @p m into @p out.
102 * @return bytes written (excluding NUL), or 0 on overflow.
103 */
104size_t ntrip_build_str_record(char *out, size_t cap, const NtripMount *m);
105
106/**
107 * @brief Build a full source-table response: the status/header block, one `STR;...\r\n` per mountpoint,
108 * then `ENDSOURCETABLE\r\n`. The Content-Length (V2) / body length (V1) is computed for you.
109 * @return total bytes written (excluding NUL), or 0 on overflow.
110 */
111size_t ntrip_build_sourcetable(char *out, size_t cap, NtripVersion version, const NtripMount *mounts,
112 size_t mount_count);
113
114#endif // DETWS_ENABLE_NTRIP_CASTER
115
116#endif // DETERMINISTICESPASYNCWEBSERVER_NTRIP_CASTER_H
User-facing configuration for DeterministicESPAsyncWebServer.
#define DETWS_NTRIP_MOUNT_MAX
Max length (incl. NUL) of an NTRIP mountpoint name the caster serves.