Warning, file /sdk/dferry/transport/ipserver.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 Copyright (C) 2014 Andreas Hartmetz <ahartmetz@gmail.com> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LGPL. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 0019 Alternatively, this file is available under the Mozilla Public License 0020 Version 1.1. You may obtain a copy of the License at 0021 http://www.mozilla.org/MPL/ 0022 */ 0023 0024 #include "ipserver.h" 0025 0026 #include "connectaddress.h" 0027 #include "ipresolver.h" 0028 0029 #include "icompletionlistener.h" 0030 #include "ipsocket.h" 0031 0032 #ifdef __unix__ 0033 #include <netinet/in.h> 0034 #include <sys/socket.h> 0035 #include <fcntl.h> 0036 #include <unistd.h> 0037 #endif 0038 #ifdef _WIN32 0039 #include <winsock2.h> 0040 #endif 0041 0042 #include <cassert> 0043 #include <cstring> 0044 0045 #include <iostream> 0046 0047 // TODO implement address family (IPv4 / IPv6) support 0048 IpServer::IpServer(const ConnectAddress &ca) 0049 : m_listenFd(-1) 0050 { 0051 assert(ca.type() == ConnectAddress::Type::Tcp); 0052 0053 const FileDescriptor fd = socket(AF_INET, SOCK_STREAM, 0); 0054 if (!isValidFileDescriptor(fd)) { 0055 std::cerr << "IpServer contruction failed A.\n"; 0056 return; 0057 } 0058 #ifdef __unix__ 0059 // don't let forks inherit the file descriptor - just in case 0060 fcntl(fd, F_SETFD, FD_CLOEXEC); 0061 #endif 0062 IpResolver resolver(ca); 0063 bool ok = resolver.resultValid(); 0064 0065 ok = ok && bind(fd, resolver.resolved(), resolver.resolvedLength()) == 0; 0066 ok = ok && (::listen(fd, /* max queued incoming connections */ 64) == 0); 0067 0068 if (ok) { 0069 m_listenFd = fd; 0070 } else { 0071 std::cerr << "IpServer contruction failed B.\n"; 0072 #ifdef _WIN32 0073 closesocket(fd); 0074 #else 0075 ::close(fd); 0076 #endif 0077 } 0078 } 0079 0080 IpServer::~IpServer() 0081 { 0082 close(); 0083 } 0084 0085 IO::Status IpServer::handleIoReady(IO::RW rw) 0086 { 0087 if (rw != IO::RW::Read) { 0088 assert(false); 0089 return IO::Status::InternalError; 0090 } 0091 FileDescriptor connFd = accept(m_listenFd, nullptr, nullptr); 0092 if (!isValidFileDescriptor(connFd)) { 0093 std::cerr << "\nIpServer::notifyRead(): accept() failed.\n\n"; 0094 return IO::Status::RemoteClosed; 0095 } 0096 #ifdef __unix__ 0097 fcntl(connFd, F_SETFD, FD_CLOEXEC); 0098 #endif 0099 m_incomingConnections.push_back(new IpSocket(connFd)); 0100 if (m_newConnectionListener) { 0101 m_newConnectionListener->handleCompletion(this); 0102 } 0103 return IO::Status::OK; 0104 } 0105 0106 bool IpServer::isListening() const 0107 { 0108 return isValidFileDescriptor(m_listenFd); 0109 } 0110 0111 void IpServer::platformClose() 0112 { 0113 if (isValidFileDescriptor(m_listenFd)) { 0114 #ifdef _WIN32 0115 closesocket(m_listenFd); 0116 #else 0117 ::close(m_listenFd); 0118 #endif 0119 m_listenFd = InvalidFileDescriptor; 0120 } 0121 } 0122 0123 FileDescriptor IpServer::fileDescriptor() const 0124 { 0125 return m_listenFd; 0126 }