1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Ice/OpaqueEndpointI.h>
6 #include <Ice/OutputStream.h>
7 #include <Ice/InputStream.h>
8 #include <Ice/Exception.h>
9 #include <Ice/DefaultsAndOverrides.h>
10 #include <Ice/Base64.h>
11 #include <Ice/HashUtil.h>
12 #include <Ice/LocalException.h>
13 
14 using namespace std;
15 using namespace Ice;
16 using namespace IceInternal;
17 
18 namespace
19 {
20 
21 static string opaqueEndpointProtocol = "opaque";
22 static string opaqueEndpointConnectionId;
23 
24 }
25 
OpaqueEndpointI(vector<string> & args)26 IceInternal::OpaqueEndpointI::OpaqueEndpointI(vector<string>& args) :
27     _type(-1), _rawEncoding(Encoding_1_0)
28 {
29     initWithOptions(args);
30 
31     if(_type < 0)
32     {
33         throw EndpointParseException(__FILE__, __LINE__, "no -t option in endpoint " + toString());
34     }
35     if(_rawBytes.empty())
36     {
37         throw EndpointParseException(__FILE__, __LINE__, "no -v option in endpoint " + toString());
38     }
39 }
40 
OpaqueEndpointI(Short type,InputStream * s)41 IceInternal::OpaqueEndpointI::OpaqueEndpointI(Short type, InputStream* s) : _type(type)
42 {
43     _rawEncoding = s->getEncoding();
44     Int sz = s->getEncapsulationSize();
45     s->readBlob(const_cast<vector<Byte>&>(_rawBytes), sz);
46 }
47 
48 namespace
49 {
50 
51 class OpaqueEndpointInfoI : public Ice::OpaqueEndpointInfo
52 {
53 public:
54 
55     OpaqueEndpointInfoI(Ice::Short type, const Ice::EncodingVersion& rawEncoding, const Ice::ByteSeq& rawBytes);
56 
57     virtual Ice::Short
type() const58     type() const ICE_NOEXCEPT
59     {
60         return _type;
61     }
62 
63     virtual bool
datagram() const64     datagram() const ICE_NOEXCEPT
65     {
66         return false;
67     }
68 
69     virtual bool
secure() const70     secure() const ICE_NOEXCEPT
71     {
72         return false;
73     }
74 
75 private:
76 
77     Ice::Short _type;
78 };
79 
80 }
81 //
82 // COMPILERFIX: inlining this constructor causes crashes with gcc 4.0.1.
83 //
OpaqueEndpointInfoI(Ice::Short type,const Ice::EncodingVersion & rawEncodingP,const Ice::ByteSeq & rawBytesP)84 OpaqueEndpointInfoI::OpaqueEndpointInfoI(Ice::Short type, const Ice::EncodingVersion& rawEncodingP,
85                                          const Ice::ByteSeq& rawBytesP) :
86     Ice::OpaqueEndpointInfo(ICE_NULLPTR, -1, false, rawEncodingP, rawBytesP),
87     _type(type)
88 {
89 }
90 
91 void
streamWrite(OutputStream * s) const92 IceInternal::OpaqueEndpointI::streamWrite(OutputStream* s) const
93 {
94     s->startEncapsulation(_rawEncoding, ICE_ENUM(FormatType, DefaultFormat));
95     s->writeBlob(_rawBytes);
96     s->endEncapsulation();
97 }
98 
99 Ice::EndpointInfoPtr
getInfo() const100 IceInternal::OpaqueEndpointI::getInfo() const ICE_NOEXCEPT
101 {
102     return ICE_MAKE_SHARED(OpaqueEndpointInfoI, _type, _rawEncoding, _rawBytes);
103 }
104 
105 Short
type() const106 IceInternal::OpaqueEndpointI::type() const
107 {
108     return _type;
109 }
110 
111 const string&
protocol() const112 IceInternal::OpaqueEndpointI::protocol() const
113 {
114     return opaqueEndpointProtocol;
115 }
116 
117 Int
timeout() const118 IceInternal::OpaqueEndpointI::timeout() const
119 {
120     return -1;
121 }
122 
123 EndpointIPtr
timeout(Int) const124 IceInternal::OpaqueEndpointI::timeout(Int) const
125 {
126     return ICE_SHARED_FROM_CONST_THIS(OpaqueEndpointI);
127 }
128 
129 const string&
connectionId() const130 IceInternal::OpaqueEndpointI::connectionId() const
131 {
132     return opaqueEndpointConnectionId;
133 }
134 
135 EndpointIPtr
connectionId(const string &) const136 IceInternal::OpaqueEndpointI::connectionId(const string&) const
137 {
138     return ICE_SHARED_FROM_CONST_THIS(OpaqueEndpointI);
139 }
140 
141 bool
compress() const142 IceInternal::OpaqueEndpointI::compress() const
143 {
144     return false;
145 }
146 
147 EndpointIPtr
compress(bool) const148 IceInternal::OpaqueEndpointI::compress(bool) const
149 {
150     return ICE_SHARED_FROM_CONST_THIS(OpaqueEndpointI);
151 }
152 
153 bool
datagram() const154 IceInternal::OpaqueEndpointI::datagram() const
155 {
156     return false;
157 }
158 
159 bool
secure() const160 IceInternal::OpaqueEndpointI::secure() const
161 {
162     return false;
163 }
164 
165 TransceiverPtr
transceiver() const166 IceInternal::OpaqueEndpointI::transceiver() const
167 {
168     return ICE_NULLPTR;
169 }
170 
171 void
connectors_async(Ice::EndpointSelectionType,const EndpointI_connectorsPtr & cb) const172 IceInternal::OpaqueEndpointI::connectors_async(Ice::EndpointSelectionType, const EndpointI_connectorsPtr& cb) const
173 {
174     cb->connectors(vector<ConnectorPtr>());
175 }
176 
177 AcceptorPtr
acceptor(const string &) const178 IceInternal::OpaqueEndpointI::acceptor(const string&) const
179 {
180     return ICE_NULLPTR;
181 }
182 
183 vector<EndpointIPtr>
expandIfWildcard() const184 IceInternal::OpaqueEndpointI::expandIfWildcard() const
185 {
186     vector<EndpointIPtr> endps;
187     endps.push_back(ICE_SHARED_FROM_CONST_THIS(OpaqueEndpointI));
188     return endps;
189 }
190 
191 vector<EndpointIPtr>
expandHost(EndpointIPtr &) const192 IceInternal::OpaqueEndpointI::expandHost(EndpointIPtr&) const
193 {
194     vector<EndpointIPtr> endps;
195     endps.push_back(ICE_SHARED_FROM_CONST_THIS(OpaqueEndpointI));
196     return endps;
197 }
198 
199 bool
equivalent(const EndpointIPtr &) const200 IceInternal::OpaqueEndpointI::equivalent(const EndpointIPtr&) const
201 {
202     return false;
203 }
204 
205 Int
hash() const206 IceInternal::OpaqueEndpointI::hash() const
207 {
208     Int h = 5381;
209     hashAdd(h, type());
210     hashAdd(h, _rawEncoding.major);
211     hashAdd(h, _rawEncoding.minor);
212     hashAdd(h, _rawBytes);
213     return h;
214 }
215 
216 string
options() const217 IceInternal::OpaqueEndpointI::options() const
218 {
219     ostringstream s;
220     if(_type > -1)
221     {
222         s << " -t " << _type;
223     }
224     s << " -e " << _rawEncoding;
225     if(!_rawBytes.empty())
226     {
227         s << " -v " << Base64::encode(_rawBytes);
228     }
229     return s.str();
230 }
231 
232 bool
233 #ifdef ICE_CPP11_MAPPING
operator ==(const Endpoint & r) const234 IceInternal::OpaqueEndpointI::operator==(const Endpoint& r) const
235 #else
236 IceInternal::OpaqueEndpointI::operator==(const LocalObject& r) const
237 #endif
238 {
239     const OpaqueEndpointI* p = dynamic_cast<const OpaqueEndpointI*>(&r);
240     if(!p)
241     {
242         return false;
243     }
244 
245     if(this == p)
246     {
247         return true;
248     }
249 
250     if(_type != p->_type)
251     {
252         return false;
253     }
254 
255     if(_rawEncoding != p->_rawEncoding)
256     {
257         return false;
258     }
259 
260     if(_rawBytes != p->_rawBytes)
261     {
262         return false;
263     }
264 
265     return true;
266 }
267 
268 bool
269 #ifdef ICE_CPP11_MAPPING
operator <(const Endpoint & r) const270 IceInternal::OpaqueEndpointI::operator<(const Endpoint& r) const
271 #else
272 IceInternal::OpaqueEndpointI::operator<(const LocalObject& r) const
273 #endif
274 {
275     const OpaqueEndpointI* p = dynamic_cast<const OpaqueEndpointI*>(&r);
276     if(!p)
277     {
278         const EndpointI* e = dynamic_cast<const EndpointI*>(&r);
279         if(!e)
280         {
281             return false;
282         }
283         return type() < e->type();
284     }
285 
286     if(this == p)
287     {
288         return false;
289     }
290 
291     if(_type < p->_type)
292     {
293         return true;
294     }
295     else if(p->_type < _type)
296     {
297         return false;
298     }
299 
300     if(_rawEncoding < p->_rawEncoding)
301     {
302         return true;
303     }
304     else if(p->_rawEncoding < _rawEncoding)
305     {
306         return false;
307     }
308 
309     if(_rawBytes < p->_rawBytes)
310     {
311         return true;
312     }
313     else if(p->_rawBytes < _rawBytes)
314     {
315         return false;
316     }
317 
318     return false;
319 }
320 
321 void
streamWriteImpl(Ice::OutputStream *) const322 IceInternal::OpaqueEndpointI::streamWriteImpl(Ice::OutputStream*) const
323 {
324     assert(false);
325 }
326 
327 bool
checkOption(const string & option,const string & argument,const string & endpoint)328 IceInternal::OpaqueEndpointI::checkOption(const string& option, const string& argument, const string& endpoint)
329 {
330     switch(option[1])
331     {
332     case 't':
333     {
334         if(_type > -1)
335         {
336             throw EndpointParseException(__FILE__, __LINE__, "multiple -t options in endpoint " + endpoint);
337         }
338         if(argument.empty())
339         {
340             throw EndpointParseException(__FILE__, __LINE__, "no argument provided for -t option in endpoint " +
341                                          endpoint);
342         }
343         istringstream p(argument);
344         Ice::Int t;
345         if(!(p >> t) || !p.eof())
346         {
347             throw EndpointParseException(__FILE__, __LINE__, "invalid type value `" + argument + "' in endpoint " +
348                                          endpoint);
349         }
350         else if(t < 0 || t > 65535)
351         {
352             throw EndpointParseException(__FILE__, __LINE__, "type value `" + argument + "' out of range in endpoint " +
353                                          endpoint);
354         }
355         _type = static_cast<Ice::Short>(t);
356         return true;
357     }
358 
359     case 'v':
360     {
361         if(!_rawBytes.empty())
362         {
363             throw EndpointParseException(__FILE__, __LINE__, "multiple -v options in endpoint " + endpoint);
364         }
365         if(argument.empty())
366         {
367             throw EndpointParseException(__FILE__, __LINE__, "no argument provided for -v option in endpoint " + endpoint);
368         }
369         for(string::size_type i = 0; i < argument.size(); ++i)
370         {
371             if(!Base64::isBase64(argument[i]))
372             {
373                 ostringstream os;
374                 os << "invalid base64 character `" << argument[i] << "' (ordinal " << static_cast<int>(argument[i])
375                    << ") in endpoint " << endpoint;
376                 throw EndpointParseException(__FILE__, __LINE__, os.str());
377             }
378         }
379         const_cast<vector<Byte>&>(_rawBytes) = Base64::decode(argument);
380         return true;
381     }
382 
383     case 'e':
384     {
385         if(argument.empty())
386         {
387             throw Ice::EndpointParseException(__FILE__, __LINE__, "no argument provided for -e option in endpoint " +
388                                               endpoint);
389         }
390 
391         try
392         {
393             _rawEncoding = Ice::stringToEncodingVersion(argument);
394         }
395         catch(const Ice::VersionParseException& ex)
396         {
397             throw Ice::EndpointParseException(__FILE__, __LINE__, "invalid encoding version `" + argument +
398                                               "' in endpoint " + endpoint + ":\n" + ex.str);
399         }
400         return true;
401     }
402 
403     default:
404     {
405         return false;
406     }
407     }
408 }
409