1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
#define AL_LOG_SECTION "socket"
#include <al/log.h>
#include "../util/error.h"
#include "socket.h"
#include "socket_internal.h"
#include "net.h"
bool nn_socket_init(struct nn_socket *sock, s32 flags)
{
al_assert(sock->type == NNWT_SOCKET_TCP);
switch (sock->type) {
case NNWT_SOCKET_TCP:
sock->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
break;
}
if (sock->fd == INVALID_SOCKET) {
log_error("socket() failed: %d.", WSAGetLastError());
return false;
}
nn_socket_apply_flags(sock, flags);
sock->internal_fd = _open_osfhandle(sock->fd, 0);
return true;
}
void nn_socket_set_blocking(struct nn_socket *sock, bool blocking)
{
u_long mode = blocking ? 0 : 1;
ioctlsocket(sock->fd, FIONBIO, &mode);
}
void nn_socket_set_nodelay(struct nn_socket *sock, s32 nodelay)
{
(void)sock;
(void)nodelay;
}
void nn_socket_set_reuse_addr(struct nn_socket *sock, s32 reuse_addr)
{
(void)sock;
(void)reuse_addr;
}
bool nn_socket_set(struct nn_socket *sock, str *addr, u16 port)
{
(void)sock;
(void)addr;
(void)port;
return false;
}
bool nn_socket_bind(struct nn_socket *sock, str *addr, u16 port)
{
sock->addr_in.sin_family = AF_INET;
al_memset(sock->addr_in.sin_zero, '\0', sizeof(sock->addr_in.sin_zero));
sock->addr_in.sin_addr.s_addr = INADDR_ANY;
sock->addr_in.sin_port = nn_htons(port);
s32 ret = bind(sock->fd, (SOCKADDR *)&sock->addr_in, sizeof(sock->addr_in));
if (ret == SOCKET_ERROR) {
log_error("bind(%.*s:%hu) failed: %d.", nn_addr_x(addr), port, WSAGetLastError());
return false;
}
log_debug("Socket bound to %.*s:%hu.", nn_addr_x(addr), port);
return true;
}
bool nn_socket_listen(struct nn_socket *sock)
{
if (listen(sock->fd, SOMAXCONN) == SOCKET_ERROR) {
log_error("listen() failed: %d.", WSAGetLastError());
return false;
}
log_debug("Listening.");
return true;
}
bool nn_socket_accept(struct nn_socket *sock, struct nn_socket *cl, s32 flags)
{
cl->type = sock->type;
if ((cl->fd = accept(sock->fd, NULL, NULL)) == INVALID_SOCKET) {
log_error("accept() failed: %d.", WSAGetLastError());
return false;
}
nn_socket_apply_flags(sock, flags);
cl->internal_fd = _open_osfhandle(cl->fd, 0);
return true;
}
bool nn_socket_connect(struct nn_socket *sock, str *addr, u16 port)
{
sock->addr_in.sin_family = AF_INET;
al_memset(sock->addr_in.sin_zero, '\0', sizeof(sock->addr_in.sin_zero));
char *c_str = al_str_to_c_str(addr);
sock->addr_in.sin_addr.s_addr = inet_addr(c_str);
al_free(c_str);
sock->addr_in.sin_port = nn_htons(port);
s32 ret = connect(sock->fd, (SOCKADDR *)&sock->addr_in, sizeof(sock->addr_in));
if (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
log_error("connect(%.*s:%hu) failed: %d.", nn_addr_x(addr), port, WSAGetLastError());
return false;
}
return true;
}
s32 nn_socket_get_fd(struct nn_socket *sock)
{
return sock->internal_fd;
}
ssize_t nn_socket_read(struct nn_socket *sock, void *buf, size_t size)
{
return (ssize_t)recv(sock->fd, buf, (s32)size, 0);
}
ssize_t nn_socket_write(struct nn_socket *sock, void *buf, size_t size)
{
return (ssize_t)send(sock->fd, buf, (s32)size, 0);
}
ssize_t nn_socket_sendto(struct nn_socket *sock, void *buf, size_t size)
{
(void)sock;
(void)buf;
(void)size;
return 0;
}
ssize_t nn_socket_recvfrom(struct nn_socket *sock, void *buf, size_t size)
{
(void)sock;
(void)buf;
(void)size;
return 0;
}
bool nn_socket_check_error(ssize_t ret)
{
if (ret == SOCKET_ERROR) {
s32 err = WSAGetLastError();
char *strerror = nn_win32_error_message(err);
log_debug("Socket error: %s (%d).", strerror ? strerror : "(None)", err);
return true;
}
return false;
}
void nn_socket_shutdown(struct nn_socket *sock)
{
if (shutdown(sock->fd, SD_BOTH) == SOCKET_ERROR) {}
}
void nn_socket_close(struct nn_socket *sock)
{
_close(sock->internal_fd);
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/close?view=msvc-170
// Based on these docs, I assume calling closesocket() is not necessary.
//closesocket(sock->fd);
}
void nn_socket_cleanup(struct nn_socket *sock)
{
(void)sock;
}
|