TEC
A lightweight C++ library enabling safe, efficient execution in multithreaded and concurrent systems.
Loading...
Searching...
No Matches
tec_socket_nd.hpp
Go to the documentation of this file.
1// Time-stamp: <Last changed 2026-02-20 16:24:51 by magnolia>
2/*----------------------------------------------------------------------
3------------------------------------------------------------------------
4Copyright (c) 2020-2026 The Emacs Cat (https://github.com/olddeuteronomy/tec).
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17------------------------------------------------------------------------
18----------------------------------------------------------------------*/
27#pragma once
28
29#ifndef _POSIX_C_SOURCE
30// This line fixes the "storage size of 'hints' isn't known" issue.
31#define _POSIX_C_SOURCE 200809L
32#endif
33
34#include <netinet/in.h>
35#include <sys/socket.h>
36#include <unistd.h>
37#include <netdb.h>
38
39#include <cerrno>
40
41#include "tec/tec_def.hpp" // IWYU pragma: keep
42#include "tec/tec_trace.hpp"
43#include "tec/tec_status.hpp"
46
47
48namespace tec {
49
62struct SocketNd : public Socket
63{
68 explicit SocketNd(const Socket& sock)
69 : Socket(sock.fd, sock.addr, sock.port, sock.buffer, sock.buffer_size)
70 {}
71
80 SocketNd(int _fd, const char* _addr, int _port, char* _buffer, size_t _buffer_size)
81 : Socket(_fd, _addr, _port, _buffer, _buffer_size)
82 {}
83
96 static Status send_nd(const NetData* nd, const SocketNd* sock)
97 {
98 TEC_ENTER("SocketNd::send_nd");
99 //
100 // Write the NetData header to the stream.
101 //
102 ssize_t sent = write(sock->fd, &nd->header, sizeof(NetData::Header));
103 if (sent == 0) {
104 auto errmsg = format("{}:{} Peer closed the connection.",
105 sock->addr, sock->port);
106 TEC_TRACE(errmsg);
107 return {EIO, errmsg, Error::Kind::NetErr};
108 }
109 else if (sent != sizeof(NetData::Header)) {
110 auto errmsg = format("{}:{} NetData::Header write error.",
111 sock->addr, sock->port);
112 TEC_TRACE(errmsg);
113 return {EIO, errmsg, Error::Kind::NetErr};
114 }
115 //
116 // Write data to the stream.
117 //
118 if (nd->size() > 0) {
119 return Socket::send(nd->bytes(), sock);
120 }
121 return {};
122 }
123
148 static Status recv_nd(NetData* nd, const SocketNd* sock)
149 {
150 TEC_ENTER("SocketNd::recv_nd");
151 Status status;
152 NetData::Header hdr;
153 //
154 // Read the header.
155 //
156 // The MSG_PEEK flag causes the receive operation to return data
157 // from the beginning of the receive queue without removing that data from the queue.
158 // Thus, a subsequent receive call will return the same data.
159 //
160 ssize_t rd = ::recv(sock->fd, &hdr, sizeof(NetData::Header),
161 MSG_PEEK);
162 if (rd == 0) {
163 auto errmsg = format("{}:{} Peer closed the connection.",
164 sock->addr, sock->port);
165 TEC_TRACE(errmsg);
166 return {EIO, errmsg, Error::Kind::NetErr};
167 }
168 else if (rd < 0) {
169 auto errmsg = format("{}:{} Socket read error.",
170 sock->addr, sock->port);
171 TEC_TRACE(errmsg);
172 return {errno, errmsg, Error::Kind::NetErr};
173 }
174 else if (rd != sizeof(NetData::Header)) {
175 auto errmsg = format("{}:{} NetData::Header read error.",
176 sock->addr, sock->port);
177 TEC_TRACE(errmsg);
178 return {EBADMSG, errmsg, Error::Kind::Invalid};
179 }
180 // Validate the header.
181 else if (!hdr.is_valid()) {
182 auto errmsg = format("{}:{} NetData::Header is invalid.",
183 sock->addr, sock->port);
184 TEC_TRACE(errmsg);
185 return {EBADMSG, errmsg, Error::Kind::Invalid};
186 }
187 // Re-read the header from the message queue (destructive this time).
188 auto rd2 = read(sock->fd, &hdr, sizeof(NetData::Header));
189 if (rd2 != sizeof(NetData::Header)) {
190 return {EIO, Error::Kind::System};
191 }
192 //
193 // Read data.
194 //
195 nd->header = hdr;
196 if (nd->size() > 0) {
197 status = Socket::recv(nd->bytes(), sock, nd->size());
198 }
199 nd->rewind();
200 return status;
201 }
202};
203
204} // namespace tec
Lightweight binary serialization container optimized for network communication.
Definition tec_net_data.hpp:51
size_t size() const
Returns current logical size of the message (according to header)
Definition tec_net_data.hpp:127
void rewind()
Resets read position to the beginning of the buffer.
Definition tec_net_data.hpp:119
Header header
Global message header.
Definition tec_net_data.hpp:54
const Bytes & bytes() const
Returns const reference to internal byte buffer.
Definition tec_net_data.hpp:85
#define TEC_ENTER(name)
Logs an entry message for a named context (e.g., function).
Definition tec_trace.hpp:211
#define TEC_TRACE(...)
Logs a formatted trace message.
Definition tec_trace.hpp:222
@ Invalid
Invalid data or state.
@ NetErr
Network-related error.
@ System
System-level error.
Global header placed at the start of every serialized buffer.
Definition tec_nd_types.hpp:134
constexpr bool is_valid() const
Check if the header appears valid.
Definition tec_nd_types.hpp:168
Specialized socket wrapper optimized for sending/receiving NetData protocol messages.
Definition tec_socket_nd.hpp:63
static Status send_nd(const NetData *nd, const SocketNd *sock)
Sends a complete NetData message (header + payload) over the socket.
Definition tec_socket_nd.hpp:96
static Status recv_nd(NetData *nd, const SocketNd *sock)
Receives one complete NetData message (header + payload)
Definition tec_socket_nd.hpp:148
SocketNd(const Socket &sock)
Constructs SocketNd by copying from an existing Socket object.
Definition tec_socket_nd.hpp:68
SocketNd(int _fd, const char *_addr, int _port, char *_buffer, size_t _buffer_size)
Constructs SocketNd with explicit parameters.
Definition tec_socket_nd.hpp:80
Lightweight wrapper around a connected socket file descriptor.
Definition tec_socket.hpp:272
static Status recv(Bytes &data, const Socket *sock, size_t length)
Receive data from a socket into a MemFile (Bytes).
Definition tec_socket.hpp:329
static Status send(const Bytes &data, const Socket *sock)
Send the entire contents of a MemFile (Bytes) through a socket.
Definition tec_socket.hpp:395
char * buffer
Buffer used in send/recv operations.
Definition tec_socket.hpp:276
int port
Peer port number.
Definition tec_socket.hpp:275
size_t buffer_size
Size of the buffer.
Definition tec_socket.hpp:277
int fd
Underlying socket file descriptor.
Definition tec_socket.hpp:273
char addr[INET6_ADDRSTRLEN]
Peer address as a null-terminated string (IPv4 or IPv6).
Definition tec_socket.hpp:274
Common definitions and utilities for the tec namespace.
Lightweight binary serialization optimized for network communication.
std::string format(const T &arg)
Formats a single argument into a string.
Definition tec_print.hpp:171
Generic BSD socket parameters and helpers.
Defines error handling types and utilities for the tec namespace.
Provides a thread-safe tracing utility for debugging in the tec namespace.