File indexing completed on 2024-04-28 16:59:42
0001 /* 0002 Copyright (C) 2017 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 "server.h" 0025 0026 #include "connectaddress.h" 0027 #include "connection.h" 0028 #include "eventdispatcher_p.h" 0029 #include "icompletionlistener.h" 0030 #include "iioeventforwarder.h" 0031 #include "inewconnectionlistener.h" 0032 #include "iserver.h" 0033 #include "itransport.h" 0034 0035 #include <cassert> 0036 0037 class ServerPrivate : public IIoEventForwarder, public ICompletionListener 0038 { 0039 public: 0040 ServerPrivate(EventDispatcher *dispatcher); 0041 0042 // IIOEventForwarder 0043 IO::Status handleIoReady(IO::RW rw) override; 0044 0045 // ICompletionListener 0046 void handleCompletion(void *transportServer) override; 0047 0048 ConnectAddress listenAddress; 0049 ConnectAddress concreteAddress; 0050 EventDispatcher *eventDispatcher; 0051 Server *server; 0052 INewConnectionListener *newConnectionListener; 0053 IServer *transportServer; 0054 }; 0055 0056 ServerPrivate::ServerPrivate(EventDispatcher *dispatcher) 0057 : IIoEventForwarder(EventDispatcherPrivate::get(dispatcher)), 0058 eventDispatcher(dispatcher) 0059 { 0060 } 0061 0062 IO::Status ServerPrivate::handleIoReady(IO::RW rw) 0063 { 0064 const IO::Status ret = transportServer->handleIoReady(rw); 0065 // ### error handling? But there is no possible permanent error with an already listening socket. 0066 return ret; 0067 } 0068 0069 void ServerPrivate::handleCompletion(void *task) 0070 { 0071 assert(task == transportServer); 0072 (void) task; 0073 if (newConnectionListener) { 0074 newConnectionListener->handleNewConnection(server); 0075 } 0076 } 0077 0078 Server::Server(EventDispatcher *dispatcher, const ConnectAddress &listenAddress) 0079 : d(new ServerPrivate(dispatcher)) 0080 { 0081 #if 0 0082 if (ca.bus() == ConnectAddress::Bus::None || ca.socketType() == ConnectAddress::AddressType::None || 0083 ca.role() == ConnectAddress::Role::None || 0084 (ca.role() != ConnectAddress::Role::Server && ca.isServerOnly())) { 0085 cerr << "\nConnection: connection constructor Exit A\n\n"; 0086 return; 0087 } 0088 #endif 0089 d->listenAddress = listenAddress; 0090 d->server = this; 0091 d->newConnectionListener = nullptr; 0092 d->transportServer = IServer::create(listenAddress, &d->concreteAddress); 0093 if (d->transportServer && d->transportServer->isListening()) { 0094 d->addIoListener(d->transportServer); 0095 d->transportServer->setNewConnectionListener(d); 0096 } else { 0097 delete d->transportServer; 0098 d->transportServer = nullptr; 0099 } 0100 0101 } 0102 0103 Server::~Server() 0104 { 0105 delete d->transportServer; 0106 0107 delete d; 0108 d = nullptr; 0109 } 0110 0111 void Server::setNewConnectionListener(INewConnectionListener *listener) 0112 { 0113 d->newConnectionListener = listener; 0114 } 0115 0116 INewConnectionListener *Server::newConnectionListener() const 0117 { 0118 return d->newConnectionListener; 0119 } 0120 0121 Connection *Server::takeNextClient() 0122 { 0123 // TODO proper error handling / propagation 0124 if (!d->transportServer) { 0125 return nullptr; 0126 } 0127 ITransport *newTransport = d->transportServer->takeNextClient(); 0128 if (!newTransport) { 0129 return nullptr; 0130 } 0131 0132 return new Connection(newTransport, d->eventDispatcher, d->concreteAddress); 0133 } 0134 0135 bool Server::isListening() const 0136 { 0137 return d->transportServer ? d->transportServer->isListening() : false; 0138 } 0139 0140 ConnectAddress Server::listenAddress() const 0141 { 0142 return d->listenAddress; 0143 } 0144 0145 ConnectAddress Server::concreteAddress() const 0146 { 0147 return d->concreteAddress; 0148 }