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