1b37003a7SShuo Chen// Copyright 2010, Shuo Chen. All rights reserved. 2b37003a7SShuo Chen// http://code.google.com/p/muduo/ 3b37003a7SShuo Chen// 4b37003a7SShuo Chen// Use of this source code is governed by a BSD-style license 5b37003a7SShuo Chen// that can be found in the License file. 6b37003a7SShuo Chen 7b37003a7SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 8b37003a7SShuo Chen 9b37003a7SShuo Chen#include "SocketsOps.h" 10b37003a7SShuo Chen#include "logging/Logging.h" 11b37003a7SShuo Chen 12b37003a7SShuo Chen#include <errno.h> 13b37003a7SShuo Chen#include <fcntl.h> 14b37003a7SShuo Chen#include <stdio.h> // snprintf 15b37003a7SShuo Chen#include <strings.h> // bzero 16b37003a7SShuo Chen#include <sys/socket.h> 17b37003a7SShuo Chen#include <unistd.h> 18b37003a7SShuo Chen 19b37003a7SShuo Chenusing namespace muduo; 20b37003a7SShuo Chen 21b37003a7SShuo Chennamespace 22b37003a7SShuo Chen{ 23b37003a7SShuo Chen 24b37003a7SShuo Chentypedef struct sockaddr SA; 25b37003a7SShuo Chen 26b37003a7SShuo Chenconst SA* sockaddr_cast(const struct sockaddr_in* addr) 27b37003a7SShuo Chen{ 28b37003a7SShuo Chen return static_cast<const SA*>(implicit_cast<const void*>(addr)); 29b37003a7SShuo Chen} 30b37003a7SShuo Chen 31b37003a7SShuo ChenSA* sockaddr_cast(struct sockaddr_in* addr) 32b37003a7SShuo Chen{ 33b37003a7SShuo Chen return static_cast<SA*>(implicit_cast<void*>(addr)); 34b37003a7SShuo Chen} 35b37003a7SShuo Chen 36b37003a7SShuo Chenvoid setNonBlockAndCloseOnExec(int sockfd) 37b37003a7SShuo Chen{ 38b37003a7SShuo Chen // non-block 39b37003a7SShuo Chen int flags = ::fcntl(sockfd, F_GETFL, 0); 40b37003a7SShuo Chen flags |= O_NONBLOCK; 41b37003a7SShuo Chen int ret = ::fcntl(sockfd, F_SETFL, flags); 42b37003a7SShuo Chen // FIXME check 43b37003a7SShuo Chen 44b37003a7SShuo Chen // close-on-exec 45b37003a7SShuo Chen flags = ::fcntl(sockfd, F_GETFD, 0); 46b37003a7SShuo Chen flags |= FD_CLOEXEC; 47b37003a7SShuo Chen ret = ::fcntl(sockfd, F_SETFD, flags); 48b37003a7SShuo Chen // FIXME check 49b37003a7SShuo Chen} 50b37003a7SShuo Chen 51b37003a7SShuo Chen} 52b37003a7SShuo Chen 53b37003a7SShuo Chenint sockets::createNonblockingOrDie() 54b37003a7SShuo Chen{ 55b37003a7SShuo Chen // socket 56b37003a7SShuo Chen#if VALGRIND 57b37003a7SShuo Chen int sockfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 58b37003a7SShuo Chen if (sockfd < 0) 59b37003a7SShuo Chen { 60b37003a7SShuo Chen LOG_SYSFATAL << "sockets::createNonblockingOrDie"; 61b37003a7SShuo Chen } 62b37003a7SShuo Chen 63b37003a7SShuo Chen setNonBlockAndCloseOnExec(sockfd); 64b37003a7SShuo Chen#else 65b4a5ce52SShuo Chen int sockfd = ::socket(AF_INET, 66b4a5ce52SShuo Chen SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 67b4a5ce52SShuo Chen IPPROTO_TCP); 68b37003a7SShuo Chen if (sockfd < 0) 69b37003a7SShuo Chen { 70b37003a7SShuo Chen LOG_SYSFATAL << "sockets::createNonblockingOrDie"; 71b37003a7SShuo Chen } 72b37003a7SShuo Chen#endif 73b37003a7SShuo Chen return sockfd; 74b37003a7SShuo Chen} 75b37003a7SShuo Chen 76b37003a7SShuo Chenvoid sockets::bindOrDie(int sockfd, const struct sockaddr_in& addr) 77b37003a7SShuo Chen{ 78b37003a7SShuo Chen int ret = ::bind(sockfd, sockaddr_cast(&addr), sizeof addr); 79b37003a7SShuo Chen if (ret < 0) 80b37003a7SShuo Chen { 81b37003a7SShuo Chen LOG_SYSFATAL << "sockets::bindOrDie"; 82b37003a7SShuo Chen } 83b37003a7SShuo Chen} 84b37003a7SShuo Chen 85b37003a7SShuo Chenvoid sockets::listenOrDie(int sockfd) 86b37003a7SShuo Chen{ 87b37003a7SShuo Chen int ret = ::listen(sockfd, SOMAXCONN); 88b37003a7SShuo Chen if (ret < 0) 89b37003a7SShuo Chen { 90b37003a7SShuo Chen LOG_SYSFATAL << "sockets::listenOrDie"; 91b37003a7SShuo Chen } 92b37003a7SShuo Chen} 93b37003a7SShuo Chen 94b37003a7SShuo Chenint sockets::accept(int sockfd, struct sockaddr_in* addr) 95b37003a7SShuo Chen{ 96b37003a7SShuo Chen socklen_t addrlen = sizeof *addr; 97b37003a7SShuo Chen#if VALGRIND 98b37003a7SShuo Chen int connfd = ::accept(sockfd, sockaddr_cast(addr), &addrlen); 99b37003a7SShuo Chen setNonBlockAndCloseOnExec(connfd); 100b37003a7SShuo Chen#else 101b37003a7SShuo Chen int connfd = ::accept4(sockfd, sockaddr_cast(addr), 102b37003a7SShuo Chen &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); 103b37003a7SShuo Chen#endif 104b37003a7SShuo Chen if (connfd < 0) 105b37003a7SShuo Chen { 106b37003a7SShuo Chen int savedErrno = errno; 107b37003a7SShuo Chen LOG_SYSERR << "Socket::accept"; 108b37003a7SShuo Chen switch (savedErrno) 109b37003a7SShuo Chen { 110b37003a7SShuo Chen case EAGAIN: 111b37003a7SShuo Chen case ECONNABORTED: 112b37003a7SShuo Chen case EINTR: 113b37003a7SShuo Chen case EPROTO: // ??? 114b37003a7SShuo Chen case EPERM: 115b37003a7SShuo Chen case EMFILE: // per-process lmit of open file desctiptor ??? 116b37003a7SShuo Chen // expected errors 117b37003a7SShuo Chen errno = savedErrno; 118b37003a7SShuo Chen break; 119b37003a7SShuo Chen case EBADF: 120b37003a7SShuo Chen case EFAULT: 121b37003a7SShuo Chen case EINVAL: 122b37003a7SShuo Chen case ENFILE: 123b37003a7SShuo Chen case ENOBUFS: 124b37003a7SShuo Chen case ENOMEM: 125b37003a7SShuo Chen case ENOTSOCK: 126b37003a7SShuo Chen case EOPNOTSUPP: 127b37003a7SShuo Chen // unexpected errors 128b37003a7SShuo Chen LOG_FATAL << "unexpected error of ::accept " << savedErrno; 129b37003a7SShuo Chen break; 130b37003a7SShuo Chen default: 131b37003a7SShuo Chen LOG_FATAL << "unknown error of ::accept " << savedErrno; 132b37003a7SShuo Chen break; 133b37003a7SShuo Chen } 134b37003a7SShuo Chen } 135b37003a7SShuo Chen return connfd; 136b37003a7SShuo Chen} 137b37003a7SShuo Chen 138b37003a7SShuo Chenvoid sockets::close(int sockfd) 139b37003a7SShuo Chen{ 140b37003a7SShuo Chen if (::close(sockfd) < 0) 141b37003a7SShuo Chen { 142b37003a7SShuo Chen LOG_SYSERR << "sockets::close"; 143b37003a7SShuo Chen } 144b37003a7SShuo Chen} 145b37003a7SShuo Chen 146b37003a7SShuo Chenvoid sockets::shutdownWrite(int sockfd) 147b37003a7SShuo Chen{ 148b37003a7SShuo Chen if (::shutdown(sockfd, SHUT_WR) < 0) 149b37003a7SShuo Chen { 150b37003a7SShuo Chen LOG_SYSERR << "sockets::shutdownWrite"; 151b37003a7SShuo Chen } 152b37003a7SShuo Chen} 153b37003a7SShuo Chen 154b37003a7SShuo Chenvoid sockets::toHostPort(char* buf, size_t size, 155b37003a7SShuo Chen const struct sockaddr_in& addr) 156b37003a7SShuo Chen{ 157b37003a7SShuo Chen char host[INET_ADDRSTRLEN] = "INVALID"; 158b37003a7SShuo Chen ::inet_ntop(AF_INET, &addr.sin_addr, host, sizeof host); 159b37003a7SShuo Chen uint16_t port = sockets::networkToHost16(addr.sin_port); 160b37003a7SShuo Chen snprintf(buf, size, "%s:%u", host, port); 161b37003a7SShuo Chen} 162b37003a7SShuo Chen 163b37003a7SShuo Chenvoid sockets::fromHostPort(const char* ip, uint16_t port, 164b37003a7SShuo Chen struct sockaddr_in* addr) 165b37003a7SShuo Chen{ 166b37003a7SShuo Chen addr->sin_family = AF_INET; 167b37003a7SShuo Chen addr->sin_port = hostToNetwork16(port); 168b37003a7SShuo Chen if (::inet_pton(AF_INET, ip, &addr->sin_addr) <= 0) 169b37003a7SShuo Chen { 170b37003a7SShuo Chen LOG_SYSERR << "sockets::fromHostPort"; 171b37003a7SShuo Chen } 172b37003a7SShuo Chen} 173b37003a7SShuo Chen 174b37003a7SShuo Chenstruct sockaddr_in sockets::getLocalAddr(int sockfd) 175b37003a7SShuo Chen{ 176b37003a7SShuo Chen struct sockaddr_in localaddr; 177b37003a7SShuo Chen bzero(&localaddr, sizeof localaddr); 178b37003a7SShuo Chen socklen_t addrlen = sizeof(localaddr); 179b37003a7SShuo Chen if (::getsockname(sockfd, sockaddr_cast(&localaddr), &addrlen) < 0) 180b37003a7SShuo Chen { 181b37003a7SShuo Chen LOG_SYSERR << "sockets::getLocalAddr"; 182b37003a7SShuo Chen } 183b37003a7SShuo Chen return localaddr; 184b37003a7SShuo Chen} 185b37003a7SShuo Chen 186b37003a7SShuo Chenint sockets::getSocketError(int sockfd) 187b37003a7SShuo Chen{ 188b37003a7SShuo Chen int optval; 189b37003a7SShuo Chen socklen_t optlen = sizeof optval; 190b37003a7SShuo Chen 191b37003a7SShuo Chen if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) 192b37003a7SShuo Chen { 193b37003a7SShuo Chen return errno; 194b37003a7SShuo Chen } 195b37003a7SShuo Chen else 196b37003a7SShuo Chen { 197b37003a7SShuo Chen return optval; 198b37003a7SShuo Chen } 199b37003a7SShuo Chen} 200