Line data Source code
1 :
2 : /* Copyright (c) 2005-2012, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This file is part of Collage <https://github.com/Eyescale/Collage>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "connectionDescription.h"
21 :
22 : #include <sstream>
23 :
24 : namespace co
25 : {
26 :
27 : #define SEPARATOR '#'
28 :
29 : namespace
30 : {
31 65 : static ConnectionType _getConnectionType( const std::string& string )
32 : {
33 65 : if( string == "TCPIP" )
34 65 : return CONNECTIONTYPE_TCPIP;
35 0 : if( string == "TCP" )
36 0 : return CONNECTIONTYPE_TCPIP;
37 0 : if( string == "SDP" )
38 0 : return CONNECTIONTYPE_SDP;
39 0 : if( string == "ANON_PIPE" )
40 0 : return CONNECTIONTYPE_PIPE;
41 0 : if( string == "PIPE" )
42 0 : return CONNECTIONTYPE_NAMEDPIPE;
43 0 : if( string == "RSP" )
44 0 : return CONNECTIONTYPE_RSP;
45 0 : if( string == "RDMA" )
46 0 : return CONNECTIONTYPE_RDMA;
47 0 : if( string == "UDT" )
48 0 : return CONNECTIONTYPE_UDT;
49 :
50 0 : LBWARN << "Unknown connection type: " << string << std::endl;
51 0 : return CONNECTIONTYPE_NONE;
52 : }
53 : }
54 :
55 0 : ConnectionDescription::ConnectionDescription( std::string& data )
56 : : type( CONNECTIONTYPE_TCPIP )
57 : , bandwidth( 0 )
58 : , port( 0 )
59 0 : , filename( "default" )
60 : {
61 0 : fromString( data );
62 0 : LBASSERTINFO( data.empty(), data );
63 0 : }
64 :
65 708 : std::string ConnectionDescription::toString() const
66 : {
67 708 : std::ostringstream description;
68 708 : serialize( description );
69 708 : return description.str();
70 : }
71 :
72 773 : void ConnectionDescription::serialize( std::ostream& os ) const
73 : {
74 773 : os << type << SEPARATOR << bandwidth << SEPARATOR << hostname << SEPARATOR
75 1546 : << interfacename << SEPARATOR << port << SEPARATOR << filename
76 773 : << SEPARATOR;
77 773 : }
78 :
79 65 : bool ConnectionDescription::fromString( std::string& data )
80 : {
81 : {
82 65 : size_t nextPos = data.find( SEPARATOR );
83 : // assume hostname[:port][:type] or filename:PIPE format
84 65 : if( nextPos == std::string::npos )
85 : {
86 0 : type = CONNECTIONTYPE_TCPIP;
87 0 : nextPos = data.find( ':' );
88 0 : if( nextPos == std::string::npos ) // assume hostname format
89 : {
90 0 : hostname = data;
91 0 : data.clear();
92 0 : return true;
93 : }
94 :
95 0 : hostname = data.substr( 0, nextPos );
96 0 : data = data.substr( nextPos + 1 );
97 :
98 0 : while( nextPos != std::string::npos )
99 : {
100 0 : nextPos = data.find( ':' );
101 0 : const std::string token = data.substr( 0, nextPos );
102 0 : data = data.substr( nextPos + 1 );
103 :
104 0 : if( !token.empty() && isdigit( token[0] )) // port
105 0 : port = atoi( token.c_str( ));
106 : else
107 : {
108 0 : type = _getConnectionType( token );
109 0 : if( type == CONNECTIONTYPE_NAMEDPIPE )
110 : {
111 0 : filename = hostname;
112 0 : hostname.clear();
113 : }
114 0 : else if( type == CONNECTIONTYPE_NONE )
115 0 : goto error;
116 : }
117 0 : }
118 :
119 0 : data.clear();
120 0 : return true;
121 : }
122 :
123 : // else assume SEPARATOR-delimited list
124 65 : const std::string typeStr = data.substr( 0, nextPos );
125 65 : data = data.substr( nextPos + 1 );
126 :
127 65 : type = _getConnectionType( typeStr );
128 :
129 65 : nextPos = data.find( SEPARATOR );
130 65 : if( nextPos == std::string::npos )
131 0 : goto error;
132 :
133 130 : const std::string bandwidthStr = data.substr( 0, nextPos );
134 65 : data = data.substr( nextPos + 1 );
135 65 : bandwidth = atoi( bandwidthStr.c_str( ));
136 :
137 65 : nextPos = data.find( SEPARATOR );
138 65 : if( nextPos == std::string::npos )
139 0 : goto error;
140 :
141 65 : hostname = data.substr( 0, nextPos );
142 65 : data = data.substr( nextPos + 1 );
143 :
144 65 : nextPos = data.find( SEPARATOR );
145 65 : if( nextPos == std::string::npos )
146 0 : goto error;
147 :
148 65 : interfacename = data.substr( 0, nextPos );
149 65 : data = data.substr( nextPos + 1 );
150 :
151 65 : nextPos = data.find( SEPARATOR );
152 65 : if( nextPos == std::string::npos )
153 0 : goto error;
154 :
155 130 : const std::string portStr = data.substr( 0, nextPos );
156 65 : data = data.substr( nextPos + 1 );
157 65 : port = atoi( portStr.c_str( ));
158 :
159 65 : nextPos = data.find( SEPARATOR );
160 65 : if( nextPos == std::string::npos )
161 0 : goto error;
162 :
163 65 : filename = data.substr( 0, nextPos );
164 130 : data = data.substr( nextPos + 1 );
165 : }
166 65 : return true;
167 :
168 : error:
169 0 : LBWARN << "Could not parse connection description: " << data << std::endl;
170 0 : return false;
171 : }
172 :
173 123 : void ConnectionDescription::setHostname( const std::string& hostname_ )
174 : {
175 123 : hostname = hostname_;
176 123 : }
177 :
178 1 : void ConnectionDescription::setInterface( const std::string& interface_ )
179 : {
180 1 : interfacename = interface_;
181 1 : }
182 :
183 0 : void ConnectionDescription::setFilename( const std::string& filename_ )
184 : {
185 0 : filename = filename_;
186 0 : }
187 :
188 0 : const std::string& ConnectionDescription::getFilename() const
189 : {
190 0 : return filename;
191 : }
192 :
193 242 : const std::string& ConnectionDescription::getHostname() const
194 : {
195 242 : return hostname;
196 : }
197 :
198 4 : const std::string& ConnectionDescription::getInterface() const
199 : {
200 4 : return interfacename;
201 : }
202 :
203 0 : bool ConnectionDescription::isSameMulticastGroup(
204 : ConstConnectionDescriptionPtr rhs )
205 : {
206 0 : return( type >= CONNECTIONTYPE_MULTICAST && type == rhs->type &&
207 0 : hostname == rhs->hostname && port == rhs->port );
208 : }
209 :
210 0 : bool ConnectionDescription::operator == ( const ConnectionDescription& rhs )
211 : const
212 : {
213 0 : return type == rhs.type && bandwidth == rhs.bandwidth &&
214 0 : port == rhs.port && hostname == rhs.hostname &&
215 0 : interfacename == rhs.interfacename && filename == rhs.filename;
216 : }
217 :
218 66 : std::string serialize( const ConnectionDescriptions& descriptions )
219 : {
220 66 : std::ostringstream data;
221 66 : data << descriptions.size() << CO_SEPARATOR;
222 :
223 393 : for( ConnectionDescriptions::const_iterator i = descriptions.begin();
224 262 : i != descriptions.end(); ++i )
225 : {
226 65 : ConnectionDescriptionPtr desc = *i;
227 65 : desc->serialize( data );
228 65 : }
229 :
230 66 : return data.str();
231 : }
232 :
233 66 : bool deserialize( std::string& data, ConnectionDescriptions& descriptions )
234 : {
235 66 : if( !descriptions.empty( ))
236 0 : LBWARN << "Connection descriptions already hold data before deserialize"
237 0 : << std::endl;
238 :
239 : // num connection descriptions
240 66 : size_t nextPos = data.find( CO_SEPARATOR );
241 66 : if( nextPos == std::string::npos || nextPos == 0 )
242 : {
243 0 : LBERROR << "Could not parse number of connection descriptions"
244 0 : << std::endl;
245 0 : return false;
246 : }
247 :
248 66 : const std::string sizeStr = data.substr( 0, nextPos );
249 66 : if( !isdigit( sizeStr[0] ))
250 : {
251 0 : LBERROR << "Could not parse number of connection descriptions"
252 0 : << std::endl;
253 0 : return false;
254 : }
255 :
256 66 : const size_t nDesc = atoi( sizeStr.c_str( ));
257 66 : data = data.substr( nextPos + 1 );
258 :
259 : // connection descriptions
260 131 : for( size_t i = 0; i < nDesc; ++i )
261 : {
262 65 : ConnectionDescriptionPtr desc = new ConnectionDescription;
263 65 : if( !desc->fromString( data ))
264 : {
265 0 : LBERROR << "Error during connection description parsing"
266 0 : << std::endl;
267 0 : return false;
268 : }
269 65 : descriptions.push_back( desc );
270 65 : }
271 :
272 66 : return true;
273 : }
274 :
275 0 : std::ostream& operator << ( std::ostream& os,
276 : const ConnectionDescription& desc)
277 : {
278 0 : os << lunchbox::disableFlush << lunchbox::disableHeader << "connection"
279 0 : << std::endl
280 0 : << "{" << std::endl << lunchbox::indent
281 0 : << "type " << desc.type << std::endl
282 0 : << "hostname \"" << desc.getHostname() << "\"" << std::endl;
283 :
284 0 : if( !desc.getInterface().empty( ))
285 0 : os << "interface \"" << desc.getInterface() << "\"" << std::endl;
286 :
287 0 : if( desc.port != 0 )
288 0 : os << "port " << desc.port << std::endl;
289 :
290 0 : if( !desc.getFilename().empty( ))
291 0 : os << "filename \"" << desc.getFilename() << "\"" << std::endl;
292 :
293 0 : if( desc.bandwidth != 0 )
294 0 : os << "bandwidth " << desc.bandwidth << std::endl;
295 :
296 0 : return os << lunchbox::exdent << "}" << lunchbox::enableHeader
297 0 : << lunchbox::enableFlush << std::endl;
298 : }
299 :
300 60 : }
|