File indexing completed on 2024-05-05 17:50:10
0001 /* 0002 Copyright (C) 2013 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 "itransport.h" 0025 0026 #include "eventdispatcher.h" 0027 #include "eventdispatcher_p.h" 0028 #include "itransportlistener.h" 0029 #include "ipsocket.h" 0030 #include "connectaddress.h" 0031 0032 #ifdef __unix__ 0033 #include "localsocket.h" 0034 #endif 0035 0036 #include <algorithm> 0037 #include <cassert> 0038 0039 ITransport::ITransport() 0040 { 0041 } 0042 0043 ITransport::~ITransport() 0044 { 0045 setReadListener(nullptr); 0046 setWriteListener(nullptr); 0047 } 0048 0049 IO::Result ITransport::readWithFileDescriptors(byte *buffer, uint32 maxSize, std::vector<int> *) 0050 { 0051 // This may be OK - if the other side tried to send file descriptors we will later notice 0052 // the difference between the message header declaring a nonzero FD count and the actual 0053 // received FD count which will always be zero if we get here. IF the other side didn't try 0054 // to send FDs, there is no problem. 0055 return read(buffer, maxSize); 0056 } 0057 0058 IO::Result ITransport::writeWithFileDescriptors(chunk, const std::vector<int> &) 0059 { 0060 // Just don't call this on a transport that doesn't support passing file descriptors 0061 IO::Result res; 0062 res.status = IO::Status::LocalClosed; 0063 return res; 0064 } 0065 0066 void ITransport::setReadListener(ITransportListener *listener) 0067 { 0068 if (m_readListener != listener) { 0069 if (m_readListener) { 0070 m_readListener->m_readTransport = nullptr; 0071 } 0072 if (listener) { 0073 if (listener->m_readTransport) { 0074 listener->m_readTransport->setReadListener(nullptr); 0075 } 0076 assert(!listener->m_readTransport); 0077 listener->m_readTransport = this; 0078 } 0079 m_readListener = listener; 0080 } 0081 updateTransportIoInterest(); 0082 } 0083 0084 void ITransport::setWriteListener(ITransportListener *listener) 0085 { 0086 if (m_writeListener != listener) { 0087 if (m_writeListener) { 0088 m_writeListener->m_writeTransport = nullptr; 0089 } 0090 if (listener) { 0091 if (listener->m_writeTransport) { 0092 listener->m_writeTransport->setWriteListener(nullptr); 0093 } 0094 assert(!listener->m_writeTransport); 0095 listener->m_writeTransport = this; 0096 } 0097 m_writeListener = listener; 0098 } 0099 updateTransportIoInterest(); 0100 } 0101 0102 void ITransport::updateTransportIoInterest() 0103 { 0104 setIoInterest((m_readListener ? uint32(IO::RW::Read) : 0) | 0105 (m_writeListener ? uint32(IO::RW::Write) : 0)); 0106 } 0107 0108 void ITransport::close() 0109 { 0110 if (!isOpen()) { 0111 return; 0112 } 0113 if (ioEventSource()) { 0114 ioEventSource()->removeIoListener(this); 0115 } 0116 platformClose(); 0117 } 0118 0119 IO::Status ITransport::handleIoReady(IO::RW rw) 0120 { 0121 IO::Status ret = IO::Status::OK; 0122 assert(uint32(rw) & ioInterest()); // only get notified about events we requested 0123 if (rw == IO::RW::Read && m_readListener) { 0124 ret = m_readListener->handleTransportCanRead(); 0125 } else if (rw == IO::RW::Write && m_writeListener) { 0126 ret = m_writeListener->handleTransportCanWrite(); 0127 } else { 0128 assert(false); 0129 } 0130 if (ret != IO::Status::OK) { 0131 // TODO call some common close, cleanup & report error method 0132 } 0133 return ret; 0134 } 0135 0136 //static 0137 ITransport *ITransport::create(const ConnectAddress &ci) 0138 { 0139 switch (ci.type()) { 0140 #ifdef __unix__ 0141 case ConnectAddress::Type::UnixPath: 0142 return new LocalSocket(ci.path()); 0143 case ConnectAddress::Type::AbstractUnixPath: // TODO this is Linux only, reflect it in code 0144 return new LocalSocket(std::string(1, '\0') + ci.path()); 0145 #endif 0146 case ConnectAddress::Type::Tcp: 0147 case ConnectAddress::Type::Tcp4: 0148 case ConnectAddress::Type::Tcp6: 0149 return new IpSocket(ci); 0150 default: 0151 assert(false); 0152 return nullptr; 0153 } 0154 }