summaryrefslogtreecommitdiff
path: root/src/net_unix.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/net_unix.h')
-rw-r--r--src/net_unix.h409
1 files changed, 0 insertions, 409 deletions
diff --git a/src/net_unix.h b/src/net_unix.h
deleted file mode 100644
index ab5bac7..0000000
--- a/src/net_unix.h
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
-Copyright (C) 2012 skuller.net
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-//
-// net_unix.h -- BSD sockets wrapper
-//
-
-static const char *os_error_string(int err)
-{
- return strerror(err);
-}
-
-// Receiving ICMP errors on unconnected UDP sockets is tricky...
-// Linux 2.2 and higher supports this via IP_RECVERR option, see ip(7).
-// What about BSD?
-
-#if USE_ICMP && (defined __linux__)
-
-static qboolean check_offender(const struct sockaddr_in *from,
- const struct sockaddr_in *to)
-{
- if (!to)
- return qfalse;
-
- if (from->sin_addr.s_addr != to->sin_addr.s_addr)
- return qfalse;
-
- if (from->sin_port && from->sin_port != to->sin_port)
- return qfalse;
-
- Com_DPrintf("%s: found offending address %s:%d\n", "process_error_queue",
- inet_ntoa(from->sin_addr), ntohs(from->sin_port));
-
- return qtrue;
-}
-
-// Returns true if failed socket operation should be retried.
-// May get called from NET_SendPacket() path, avoid interfering with net_from.
-static qboolean process_error_queue(netsrc_t sock, const struct sockaddr_in *to_addr)
-{
- byte buffer[1024];
- struct sockaddr_in from_addr;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- struct sock_extended_err *ee;
- netadr_t from;
- int tries;
- qboolean found = qfalse;
-
- for (tries = 0; tries < MAX_ERROR_RETRIES; tries++) {
- memset(&from_addr, 0, sizeof(from_addr));
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = &from_addr;
- msg.msg_namelen = sizeof(from_addr);
- msg.msg_control = buffer;
- msg.msg_controllen = sizeof(buffer);
-
- if (recvmsg(udp_sockets[sock], &msg, MSG_ERRQUEUE) == -1) {
- if (errno != EWOULDBLOCK)
- Com_DPrintf("%s: %s\n", __func__, strerror(errno));
- break;
- }
-
- if (!(msg.msg_flags & MSG_ERRQUEUE)) {
- Com_DPrintf("%s: no extended error received\n", __func__);
- break;
- }
-
- // find an ICMP error message
- for (cmsg = CMSG_FIRSTHDR(&msg);
- cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level != IPPROTO_IP) {
- continue;
- }
- if (cmsg->cmsg_type != IP_RECVERR) {
- continue;
- }
- ee = (struct sock_extended_err *)CMSG_DATA(cmsg);
- if (ee->ee_origin == SO_EE_ORIGIN_ICMP) {
- break;
- }
- }
-
- if (!cmsg) {
- Com_DPrintf("%s: no ICMP error found\n", __func__);
- break;
- }
-
- found |= check_offender(&from_addr, to_addr);
-
- NET_SockadrToNetadr(&from_addr, &from);
-
- // handle ICMP error
- NET_ErrorEvent(sock, &from, ee->ee_errno, ee->ee_info);
- }
-
- return !!tries && !found;
-}
-
-#endif // !__linux__
-
-static ssize_t os_udp_recv(netsrc_t sock, void *data,
- size_t len, netadr_t *from)
-{
- struct sockaddr_in addr;
- socklen_t addrlen;
- ssize_t ret;
-
-#if USE_ICMP && (defined __linux__)
- int tries;
- for (tries = 0; tries < MAX_ERROR_RETRIES; tries++) {
-#endif
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
- ret = recvfrom(udp_sockets[sock], data, len, 0,
- (struct sockaddr *)&addr, &addrlen);
-
- NET_SockadrToNetadr(&addr, from);
-
- if (ret >= 0)
- return ret;
-
- net_error = errno;
-
- // wouldblock is silent
- if (net_error == EWOULDBLOCK)
- return NET_AGAIN;
-
-#if USE_ICMP && (defined __linux__)
- // recvfrom() fails on Linux if there is an ICMP originated pending
- // error on socket. Suck up error queue and retry...
-
- if (!process_error_queue(sock, NULL))
- break;
- }
-#endif
-
- return NET_ERROR;
-}
-
-static ssize_t os_udp_send(netsrc_t sock, const void *data,
- size_t len, const netadr_t *to)
-{
- struct sockaddr_in addr;
- ssize_t ret;
-
- NET_NetadrToSockadr(to, &addr);
-
-#if USE_ICMP && (defined __linux__)
- int tries;
- for (tries = 0; tries < MAX_ERROR_RETRIES; tries++) {
-#endif
- ret = sendto(udp_sockets[sock], data, len, 0,
- (struct sockaddr *)&addr, sizeof(addr));
- if (ret >= 0)
- return ret;
-
- net_error = errno;
-
- // wouldblock is silent
- if (net_error == EWOULDBLOCK)
- return NET_AGAIN;
-
-#if USE_ICMP && (defined __linux__)
- // sendto() fails on Linux if there is an ICMP originated pending error
- // on socket. Suck up error queue and retry...
- //
- // But how do I distingiush between a failure caused by completely
- // unrelated ICMP error sitting in the queue and an error directly
- // related to this sendto() call?
- //
- // On one hand, I don't want to drop packets to legitimate clients, and
- // have to retry sendto() after processing error queue. On other
- // hand, infinite loop should be avoided if sendto() call regenerates
- // the message in error queue.
- //
- // This mess is worked around by passing destination address to
- // process_error_queue() and checking if this address/port pair is
- // found in the queue. If it is found, or the queue is empty, do not
- // retry.
-
- if (!process_error_queue(sock, &addr))
- break;
- }
-#endif
-
- return NET_ERROR;
-}
-
-static neterr_t os_get_error(void)
-{
- net_error = errno;
- if (net_error == EWOULDBLOCK)
- return NET_AGAIN;
-
- return NET_ERROR;
-}
-
-static ssize_t os_recv(qsocket_t sock, void *data, size_t len, int flags)
-{
- ssize_t ret = recv(sock, data, len, flags);
-
- if (ret == -1)
- return os_get_error();
-
- return ret;
-}
-
-static ssize_t os_send(qsocket_t sock, const void *data, size_t len, int flags)
-{
- ssize_t ret = send(sock, data, len, flags);
-
- if (ret == -1)
- return os_get_error();
-
- return ret;
-}
-
-static neterr_t os_listen(qsocket_t sock, int backlog)
-{
- if (listen(sock, backlog) == -1) {
- net_error = errno;
- return NET_ERROR;
- }
-
- return NET_OK;
-}
-
-static neterr_t os_accept(qsocket_t sock, qsocket_t *newsock, netadr_t *from)
-{
- struct sockaddr_in addr;
- socklen_t addrlen;
- int s;
-
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
- s = accept(sock, (struct sockaddr *)&addr, &addrlen);
-
- NET_SockadrToNetadr(&addr, from);
-
- if (s == -1) {
- *newsock = -1;
- return os_get_error();
- }
-
- *newsock = s;
- return NET_OK;
-}
-
-static neterr_t os_connect(qsocket_t sock, const netadr_t *to)
-{
- struct sockaddr_in addr;
-
- NET_NetadrToSockadr(to, &addr);
-
- if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
- net_error = errno;
- if (net_error == EINPROGRESS)
- return NET_OK;
-
- return NET_ERROR;
- }
-
- return NET_OK;
-}
-
-static neterr_t os_make_nonblock(qsocket_t sock, int val)
-{
- if (ioctl(sock, FIONBIO, &val) == -1) {
- net_error = errno;
- return NET_ERROR;
- }
-
- return NET_OK;
-}
-
-static neterr_t os_setsockopt(qsocket_t sock, int level, int name, int val)
-{
- if (setsockopt(sock, level, name, &val, sizeof(val)) == -1) {
- net_error = errno;
- return NET_ERROR;
- }
-
- return NET_OK;
-}
-
-static neterr_t os_getsockopt(qsocket_t sock, int level, int name, int *val)
-{
- socklen_t _optlen = sizeof(*val);
-
- if (getsockopt(sock, level, name, val, &_optlen) == -1) {
- net_error = errno;
- return NET_ERROR;
- }
-
- return NET_OK;
-}
-
-static neterr_t os_bind(qsocket_t sock, const struct sockaddr *addr, size_t addrlen)
-{
- if (bind(sock, addr, addrlen) == -1) {
- net_error = errno;
- return NET_ERROR;
- }
-
- return NET_OK;
-}
-
-static neterr_t os_getsockname(qsocket_t sock, netadr_t *name)
-{
- struct sockaddr_in addr;
- socklen_t addrlen;
-
- memset(&addr, 0, sizeof(addr));
- addrlen = sizeof(addr);
- if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) == -1) {
- net_error = errno;
- return NET_ERROR;
- }
-
- NET_SockadrToNetadr(&addr, name);
- return NET_OK;
-}
-
-static void os_closesocket(qsocket_t sock)
-{
- close(sock);
-}
-
-static qsocket_t os_socket(int domain, int type, int protocol)
-{
- int s = socket(domain, type, protocol);
-
- if (s == -1) {
- net_error = errno;
- return -1;
- }
-
- return s;
-}
-
-static ioentry_t *_os_get_io(qsocket_t fd, const char *func)
-{
- if (fd < 0 || fd >= FD_SETSIZE)
- Com_Error(ERR_FATAL, "%s: fd out of range: %d", func, fd);
-
- return &io_entries[fd];
-}
-
-static ioentry_t *os_add_io(qsocket_t fd)
-{
- if (fd >= io_numfds) {
- io_numfds = fd + 1;
- }
-
- return _os_get_io(fd, __func__);
-}
-
-static ioentry_t *os_get_io(qsocket_t fd)
-{
- return _os_get_io(fd, __func__);
-}
-
-static qsocket_t os_get_fd(ioentry_t *e)
-{
- return e - io_entries;
-}
-
-static int os_select(int nfds, fd_set *rfds, fd_set *wfds,
- fd_set *efds, struct timeval *tv)
-{
- int ret = select(nfds, rfds, wfds, efds, tv);
-
- if (ret == -1) {
- net_error = errno;
- if (net_error == EINTR)
- return 0;
- }
-
- return ret;
-}
-
-static void os_net_init(void)
-{
-}
-
-static void os_net_shutdown(void)
-{
-}
-