Line data Source code
1 :
2 : /* Copyright (c) 2007-2012, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2011, Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This file is part of Collage <https://github.com/Eyescale/Collage>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : #include "pipeConnection.h"
22 :
23 : #include "connectionDescription.h"
24 : #include "node.h"
25 : #ifdef _WIN32
26 : #include "namedPipeConnection.h"
27 : #endif
28 :
29 : #include <lunchbox/log.h>
30 : #include <lunchbox/thread.h>
31 :
32 : #include <errno.h>
33 :
34 : namespace co
35 : {
36 214 : PipeConnection::PipeConnection()
37 : {
38 428 : ConnectionDescriptionPtr description = _getDescription();
39 214 : description->type = CONNECTIONTYPE_PIPE;
40 214 : description->bandwidth = 1024000;
41 214 : }
42 :
43 624 : PipeConnection::~PipeConnection()
44 : {
45 208 : _close();
46 416 : }
47 :
48 : //----------------------------------------------------------------------
49 : // connect
50 : //----------------------------------------------------------------------
51 107 : bool PipeConnection::connect()
52 : {
53 107 : LBASSERT(getDescription()->type == CONNECTIONTYPE_PIPE);
54 :
55 107 : if (!isClosed())
56 0 : return false;
57 :
58 107 : _setState(STATE_CONNECTING);
59 107 : _sibling = new PipeConnection;
60 107 : _sibling->_sibling = this;
61 :
62 107 : if (!_createPipes())
63 : {
64 0 : close();
65 0 : return false;
66 : }
67 :
68 107 : _setState(STATE_CONNECTED);
69 107 : _sibling->_setState(STATE_CONNECTED);
70 107 : _connected = true;
71 107 : return true;
72 : }
73 :
74 : #ifdef _WIN32
75 :
76 : Connection::Notifier PipeConnection::getNotifier() const
77 : {
78 : if (!_namedPipe)
79 : return 0;
80 : return _namedPipe->getNotifier();
81 : }
82 :
83 : bool PipeConnection::_createPipes()
84 : {
85 : std::stringstream pipeName;
86 : pipeName << "\\\\.\\pipe\\Collage." << servus::make_UUID();
87 :
88 : ConnectionDescriptionPtr desc = new ConnectionDescription;
89 : desc->type = CONNECTIONTYPE_NAMEDPIPE;
90 : desc->setFilename(pipeName.str());
91 :
92 : ConnectionPtr connection = Connection::create(desc);
93 : _namedPipe = static_cast<NamedPipeConnection*>(connection.get());
94 : if (!_namedPipe->listen())
95 : return false;
96 : _namedPipe->acceptNB();
97 :
98 : connection = Connection::create(desc);
99 : _sibling->_namedPipe = static_cast<NamedPipeConnection*>(connection.get());
100 : if (!_sibling->_namedPipe->connect())
101 : {
102 : _sibling->_namedPipe = 0;
103 : return false;
104 : }
105 :
106 : connection = _namedPipe->acceptSync();
107 : _namedPipe = static_cast<NamedPipeConnection*>(connection.get());
108 : return true;
109 : }
110 :
111 : void PipeConnection::_close()
112 : {
113 : if (isClosed())
114 : return;
115 :
116 : _connected = false;
117 : _namedPipe->close();
118 : _namedPipe = 0;
119 : _sibling = 0;
120 :
121 : _setState(STATE_CLOSED);
122 : }
123 :
124 : void PipeConnection::readNB(void* buffer, const uint64_t bytes)
125 : {
126 : if (isClosed())
127 : return;
128 : _namedPipe->readNB(buffer, bytes);
129 : }
130 :
131 : int64_t PipeConnection::readSync(void* buffer, const uint64_t bytes,
132 : const bool ignored)
133 : {
134 : if (isClosed())
135 : return -1;
136 :
137 : const int64_t bytesRead = _namedPipe->readSync(buffer, bytes, ignored);
138 :
139 : if (bytesRead == -1)
140 : close();
141 :
142 : return bytesRead;
143 : }
144 :
145 : int64_t PipeConnection::write(const void* buffer, const uint64_t bytes)
146 : {
147 : if (!isConnected())
148 : return -1;
149 :
150 : return _namedPipe->write(buffer, bytes);
151 : }
152 :
153 : #else // !_WIN32
154 :
155 107 : bool PipeConnection::_createPipes()
156 : {
157 : int pipeFDs[2];
158 107 : if (::pipe(pipeFDs) == -1)
159 : {
160 0 : LBERROR << "Could not create pipe: " << strerror(errno);
161 0 : close();
162 0 : return false;
163 : }
164 :
165 107 : _readFD = pipeFDs[0];
166 107 : _sibling->_writeFD = pipeFDs[1];
167 :
168 107 : if (::pipe(pipeFDs) == -1)
169 : {
170 0 : LBERROR << "Could not create pipe: " << strerror(errno);
171 0 : close();
172 0 : return false;
173 : }
174 :
175 107 : _sibling->_readFD = pipeFDs[0];
176 107 : _writeFD = pipeFDs[1];
177 107 : return true;
178 : }
179 :
180 369 : void PipeConnection::_close()
181 : {
182 369 : if (isClosed())
183 161 : return;
184 :
185 208 : if (_writeFD > 0)
186 : {
187 208 : ::close(_writeFD);
188 208 : _writeFD = 0;
189 : }
190 208 : if (_readFD > 0)
191 : {
192 208 : ::close(_readFD);
193 208 : _readFD = 0;
194 : }
195 :
196 208 : _connected = false;
197 208 : _setState(STATE_CLOSED);
198 208 : _sibling = 0;
199 : }
200 : #endif // else _WIN32
201 :
202 342 : ConnectionPtr PipeConnection::acceptSync()
203 : {
204 342 : _connected.waitEQ(true);
205 342 : return _sibling;
206 : }
207 63 : }
|