diff options
author | Andrey Nazarov <skuller@skuller.net> | 2012-07-24 19:36:31 +0400 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2012-07-24 20:55:04 +0400 |
commit | 0b5a71869a4fd08524ea9c2a986b4744d0913e30 (patch) | |
tree | f50eea3188d5a221a8d3e2455d6635eddec9e35a /src/net_unix.h | |
parent | 009390601fe318af50cde0f7f3449ed65365ea29 (diff) |
Rework source tree layout.
Instead of having a mix of semi-randomly prefixed .c and .h files at
src/, split the sources and public headers into src/ and inc/
directories. Further partition them down per subsystem. Add include
guards to public headers. Split some headers into multiple ones.
Diffstat (limited to 'src/net_unix.h')
-rw-r--r-- | src/net_unix.h | 409 |
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) -{ -} - |