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