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