comparison seobeo/s_linux_network.c @ 4:0b3b4f5887bb

[Seobeo] Updated so that it create socket for both server and clients.
author June Park <parkjune1995@gmail.com>
date Fri, 26 Sep 2025 15:14:46 -0700
parents 2758f5527d2b
children 1e61008b9980
comparison
equal deleted inserted replaced
3:2758f5527d2b 4:0b3b4f5887bb
1 #include "seobeo/seobeo.h" 1 #include "seobeo/seobeo.h"
2 2
3 int Seobeo_CreateSocket(int32 stream, char* port, int32 backlog) 3 int Seobeo_CreateSocket(int32 stream, const char *host, const char* port, int32 backlog)
4 { 4 {
5 int32 sock_fd; 5 struct addrinfo hints = {0}, *server_infos, *free_server_info;
6 struct addrinfo hints, *server_infos, *free_server_info; 6 int32 sock_fd, yes = 1; // Need this for setsockopt
7 int32 yes = 1; // Need this for setsockopt 7
8 8 hints.ai_family = AF_INET;
9 memset(&hints, 0, sizeof(hints)); 9 hints.ai_socktype = stream ? SOCK_STREAM : SOCK_DGRAM;
10 if (stream) 10 hints.ai_protocol = stream ? IPPROTO_TCP : IPPROTO_UDP;
11 { 11 hints.ai_flags = stream ? AI_PASSIVE : 0;
12 hints.ai_family = AF_INET; 12
13 hints.ai_socktype = SOCK_STREAM; 13 if (getaddrinfo(host, port, &hints, &server_infos) != 0)
14 hints.ai_protocol = IPPROTO_TCP;
15 hints.ai_flags = AI_PASSIVE;
16 }
17 else
18 {
19 hints.ai_family = AF_INET;
20 hints.ai_socktype = SOCK_DGRAM;
21 hints.ai_protocol = IPPROTO_UDP;
22 hints.ai_flags = AI_PASSIVE;
23 }
24
25
26 if (getaddrinfo(NULL, port, &hints, &server_infos) != 0)
27 { 14 {
28 perror("getaddrinfo"); 15 perror("getaddrinfo");
29 return -1; 16 return -1;
30 } 17 }
31 18
60 perror("setsockopt"); 47 perror("setsockopt");
61 continue; 48 continue;
62 } 49 }
63 50
64 // UDP should be non blocking 51 // UDP should be non blocking
65 if(!stream) 52 if(!stream)
66 { 53 {
67 if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) != 0) 54 if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) != 0)
68 { 55 {
69 close(sock_fd); 56 close(sock_fd);
70 perror("v_network: Couldn't make socket non-blocking\n"); 57 perror("v_network: Couldn't make socket non-blocking\n");
71 return -1; 58 return -1;
72 } 59 }
73 } 60 }
74 61
75 // binded to a open server infos; 62 // binded to a open server infos;
76 break; 63 break;
77 } 64 }
84 perror("No free server"); 71 perror("No free server");
85 return -1; 72 return -1;
86 } 73 }
87 74
88 // TCP listen 75 // TCP listen
89 if(stream) 76 if(stream)
90 { 77 {
91 if (listen(sock_fd, backlog) != 0) 78 if (listen(sock_fd, backlog) != 0)
92 { 79 {
93 perror("listen"); 80 perror("listen");
81 close(sock_fd);
94 return -1; 82 return -1;
95 } 83 }
96 } 84 }
97 85
98 return sock_fd; 86 return sock_fd;
99 } 87 }
100 88
101 89 Seobeo_PHandle Seobeo_Stream_Handle_Create(const char *host, const char* port)
102 void Seobeo_ListenClient(int sock_fd, void (*handle_client)(int)) 90 {
103 { 91 Seobeo_PHandle p_handle;
104 int32 client_fd; 92 p_handle = malloc(sizeof(*p_handle));
105 struct sockaddr_storage client_addr; 93
106 socklen_t sin_size; 94 p_handle->socket = Seobeo_CreateSocket(1, host, port, 10); // socke fd
107 95 p_handle->host = host != NULL ? strdup(host) : "localhost";
96 p_handle->port = strdup(port);
97
98 p_handle->read_buffer = malloc(sizeof(*p_handle->read_buffer) * INITIAL_BUFFER_CAPACITY);
99 p_handle->read_buffer_capacity = INITIAL_BUFFER_CAPACITY;
100 p_handle->read_buffer_len = 0;
101
102 p_handle->write_buffer = malloc(sizeof(*p_handle->read_buffer) * INITIAL_BUFFER_CAPACITY);
103 p_handle->write_buffer_capacity = INITIAL_BUFFER_CAPACITY;
104 p_handle->write_buffer_len = 0;
105
106 p_handle->file = NULL;
107 p_handle->text_copy = NULL;
108 p_handle->file_name = NULL;
109
110 return p_handle;
111 }
112
113 Seobeo_PHandle Seobeo_Stream_Handle_Accept(Seobeo_PHandle server_h)
114 {
115 struct sockaddr_storage addr;
116 socklen_t addrlen = sizeof addr;
108 char client_inet_addr[INET6_ADDRSTRLEN]; 117 char client_inet_addr[INET6_ADDRSTRLEN];
109 118 int client_fd = accept(server_h->socket,
110 while (1) 119 (struct sockaddr*)&addr,
111 { 120 &addrlen);
112 sin_size = sizeof(client_addr); 121 inet_ntop(
113 client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size); 122 addr.ss_family,
114 123 Seobeo_GetIP4OrIP6((struct sockaddr *)&addr),
115 if (client_fd == -1) 124 client_inet_addr, sizeof client_inet_addr);
125
126 if (client_fd == -1)
127 {
128 return NULL;
129 }
130
131 Seobeo_PHandle h = malloc(sizeof *h);
132
133 h->socket = client_fd;
134 h->host = strdup(client_inet_addr);
135 h->port = NULL;
136
137 h->read_buffer_capacity = server_h->read_buffer_capacity;
138 h->read_buffer_len = 0;
139 h->read_buffer = malloc(h->read_buffer_capacity);
140
141 h->write_buffer_capacity = server_h->write_buffer_capacity;
142 h->write_buffer_len = 0;
143 h->write_buffer = malloc(h->write_buffer_capacity);
144
145 return h;
146 }
147
148 void Seobeo_Handle_Destroy(Seobeo_PHandle h)
149 {
150 close(h->socket);
151 free(h->host);
152 free(h->port);
153 free(h->read_buffer);
154 free(h->write_buffer);
155 free(h->file);
156 free(h->text_copy);
157 free(h->file_name);
158 free(h);
159 }
160
161 int Seobeo_Handle_Flush(Seobeo_PHandle h)
162 {
163 uint32 total = h->write_buffer_len;
164 uint32 sent = 0;
165
166 while (sent < total) {
167 ssize_t n = write(
168 h->socket,
169 h->write_buffer + sent,
170 total - sent
171 );
172 if (n < 0) {
173 if (errno == EINTR) continue;
174 if (errno == EAGAIN) return 1;
175 return -1;
176 }
177 sent += (uint32)n;
178 }
179
180 h->write_buffer_len = 0;
181 return 0;
182 }
183
184
185 int Seobeo_Handle_QueueData(Seobeo_PHandle h, const uint8_t *data, uint32_t data_size)
186 {
187 if (h->write_buffer_len + data_size > h->write_buffer_capacity) {
188 int rc = Seobeo_Handle_Flush(h);
189 if (rc < 0) return -1;
190 if (rc > 0) return 1;
191 }
192
193 if (data_size > h->write_buffer_capacity)
194 {
195 uint32_t offset = 0;
196 while (offset < data_size)
116 { 197 {
117 perror("accept"); 198 ssize_t n = write(h->socket,
118 break; 199 data + offset,
119 } 200 data_size - offset);
120 201 if (n < 0) {
121 inet_ntop( 202 if (errno == EINTR) continue;
122 client_addr.ss_family, 203 if (errno == EAGAIN) return 1;
123 Seobeo_GetIP4OrIP6((struct sockaddr *)&client_addr), 204 return -1;
124 client_inet_addr, sizeof client_inet_addr); 205 }
125 206 offset += (uint32_t)n;
126 printf("server: got connection from %s\n", client_inet_addr); 207 }
127 208 return 0;
128 // Create a child process 209 }
129 if (!fork()) 210
130 { 211 memcpy(h->write_buffer + h->write_buffer_len,
131 close(sock_fd); 212 data,
132 handle_client(client_fd); 213 data_size);
133 exit(0); 214 h->write_buffer_len += data_size;
134 } 215 return 0;
135
136 close(client_fd);
137 }
138 } 216 }
139 217
140 void *Seobeo_GetIP4OrIP6(struct sockaddr *sa) 218 void *Seobeo_GetIP4OrIP6(struct sockaddr *sa)
141 { 219 {
142 if (sa->sa_family == AF_INET) 220 if (sa->sa_family == AF_INET)