#include <assert.h>
#include <stdint.h>
+#include <catta/log.h>
+
// helper: convert WSAGetLastError() to an errno constant
static int wsa_errno(void)
{
}
}
+void winsock_init(void)
+{
+ WSADATA wsa;
+ int error;
+
+ if((error = WSAStartup(MAKEWORD(2,2), &wsa)) != 0)
+ catta_log_error("WSAStartup() failed: %d", error);
+}
+
+void winsock_exit(void)
+{
+ if(WSACleanup() == SOCKET_ERROR)
+ catta_log_warn("WSACleanup() failed: %d", WSAGetLastError());
+}
+
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
{
LPFN_WSARECVMSG WSARecvMsg = NULL;
#include <mswsock.h>
+// wrappers around WSAStartup/WSACleanup to avoid clutter
+void winsock_init(void);
+void winsock_exit(void);
+
+
// Winsock doesn't have recvmsg/sendmsg but offers the same functionality
// with WSARecvMsg/WSASendMsg, so we implement the former in terms of the
// latter.
#ifndef _WIN32
#define closesocket close
+#define winsock_init()
+#define winsock_exit()
#endif
typedef struct CattaLegacyUnicastReflectSlot CattaLegacyUnicastReflectSlot;
else
catta_server_config_init(&s->config);
+ winsock_init(); // on Windows, call WSAStartup; no-op on other platforms
if ((e = setup_sockets(s)) < 0) {
if (error)
*error = e;
catta_server_config_free(&s->config);
catta_free(s);
+ winsock_exit();
return NULL;
}
catta_server_config_free(&s->config);
catta_free(s);
+ winsock_exit(); // on Windows, call WSACleanup(); no-op on other platforms
}
const char* catta_server_get_domain_name(CattaServer *s) {
if (!(s = catta_new(CattaSimplePoll, 1)))
return NULL;
+ winsock_init(); // on Windows, pipe uses sockets; no-op on other platforms
if (pipe(s->wakeup_pipe) < 0) {
catta_free(s);
+ winsock_exit();
return NULL;
}
closesocket(s->wakeup_pipe[1]);
catta_free(s);
+ winsock_exit(); // match the winsock_init in catta_simple_poll_new
}
static int rebuild(CattaSimplePoll *s) {