Skip to content

Commit 9f3b872

Browse files
Update network.c
1 parent 4e368d5 commit 9f3b872

File tree

1 file changed

+78
-37
lines changed

1 file changed

+78
-37
lines changed

code/logic/network.c

Lines changed: 78 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,41 @@
2626

2727
// Helper function to resolve the port number
2828
static int resolve_port(const char *port_str) {
29-
return atoi(port_str);
29+
if (!port_str || !*port_str) return -1;
30+
31+
// Make sure the string is numeric
32+
for (const char *p = port_str; *p; ++p) {
33+
if (!isdigit((unsigned char)*p)) return -1;
34+
}
35+
36+
int port = atoi(port_str);
37+
if (port <= 0 || port > 65535) return -1;
38+
return port;
3039
}
3140

3241
// Initialize socket (for both client and server)
3342
static int init_socket(const char *protocol) {
34-
int sock = -1;
35-
36-
if (strcmp(protocol, "tcp") == 0) {
37-
sock = socket(AF_INET, SOCK_STREAM, 0);
38-
} else if (strcmp(protocol, "udp") == 0) {
39-
sock = socket(AF_INET, SOCK_DGRAM, 0);
40-
} else if (strcmp(protocol, "raw") == 0) {
41-
sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
42-
} else if (strcmp(protocol, "icmp") == 0) {
43-
sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
44-
} else {
45-
return -1; // Unsupported protocol
43+
if (!protocol) return -1;
44+
45+
struct {
46+
const char *name;
47+
int type;
48+
int proto;
49+
} protocols[] = {
50+
{ "tcp", SOCK_STREAM, 0 },
51+
{ "udp", SOCK_DGRAM, 0 },
52+
{ "raw", SOCK_RAW, IPPROTO_RAW },
53+
{ "icmp", SOCK_RAW, IPPROTO_ICMP },
54+
};
55+
56+
for (size_t i = 0; i < sizeof(protocols)/sizeof(protocols[0]); ++i) {
57+
if (strcmp(protocol, protocols[i].name) == 0) {
58+
int sock = socket(AF_INET, protocols[i].type, protocols[i].proto);
59+
return sock >= 0 ? sock : -1;
60+
}
4661
}
4762

48-
return sock;
63+
return -1; // Unsupported protocol
4964
}
5065

5166
// Open a new network stream (TCP/UDP)
@@ -91,11 +106,12 @@ fossil_nstream_t *fossil_nstream_open(const char *protocol, const char *host, co
91106

92107
// Send data through the network stream
93108
ssize_t fossil_nstream_send(fossil_nstream_t *ns, const void *buf, size_t len) {
94-
if (strcmp(ns->protocol, "udp") == 0) {
95-
return sendto(ns->socket, buf, len, 0, (struct sockaddr *)&ns->addr, sizeof(ns->addr));
96-
} else if (strcmp(ns->protocol, "raw") == 0 || strcmp(ns->protocol, "icmp") == 0) {
109+
if (!ns || ns->socket < 0 || !buf || len == 0) return -1;
110+
111+
if (strcmp(ns->protocol, "udp") == 0 || strcmp(ns->protocol, "raw") == 0 || strcmp(ns->protocol, "icmp") == 0) {
97112
return sendto(ns->socket, buf, len, 0, (struct sockaddr *)&ns->addr, sizeof(ns->addr));
98113
}
114+
99115
return send(ns->socket, buf, len, 0);
100116
}
101117

@@ -127,12 +143,14 @@ fossil_nstream_t *fossil_nstream_accept(fossil_nstream_t *ns) {
127143

128144
if (client_sock < 0) return NULL;
129145

130-
fossil_nstream_t *client_ns = malloc(sizeof(fossil_nstream_t));
146+
fossil_nstream_t *client_ns = calloc(1, sizeof(fossil_nstream_t)); // safer
131147
if (!client_ns) return NULL;
132148

133149
client_ns->socket = client_sock;
134150
client_ns->addr = client_addr;
135-
strcpy(client_ns->protocol, ns->protocol); // Inherit protocol from server
151+
strncpy(client_ns->protocol, ns->protocol, sizeof(client_ns->protocol) - 1);
152+
client_ns->protocol[sizeof(client_ns->protocol) - 1] = '\0';
153+
client_ns->is_tls = ns->is_tls; // inherit TLS flag
136154

137155
return client_ns;
138156
}
@@ -145,18 +163,16 @@ void fossil_nstream_close(fossil_nstream_t *ns) {
145163

146164
// Set socket to non-blocking mode
147165
int fossil_nstream_set_nonblocking(fossil_nstream_t *ns, int enable) {
166+
if (!ns || ns->socket < 0) return -1;
148167
#ifdef _WIN32
149168
u_long mode = enable ? 1 : 0;
150169
return ioctlsocket(ns->socket, FIONBIO, &mode);
151170
#else
152171
int flags = fcntl(ns->socket, F_GETFL, 0);
153172
if (flags == -1) return -1;
154173

155-
if (enable) {
156-
flags |= O_NONBLOCK;
157-
} else {
158-
flags &= ~O_NONBLOCK;
159-
}
174+
if (enable) flags |= O_NONBLOCK;
175+
else flags &= ~O_NONBLOCK;
160176

161177
return fcntl(ns->socket, F_SETFL, flags);
162178
#endif
@@ -190,40 +206,59 @@ int fossil_nstream_wait_writable(fossil_nstream_t *ns, int timeout_ms) {
190206

191207
// Connect with timeout
192208
int fossil_nstream_connect_timeout(fossil_nstream_t *ns, const char *host, const char *port, int timeout_ms) {
209+
if (!ns || ns->socket < 0 || !host || !port) return -1;
210+
193211
struct sockaddr_in server_addr;
212+
memset(&server_addr, 0, sizeof(server_addr));
194213
server_addr.sin_family = AF_INET;
195214
server_addr.sin_port = htons(resolve_port(port));
196-
server_addr.sin_addr.s_addr = inet_addr(host);
197215

198-
// Set socket to non-blocking
199-
fossil_nstream_set_nonblocking(ns, 1);
216+
in_addr_t addr = inet_addr(host);
217+
if (addr == INADDR_NONE) return -1; // Invalid address
200218

201-
int result = connect(ns->socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
219+
server_addr.sin_addr.s_addr = addr;
220+
221+
// Set non-blocking
222+
if (fossil_nstream_set_nonblocking(ns, 1) != 0) return -1;
202223

224+
int result = connect(ns->socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
203225
if (result < 0) {
204226
#ifdef _WIN32
205-
if (WSAGetLastError() == WSAEWOULDBLOCK) {
227+
int last_error = WSAGetLastError();
228+
if (last_error == WSAEWOULDBLOCK) {
206229
#else
207230
if (errno == EINPROGRESS) {
208231
#endif
209-
struct timeval timeout;
210-
timeout.tv_sec = timeout_ms / 1000;
211-
timeout.tv_usec = (timeout_ms % 1000) * 1000;
212-
213232
fd_set writefds;
214233
FD_ZERO(&writefds);
215234
FD_SET(ns->socket, &writefds);
216235

236+
struct timeval timeout;
237+
timeout.tv_sec = timeout_ms / 1000;
238+
timeout.tv_usec = (timeout_ms % 1000) * 1000;
239+
217240
result = select(ns->socket + 1, NULL, &writefds, NULL, &timeout);
218-
if (result <= 0) return -1; // Timeout or error
241+
if (result <= 0) {
242+
fossil_nstream_set_nonblocking(ns, 0);
243+
return -1; // Timeout or select error
244+
}
245+
246+
// Check if there was a socket error
247+
int so_error = 0;
248+
socklen_t len = sizeof(so_error);
249+
getsockopt(ns->socket, SOL_SOCKET, SO_ERROR, (char *)&so_error, &len);
250+
if (so_error != 0) {
251+
fossil_nstream_set_nonblocking(ns, 0);
252+
return -1;
253+
}
219254
} else {
220-
return -1; // Immediate error
255+
fossil_nstream_set_nonblocking(ns, 0);
256+
return -1;
221257
}
222258
}
223259

224-
// Set socket back to blocking
260+
// Set back to blocking
225261
fossil_nstream_set_nonblocking(ns, 0);
226-
227262
return 0;
228263
}
229264

@@ -280,5 +315,11 @@ ssize_t fossil_nstream_ssl_recv(fossil_nstream_t *ns, void *buf, size_t len) {
280315

281316
// Get the string representation of the last error
282317
const char *fossil_nstream_strerror(void) {
318+
#ifdef _WIN32
319+
static char buf[64];
320+
snprintf(buf, sizeof(buf), "WSA Error: %d", WSAGetLastError());
321+
return buf;
322+
#else
283323
return strerror(errno);
324+
#endif
284325
}

0 commit comments

Comments
 (0)