ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
connection_endpoint.c
Go to the documentation of this file.
1
5
7#include <ascii-chat/common.h>
9
10#include <string.h>
11
13 switch (protocol) {
15 return "TCP";
17 return "WebSocket";
19 return "QUIC";
20 default:
21 return "Unknown";
22 }
23}
24
25static asciichat_error_t connection_endpoint_from_parts(connection_endpoint_t *endpoint_out, const url_parts_t *parts,
26 connection_endpoint_protocol_t protocol, uint16_t default_port,
27 const char *input) {
28 if (!endpoint_out || !parts || !parts->host) {
29 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid endpoint parse state");
30 }
31
32 if (strlen(input) >= sizeof(endpoint_out->input) || strlen(parts->host) >= sizeof(endpoint_out->host)) {
33 return SET_ERRNO(ERROR_INVALID_PARAM, "Connection endpoint exceeds URL or host storage capacity");
34 }
35
36 memset(endpoint_out, 0, sizeof(*endpoint_out));
37 endpoint_out->protocol = protocol;
38 SAFE_STRNCPY(endpoint_out->input, input, sizeof(endpoint_out->input));
39 SAFE_STRNCPY(endpoint_out->host, parts->host, sizeof(endpoint_out->host));
40 endpoint_out->port = parts->port > 0 ? (uint16_t)parts->port : default_port;
41 endpoint_out->has_explicit_port = parts->port > 0;
42 return ASCIICHAT_OK;
43}
44
46 connection_endpoint_t *endpoint_out) {
47 if (!input || !*input || !endpoint_out) {
48 return SET_ERRNO(ERROR_INVALID_PARAM, "input or endpoint_out is NULL");
49 }
50
51 url_parts_t parts = {0};
52 asciichat_error_t result;
53
54 if (strncasecmp(input, "quic://", sizeof("quic://") - 1) == 0) {
55 char rewritten[URL_BUFFER_SIZE];
56 if (strlen(input) - 1 >= sizeof(rewritten))
57 return SET_ERRNO(ERROR_INVALID_PARAM, "QUIC endpoint is too long");
58 SAFE_SNPRINTF(rewritten, sizeof(rewritten), "tcp://%s", input + 7);
59 result = url_parse(rewritten, &parts);
60 if (result != ASCIICHAT_OK)
61 return result;
62 if (parts.userinfo || (parts.path && *parts.path)) {
63 url_parts_destroy(&parts);
64 return SET_ERRNO(ERROR_INVALID_PARAM, "QUIC endpoint must not include user information or a path");
65 }
66 result = connection_endpoint_from_parts(endpoint_out, &parts, CONNECTION_ENDPOINT_QUIC, default_port, input);
67 if (result == ASCIICHAT_OK && parts.ipv6)
68 SAFE_STRNCPY(endpoint_out->host, parts.ipv6, sizeof(endpoint_out->host));
69 url_parts_destroy(&parts);
70 return result;
71 }
72
73 if (url_is_websocket(input)) {
74 result = url_parse(input, &parts);
75 if (result != ASCIICHAT_OK) {
76 return result;
77 }
78 result = connection_endpoint_from_parts(endpoint_out, &parts, CONNECTION_ENDPOINT_WEBSOCKET, default_port, input);
79 url_parts_destroy(&parts);
80 return result;
81 }
82
83 if (url_is_tcp(input)) {
84 result = url_parse(input, &parts);
85 if (result != ASCIICHAT_OK) {
86 return result;
87 }
88 result = connection_endpoint_from_parts(endpoint_out, &parts, CONNECTION_ENDPOINT_TCP, default_port, input);
89 url_parts_destroy(&parts);
90 return result;
91 }
92
93 /* Unsupported explicit scheme. Bare hostnames are allowed and have no "://". */
94 if (strstr(input, "://") != NULL) {
95 return SET_ERRNO(ERROR_INVALID_PARAM, "Unsupported connection scheme: %s", input);
96 }
97
98 result = url_parse(input, &parts);
99 if (result != ASCIICHAT_OK) {
100 return result;
101 }
102
103 result = connection_endpoint_from_parts(endpoint_out, &parts, CONNECTION_ENDPOINT_TCP, default_port, input);
104 url_parts_destroy(&parts);
105 return result;
106}
#define SET_ERRNO(code,...)
⚙️ Common definitions, error codes, macros, and types shared throughout the application
asciichat_error_t connection_endpoint_resolve(const char *input, uint16_t default_port, connection_endpoint_t *endpoint_out)
For connection endpoint, this is the live record that ties protocol, port, has_explicit_port together...
const char * connection_endpoint_protocol_name(connection_endpoint_protocol_t protocol)
Shared endpoint normalization for TCP and WebSocket connections.
connection_endpoint_protocol_t
@ CONNECTION_ENDPOINT_TCP
@ CONNECTION_ENDPOINT_QUIC
@ CONNECTION_ENDPOINT_WEBSOCKET
unsigned short uint16_t
Definition common.h:61
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:423
#define SAFE_SNPRINTF(buffer, buffer_size,...)
Definition common.h:507
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define URL_BUFFER_SIZE
void url_parts_destroy(url_parts_t *parts)
Free parsed URL components.
Definition url.c:304
bool url_is_websocket(const char *url)
Check if a URL string is a valid WebSocket URL.
Definition url.c:330
asciichat_error_t url_parse(const char *url, url_parts_t *parts_out)
Parse HTTP(S), WebSocket, and TCP URL into components.
Definition url.c:166
bool url_is_tcp(const char *url)
Check if a URL string is a valid TCP URL.
Definition url.c:365
🔤 String Manipulation and Shell Escaping Utilities
connection_endpoint_protocol_t protocol
Structure containing parsed URL components.
Definition url.h:65
char * userinfo
Optional userinfo (user:pass) - may be NULL (allocated if present).
Definition url.h:67
char * path
Extracted path, query, and fragment (allocated if present, may be NULL).
Definition url.h:71
char * ipv6
IPv6 address if host is bracketed IPv6 - may be NULL (allocated if present).
Definition url.h:69
char * host
Canonical ASCII hostname or IP address (allocated).
Definition url.h:68
int port
Extracted port number (0 if not specified).
Definition url.h:70
🌐 Production-Grade URL Validation and Parsing