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