Skip to content

Commit c1abc3c

Browse files
Merge pull request #11 from dreamer-coding/network_io
2 parents f454a5d + 57f9342 commit c1abc3c

File tree

8 files changed

+619
-3
lines changed

8 files changed

+619
-3
lines changed

code/logic/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(TEST_CODE
1515
soap.c
1616
stream.c
1717
keyboard.c
18+
network.c
1819
)
1920

2021
# Create the library target
@@ -23,6 +24,11 @@ add_library(fossil-io STATIC ${TEST_CODE} ${HEADER_FILES})
2324
# Link the math library
2425
target_link_libraries(fossil-io PUBLIC m)
2526

27+
# Link to Winsock library only on Windows
28+
if(WIN32)
29+
target_link_libraries(fossil-io PUBLIC ws2_32)
30+
endif()
31+
2632
# Set the library to be installed
2733
install(TARGETS fossil-io
2834
ARCHIVE DESTINATION lib

code/logic/fossil/io/framework.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
// Include the necessary headers
1818
#include "keyboard.h"
19+
#include "network.h"
1920
#include "output.h"
2021
#include "input.h"
2122
#include "error.h"

code/logic/fossil/io/network.h

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* -----------------------------------------------------------------------------
3+
* Project: Fossil Logic
4+
*
5+
* This file is part of the Fossil Logic project, which aims to develop high-
6+
* performance, cross-platform applications and libraries. The code contained
7+
* herein is subject to the terms and conditions defined in the project license.
8+
*
9+
* Author: Michael Gene Brockus (Dreamer)
10+
*
11+
* Copyright (C) 2024 Fossil Logic. All rights reserved.
12+
* -----------------------------------------------------------------------------
13+
*/
14+
#ifndef FOSSIL_IO_NETWORK_H
15+
#define FOSSIL_IO_NETWORK_H
16+
17+
#include <stdint.h>
18+
19+
#ifdef _WIN32
20+
#include <winsock2.h>
21+
#include <ws2tcpip.h>
22+
typedef SOCKET fossil_io_socket_t;
23+
#define FOSSIL_IO_INVALID_SOCKET INVALID_SOCKET
24+
#else
25+
#include <sys/types.h>
26+
#include <sys/socket.h>
27+
#include <netinet/in.h>
28+
#include <arpa/inet.h>
29+
#include <unistd.h>
30+
#define closesocket close
31+
typedef int fossil_io_socket_t;
32+
#define FOSSIL_IO_INVALID_SOCKET (-1)
33+
#endif
34+
35+
#ifdef __cplusplus
36+
extern "C" {
37+
#endif
38+
39+
/**
40+
* Initialize the network stack (needed for Windows).
41+
* Returns 0 on success, non-zero on failure.
42+
*/
43+
int fossil_io_network_create(void);
44+
45+
/**
46+
* Clean up network stack (needed for Windows).
47+
*/
48+
void fossil_io_network_destroy(void);
49+
50+
/**
51+
* Create a new TCP socket.
52+
* Returns a valid socket on success or FOSSIL_IO_INVALID_SOCKET on failure.
53+
*/
54+
fossil_io_socket_t fossil_io_network_create_socket(void);
55+
56+
/**
57+
* Bind a socket to a specific port (IPv4/IPv6).
58+
* Returns 0 on success, -1 on failure.
59+
*/
60+
int fossil_io_network_bind(fossil_io_socket_t sock, const char *ip, uint16_t port);
61+
62+
/**
63+
* Listen for incoming connections.
64+
* Returns 0 on success, -1 on failure.
65+
*/
66+
int fossil_io_network_listen(fossil_io_socket_t sock, int backlog);
67+
68+
/**
69+
* Accept a new connection.
70+
* Returns a valid socket on success, or FOSSIL_IO_INVALID_SOCKET on failure.
71+
*/
72+
fossil_io_socket_t fossil_io_network_accept(fossil_io_socket_t sock, char *client_ip, uint16_t *client_port);
73+
74+
/**
75+
* Connect to a remote server.
76+
* Returns 0 on success, -1 on failure.
77+
*/
78+
int fossil_io_network_connect(fossil_io_socket_t sock, const char *ip, uint16_t port);
79+
80+
/**
81+
* Send data over a socket.
82+
* Returns the number of bytes sent, or -1 on failure.
83+
*/
84+
int fossil_io_network_send(fossil_io_socket_t sock, const void *data, size_t len);
85+
86+
/**
87+
* Receive data from a socket.
88+
* Returns the number of bytes received, or -1 on failure.
89+
*/
90+
int fossil_io_network_receive(fossil_io_socket_t sock, void *buffer, size_t len);
91+
92+
/**
93+
* Close a socket.
94+
*/
95+
void fossil_io_network_close(fossil_io_socket_t sock);
96+
97+
#ifdef __cplusplus
98+
}
99+
/**
100+
* C++ wrapper for the output functions.
101+
*/
102+
namespace fossil {
103+
/**
104+
* Namespace for input/output operations.
105+
*/
106+
namespace io {
107+
/**
108+
* Class for network operations.
109+
*/
110+
class Network {
111+
public:
112+
/**
113+
* Initialize the network stack (needed for Windows).
114+
* Returns 0 on success, non-zero on failure.
115+
*/
116+
static int init(void) {
117+
return fossil_io_network_create();
118+
}
119+
120+
/**
121+
* Clean up network stack (needed for Windows).
122+
*/
123+
static void cleanup(void) {
124+
fossil_io_network_destroy();
125+
}
126+
127+
/**
128+
* Create a new TCP socket.
129+
* Returns a valid socket on success or FOSSIL_IO_INVALID_SOCKET on failure.
130+
*/
131+
static fossil_io_socket_t create_socket(void) {
132+
return fossil_io_network_create_socket();
133+
}
134+
135+
/**
136+
* Bind a socket to a specific port (IPv4/IPv6).
137+
* Returns 0 on success, -1 on failure.
138+
*/
139+
static int bind(fossil_io_socket_t sock, const char *ip, uint16_t port) {
140+
return fossil_io_network_bind(sock, ip, port);
141+
}
142+
143+
/**
144+
* Listen for incoming connections.
145+
* Returns 0 on success, -1 on failure.
146+
*/
147+
static int listen(fossil_io_socket_t sock, int backlog) {
148+
return fossil_io_network_listen(sock, backlog);
149+
}
150+
151+
/**
152+
* Accept a new connection.
153+
* Returns a valid socket on success, or FOSSIL_IO_INVALID_SOCKET on failure.
154+
*/
155+
static fossil_io_socket_t accept(fossil_io_socket_t sock, char *client_ip, uint16_t *client_port) {
156+
return fossil_io_network_accept(sock, client_ip, client_port);
157+
}
158+
159+
/**
160+
* Connect to a remote server.
161+
* Returns 0 on success, -1 on failure.
162+
*/
163+
static int connect(fossil_io_socket_t sock, const char *ip, uint16_t port) {
164+
return fossil_io_network_connect(sock, ip, port);
165+
}
166+
167+
/**
168+
* Send data over a socket.
169+
* Returns the number of bytes sent, or -1 on failure.
170+
*/
171+
static int send(fossil_io_socket_t sock, const void *data, size_t len) {
172+
return fossil_io_network_send(sock, data, len);
173+
}
174+
175+
/**
176+
* Receive data from a socket.
177+
* Returns the number of bytes received, or -1 on failure.
178+
*/
179+
static int receive(fossil_io_socket_t sock, void *buffer, size_t len) {
180+
return fossil_io_network_receive(sock, buffer, len);
181+
}
182+
183+
/**
184+
* Close a socket.
185+
*/
186+
static void close(fossil_io_socket_t sock) {
187+
fossil_io_network_close(sock);
188+
}
189+
190+
};
191+
}
192+
}
193+
194+
#endif
195+
196+
#endif /* FOSSIL_IO_FRAMEWORK_H */

code/logic/meson.build

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
dir = include_directories('.')
22
cc = meson.get_compiler('c')
33

4+
# Check if the host system is Windows
5+
if host_machine.system() == 'windows'
6+
winsock_dep = cc.find_library('ws2_32', required: true)
7+
else
8+
winsock_dep = []
9+
endif
10+
411
fossil_io_lib = library('fossil-io',
5-
files('parser.c', 'input.c', 'output.c', 'error.c', 'soap.c', 'stream.c', 'keyboard.c'),
12+
files('parser.c', 'input.c', 'output.c', 'error.c', 'soap.c', 'stream.c', 'keyboard.c', 'network.c'),
613
install: true,
7-
dependencies: cc.find_library('m', required : false),
14+
dependencies: [cc.find_library('m', required: false), winsock_dep],
815
include_directories: dir)
916

1017
fossil_io_dep = declare_dependency(

code/logic/network.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* -----------------------------------------------------------------------------
3+
* Project: Fossil Logic
4+
*
5+
* This file is part of the Fossil Logic project, which aims to develop high-
6+
* performance, cross-platform applications and libraries. The code contained
7+
* herein is subject to the terms and conditions defined in the project license.
8+
*
9+
* Author: Michael Gene Brockus (Dreamer)
10+
*
11+
* Copyright (C) 2024 Fossil Logic. All rights reserved.
12+
* -----------------------------------------------------------------------------
13+
*/
14+
#include "fossil/io/network.h"
15+
#include <stdio.h>
16+
#include <string.h>
17+
#include <errno.h> // For POSIX error handling
18+
#include <stdlib.h> // For exit()
19+
20+
#ifdef _WIN32
21+
static WSADATA wsa;
22+
#endif
23+
24+
int fossil_io_network_create(void) {
25+
#ifdef _WIN32
26+
return WSAStartup(MAKEWORD(2, 2), &wsa);
27+
#else
28+
return 0; // No initialization needed on Unix-like systems
29+
#endif
30+
}
31+
32+
void fossil_io_network_destroy(void) {
33+
#ifdef _WIN32
34+
WSACleanup();
35+
#endif
36+
}
37+
38+
fossil_io_socket_t fossil_io_network_create_socket(void) {
39+
fossil_io_socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
40+
if (sock == FOSSIL_IO_INVALID_SOCKET) {
41+
#ifdef _WIN32
42+
fprintf(stderr, "Socket creation failed with error: %d\n", WSAGetLastError());
43+
#else
44+
perror("Socket creation failed");
45+
#endif
46+
}
47+
return sock;
48+
}
49+
50+
int fossil_io_network_bind(fossil_io_socket_t sock, const char *ip, uint16_t port) {
51+
struct sockaddr_in addr;
52+
addr.sin_family = AF_INET;
53+
addr.sin_port = htons(port);
54+
addr.sin_addr.s_addr = ip ? inet_addr(ip) : INADDR_ANY;
55+
56+
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
57+
#ifdef _WIN32
58+
fprintf(stderr, "Bind failed with error: %d\n", WSAGetLastError());
59+
#else
60+
perror("Bind failed");
61+
#endif
62+
return -1;
63+
}
64+
return 0;
65+
}
66+
67+
int fossil_io_network_listen(fossil_io_socket_t sock, int backlog) {
68+
if (listen(sock, backlog) == -1) {
69+
#ifdef _WIN32
70+
fprintf(stderr, "Listen failed with error: %d\n", WSAGetLastError());
71+
#else
72+
perror("Listen failed");
73+
#endif
74+
return -1;
75+
}
76+
return 0;
77+
}
78+
79+
fossil_io_socket_t fossil_io_network_accept(fossil_io_socket_t sock, char *client_ip, uint16_t *client_port) {
80+
struct sockaddr_in client_addr;
81+
socklen_t addr_len = sizeof(client_addr);
82+
fossil_io_socket_t client_sock = accept(sock, (struct sockaddr*)&client_addr, &addr_len);
83+
84+
if (client_sock == FOSSIL_IO_INVALID_SOCKET) {
85+
#ifdef _WIN32
86+
fprintf(stderr, "Accept failed with error: %d\n", WSAGetLastError());
87+
#else
88+
perror("Accept failed");
89+
#endif
90+
} else if (client_ip) {
91+
strcpy(client_ip, inet_ntoa(client_addr.sin_addr));
92+
if (client_port) {
93+
*client_port = ntohs(client_addr.sin_port);
94+
}
95+
}
96+
97+
return client_sock;
98+
}
99+
100+
int fossil_io_network_connect(fossil_io_socket_t sock, const char *ip, uint16_t port) {
101+
struct sockaddr_in server_addr;
102+
server_addr.sin_family = AF_INET;
103+
server_addr.sin_port = htons(port);
104+
server_addr.sin_addr.s_addr = inet_addr(ip);
105+
106+
if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
107+
#ifdef _WIN32
108+
fprintf(stderr, "Connect failed with error: %d\n", WSAGetLastError());
109+
#else
110+
perror("Connect failed");
111+
#endif
112+
return -1;
113+
}
114+
return 0;
115+
}
116+
117+
int fossil_io_network_send(fossil_io_socket_t sock, const void *data, size_t len) {
118+
int bytes_sent = send(sock, data, (int)len, 0);
119+
if (bytes_sent == -1) {
120+
#ifdef _WIN32
121+
fprintf(stderr, "Send failed with error: %d\n", WSAGetLastError());
122+
#else
123+
perror("Send failed");
124+
#endif
125+
}
126+
return bytes_sent;
127+
}
128+
129+
int fossil_io_network_receive(fossil_io_socket_t sock, void *buffer, size_t len) {
130+
int bytes_received = recv(sock, buffer, (int)len, 0);
131+
if (bytes_received == -1) {
132+
#ifdef _WIN32
133+
fprintf(stderr, "Receive failed with error: %d\n", WSAGetLastError());
134+
#else
135+
perror("Receive failed");
136+
#endif
137+
}
138+
return bytes_received;
139+
}
140+
141+
void fossil_io_network_close(fossil_io_socket_t sock) {
142+
#ifdef _WIN32
143+
if (closesocket(sock) == SOCKET_ERROR) {
144+
fprintf(stderr, "Close socket failed with error: %d\n", WSAGetLastError());
145+
}
146+
#else
147+
if (close(sock) == -1) {
148+
perror("Close socket failed");
149+
}
150+
#endif
151+
}

0 commit comments

Comments
 (0)