📄 core.c
字号:
/* * core.c - socket and file descriptor core implementations * * Copyright (C) 2001 Stefan Jahn <stefan@lkcc.org> * * This 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, or (at your option) * any later version. * * This software 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 package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: core.c,v 1.21 2001/09/15 16:10:58 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#ifndef __MINGW32__# include <sys/socket.h># include <netinet/in.h># include <arpa/inet.h>#endif#if HAVE_UNISTD_H# include <unistd.h>#endif#if HAVE_NETINET_TCP_H# include <netinet/tcp.h>#endif#if HAVE_SYS_SENDFILE_H# include <sys/sendfile.h>#endif#if defined (HAVE_SYS_UIO_H) && defined (__FreeBSD__)# include <sys/uio.h>#endif#ifdef __MINGW32__# include <winsock2.h>#endif#if HAVE_MSWSOCK_H# include <mswsock.h>#endif#include "libserveez/util.h"#include "libserveez/core.h"/* * Set the given file descriptor to nonblocking I/O. This heavily differs * in Win32 and Unix. The given file descriptor @var{fd} must be a socket * descriptor under Win32, otherwise the function fails. Return zero on * success, otherwise non-zero. */intsvz_fd_nonblock (int fd){#ifdef __MINGW32__ unsigned long blockMode = 1; if (ioctlsocket (fd, FIONBIO, &blockMode) == SOCKET_ERROR) { svz_log (LOG_ERROR, "ioctlsocket: %s\n", NET_ERROR); return -1; }#else /* not __MINGW32__ */ int flag; flag = fcntl (fd, F_GETFL); if (fcntl (fd, F_SETFL, flag | O_NONBLOCK) < 0) { svz_log (LOG_ERROR, "fcntl: %s\n", NET_ERROR); return -1; }#endif /* not __MINGW32__ */ return 0;}/* * Set the given file descriptor to blocking I/O. This routine is the * counter part to @code{svz_fd_nonblock()}. */intsvz_fd_block (int fd){#ifdef __MINGW32__ unsigned long blockMode = 0; if (ioctlsocket (fd, FIONBIO, &blockMode) == SOCKET_ERROR) { svz_log (LOG_ERROR, "ioctlsocket: %s\n", NET_ERROR); return -1; }#else /* not __MINGW32__ */ int flag; flag = fcntl (fd, F_GETFL); if (fcntl (fd, F_SETFL, flag & ~O_NONBLOCK) < 0) { svz_log (LOG_ERROR, "fcntl: %s\n", NET_ERROR); return -1; }#endif /* not __MINGW32__ */ return 0;}/* * Set the close-on-exec flag of the given file descriptor @var{fd} and * return zero on success. Otherwise return non-zero. */intsvz_fd_cloexec (int fd){#ifndef __MINGW32__ /* * ... SNIP : from the cygwin mail archives 1999/05 ... * The problem is in socket() call on W95 - the socket returned * is non-inheritable handle (unlike NT and Unixes, where * sockets are inheritable). To fix the problem DuplicateHandle * call is used to create inheritable handle, and original * handle is closed. * ... SNAP ... * * Thus here is NO NEED to set the FD_CLOEXEC flag and no * chance anyway. */ int flag; flag = fcntl (fd, F_GETFD); if ((fcntl (fd, F_SETFD, flag | FD_CLOEXEC)) < 0) { svz_log (LOG_ERROR, "fcntl: %s\n", NET_ERROR); return -1; }#endif /* !__MINGW32__ */ return 0;}/* * Create a new non-blocking socket which does not get inherited on * @code{exec()}. The protocol is specified by @var{proto}. Return the * socket descriptor or -1 on errors. */SOCKETsvz_socket_create (int proto){ int stype; /* socket type (STREAM or DGRAM or RAW) */ int ptype; /* protocol type (IP or UDP or ICMP) */ SOCKET sockfd; /* Assign the appropriate socket type. */ switch (proto) { case PROTO_TCP: stype = SOCK_STREAM; ptype = IPPROTO_IP; break; case PROTO_UDP: stype = SOCK_DGRAM; ptype = IPPROTO_UDP; break; case PROTO_ICMP: stype = SOCK_RAW; ptype = IPPROTO_ICMP; break; /* This protocol is for sending packets only. The kernel filters any received packets by the socket protocol (here: IPPROTO_RAW which is unspecified). */ case PROTO_RAW: stype = SOCK_RAW; ptype = IPPROTO_RAW; break; default: stype = SOCK_STREAM; ptype = IPPROTO_IP; break; } /* Create a socket for communication with a server. */ if ((sockfd = socket (AF_INET, stype, ptype)) == INVALID_SOCKET) { svz_log (LOG_ERROR, "socket: %s\n", NET_ERROR); return (SOCKET) -1; } /* Make the socket non-blocking. */ if (svz_fd_nonblock (sockfd) != 0) { closesocket (sockfd); return (SOCKET) -1; } /* Do not inherit this socket. */ if (svz_fd_cloexec (sockfd) != 0) { closesocket (sockfd); return (SOCKET) -1; } return sockfd;}/* * Connect the given socket descriptor @var{sockfd} to the host @var{host} * at the network port @var{port}. Return non-zero on errors. */intsvz_socket_connect (SOCKET sockfd, unsigned long host, unsigned short port){ struct sockaddr_in server; int error; /* Setup the server address. */ server.sin_family = AF_INET; server.sin_addr.s_addr = host; server.sin_port = port; /* Try to connect to the server, */ if (connect (sockfd, (struct sockaddr *) &server, sizeof (server)) == -1) {#ifdef __MINGW32__ error = WSAGetLastError ();#else error = errno;#endif if (error != SOCK_INPROGRESS && error != SOCK_UNAVAILABLE) { svz_log (LOG_ERROR, "connect: %s\n", NET_ERROR); closesocket (sockfd); return -1; }#if ENABLE_DEBUG svz_log (LOG_DEBUG, "connect: %s\n", NET_ERROR);#endif } return 0;}/* * Converts the given ip address @var{ip} to the dotted decimal * representation. The string is a statically allocated buffer, please * copy the result. The given ip address MUST be in network byte order. */char *svz_inet_ntoa (unsigned long ip){#if !BROKEN_INET_NTOA struct in_addr addr; addr.s_addr = ip; return inet_ntoa (addr);#else /* BROKEN_INET_NTOA */ static char addr[16]; /* * Now, this is strange: IP is given in host byte order. Nevertheless * conversion is endian-specific. To the binary AND and SHIFT operations * work differently on different architectures ? */ sprintf (addr, "%lu.%lu.%lu.%lu",#if WORDS_BIGENDIAN (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);#else /* Little Endian */ ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);#endif return addr;#endif /* BROKEN_INET_NTOA */}/* * Converts the Internet host address @var{str} from the standard * numbers-and-dots notation into binary data and stores it in the * structure that @var{addr} points to. @code{svz_inet_aton()} returns * zero if the address is valid, nonzero if not. * This function handles an ip address of "*" special and sets * @code{INADDR_ANY} for it. */intsvz_inet_aton (char *str, struct sockaddr_in *addr){#ifdef __MINGW32__ int len;#endif /* Handle "*" special: use INADDR_ANY for it */ if (!strcmp (str, "*")) { /* FIXME: does that work ? */ addr->sin_addr.s_addr = INADDR_ANY; return 0; }#if HAVE_INET_ATON if (inet_aton (str, &addr->sin_addr) == 0) { return -1; }#elif defined (__MINGW32__) len = sizeof (struct sockaddr_in); if (WSAStringToAddress (str, AF_INET, NULL, (struct sockaddr *) addr, &len) != 0) { return -1; }#else /* not HAVE_INET_ATON and not __MINGW32__ */ addr->sin_addr.s_addr = inet_addr (str);#endif /* not HAVE_INET_ATON */ return 0;}/* * Enable or disable the @code{TCP_CORK} socket option of the given socket * descriptor @var{fd}. This is useful for performance reasons when using * @code{sendfile()} with any prepending or trailing data not inside the * file to transmit. The function return zero on success, otherwise non-zero. */intsvz_tcp_cork (SOCKET fd, int set){#ifdef TCP_CORK int flags; /* get current socket options */ if ((flags = fcntl (fd, F_GETFL)) < 0) { svz_log (LOG_ERROR, "fcntl: %s\n", NET_ERROR); return -1; } /* set or unset the cork option */ flags = set ? flags | TCP_CORK : flags & ~TCP_CORK; /* apply new socket option */ if (fcntl (fd, F_SETFL, flags) < 0) { svz_log (LOG_ERROR, "fcntl: %s\n", NET_ERROR); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -