1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <IceBT/EndpointI.h>
6 #include <IceBT/AcceptorI.h>
7 #include <IceBT/ConnectorI.h>
8 #include <IceBT/Engine.h>
9 #include <IceBT/Instance.h>
10 #include <IceBT/Util.h>
11
12 #include <Ice/LocalException.h>
13 #include <Ice/DefaultsAndOverrides.h>
14 #include <Ice/HashUtil.h>
15 #include <Ice/Object.h>
16 #include <Ice/Properties.h>
17 #include <Ice/UUID.h>
18 #include <IceUtil/StringUtil.h>
19
20 using namespace std;
21 using namespace Ice;
22 using namespace IceBT;
23
24 #ifndef ICE_CPP11_MAPPING
upCast(EndpointI * p)25 IceUtil::Shared* IceBT::upCast(EndpointI* p) { return p; }
26 #endif
27
EndpointI(const InstancePtr & instance,const string & addr,const string & uuid,const string & name,Int channel,Int timeout,const string & connectionId,bool compress)28 IceBT::EndpointI::EndpointI(const InstancePtr& instance, const string& addr, const string& uuid, const string& name,
29 Int channel, Int timeout, const string& connectionId, bool compress) :
30 _instance(instance),
31 _addr(addr),
32 _uuid(uuid),
33 _name(name),
34 _channel(channel),
35 _timeout(timeout),
36 _connectionId(connectionId),
37 _compress(compress),
38 _hashValue(0)
39 {
40 hashInit();
41 }
42
EndpointI(const InstancePtr & instance)43 IceBT::EndpointI::EndpointI(const InstancePtr& instance) :
44 _instance(instance),
45 _channel(0),
46 _timeout(instance->defaultTimeout()),
47 _compress(false),
48 _hashValue(0)
49 {
50 }
51
EndpointI(const InstancePtr & instance,InputStream * s)52 IceBT::EndpointI::EndpointI(const InstancePtr& instance, InputStream* s) :
53 _instance(instance),
54 _channel(0),
55 _timeout(-1),
56 _compress(false),
57 _hashValue(0)
58 {
59 //
60 // _name and _channel are not marshaled.
61 //
62 s->read(const_cast<string&>(_addr), false);
63 s->read(const_cast<string&>(_uuid), false);
64 s->read(const_cast<Int&>(_timeout));
65 s->read(const_cast<bool&>(_compress));
66 hashInit();
67 }
68
69 void
streamWriteImpl(OutputStream * s) const70 IceBT::EndpointI::streamWriteImpl(OutputStream* s) const
71 {
72 //
73 // _name and _channel are not marshaled.
74 //
75 s->write(_addr, false);
76 s->write(_uuid, false);
77 s->write(_timeout);
78 s->write(_compress);
79 }
80
81 Ice::Short
type() const82 IceBT::EndpointI::type() const
83 {
84 return _instance->type();
85 }
86
87 const string&
protocol() const88 IceBT::EndpointI::protocol() const
89 {
90 return _instance->protocol();
91 }
92
93 Int
timeout() const94 IceBT::EndpointI::timeout() const
95 {
96 return _timeout;
97 }
98
99 IceInternal::EndpointIPtr
timeout(Int timeout) const100 IceBT::EndpointI::timeout(Int timeout) const
101 {
102 if(timeout == _timeout)
103 {
104 return ICE_SHARED_FROM_CONST_THIS(EndpointI);
105 }
106 else
107 {
108 return ICE_MAKE_SHARED(EndpointI, _instance, _addr, _uuid, _name, _channel, timeout, _connectionId, _compress);
109 }
110 }
111
112 const string&
connectionId() const113 IceBT::EndpointI::connectionId() const
114 {
115 return _connectionId;
116 }
117
118 IceInternal::EndpointIPtr
connectionId(const string & connectionId) const119 IceBT::EndpointI::connectionId(const string& connectionId) const
120 {
121 if(connectionId == _connectionId)
122 {
123 return ICE_SHARED_FROM_CONST_THIS(EndpointI);
124 }
125 else
126 {
127 return ICE_MAKE_SHARED(EndpointI, _instance, _addr, _uuid, _name, _channel, _timeout, connectionId, _compress);
128 }
129 }
130
131 bool
compress() const132 IceBT::EndpointI::compress() const
133 {
134 return _compress;
135 }
136
137 IceInternal::EndpointIPtr
compress(bool compress) const138 IceBT::EndpointI::compress(bool compress) const
139 {
140 if(compress == _compress)
141 {
142 return ICE_SHARED_FROM_CONST_THIS(EndpointI);
143 }
144 else
145 {
146 return ICE_MAKE_SHARED(EndpointI, _instance, _addr, _uuid, _name, _channel, _timeout, _connectionId, compress);
147 }
148 }
149
150 bool
datagram() const151 IceBT::EndpointI::datagram() const
152 {
153 return false;
154 }
155
156 bool
secure() const157 IceBT::EndpointI::secure() const
158 {
159 return _instance->secure();
160 }
161
162 IceInternal::TransceiverPtr
transceiver() const163 IceBT::EndpointI::transceiver() const
164 {
165 return 0;
166 }
167
168 void
connectors_async(EndpointSelectionType,const IceInternal::EndpointI_connectorsPtr & cb) const169 IceBT::EndpointI::connectors_async(EndpointSelectionType /*selType*/, const IceInternal::EndpointI_connectorsPtr& cb) const
170 {
171 vector<IceInternal::ConnectorPtr> connectors;
172 connectors.push_back(new ConnectorI(_instance, _addr, _uuid, _timeout, _connectionId));
173 cb->connectors(connectors);
174 }
175
176 IceInternal::AcceptorPtr
acceptor(const string & adapterName) const177 IceBT::EndpointI::acceptor(const string& adapterName) const
178 {
179 return new AcceptorI(ICE_SHARED_FROM_CONST_THIS(EndpointI), _instance, adapterName, _addr, _uuid, _name, _channel);
180 }
181
182 vector<IceInternal::EndpointIPtr>
expandIfWildcard() const183 IceBT::EndpointI::expandIfWildcard() const
184 {
185 vector<IceInternal::EndpointIPtr> endps;
186
187 if(_addr.empty())
188 {
189 //
190 // getDefaultAdapterAddress will raise BluetoothException if no adapter is present.
191 //
192 string addr = _instance->engine()->getDefaultAdapterAddress();
193 endps.push_back(ICE_MAKE_SHARED(EndpointI, _instance, addr, _uuid, _name, _channel, _timeout, _connectionId,
194 _compress));
195 }
196 else
197 {
198 endps.push_back(ICE_SHARED_FROM_CONST_THIS(EndpointI));
199 }
200
201 return endps;
202 }
203
204 vector<IceInternal::EndpointIPtr>
expandHost(IceInternal::EndpointIPtr &) const205 IceBT::EndpointI::expandHost(IceInternal::EndpointIPtr&) const
206 {
207 //
208 // Nothing to do here.
209 //
210 vector<IceInternal::EndpointIPtr> endps;
211 endps.push_back(ICE_SHARED_FROM_CONST_THIS(EndpointI));
212 return endps;
213 }
214
215 bool
equivalent(const IceInternal::EndpointIPtr & endpoint) const216 IceBT::EndpointI::equivalent(const IceInternal::EndpointIPtr& endpoint) const
217 {
218 const EndpointI* btEndpointI = dynamic_cast<const EndpointI*>(endpoint.get());
219 if(!btEndpointI)
220 {
221 return false;
222 }
223 return btEndpointI->type() == type() && btEndpointI->_addr == _addr && btEndpointI->_uuid == _uuid;
224 }
225
226 bool
227 #ifdef ICE_CPP11_MAPPING
operator ==(const Ice::Endpoint & r) const228 IceBT::EndpointI::operator==(const Ice::Endpoint& r) const
229 #else
230 IceBT::EndpointI::operator==(const Ice::LocalObject& r) const
231 #endif
232 {
233 const EndpointI* p = dynamic_cast<const EndpointI*>(&r);
234 if(!p)
235 {
236 return false;
237 }
238
239 if(this == p)
240 {
241 return true;
242 }
243
244 if(_addr != p->_addr)
245 {
246 return false;
247 }
248
249 if(_uuid != p->_uuid)
250 {
251 return false;
252 }
253
254 if(_connectionId != p->_connectionId)
255 {
256 return false;
257 }
258
259 if(_channel != p->_channel)
260 {
261 return false;
262 }
263
264 if(_timeout != p->_timeout)
265 {
266 return false;
267 }
268
269 if(_compress != p->_compress)
270 {
271 return false;
272 }
273
274 return true;
275 }
276
277 bool
278 #ifdef ICE_CPP11_MAPPING
operator <(const Ice::Endpoint & r) const279 IceBT::EndpointI::operator<(const Ice::Endpoint& r) const
280 #else
281 IceBT::EndpointI::operator<(const Ice::LocalObject& r) const
282 #endif
283 {
284 const EndpointI* p = dynamic_cast<const EndpointI*>(&r);
285 if(!p)
286 {
287 const IceInternal::EndpointI* e = dynamic_cast<const IceInternal::EndpointI*>(&r);
288 if(!e)
289 {
290 return false;
291 }
292 return type() < e->type();
293 }
294
295 if(this == p)
296 {
297 return false;
298 }
299
300 if(type() < p->type())
301 {
302 return true;
303 }
304 else if(p->type() < type())
305 {
306 return false;
307 }
308
309 if(_addr < p->_addr)
310 {
311 return true;
312 }
313 else if(p->_addr < _addr)
314 {
315 return false;
316 }
317
318 if(_uuid < p->_uuid)
319 {
320 return true;
321 }
322 else if(p->_uuid < _uuid)
323 {
324 return false;
325 }
326
327 if(_connectionId < p->_connectionId)
328 {
329 return true;
330 }
331 else if(p->_connectionId < _connectionId)
332 {
333 return false;
334 }
335
336 if(_channel < p->_channel)
337 {
338 return true;
339 }
340 else if(p->_channel < _channel)
341 {
342 return false;
343 }
344
345 if(_timeout < p->_timeout)
346 {
347 return true;
348 }
349 else if(p->_timeout < _timeout)
350 {
351 return false;
352 }
353
354 if(!_compress && p->_compress)
355 {
356 return true;
357 }
358 else if(p->_compress < _compress)
359 {
360 return false;
361 }
362
363 return false;
364 }
365
366 Ice::Int
hash() const367 IceBT::EndpointI::hash() const
368 {
369 return _hashValue;
370 }
371
372 string
options() const373 IceBT::EndpointI::options() const
374 {
375 //
376 // WARNING: Certain features, such as proxy validation in Glacier2,
377 // depend on the format of proxy strings. Changes to toString() and
378 // methods called to generate parts of the reference string could break
379 // these features. Please review for all features that depend on the
380 // format of proxyToString() before changing this and related code.
381 //
382 ostringstream s;
383
384 if(!_addr.empty())
385 {
386 s << " -a ";
387 bool addQuote = _addr.find(':') != string::npos;
388 if(addQuote)
389 {
390 s << "\"";
391 }
392 s << _addr;
393 if(addQuote)
394 {
395 s << "\"";
396 }
397 }
398
399 if(!_uuid.empty())
400 {
401 s << " -u ";
402 bool addQuote = _uuid.find(':') != string::npos;
403 if(addQuote)
404 {
405 s << "\"";
406 }
407 s << _uuid;
408 if(addQuote)
409 {
410 s << "\"";
411 }
412 }
413
414 if(_channel > 0)
415 {
416 s << " -c " << _channel;
417 }
418
419 if(_timeout == -1)
420 {
421 s << " -t infinite";
422 }
423 else
424 {
425 s << " -t " << _timeout;
426 }
427
428 if(_compress)
429 {
430 s << " -z";
431 }
432
433 return s.str();
434 }
435
436 Ice::EndpointInfoPtr
getInfo() const437 IceBT::EndpointI::getInfo() const ICE_NOEXCEPT
438 {
439 EndpointInfoPtr info = ICE_MAKE_SHARED(EndpointInfoI, ICE_SHARED_FROM_CONST_THIS(EndpointI));
440 info->addr = _addr;
441 info->uuid = _uuid;
442 return info;
443 }
444
445 void
initWithOptions(vector<string> & args,bool oaEndpoint)446 IceBT::EndpointI::initWithOptions(vector<string>& args, bool oaEndpoint)
447 {
448 IceInternal::EndpointI::initWithOptions(args);
449
450 if(_addr.empty())
451 {
452 const_cast<string&>(_addr) = _instance->defaultHost();
453 }
454 else if(_addr == "*")
455 {
456 if(oaEndpoint)
457 {
458 const_cast<string&>(_addr) = string();
459 }
460 else
461 {
462 throw EndpointParseException(__FILE__, __LINE__,
463 "`-a *' not valid for proxy endpoint `" + toString() + "'");
464 }
465 }
466
467 if(_name.empty())
468 {
469 const_cast<string&>(_name) = "Ice Service";
470 }
471
472 if(_uuid.empty())
473 {
474 if(oaEndpoint)
475 {
476 //
477 // Generate a UUID for object adapters that don't specify one.
478 //
479 const_cast<string&>(_uuid) = generateUUID();
480 }
481 else
482 {
483 throw EndpointParseException(__FILE__, __LINE__, "a UUID must be specified using the -u option");
484 }
485 }
486
487 if(_channel < 0)
488 {
489 const_cast<Int&>(_channel) = 0;
490 }
491
492 if(!oaEndpoint && _channel != 0)
493 {
494 throw EndpointParseException(__FILE__, __LINE__, "the -c option can only be used for object adapter endpoints");
495 }
496
497 hashInit();
498 }
499
500 IceBT::EndpointIPtr
endpoint(const AcceptorIPtr & acceptor) const501 IceBT::EndpointI::endpoint(const AcceptorIPtr& acceptor) const
502 {
503 return ICE_MAKE_SHARED(EndpointI, _instance, _addr, _uuid, _name, acceptor->effectiveChannel(), _timeout,
504 _connectionId, _compress);
505 }
506
507 void
hashInit()508 IceBT::EndpointI::hashInit()
509 {
510 Int h = 5381;
511 IceInternal::hashAdd(h, _addr);
512 IceInternal::hashAdd(h, _uuid);
513 IceInternal::hashAdd(h, _timeout);
514 IceInternal::hashAdd(h, _connectionId);
515 IceInternal::hashAdd(h, _compress);
516 const_cast<Int&>(_hashValue) = h;
517 }
518
519 bool
checkOption(const string & option,const string & argument,const string & endpoint)520 IceBT::EndpointI::checkOption(const string& option, const string& argument, const string& endpoint)
521 {
522 string arg = IceUtilInternal::trim(argument);
523 if(option == "-a")
524 {
525 if(arg.empty())
526 {
527 throw EndpointParseException(__FILE__, __LINE__, "no argument provided for -a option in endpoint " +
528 endpoint);
529 }
530 if(arg != "*" && !isValidDeviceAddress(arg))
531 {
532 throw EndpointParseException(__FILE__, __LINE__, "invalid argument provided for -a option in endpoint " +
533 endpoint);
534 }
535 const_cast<string&>(_addr) = arg;
536 }
537 else if(option == "-u")
538 {
539 if(arg.empty())
540 {
541 throw EndpointParseException(__FILE__, __LINE__, "no argument provided for -u option in endpoint " +
542 endpoint);
543 }
544 const_cast<string&>(_uuid) = arg;
545 }
546 else if(option == "-c")
547 {
548 if(arg.empty())
549 {
550 throw EndpointParseException(__FILE__, __LINE__, "no argument provided for -c option in endpoint " +
551 endpoint);
552 }
553
554 istringstream t(argument);
555 if(!(t >> const_cast<Int&>(_channel)) || !t.eof() || _channel < 0 || _channel > 30)
556 {
557 throw EndpointParseException(__FILE__, __LINE__, "invalid channel value `" + arg + "' in endpoint " +
558 endpoint);
559 }
560 }
561 else if(option == "-t")
562 {
563 if(arg.empty())
564 {
565 throw EndpointParseException(__FILE__, __LINE__, "no argument provided for -t option in endpoint " +
566 endpoint);
567 }
568
569 if(arg == "infinite")
570 {
571 const_cast<Int&>(_timeout) = -1;
572 }
573 else
574 {
575 istringstream t(argument);
576 if(!(t >> const_cast<Int&>(_timeout)) || !t.eof() || _timeout < 1)
577 {
578 throw EndpointParseException(__FILE__, __LINE__, "invalid timeout value `" + arg + "' in endpoint " +
579 endpoint);
580 }
581 }
582 }
583 else if(option == "-z")
584 {
585 if(!arg.empty())
586 {
587 throw EndpointParseException(__FILE__, __LINE__, "unexpected argument `" + arg +
588 "' provided for -z option in " + endpoint);
589 }
590 const_cast<bool&>(_compress) = true;
591 }
592 else if(option == "--name")
593 {
594 if(arg.empty())
595 {
596 throw EndpointParseException(__FILE__, __LINE__, "no argument provided for --name option in endpoint " +
597 endpoint);
598 }
599 const_cast<string&>(_name) = arg;
600 }
601 else
602 {
603 return false;
604 }
605 return true;
606 }
607
EndpointInfoI(const EndpointIPtr & endpoint)608 IceBT::EndpointInfoI::EndpointInfoI(const EndpointIPtr& endpoint) : _endpoint(endpoint)
609 {
610 }
611
~EndpointInfoI()612 IceBT::EndpointInfoI::~EndpointInfoI()
613 {
614 }
615
616 Ice::Short
type() const617 IceBT::EndpointInfoI::type() const ICE_NOEXCEPT
618 {
619 return _endpoint->type();
620 }
621
622 bool
datagram() const623 IceBT::EndpointInfoI::datagram() const ICE_NOEXCEPT
624 {
625 return _endpoint->datagram();
626 }
627
628 bool
secure() const629 IceBT::EndpointInfoI::secure() const ICE_NOEXCEPT
630 {
631 return _endpoint->secure();
632 }
633
EndpointFactoryI(const InstancePtr & instance)634 IceBT::EndpointFactoryI::EndpointFactoryI(const InstancePtr& instance) : _instance(instance)
635 {
636 }
637
~EndpointFactoryI()638 IceBT::EndpointFactoryI::~EndpointFactoryI()
639 {
640 }
641
642 Short
type() const643 IceBT::EndpointFactoryI::type() const
644 {
645 return _instance->type();
646 }
647
648 string
protocol() const649 IceBT::EndpointFactoryI::protocol() const
650 {
651 return _instance->protocol();
652 }
653
654 IceInternal::EndpointIPtr
create(vector<string> & args,bool oaEndpoint) const655 IceBT::EndpointFactoryI::create(vector<string>& args, bool oaEndpoint) const
656 {
657 EndpointIPtr endpt = ICE_MAKE_SHARED(EndpointI, _instance);
658 endpt->initWithOptions(args, oaEndpoint);
659 return endpt;
660 }
661
662 IceInternal::EndpointIPtr
read(InputStream * s) const663 IceBT::EndpointFactoryI::read(InputStream* s) const
664 {
665 return ICE_MAKE_SHARED(EndpointI, _instance, s);
666 }
667
668 void
destroy()669 IceBT::EndpointFactoryI::destroy()
670 {
671 _instance = 0;
672 }
673
674 IceInternal::EndpointFactoryPtr
clone(const IceInternal::ProtocolInstancePtr & instance) const675 IceBT::EndpointFactoryI::clone(const IceInternal::ProtocolInstancePtr& instance) const
676 {
677 return new EndpointFactoryI(new Instance(_instance->engine(), instance->type(), instance->protocol()));
678 }
679