ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
ntrip_caster.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file protocore_ntrip_caster.h
6 * @brief NTRIP caster protocol codec (PROTOCORE_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 (protocore_ntrip_caster_listener.h) drives it and pumps bytes. Zero heap.
22 *
23 * @author Douglas Quigg (dstroy0)
24 * @date 2026
25 */
26
27#ifndef PROTOCORE_NTRIP_CASTER_H
28#define PROTOCORE_NTRIP_CASTER_H
29
30#include "protocore_config.h" // the entry point: protocore_types.h for the widths
31
32#if PROTOCORE_ENABLE_NTRIP_CASTER
33
35
36/** @brief NTRIP protocol revision detected in / used for a request or response. */
37typedef enum PROTO_ENUM_PACKED
38{
39 NTRIP_V1 = 1, ///< legacy: ICY 200 OK / SOURCETABLE 200 OK
40 NTRIP_V2 = 2, ///< RFC-style: HTTP/1.1 200 OK, Content-Type: gnss/data
41} NtripVersion;
42
43/** @brief A parsed NTRIP rover request. String spans point into the caller's request buffer. */
44typedef struct
45{
46 proto_bool complete; ///< the full request header block (up to a blank line) was present
47 proto_bool is_get; ///< the request line was a GET
48 NtripVersion version; ///< NTRIP_V2 if an Ntrip-Version: Ntrip/2.0 header was present, else NTRIP_V1
49 char mountpoint[PROTOCORE_NTRIP_MOUNT_MAX]; ///< requested mountpoint (empty = source-table request, "GET /")
50 proto_bool want_sourcetable; ///< the request targets "/" (list the source table)
51 const char *auth_b64; ///< base64 of user:pass from an "Authorization: Basic" header, or null
52 uint16_t auth_b64_len; ///< length of @c auth_b64 (0 if none)
53} NtripRequest;
54
55/**
56 * @brief Parse an NTRIP request from the bytes buffered so far.
57 *
58 * @return true once the request header block is complete (a `\r\n\r\n` or `\n\n` was seen) and @p out is
59 * filled; false if more bytes are still needed. A completed request with @c is_get false is a
60 * malformed / unsupported request the caller should reject.
61 */
62proto_bool protocore_ntrip_request_parse(const char *buf, size_t len, NtripRequest *out);
63
64/**
65 * @brief Build the stream-accept response the caster sends before streaming RTCM to a rover.
66 * @return bytes written (excluding any NUL), or 0 on overflow. V1 = "ICY 200 OK\r\n\r\n";
67 * V2 = an HTTP/1.1 200 response with Content-Type: gnss/data.
68 */
69size_t protocore_ntrip_build_stream_response(char *out, size_t cap, NtripVersion version);
70
71/**
72 * @brief Build an error response for an unknown mountpoint / bad request.
73 * @return bytes written, or 0 on overflow. V1 = a bare "SOURCETABLE 200 OK" fallback is NOT used here;
74 * this emits a 404-style line ("HTTP/1.1 404 Not Found" for V2, "ERROR - Bad Request" for V1).
75 */
76size_t protocore_ntrip_build_error_response(char *out, size_t cap, NtripVersion version);
77
78/**
79 * @brief Build an unauthorized response for a mountpoint that requires (and did not get valid) HTTP
80 * Basic credentials. V2 = "HTTP/1.1 401 Unauthorized" with a WWW-Authenticate: Basic challenge;
81 * V1 = "ERROR - Bad Password". @return bytes written, or 0 on overflow.
82 */
83size_t protocore_ntrip_build_unauthorized_response(char *out, size_t cap, NtripVersion version);
84
85/** @brief One mountpoint's source-table (`STR;...`) description. Unset string fields default sensibly. */
86typedef struct
87{
88 const char *mountpoint; ///< e.g. "BASE1" (required)
89 const char *identifier; ///< source / place identifier, e.g. "Lab roof"
90 const char *format_details; ///< RTCM message list, e.g. "1005(1),1006(10)"
91 const char *nav_system; ///< e.g. "GPS" or "GPS+GLO"
92 const char *country; ///< 3-char code, e.g. "USA"
93 const char *generator; ///< producing hardware/software (null -> "PC")
94 double lat_deg; ///< approximate base latitude (source-table advertises 2 decimals)
95 double lon_deg; ///< approximate base longitude
96 proto_bool nmea_required; ///< rover must send a GGA (1) or not (0); false for a single-base caster
97} NtripMount;
98
99/**
100 * @brief Build one NTRIP source-table `STR;...` record (no trailing CRLF) for @p m into @p out.
101 * @return bytes written (excluding NUL), or 0 on overflow.
102 */
103size_t protocore_ntrip_build_str_record(char *out, size_t cap, const NtripMount *m);
104
105/**
106 * @brief Build a full source-table response: the status/header block, one `STR;...\r\n` per mountpoint,
107 * then `ENDSOURCETABLE\r\n`. The Content-Length (V2) / body length (V1) is computed for you.
108 * @return total bytes written (excluding NUL), or 0 on overflow.
109 */
110size_t protocore_ntrip_build_sourcetable(char *out, size_t cap, NtripVersion version, const NtripMount *mounts,
111 size_t mount_count);
112
114
115#endif // PROTOCORE_ENABLE_NTRIP_CASTER
116
117#endif // PROTOCORE_NTRIP_CASTER_H
#define PROTOCORE_NTRIP_MOUNT_MAX
Max length (incl. NUL) of an NTRIP mountpoint name the caster serves.
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97