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 65b4a5ce52SShuo Chen int sockfd = ::socket(AF_INET, 66b4a5ce52SShuo Chen SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 67b4a5ce52SShuo Chen IPPROTO_TCP); 68bfe73648SShuo Chen if (sockfd < 0) 69bfe73648SShuo Chen { 70bfe73648SShuo Chen LOG_SYSFATAL << "sockets::createNonblockingOrDie"; 71bfe73648SShuo Chen } 72bfe73648SShuo Chen#endif 73bfe73648SShuo Chen return sockfd; 74bfe73648SShuo Chen} 75bfe73648SShuo Chen 76bfe73648SShuo Chenvoid sockets::bindOrDie(int sockfd, const struct sockaddr_in& addr) 77bfe73648SShuo Chen{ 78bfe73648SShuo Chen int ret = ::bind(sockfd, sockaddr_cast(&addr), sizeof addr); 79bfe73648SShuo Chen if (ret < 0) 80bfe73648SShuo Chen { 81bfe73648SShuo Chen LOG_SYSFATAL << "sockets::bindOrDie"; 82bfe73648SShuo Chen } 83bfe73648SShuo Chen} 84bfe73648SShuo Chen 85bfe73648SShuo Chenvoid sockets::listenOrDie(int sockfd) 86bfe73648SShuo Chen{ 87bfe73648SShuo Chen int ret = ::listen(sockfd, SOMAXCONN); 88bfe73648SShuo Chen if (ret < 0) 89bfe73648SShuo Chen { 90bfe73648SShuo Chen LOG_SYSFATAL << "sockets::listenOrDie"; 91bfe73648SShuo Chen } 92bfe73648SShuo Chen} 93bfe73648SShuo Chen 94bfe73648SShuo Chenint sockets::accept(int sockfd, struct sockaddr_in* addr) 95bfe73648SShuo Chen{ 96bfe73648SShuo Chen socklen_t addrlen = sizeof *addr; 97bfe73648SShuo Chen#if VALGRIND 98bfe73648SShuo Chen int connfd = ::accept(sockfd, sockaddr_cast(addr), &addrlen); 99bfe73648SShuo Chen setNonBlockAndCloseOnExec(connfd); 100bfe73648SShuo Chen#else 101bfe73648SShuo Chen int connfd = ::accept4(sockfd, sockaddr_cast(addr), 102bfe73648SShuo Chen &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); 103bfe73648SShuo Chen#endif 104bfe73648SShuo Chen if (connfd < 0) 105bfe73648SShuo Chen { 106bfe73648SShuo Chen int savedErrno = errno; 107bfe73648SShuo Chen LOG_SYSERR << "Socket::accept"; 108bfe73648SShuo Chen switch (savedErrno) 109bfe73648SShuo Chen { 110bfe73648SShuo Chen case EAGAIN: 111bfe73648SShuo Chen case ECONNABORTED: 112bfe73648SShuo Chen case EINTR: 113bfe73648SShuo Chen case EPROTO: // ??? 114bfe73648SShuo Chen case EPERM: 115bfe73648SShuo Chen case EMFILE: // per-process lmit of open file desctiptor ??? 116bfe73648SShuo Chen // expected errors 117bfe73648SShuo Chen errno = savedErrno; 118bfe73648SShuo Chen break; 119bfe73648SShuo Chen case EBADF: 120bfe73648SShuo Chen case EFAULT: 121bfe73648SShuo Chen case EINVAL: 122bfe73648SShuo Chen case ENFILE: 123bfe73648SShuo Chen case ENOBUFS: 124bfe73648SShuo Chen case ENOMEM: 125bfe73648SShuo Chen case ENOTSOCK: 126bfe73648SShuo Chen case EOPNOTSUPP: 127bfe73648SShuo Chen // unexpected errors 128bfe73648SShuo Chen LOG_FATAL << "unexpected error of ::accept " << savedErrno; 129bfe73648SShuo Chen break; 130bfe73648SShuo Chen default: 131bfe73648SShuo Chen LOG_FATAL << "unknown error of ::accept " << savedErrno; 132bfe73648SShuo Chen break; 133bfe73648SShuo Chen } 134bfe73648SShuo Chen } 135bfe73648SShuo Chen return connfd; 136bfe73648SShuo Chen} 137bfe73648SShuo Chen 138bfe73648SShuo Chenvoid sockets::close(int sockfd) 139bfe73648SShuo Chen{ 140bfe73648SShuo Chen if (::close(sockfd) < 0) 141bfe73648SShuo Chen { 142bfe73648SShuo Chen LOG_SYSERR << "sockets::close"; 143bfe73648SShuo Chen } 144bfe73648SShuo Chen} 145bfe73648SShuo Chen 146bfe73648SShuo Chenvoid sockets::toHostPort(char* buf, size_t size, 147bfe73648SShuo Chen const struct sockaddr_in& addr) 148bfe73648SShuo Chen{ 149bfe73648SShuo Chen char host[INET_ADDRSTRLEN] = "INVALID"; 150bfe73648SShuo Chen ::inet_ntop(AF_INET, &addr.sin_addr, host, sizeof host); 151bfe73648SShuo Chen uint16_t port = sockets::networkToHost16(addr.sin_port); 152bfe73648SShuo Chen snprintf(buf, size, "%s:%u", host, port); 153bfe73648SShuo Chen} 154bfe73648SShuo Chen 155bfe73648SShuo Chenvoid sockets::fromHostPort(const char* ip, uint16_t port, 156bfe73648SShuo Chen struct sockaddr_in* addr) 157bfe73648SShuo Chen{ 158bfe73648SShuo Chen addr->sin_family = AF_INET; 159bfe73648SShuo Chen addr->sin_port = hostToNetwork16(port); 160bfe73648SShuo Chen if (::inet_pton(AF_INET, ip, &addr->sin_addr) <= 0) 161bfe73648SShuo Chen { 162bfe73648SShuo Chen LOG_SYSERR << "sockets::fromHostPort"; 163bfe73648SShuo Chen } 164bfe73648SShuo Chen} 165bfe73648SShuo Chen 166bfe73648SShuo Chenstruct sockaddr_in sockets::getLocalAddr(int sockfd) 167bfe73648SShuo Chen{ 168bfe73648SShuo Chen struct sockaddr_in localaddr; 169bfe73648SShuo Chen bzero(&localaddr, sizeof localaddr); 170bfe73648SShuo Chen socklen_t addrlen = sizeof(localaddr); 171bfe73648SShuo Chen if (::getsockname(sockfd, sockaddr_cast(&localaddr), &addrlen) < 0) 172bfe73648SShuo Chen { 173bfe73648SShuo Chen LOG_SYSERR << "sockets::getLocalAddr"; 174bfe73648SShuo Chen } 175bfe73648SShuo Chen return localaddr; 176bfe73648SShuo Chen} 177bfe73648SShuo Chen 17817c057c3SShuo Chenint sockets::getSocketError(int sockfd) 17917c057c3SShuo Chen{ 18017c057c3SShuo Chen int optval; 18117c057c3SShuo Chen socklen_t optlen = sizeof optval; 18217c057c3SShuo Chen 18317c057c3SShuo Chen if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) 18417c057c3SShuo Chen { 18517c057c3SShuo Chen return errno; 18617c057c3SShuo Chen } 18717c057c3SShuo Chen else 18817c057c3SShuo Chen { 18917c057c3SShuo Chen return optval; 19017c057c3SShuo Chen } 19117c057c3SShuo Chen} 192