1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 using System;
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.Text;
9 using System.Globalization;
10 
11 namespace IceInternal
12 {
13     public abstract class Reference : ICloneable
14     {
15         public enum Mode {
16                             ModeTwoway,
17                             ModeOneway,
18                             ModeBatchOneway,
19                             ModeDatagram,
20                             ModeBatchDatagram,
21                             ModeLast=ModeBatchDatagram
22                          };
23 
24         public interface GetConnectionCallback
25         {
setConnection(Ice.ConnectionI connection, bool compress)26             void setConnection(Ice.ConnectionI connection, bool compress);
setException(Ice.LocalException ex)27             void setException(Ice.LocalException ex);
28         }
29 
getMode()30         public Mode getMode()
31         {
32             return _mode;
33         }
34 
getSecure()35         public bool getSecure()
36         {
37             return secure_;
38         }
39 
getProtocol()40         public Ice.ProtocolVersion getProtocol()
41         {
42             return _protocol;
43         }
44 
getEncoding()45         public Ice.EncodingVersion getEncoding()
46         {
47             return _encoding;
48         }
49 
getIdentity()50         public Ice.Identity getIdentity()
51         {
52             return _identity;
53         }
54 
getFacet()55         public string getFacet()
56         {
57             return _facet;
58         }
59 
getInstance()60         public Instance getInstance()
61         {
62             return _instance;
63         }
64 
getContext()65         public Dictionary<string, string> getContext()
66         {
67             return _context;
68         }
69 
70         public int
getInvocationTimeout()71         getInvocationTimeout()
72         {
73             return _invocationTimeout;
74         }
75 
76         public Ice.Optional<bool>
getCompress()77         getCompress()
78         {
79             return overrideCompress_ ? compress_ : new Ice.Optional<bool>();
80         }
81 
getCommunicator()82         public Ice.Communicator getCommunicator()
83         {
84             return _communicator;
85         }
86 
getEndpoints()87         public abstract EndpointI[] getEndpoints();
getAdapterId()88         public abstract string getAdapterId();
getLocatorInfo()89         public abstract LocatorInfo getLocatorInfo();
getRouterInfo()90         public abstract RouterInfo getRouterInfo();
getCollocationOptimized()91         public abstract bool getCollocationOptimized();
getCacheConnection()92         public abstract bool getCacheConnection();
getPreferSecure()93         public abstract bool getPreferSecure();
getEndpointSelection()94         public abstract Ice.EndpointSelectionType getEndpointSelection();
getLocatorCacheTimeout()95         public abstract int getLocatorCacheTimeout();
getConnectionId()96         public abstract string getConnectionId();
getTimeout()97         public abstract Ice.Optional<int> getTimeout();
getThreadPool()98         public abstract ThreadPool getThreadPool();
99 
100         //
101         // The change* methods (here and in derived classes) create
102         // a new reference based on the existing one, with the
103         // corresponding value changed.
104         //
changeContext(Dictionary<string, string> newContext)105         public Reference changeContext(Dictionary<string, string> newContext)
106         {
107             if(newContext == null)
108             {
109                 newContext = _emptyContext;
110             }
111             Reference r = _instance.referenceFactory().copy(this);
112             if(newContext.Count == 0)
113             {
114                 r._context = _emptyContext;
115             }
116             else
117             {
118                 r._context = new Dictionary<string, string>(newContext);
119             }
120             return r;
121         }
122 
changeMode(Mode newMode)123         public Reference changeMode(Mode newMode)
124         {
125             if(newMode == _mode)
126             {
127                 return this;
128             }
129             Reference r = _instance.referenceFactory().copy(this);
130             r._mode = newMode;
131             return r;
132         }
133 
changeSecure(bool newSecure)134         public Reference changeSecure(bool newSecure)
135         {
136             if(newSecure == secure_)
137             {
138                 return this;
139             }
140             Reference r = _instance.referenceFactory().copy(this);
141             r.secure_ = newSecure;
142             return r;
143         }
144 
changeIdentity(Ice.Identity newIdentity)145         public Reference changeIdentity(Ice.Identity newIdentity)
146         {
147             if(newIdentity.Equals(_identity))
148             {
149                 return this;
150             }
151             Reference r = _instance.referenceFactory().copy(this);
152             r._identity = newIdentity; // Identity is a value type, therefore a copy of newIdentity is made.
153             return r;
154         }
155 
changeFacet(string newFacet)156         public Reference changeFacet(string newFacet)
157         {
158             if(newFacet.Equals(_facet))
159             {
160                 return this;
161             }
162             Reference r = _instance.referenceFactory().copy(this);
163             r._facet = newFacet;
164             return r;
165         }
166 
changeInvocationTimeout(int newTimeout)167         public Reference changeInvocationTimeout(int newTimeout)
168         {
169             if(newTimeout == _invocationTimeout)
170             {
171                 return this;
172             }
173             Reference r = _instance.referenceFactory().copy(this);
174             r._invocationTimeout = newTimeout;
175             return r;
176         }
177 
changeEncoding(Ice.EncodingVersion newEncoding)178         public virtual Reference changeEncoding(Ice.EncodingVersion newEncoding)
179         {
180             if(newEncoding.Equals(_encoding))
181             {
182                 return this;
183             }
184             Reference r = _instance.referenceFactory().copy(this);
185             r._encoding = newEncoding;
186             return r;
187         }
188 
changeCompress(bool newCompress)189         public virtual Reference changeCompress(bool newCompress)
190         {
191             if(overrideCompress_ && compress_ == newCompress)
192             {
193                 return this;
194             }
195 
196             Reference r = _instance.referenceFactory().copy(this);
197             r.compress_ = newCompress;
198             r.overrideCompress_ = true;
199             return r;
200         }
201 
changeEndpoints(EndpointI[] newEndpoints)202         public abstract Reference changeEndpoints(EndpointI[] newEndpoints);
changeAdapterId(string newAdapterId)203         public abstract Reference changeAdapterId(string newAdapterId);
changeLocator(Ice.LocatorPrx newLocator)204         public abstract Reference changeLocator(Ice.LocatorPrx newLocator);
changeRouter(Ice.RouterPrx newRouter)205         public abstract Reference changeRouter(Ice.RouterPrx newRouter);
changeCollocationOptimized(bool newCollocationOptimized)206         public abstract Reference changeCollocationOptimized(bool newCollocationOptimized);
changeCacheConnection(bool newCache)207         public abstract Reference changeCacheConnection(bool newCache);
changePreferSecure(bool newPreferSecure)208         public abstract Reference changePreferSecure(bool newPreferSecure);
changeEndpointSelection(Ice.EndpointSelectionType newType)209         public abstract Reference changeEndpointSelection(Ice.EndpointSelectionType newType);
changeLocatorCacheTimeout(int newTimeout)210         public abstract Reference changeLocatorCacheTimeout(int newTimeout);
211 
changeTimeout(int newTimeout)212         public abstract Reference changeTimeout(int newTimeout);
changeConnectionId(string connectionId)213         public abstract Reference changeConnectionId(string connectionId);
changeConnection(Ice.ConnectionI connection)214         public abstract Reference changeConnection(Ice.ConnectionI connection);
215 
GetHashCode()216         public override int GetHashCode()
217         {
218             lock(this)
219             {
220                 if(hashInitialized_)
221                 {
222                     return hashValue_;
223                 }
224                 int h = 5381;
225                 HashUtil.hashAdd(ref h, _mode);
226                 HashUtil.hashAdd(ref h, secure_);
227                 HashUtil.hashAdd(ref h, _identity);
228                 HashUtil.hashAdd(ref h, _context);
229                 HashUtil.hashAdd(ref h, _facet);
230                 HashUtil.hashAdd(ref h, overrideCompress_);
231                 if(overrideCompress_)
232                 {
233                     HashUtil.hashAdd(ref h, compress_);
234                 }
235                 HashUtil.hashAdd(ref h, _protocol);
236                 HashUtil.hashAdd(ref h, _encoding);
237                 HashUtil.hashAdd(ref h, _invocationTimeout);
238                 hashValue_ = h;
239                 hashInitialized_ = true;
240                 return hashValue_;
241             }
242         }
243 
getCompressOverride(out bool compress)244         public bool getCompressOverride(out bool compress)
245         {
246             DefaultsAndOverrides defaultsAndOverrides = getInstance().defaultsAndOverrides();
247             if(defaultsAndOverrides.overrideCompress)
248             {
249                 compress = defaultsAndOverrides.overrideCompressValue;
250             }
251             else if(overrideCompress_)
252             {
253                 compress = compress_;
254             }
255             else
256             {
257                 compress = false;
258                 return false;
259             }
260             return true;
261         }
262 
isIndirect()263         public abstract bool isIndirect();
isWellKnown()264         public abstract bool isWellKnown();
265 
266         //
267         // Marshal the reference.
268         //
streamWrite(Ice.OutputStream s)269         public virtual void streamWrite(Ice.OutputStream s)
270         {
271             //
272             // Don't write the identity here. Operations calling streamWrite
273             // write the identity.
274             //
275 
276             //
277             // For compatibility with the old FacetPath.
278             //
279             if(_facet.Length == 0)
280             {
281                 s.writeStringSeq(null);
282             }
283             else
284             {
285                 string[] facetPath = { _facet };
286                 s.writeStringSeq(facetPath);
287             }
288 
289             s.writeByte((byte)_mode);
290 
291             s.writeBool(secure_);
292 
293             if(!s.getEncoding().Equals(Ice.Util.Encoding_1_0))
294             {
295                 _protocol.ice_writeMembers(s);
296                 _encoding.ice_writeMembers(s);
297             }
298 
299             // Derived class writes the remainder of the reference.
300         }
301 
302         //
303         // Convert the reference to its string form.
304         //
ToString()305         public override string ToString()
306         {
307             //
308             // WARNING: Certain features, such as proxy validation in Glacier2,
309             // depend on the format of proxy strings. Changes to toString() and
310             // methods called to generate parts of the reference string could break
311             // these features. Please review for all features that depend on the
312             // format of proxyToString() before changing this and related code.
313             //
314             StringBuilder s = new StringBuilder();
315 
316             Ice.ToStringMode toStringMode = _instance.toStringMode();
317 
318             //
319             // If the encoded identity string contains characters which
320             // the reference parser uses as separators, then we enclose
321             // the identity string in quotes.
322             //
323             string id = Ice.Util.identityToString(_identity, toStringMode);
324             if(IceUtilInternal.StringUtil.findFirstOf(id, " :@") != -1)
325             {
326                 s.Append('"');
327                 s.Append(id);
328                 s.Append('"');
329             }
330             else
331             {
332                 s.Append(id);
333             }
334 
335             if(_facet.Length > 0)
336             {
337                 //
338                 // If the encoded facet string contains characters which
339                 // the reference parser uses as separators, then we enclose
340                 // the facet string in quotes.
341                 //
342                 s.Append(" -f ");
343                 string fs = IceUtilInternal.StringUtil.escapeString(_facet, "", toStringMode);
344                 if(IceUtilInternal.StringUtil.findFirstOf(fs, " :@") != -1)
345                 {
346                     s.Append('"');
347                     s.Append(fs);
348                     s.Append('"');
349                 }
350                 else
351                 {
352                     s.Append(fs);
353                 }
354             }
355 
356             switch(_mode)
357             {
358             case Mode.ModeTwoway:
359             {
360                 s.Append(" -t");
361                 break;
362             }
363 
364             case Mode.ModeOneway:
365             {
366                 s.Append(" -o");
367                 break;
368             }
369 
370             case Mode.ModeBatchOneway:
371             {
372                 s.Append(" -O");
373                 break;
374             }
375 
376             case Mode.ModeDatagram:
377             {
378                 s.Append(" -d");
379                 break;
380             }
381 
382             case Mode.ModeBatchDatagram:
383             {
384                 s.Append(" -D");
385                 break;
386             }
387             }
388 
389             if(secure_)
390             {
391                 s.Append(" -s");
392             }
393 
394             if(!_protocol.Equals(Ice.Util.Protocol_1_0))
395             {
396                 //
397                 // We only print the protocol if it's not 1.0. It's fine as
398                 // long as we don't add Ice.Default.ProtocolVersion, a
399                 // stringified proxy will convert back to the same proxy with
400                 // stringToProxy.
401                 //
402                 s.Append(" -p ");
403                 s.Append(Ice.Util.protocolVersionToString(_protocol));
404             }
405 
406             //
407             // Always print the encoding version to ensure a stringified proxy
408             // will convert back to a proxy with the same encoding with
409             // stringToProxy (and won't use Ice.Default.EncodingVersion).
410             //
411             s.Append(" -e ");
412             s.Append(Ice.Util.encodingVersionToString(_encoding));
413 
414             return s.ToString();
415 
416             // Derived class writes the remainder of the string.
417         }
418 
toProperty(string prefix)419         public abstract Dictionary<string, string> toProperty(string prefix);
420 
getRequestHandler(Ice.ObjectPrxHelperBase proxy)421         public abstract RequestHandler getRequestHandler(Ice.ObjectPrxHelperBase proxy);
422 
getBatchRequestQueue()423         public abstract BatchRequestQueue getBatchRequestQueue();
424 
Equals(object obj)425         public override bool Equals(object obj)
426         {
427             //
428             // Note: if(this == obj) and type test are performed by each non-abstract derived class.
429             //
430 
431             Reference r = (Reference)obj; // Guaranteed to succeed.
432 
433             if(_mode != r._mode)
434             {
435                 return false;
436             }
437 
438             if(secure_ != r.secure_)
439             {
440                 return false;
441             }
442 
443             if(!_identity.Equals(r._identity))
444             {
445                 return false;
446             }
447 
448             if(!Ice.CollectionComparer.Equals(_context, r._context))
449             {
450                 return false;
451             }
452 
453             if(!_facet.Equals(r._facet))
454             {
455                 return false;
456             }
457 
458             if(overrideCompress_ != r.overrideCompress_)
459             {
460                 return false;
461             }
462             if(overrideCompress_ && compress_ != r.compress_)
463             {
464                 return false;
465             }
466 
467             if(!_protocol.Equals(r._protocol))
468             {
469                 return false;
470             }
471 
472             if(!_encoding.Equals(r._encoding))
473             {
474                 return false;
475             }
476 
477             if(_invocationTimeout != r._invocationTimeout)
478             {
479                 return false;
480             }
481 
482             return true;
483         }
484 
Clone()485         public object Clone()
486         {
487             //
488             // A member-wise copy is safe because the members are immutable.
489             //
490             return MemberwiseClone();
491         }
492 
493         protected int hashValue_;
494         protected bool hashInitialized_;
495         private static Dictionary<string, string> _emptyContext = new Dictionary<string, string>();
496 
497         private Instance _instance;
498         private Ice.Communicator _communicator;
499 
500         private Mode _mode;
501         private Ice.Identity _identity;
502         private Dictionary<string, string> _context;
503         private string _facet;
504         protected bool secure_;
505         private Ice.ProtocolVersion _protocol;
506         private Ice.EncodingVersion _encoding;
507         private int _invocationTimeout;
508 
509         protected bool overrideCompress_;
510         protected bool compress_; // Only used if _overrideCompress == true
511 
Reference(Instance instance, Ice.Communicator communicator, Ice.Identity identity, string facet, Mode mode, bool secure, Ice.ProtocolVersion protocol, Ice.EncodingVersion encoding, int invocationTimeout, Dictionary<string, string> context)512         protected Reference(Instance instance,
513                             Ice.Communicator communicator,
514                             Ice.Identity identity,
515                             string facet,
516                             Mode mode,
517                             bool secure,
518                             Ice.ProtocolVersion protocol,
519                             Ice.EncodingVersion encoding,
520                             int invocationTimeout,
521                             Dictionary<string, string> context)
522         {
523             //
524             // Validate string arguments.
525             //
526             Debug.Assert(identity.name != null);
527             Debug.Assert(identity.category != null);
528             Debug.Assert(facet != null);
529 
530             _instance = instance;
531             _communicator = communicator;
532             _mode = mode;
533             _identity = identity;
534             _context = context != null ? new Dictionary<string, string>(context) : _emptyContext;
535             _facet = facet;
536             _protocol = protocol;
537             _encoding = encoding;
538             _invocationTimeout = invocationTimeout;
539             secure_ = secure;
540             hashInitialized_ = false;
541             overrideCompress_ = false;
542             compress_ = false;
543         }
544 
545         protected static Random rand_ = new Random(unchecked((int)DateTime.Now.Ticks));
546     }
547 
548     public class FixedReference : Reference
549     {
FixedReference(Instance instance, Ice.Communicator communicator, Ice.Identity identity, string facet, Mode mode, bool secure, Ice.ProtocolVersion protocol, Ice.EncodingVersion encoding, Ice.ConnectionI connection, int invocationTimeout, Dictionary<string, string> context, Ice.Optional<bool> compress)550         public FixedReference(Instance instance,
551                               Ice.Communicator communicator,
552                               Ice.Identity identity,
553                               string facet,
554                               Mode mode,
555                               bool secure,
556                               Ice.ProtocolVersion protocol,
557                               Ice.EncodingVersion encoding,
558                               Ice.ConnectionI connection,
559                               int invocationTimeout,
560                               Dictionary<string, string> context,
561                               Ice.Optional<bool> compress)
562         : base(instance, communicator, identity, facet, mode, secure, protocol, encoding, invocationTimeout, context)
563         {
564             _fixedConnection = connection;
565             if(compress.HasValue)
566             {
567                 overrideCompress_ = true;
568                 compress_ = compress.Value;
569             }
570         }
571 
getEndpoints()572         public override EndpointI[] getEndpoints()
573         {
574             return _emptyEndpoints;
575         }
576 
getAdapterId()577         public override string getAdapterId()
578         {
579             return "";
580         }
581 
getLocatorInfo()582         public override LocatorInfo getLocatorInfo()
583         {
584             return null;
585         }
586 
getRouterInfo()587         public override RouterInfo getRouterInfo()
588         {
589             return null;
590         }
591 
getCollocationOptimized()592         public override bool getCollocationOptimized()
593         {
594             return false;
595         }
596 
getCacheConnection()597         public override bool getCacheConnection()
598         {
599             return true;
600         }
601 
getPreferSecure()602         public override bool getPreferSecure()
603         {
604             return false;
605         }
606 
getEndpointSelection()607         public override Ice.EndpointSelectionType getEndpointSelection()
608         {
609             return Ice.EndpointSelectionType.Random;
610         }
611 
getLocatorCacheTimeout()612         public override int getLocatorCacheTimeout()
613         {
614             return 0;
615         }
616 
getConnectionId()617         public override string getConnectionId()
618         {
619             return "";
620         }
621 
getTimeout()622         public override Ice.Optional<int> getTimeout()
623         {
624             return new Ice.Optional<int>();
625         }
626 
getThreadPool()627         public override ThreadPool getThreadPool()
628         {
629             return _fixedConnection.getThreadPool();
630         }
631 
changeEndpoints(EndpointI[] newEndpoints)632         public override Reference changeEndpoints(EndpointI[] newEndpoints)
633         {
634             throw new Ice.FixedProxyException();
635         }
636 
changeAdapterId(string newAdapterId)637         public override Reference changeAdapterId(string newAdapterId)
638         {
639             throw new Ice.FixedProxyException();
640         }
641 
changeLocator(Ice.LocatorPrx newLocator)642         public override Reference changeLocator(Ice.LocatorPrx newLocator)
643         {
644             throw new Ice.FixedProxyException();
645         }
646 
changeRouter(Ice.RouterPrx newRouter)647         public override Reference changeRouter(Ice.RouterPrx newRouter)
648         {
649             throw new Ice.FixedProxyException();
650         }
651 
changeCollocationOptimized(bool newCollocationOptimized)652         public override Reference changeCollocationOptimized(bool newCollocationOptimized)
653         {
654             throw new Ice.FixedProxyException();
655         }
656 
changeCacheConnection(bool newCache)657         public override Reference changeCacheConnection(bool newCache)
658         {
659             throw new Ice.FixedProxyException();
660         }
661 
changePreferSecure(bool prefSec)662         public override Reference changePreferSecure(bool prefSec)
663         {
664             throw new Ice.FixedProxyException();
665         }
666 
changeEndpointSelection(Ice.EndpointSelectionType newType)667         public override Reference changeEndpointSelection(Ice.EndpointSelectionType newType)
668         {
669             throw new Ice.FixedProxyException();
670         }
671 
changeLocatorCacheTimeout(int newTimeout)672         public override Reference changeLocatorCacheTimeout(int newTimeout)
673         {
674             throw new Ice.FixedProxyException();
675         }
676 
changeTimeout(int newTimeout)677         public override Reference changeTimeout(int newTimeout)
678         {
679             throw new Ice.FixedProxyException();
680         }
681 
changeConnectionId(string connectionId)682         public override Reference changeConnectionId(string connectionId)
683         {
684             throw new Ice.FixedProxyException();
685         }
686 
changeConnection(Ice.ConnectionI connection)687         public override Reference changeConnection(Ice.ConnectionI connection)
688         {
689             if(_fixedConnection == connection)
690             {
691                 return this;
692             }
693             FixedReference r = (FixedReference)getInstance().referenceFactory().copy(this);
694             r._fixedConnection = connection;
695             return r;
696         }
697 
isIndirect()698         public override bool isIndirect()
699         {
700             return false;
701         }
702 
isWellKnown()703         public override bool isWellKnown()
704         {
705             return false;
706         }
707 
streamWrite(Ice.OutputStream s)708         public override void streamWrite(Ice.OutputStream s)
709         {
710             throw new Ice.FixedProxyException();
711         }
712 
toProperty(string prefix)713         public override Dictionary<string, string> toProperty(string prefix)
714         {
715             throw new Ice.FixedProxyException();
716         }
717 
getRequestHandler(Ice.ObjectPrxHelperBase proxy)718         public override RequestHandler getRequestHandler(Ice.ObjectPrxHelperBase proxy)
719         {
720             switch(getMode())
721             {
722             case Mode.ModeTwoway:
723             case Mode.ModeOneway:
724             case Mode.ModeBatchOneway:
725             {
726                 if(_fixedConnection.endpoint().datagram())
727                 {
728                     throw new Ice.NoEndpointException(ToString());
729                 }
730                 break;
731             }
732 
733             case Mode.ModeDatagram:
734             case Mode.ModeBatchDatagram:
735             {
736                 if(!_fixedConnection.endpoint().datagram())
737                 {
738                     throw new Ice.NoEndpointException(ToString());
739                 }
740                 break;
741             }
742             }
743 
744             //
745             // If a secure connection is requested or secure overrides is set,
746             // check if the connection is secure.
747             //
748             bool secure;
749             DefaultsAndOverrides defaultsAndOverrides = getInstance().defaultsAndOverrides();
750             if(defaultsAndOverrides.overrideSecure)
751             {
752                 secure = defaultsAndOverrides.overrideSecureValue;
753             }
754             else
755             {
756                 secure = getSecure();
757             }
758             if(secure && !_fixedConnection.endpoint().secure())
759             {
760                 throw new Ice.NoEndpointException(ToString());
761             }
762 
763             _fixedConnection.throwException(); // Throw in case our connection is already destroyed.
764 
765             bool compress = false;
766             if(defaultsAndOverrides.overrideCompress)
767             {
768                 compress = defaultsAndOverrides.overrideCompressValue;
769             }
770             else if(overrideCompress_)
771             {
772                 compress = compress_;
773             }
774 
775             return proxy.iceSetRequestHandler(new ConnectionRequestHandler(this, _fixedConnection, compress));
776         }
777 
getBatchRequestQueue()778         public override BatchRequestQueue getBatchRequestQueue()
779         {
780             return _fixedConnection.getBatchRequestQueue();
781         }
782 
Equals(object obj)783         public override bool Equals(object obj)
784         {
785             if(ReferenceEquals(this, obj))
786             {
787                 return true;
788             }
789             FixedReference rhs = obj as FixedReference;
790             if(rhs == null)
791             {
792                 return false;
793             }
794             if(!base.Equals(rhs))
795             {
796                 return false;
797             }
798             return _fixedConnection.Equals(rhs._fixedConnection);
799         }
800 
801         //
802         // If we override Equals, we must also override GetHashCode.
803         //
GetHashCode()804         public override int GetHashCode()
805         {
806             return base.GetHashCode();
807         }
808 
809         private Ice.ConnectionI _fixedConnection;
810         private static EndpointI[] _emptyEndpoints = new EndpointI[0];
811     }
812 
813     public class RoutableReference : Reference
814     {
getEndpoints()815         public override EndpointI[] getEndpoints()
816         {
817             return _endpoints;
818         }
819 
getAdapterId()820         public override string getAdapterId()
821         {
822             return _adapterId;
823         }
824 
getLocatorInfo()825         public override LocatorInfo getLocatorInfo()
826         {
827             return _locatorInfo;
828         }
829 
getRouterInfo()830         public override RouterInfo getRouterInfo()
831         {
832             return _routerInfo;
833         }
834 
getCollocationOptimized()835         public override bool getCollocationOptimized()
836         {
837             return _collocationOptimized;
838         }
839 
getCacheConnection()840         public override bool getCacheConnection()
841         {
842             return _cacheConnection;
843         }
844 
getPreferSecure()845         public override bool getPreferSecure()
846         {
847             return _preferSecure;
848         }
849 
getEndpointSelection()850         public override Ice.EndpointSelectionType getEndpointSelection()
851         {
852             return _endpointSelection;
853         }
854 
getLocatorCacheTimeout()855         public override int getLocatorCacheTimeout()
856         {
857             return _locatorCacheTimeout;
858         }
859 
getConnectionId()860         public override string getConnectionId()
861         {
862             return _connectionId;
863         }
864 
getTimeout()865         public override Ice.Optional<int> getTimeout()
866         {
867             return _overrideTimeout ? _timeout : new Ice.Optional<int>();
868         }
869 
getThreadPool()870         public override ThreadPool getThreadPool()
871         {
872             return getInstance().clientThreadPool();
873         }
874 
changeEncoding(Ice.EncodingVersion newEncoding)875         public override Reference changeEncoding(Ice.EncodingVersion newEncoding)
876         {
877             RoutableReference r = (RoutableReference)base.changeEncoding(newEncoding);
878             if(r != this)
879             {
880                 LocatorInfo locInfo = r._locatorInfo;
881                 if(locInfo != null && !locInfo.getLocator().ice_getEncodingVersion().Equals(newEncoding))
882                 {
883                     r._locatorInfo = getInstance().locatorManager().get(
884                         (Ice.LocatorPrx)locInfo.getLocator().ice_encodingVersion(newEncoding));
885                 }
886             }
887             return r;
888         }
889 
changeCompress(bool newCompress)890         public override Reference changeCompress(bool newCompress)
891         {
892             RoutableReference r = (RoutableReference)base.changeCompress(newCompress);
893             if(r != this && _endpoints.Length > 0) // Also override the compress flag on the endpoints if it was updated
894             {
895                 EndpointI[] newEndpoints = new EndpointI[_endpoints.Length];
896                 for(int i = 0; i < _endpoints.Length; i++)
897                 {
898                     newEndpoints[i] = _endpoints[i].compress(newCompress);
899                 }
900                 r._endpoints = newEndpoints;
901             }
902             return r;
903         }
904 
changeEndpoints(EndpointI[] newEndpoints)905         public override Reference changeEndpoints(EndpointI[] newEndpoints)
906         {
907             if(Equals(newEndpoints, _endpoints))
908             {
909                 return this;
910             }
911             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
912             r._endpoints = newEndpoints;
913             r._adapterId = "";
914             r.applyOverrides(ref r._endpoints);
915             return r;
916         }
917 
changeAdapterId(string newAdapterId)918         public override Reference changeAdapterId(string newAdapterId)
919         {
920             if(_adapterId.Equals(newAdapterId))
921             {
922                 return this;
923             }
924             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
925             r._adapterId = newAdapterId;
926             r._endpoints = _emptyEndpoints;
927             return r;
928         }
929 
changeLocator(Ice.LocatorPrx newLocator)930         public override Reference changeLocator(Ice.LocatorPrx newLocator)
931         {
932             LocatorInfo newLocatorInfo = getInstance().locatorManager().get(newLocator);
933             if(newLocatorInfo != null && _locatorInfo != null && newLocatorInfo.Equals(_locatorInfo))
934             {
935                 return this;
936             }
937             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
938             r._locatorInfo = newLocatorInfo;
939             return r;
940         }
941 
changeRouter(Ice.RouterPrx newRouter)942         public override Reference changeRouter(Ice.RouterPrx newRouter)
943         {
944             RouterInfo newRouterInfo = getInstance().routerManager().get(newRouter);
945             if(newRouterInfo != null && _routerInfo != null && newRouterInfo.Equals(_routerInfo))
946             {
947                 return this;
948             }
949             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
950             r._routerInfo = newRouterInfo;
951             return r;
952         }
953 
changeCollocationOptimized(bool newCollocationOptimized)954         public override Reference changeCollocationOptimized(bool newCollocationOptimized)
955         {
956             if(newCollocationOptimized == _collocationOptimized)
957             {
958                 return this;
959             }
960             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
961             r._collocationOptimized = newCollocationOptimized;
962             return r;
963         }
964 
changeCacheConnection(bool newCache)965         public override Reference changeCacheConnection(bool newCache)
966         {
967             if(newCache == _cacheConnection)
968             {
969                 return this;
970             }
971             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
972             r._cacheConnection = newCache;
973             return r;
974         }
975 
changePreferSecure(bool newPreferSecure)976         public override Reference changePreferSecure(bool newPreferSecure)
977         {
978             if(newPreferSecure == _preferSecure)
979             {
980                 return this;
981             }
982             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
983             r._preferSecure = newPreferSecure;
984             return r;
985         }
986 
changeEndpointSelection(Ice.EndpointSelectionType newType)987         public override Reference changeEndpointSelection(Ice.EndpointSelectionType newType)
988         {
989             if(newType == _endpointSelection)
990             {
991                 return this;
992             }
993             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
994             r._endpointSelection = newType;
995             return r;
996         }
997 
changeLocatorCacheTimeout(int newTimeout)998         public override Reference changeLocatorCacheTimeout(int newTimeout)
999         {
1000             if(newTimeout == _locatorCacheTimeout)
1001             {
1002                 return this;
1003             }
1004             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
1005             r._locatorCacheTimeout = newTimeout;
1006             return r;
1007         }
1008 
changeTimeout(int newTimeout)1009         public override Reference changeTimeout(int newTimeout)
1010         {
1011             if(_overrideTimeout && _timeout == newTimeout)
1012             {
1013                 return this;
1014             }
1015 
1016             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
1017             r._timeout = newTimeout;
1018             r._overrideTimeout = true;
1019             if(_endpoints.Length > 0)
1020             {
1021                 EndpointI[] newEndpoints = new EndpointI[_endpoints.Length];
1022                 for(int i = 0; i < _endpoints.Length; i++)
1023                 {
1024                     newEndpoints[i] = _endpoints[i].timeout(newTimeout);
1025                 }
1026                 r._endpoints = newEndpoints;
1027             }
1028             return r;
1029         }
1030 
changeConnectionId(string id)1031         public override Reference changeConnectionId(string id)
1032         {
1033             if(_connectionId.Equals(id))
1034             {
1035                 return this;
1036             }
1037             RoutableReference r = (RoutableReference)getInstance().referenceFactory().copy(this);
1038             r._connectionId = id;
1039             if(_endpoints.Length > 0)
1040             {
1041                 EndpointI[] newEndpoints = new EndpointI[_endpoints.Length];
1042                 for(int i = 0; i < _endpoints.Length; i++)
1043                 {
1044                     newEndpoints[i] = _endpoints[i].connectionId(id);
1045                 }
1046                 r._endpoints = newEndpoints;
1047             }
1048             return r;
1049         }
1050 
changeConnection(Ice.ConnectionI connection)1051         public override Reference changeConnection(Ice.ConnectionI connection)
1052         {
1053             return new FixedReference(getInstance(),
1054                                       getCommunicator(),
1055                                       getIdentity(),
1056                                       getFacet(),
1057                                       getMode(),
1058                                       getSecure(),
1059                                       getProtocol(),
1060                                       getEncoding(),
1061                                       connection,
1062                                       getInvocationTimeout(),
1063                                       getContext(),
1064                                       getCompress());
1065         }
1066 
isIndirect()1067         public override bool isIndirect()
1068         {
1069             return _endpoints.Length == 0;
1070         }
1071 
isWellKnown()1072         public override bool isWellKnown()
1073         {
1074             return _endpoints.Length == 0 && _adapterId.Length == 0;
1075         }
1076 
streamWrite(Ice.OutputStream s)1077         public override void streamWrite(Ice.OutputStream s)
1078         {
1079             base.streamWrite(s);
1080 
1081             s.writeSize(_endpoints.Length);
1082             if(_endpoints.Length > 0)
1083             {
1084                 Debug.Assert(_adapterId.Length == 0);
1085                 foreach(EndpointI endpoint in _endpoints)
1086                 {
1087                     s.writeShort(endpoint.type());
1088                     endpoint.streamWrite(s);
1089                 }
1090             }
1091             else
1092             {
1093                 s.writeString(_adapterId); // Adapter id.
1094             }
1095         }
1096 
ToString()1097         public override string ToString()
1098         {
1099             //
1100             // WARNING: Certain features, such as proxy validation in Glacier2,
1101             // depend on the format of proxy strings. Changes to toString() and
1102             // methods called to generate parts of the reference string could break
1103             // these features. Please review for all features that depend on the
1104             // format of proxyToString() before changing this and related code.
1105             //
1106             StringBuilder s = new StringBuilder();
1107             s.Append(base.ToString());
1108 
1109             if(_endpoints.Length > 0)
1110             {
1111                 for(int i = 0; i < _endpoints.Length; i++)
1112                 {
1113                     string endp = _endpoints[i].ToString();
1114                     if(endp != null && endp.Length > 0)
1115                     {
1116                         s.Append(':');
1117                         s.Append(endp);
1118                     }
1119                 }
1120             }
1121             else if(_adapterId.Length > 0)
1122             {
1123                 s.Append(" @ ");
1124 
1125                 //
1126                 // If the encoded adapter id string contains characters which
1127                 // the reference parser uses as separators, then we enclose
1128                 // the adapter id string in quotes.
1129                 //
1130                 string a = IceUtilInternal.StringUtil.escapeString(_adapterId, null, getInstance().toStringMode());
1131                 if(IceUtilInternal.StringUtil.findFirstOf(a, " :@") != -1)
1132                 {
1133                     s.Append('"');
1134                     s.Append(a);
1135                     s.Append('"');
1136                 }
1137                 else
1138                 {
1139                     s.Append(a);
1140                  }
1141             }
1142             return s.ToString();
1143         }
1144 
toProperty(string prefix)1145         public override Dictionary<string, string> toProperty(string prefix)
1146         {
1147             Dictionary<string, string> properties = new Dictionary<string, string>();
1148 
1149             properties[prefix] = ToString();
1150             properties[prefix + ".CollocationOptimized"] = _collocationOptimized ? "1" : "0";
1151             properties[prefix + ".ConnectionCached"] = _cacheConnection ? "1" : "0";
1152             properties[prefix + ".PreferSecure"] = _preferSecure ? "1" : "0";
1153             properties[prefix + ".EndpointSelection"] =
1154                        _endpointSelection == Ice.EndpointSelectionType.Random ? "Random" : "Ordered";
1155             properties[prefix + ".LocatorCacheTimeout"] = _locatorCacheTimeout.ToString(CultureInfo.InvariantCulture);
1156             properties[prefix + ".InvocationTimeout"] = getInvocationTimeout().ToString(CultureInfo.InvariantCulture);
1157 
1158             if(_routerInfo != null)
1159             {
1160                 Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)_routerInfo.getRouter();
1161                 Dictionary<string, string> routerProperties = h.iceReference().toProperty(prefix + ".Router");
1162                 foreach(KeyValuePair<string, string> entry in routerProperties)
1163                 {
1164                     properties[entry.Key] = entry.Value;
1165                 }
1166             }
1167 
1168             if(_locatorInfo != null)
1169             {
1170                 Ice.ObjectPrxHelperBase h = (Ice.ObjectPrxHelperBase)_locatorInfo.getLocator();
1171                 Dictionary<string, string> locatorProperties = h.iceReference().toProperty(prefix + ".Locator");
1172                 foreach(KeyValuePair<string, string> entry in locatorProperties)
1173                 {
1174                     properties[entry.Key] = entry.Value;
1175                 }
1176             }
1177 
1178             return properties;
1179         }
1180 
1181         //
1182         // If we override Equals, we must also override GetHashCode.
1183         //
GetHashCode()1184         public override int GetHashCode()
1185         {
1186             lock(this)
1187             {
1188                 if(!hashInitialized_)
1189                 {
1190                     int h = base.GetHashCode(); // Initializes hashValue_.
1191                     HashUtil.hashAdd(ref h, _adapterId);
1192                     hashValue_ = h;
1193                 }
1194                 return hashValue_;
1195             }
1196         }
1197 
Equals(object obj)1198         public override bool Equals(object obj)
1199         {
1200             if(ReferenceEquals(this, obj))
1201             {
1202                 return true;
1203             }
1204 
1205             RoutableReference rhs = obj as RoutableReference;
1206             if(rhs == null)
1207             {
1208                 return false;
1209             }
1210 
1211             if(!base.Equals(obj))
1212             {
1213                 return false;
1214             }
1215 
1216             if(_locatorInfo == null ? rhs._locatorInfo != null : !_locatorInfo.Equals(rhs._locatorInfo))
1217             {
1218                 return false;
1219             }
1220             if(_routerInfo == null ? rhs._routerInfo != null : !_routerInfo.Equals(rhs._routerInfo))
1221             {
1222                 return false;
1223             }
1224             if(_collocationOptimized != rhs._collocationOptimized)
1225             {
1226                 return false;
1227             }
1228             if(_cacheConnection != rhs._cacheConnection)
1229             {
1230                 return false;
1231             }
1232             if(_preferSecure != rhs._preferSecure)
1233             {
1234                 return false;
1235             }
1236             if(_endpointSelection != rhs._endpointSelection)
1237             {
1238                 return false;
1239             }
1240             if(_locatorCacheTimeout != rhs._locatorCacheTimeout)
1241             {
1242                 return false;
1243             }
1244             if(_overrideTimeout != rhs._overrideTimeout)
1245             {
1246                 return false;
1247             }
1248             if(_overrideTimeout && _timeout != rhs._timeout)
1249             {
1250                 return false;
1251             }
1252             if(!_connectionId.Equals(rhs._connectionId))
1253             {
1254                 return false;
1255             }
1256             if(!_adapterId.Equals(rhs._adapterId))
1257             {
1258                 return false;
1259             }
1260             if(!IceUtilInternal.Arrays.Equals(_endpoints, rhs._endpoints))
1261             {
1262                 return false;
1263             }
1264             return true;
1265         }
1266 
1267         private sealed class RouterEndpointsCallback : RouterInfo.GetClientEndpointsCallback
1268         {
RouterEndpointsCallback(RoutableReference ir, GetConnectionCallback cb)1269             internal RouterEndpointsCallback(RoutableReference ir, GetConnectionCallback cb)
1270             {
1271                 _ir = ir;
1272                 _cb = cb;
1273             }
1274 
setEndpoints(EndpointI[] endpts)1275             public void setEndpoints(EndpointI[] endpts)
1276             {
1277                 if(endpts.Length > 0)
1278                 {
1279                     _ir.applyOverrides(ref endpts);
1280                     _ir.createConnection(endpts, _cb);
1281                 }
1282                 else
1283                 {
1284                     _ir.getConnectionNoRouterInfo(_cb);
1285                 }
1286             }
1287 
setException(Ice.LocalException ex)1288             public void setException(Ice.LocalException ex)
1289             {
1290                 _cb.setException(ex);
1291             }
1292 
1293             private RoutableReference _ir;
1294             private GetConnectionCallback _cb;
1295         }
1296 
getRequestHandler(Ice.ObjectPrxHelperBase proxy)1297         public override RequestHandler getRequestHandler(Ice.ObjectPrxHelperBase proxy)
1298         {
1299             return getInstance().requestHandlerFactory().getRequestHandler(this, proxy);
1300         }
1301 
getBatchRequestQueue()1302         public override BatchRequestQueue getBatchRequestQueue()
1303         {
1304             return new BatchRequestQueue(getInstance(), getMode() == Reference.Mode.ModeBatchDatagram);
1305         }
1306 
getConnection(GetConnectionCallback callback)1307         public void getConnection(GetConnectionCallback callback)
1308         {
1309             if(_routerInfo != null)
1310             {
1311                 //
1312                 // If we route, we send everything to the router's client
1313                 // proxy endpoints.
1314                 //
1315                 _routerInfo.getClientEndpoints(new RouterEndpointsCallback(this, callback));
1316             }
1317             else
1318             {
1319                 getConnectionNoRouterInfo(callback);
1320             }
1321         }
1322 
1323         private sealed class LocatorEndpointsCallback : LocatorInfo.GetEndpointsCallback
1324         {
LocatorEndpointsCallback(RoutableReference ir, GetConnectionCallback cb)1325             internal LocatorEndpointsCallback(RoutableReference ir, GetConnectionCallback cb)
1326             {
1327                 _ir = ir;
1328                 _cb = cb;
1329             }
1330 
setEndpoints(EndpointI[] endpoints, bool cached)1331             public void setEndpoints(EndpointI[] endpoints, bool cached)
1332             {
1333                 if(endpoints.Length == 0)
1334                 {
1335                     _cb.setException(new Ice.NoEndpointException(_ir.ToString()));
1336                     return;
1337                 }
1338 
1339                 _ir.applyOverrides(ref endpoints);
1340                 _ir.createConnection(endpoints, new ConnectionCallback(_ir, _cb, cached));
1341             }
1342 
setException(Ice.LocalException ex)1343             public void setException(Ice.LocalException ex)
1344             {
1345                 _cb.setException(ex);
1346             }
1347 
1348             private RoutableReference _ir;
1349             private GetConnectionCallback _cb;
1350         }
1351 
1352         private sealed class ConnectionCallback : GetConnectionCallback
1353         {
ConnectionCallback(RoutableReference ir, GetConnectionCallback cb, bool cached)1354             internal ConnectionCallback(RoutableReference ir, GetConnectionCallback cb, bool cached)
1355             {
1356                 _ir = ir;
1357                 _cb = cb;
1358                 _cached = cached;
1359             }
1360 
setConnection(Ice.ConnectionI connection, bool compress)1361             public void setConnection(Ice.ConnectionI connection, bool compress)
1362             {
1363                 _cb.setConnection(connection, compress);
1364             }
1365 
setException(Ice.LocalException exc)1366             public void setException(Ice.LocalException exc)
1367             {
1368                 try
1369                 {
1370                     throw exc;
1371                 }
1372                 catch(Ice.NoEndpointException ex)
1373                 {
1374                     _cb.setException(ex); // No need to retry if there's no endpoints.
1375                 }
1376                 catch(Ice.LocalException ex)
1377                 {
1378                     Debug.Assert(_ir._locatorInfo != null);
1379                     _ir._locatorInfo.clearCache(_ir);
1380                     if(_cached)
1381                     {
1382                         TraceLevels traceLevels = _ir.getInstance().traceLevels();
1383                         if(traceLevels.retry >= 2)
1384                         {
1385                             String s = "connection to cached endpoints failed\n" +
1386                                        "removing endpoints from cache and trying again\n" + ex;
1387                             _ir.getInstance().initializationData().logger.trace(traceLevels.retryCat, s);
1388                         }
1389                         _ir.getConnectionNoRouterInfo(_cb); // Retry.
1390                         return;
1391                     }
1392                     _cb.setException(ex);
1393                 }
1394             }
1395 
1396             private RoutableReference _ir;
1397             private GetConnectionCallback _cb;
1398             private bool _cached;
1399         }
1400 
getConnectionNoRouterInfo(GetConnectionCallback callback)1401         private void getConnectionNoRouterInfo(GetConnectionCallback callback)
1402         {
1403             if(_endpoints.Length > 0)
1404             {
1405                 createConnection(_endpoints, callback);
1406                 return;
1407             }
1408 
1409             if(_locatorInfo != null)
1410             {
1411                 _locatorInfo.getEndpoints(this, _locatorCacheTimeout, new LocatorEndpointsCallback(this, callback));
1412             }
1413             else
1414             {
1415                 callback.setException(new Ice.NoEndpointException(ToString()));
1416             }
1417         }
1418 
RoutableReference(Instance instance, Ice.Communicator communicator, Ice.Identity identity, string facet, Mode mode, bool secure, Ice.ProtocolVersion protocol, Ice.EncodingVersion encoding, EndpointI[] endpoints, string adapterId, LocatorInfo locatorInfo, RouterInfo routerInfo, bool collocationOptimized, bool cacheConnection, bool preferSecure, Ice.EndpointSelectionType endpointSelection, int locatorCacheTimeout, int invocationTimeout, Dictionary<string, string> context)1419         public RoutableReference(Instance instance,
1420                                  Ice.Communicator communicator,
1421                                  Ice.Identity identity,
1422                                  string facet,
1423                                  Mode mode,
1424                                  bool secure,
1425                                  Ice.ProtocolVersion protocol,
1426                                  Ice.EncodingVersion encoding,
1427                                  EndpointI[] endpoints,
1428                                  string adapterId,
1429                                  LocatorInfo locatorInfo,
1430                                  RouterInfo routerInfo,
1431                                  bool collocationOptimized,
1432                                  bool cacheConnection,
1433                                  bool preferSecure,
1434                                  Ice.EndpointSelectionType endpointSelection,
1435                                  int locatorCacheTimeout,
1436                                  int invocationTimeout,
1437                                  Dictionary<string, string> context)
1438         : base(instance, communicator, identity, facet, mode, secure, protocol, encoding, invocationTimeout, context)
1439         {
1440             _endpoints = endpoints;
1441             _adapterId = adapterId;
1442             _locatorInfo = locatorInfo;
1443             _routerInfo = routerInfo;
1444             _collocationOptimized = collocationOptimized;
1445             _cacheConnection = cacheConnection;
1446             _preferSecure = preferSecure;
1447             _endpointSelection = endpointSelection;
1448             _locatorCacheTimeout = locatorCacheTimeout;
1449             _overrideTimeout = false;
1450             _timeout = -1;
1451 
1452             if(_endpoints == null)
1453             {
1454                 _endpoints = _emptyEndpoints;
1455             }
1456 
1457             if(_adapterId == null)
1458             {
1459                 _adapterId = "";
1460             }
1461 
1462             Debug.Assert(_adapterId.Length == 0 || _endpoints.Length == 0);
1463         }
1464 
applyOverrides(ref EndpointI[] endpts)1465         protected void applyOverrides(ref EndpointI[] endpts)
1466         {
1467             for(int i = 0; i < endpts.Length; ++i)
1468             {
1469                 endpts[i] = endpts[i].connectionId(_connectionId);
1470                 if(overrideCompress_)
1471                 {
1472                     endpts[i] = endpts[i].compress(compress_);
1473                 }
1474                 if(_overrideTimeout)
1475                 {
1476                     endpts[i] = endpts[i].timeout(_timeout);
1477                 }
1478             }
1479         }
1480 
filterEndpoints(EndpointI[] allEndpoints)1481         private EndpointI[] filterEndpoints(EndpointI[] allEndpoints)
1482         {
1483             List<EndpointI> endpoints = new List<EndpointI>();
1484 
1485             //
1486             // Filter out unknown endpoints.
1487             //
1488             for(int i = 0; i < allEndpoints.Length; i++)
1489             {
1490                 if(!(allEndpoints[i] is OpaqueEndpointI))
1491                 {
1492                     endpoints.Add(allEndpoints[i]);
1493                 }
1494             }
1495 
1496             //
1497             // Filter out endpoints according to the mode of the reference.
1498             //
1499             switch(getMode())
1500             {
1501                 case Mode.ModeTwoway:
1502                 case Mode.ModeOneway:
1503                 case Mode.ModeBatchOneway:
1504                 {
1505                     //
1506                     // Filter out datagram endpoints.
1507                     //
1508                     List<EndpointI> tmp = new List<EndpointI>();
1509                     foreach(EndpointI endpoint in endpoints)
1510                     {
1511                         if(!endpoint.datagram())
1512                         {
1513                             tmp.Add(endpoint);
1514                         }
1515                     }
1516                     endpoints = tmp;
1517                     break;
1518                 }
1519 
1520                 case Mode.ModeDatagram:
1521                 case Mode.ModeBatchDatagram:
1522                 {
1523                     //
1524                     // Filter out non-datagram endpoints.
1525                     //
1526                     List<EndpointI> tmp = new List<EndpointI>();
1527                     foreach(EndpointI endpoint in endpoints)
1528                     {
1529                         if(endpoint.datagram())
1530                         {
1531                             tmp.Add(endpoint);
1532                         }
1533                     }
1534                     endpoints = tmp;
1535                     break;
1536                 }
1537             }
1538 
1539             //
1540             // Sort the endpoints according to the endpoint selection type.
1541             //
1542             switch(getEndpointSelection())
1543             {
1544                 case Ice.EndpointSelectionType.Random:
1545                 {
1546                     lock(rand_)
1547                     {
1548                         for(int i = 0; i < endpoints.Count - 1; ++i)
1549                         {
1550                             int r = rand_.Next(endpoints.Count - i) + i;
1551                             Debug.Assert(r >= i && r < endpoints.Count);
1552                             if(r != i)
1553                             {
1554                                 EndpointI tmp = endpoints[i];
1555                                 endpoints[i] = endpoints[r];
1556                                 endpoints[r] = tmp;
1557                             }
1558                         }
1559                     }
1560                     break;
1561                 }
1562                 case Ice.EndpointSelectionType.Ordered:
1563                 {
1564                     // Nothing to do.
1565                     break;
1566                 }
1567                 default:
1568                 {
1569                     Debug.Assert(false);
1570                     break;
1571                 }
1572             }
1573 
1574             //
1575             // If a secure connection is requested or secure overrides
1576             // is set, remove all non-secure endpoints. Otherwise make
1577             // non-secure endpoints preferred over secure endpoints by
1578             // partitioning the endpoint vector, so that non-secure
1579             // endpoints come first.
1580             //
1581             DefaultsAndOverrides overrides = getInstance().defaultsAndOverrides();
1582             if(overrides.overrideSecure ? overrides.overrideSecureValue : getSecure())
1583             {
1584                 List<EndpointI> tmp = new List<EndpointI>();
1585                 foreach(EndpointI endpoint in endpoints)
1586                 {
1587                     if(endpoint.secure())
1588                     {
1589                         tmp.Add(endpoint);
1590                     }
1591                 }
1592                 endpoints = tmp;
1593             }
1594             else if(getPreferSecure())
1595             {
1596                 IceUtilInternal.Collections.Sort(ref endpoints, _preferSecureEndpointComparator);
1597             }
1598             else
1599             {
1600                 IceUtilInternal.Collections.Sort(ref endpoints, _preferNonSecureEndpointComparator);
1601             }
1602 
1603             EndpointI[] arr = new EndpointI[endpoints.Count];
1604             endpoints.CopyTo(arr);
1605             return arr;
1606         }
1607 
1608         private sealed class CreateConnectionCallback : OutgoingConnectionFactory.CreateConnectionCallback
1609         {
CreateConnectionCallback(RoutableReference rr, EndpointI[] endpoints, GetConnectionCallback cb)1610             internal CreateConnectionCallback(RoutableReference rr, EndpointI[] endpoints, GetConnectionCallback cb)
1611             {
1612                 _rr = rr;
1613                 _endpoints = endpoints;
1614                 _callback = cb;
1615             }
1616 
setConnection(Ice.ConnectionI connection, bool compress)1617             public void setConnection(Ice.ConnectionI connection, bool compress)
1618             {
1619                 //
1620                 // If we have a router, set the object adapter for this router
1621                 // (if any) to the new connection, so that callbacks from the
1622                 // router can be received over this new connection.
1623                 //
1624                 if(_rr._routerInfo != null && _rr._routerInfo.getAdapter() != null)
1625                 {
1626                     connection.setAdapter(_rr._routerInfo.getAdapter());
1627                 }
1628                 _callback.setConnection(connection, compress);
1629             }
1630 
setException(Ice.LocalException ex)1631             public void setException(Ice.LocalException ex)
1632             {
1633                 if(_exception == null)
1634                 {
1635                     _exception = ex;
1636                 }
1637 
1638                 if(_endpoints == null || ++_i == _endpoints.Length)
1639                 {
1640                     _callback.setException(_exception);
1641                     return;
1642                 }
1643 
1644                 bool more = _i != _endpoints.Length - 1;
1645                 EndpointI[] endpoint = new EndpointI[]{ _endpoints[_i] };
1646                 _rr.getInstance().outgoingConnectionFactory().create(endpoint, more, _rr.getEndpointSelection(), this);
1647             }
1648 
1649             private RoutableReference _rr;
1650             private EndpointI[] _endpoints;
1651             private GetConnectionCallback _callback;
1652             private int _i = 0;
1653             private Ice.LocalException _exception = null;
1654         }
1655 
createConnection(EndpointI[] allEndpoints, GetConnectionCallback callback)1656         protected void createConnection(EndpointI[] allEndpoints, GetConnectionCallback callback)
1657         {
1658             EndpointI[] endpoints = filterEndpoints(allEndpoints);
1659             if(endpoints.Length == 0)
1660             {
1661                 callback.setException(new Ice.NoEndpointException(ToString()));
1662                 return;
1663             }
1664 
1665             //
1666             // Finally, create the connection.
1667             //
1668             OutgoingConnectionFactory factory = getInstance().outgoingConnectionFactory();
1669             if(getCacheConnection() || endpoints.Length == 1)
1670             {
1671                 //
1672                 // Get an existing connection or create one if there's no
1673                 // existing connection to one of the given endpoints.
1674                 //
1675                 factory.create(endpoints, false, getEndpointSelection(),
1676                                new CreateConnectionCallback(this, null, callback));
1677             }
1678             else
1679             {
1680                 //
1681                 // Go through the list of endpoints and try to create the
1682                 // connection until it succeeds. This is different from just
1683                 // calling create() with the given endpoints since this might
1684                 // create a new connection even if there's an existing
1685                 // connection for one of the endpoints.
1686                 //
1687 
1688                 factory.create(new EndpointI[]{ endpoints[0] }, true, getEndpointSelection(),
1689                                new CreateConnectionCallback(this, endpoints, callback));
1690             }
1691         }
1692 
1693         private class EndpointComparator : IComparer<EndpointI>
1694         {
EndpointComparator(bool preferSecure)1695             public EndpointComparator(bool preferSecure)
1696             {
1697                 _preferSecure = preferSecure;
1698             }
1699 
Compare(EndpointI le, EndpointI re)1700             public int Compare(EndpointI le, EndpointI re)
1701             {
1702                 bool ls = le.secure();
1703                 bool rs = re.secure();
1704                 if((ls && rs) || (!ls && !rs))
1705                 {
1706                     return 0;
1707                 }
1708                 else if(!ls && rs)
1709                 {
1710                     if(_preferSecure)
1711                     {
1712                         return 1;
1713                     }
1714                     else
1715                     {
1716                         return -1;
1717                     }
1718                 }
1719                 else
1720                 {
1721                     if(_preferSecure)
1722                     {
1723                         return -1;
1724                     }
1725                     else
1726                     {
1727                         return 1;
1728                     }
1729                 }
1730             }
1731 
1732             private bool _preferSecure;
1733         }
1734 
1735         private static EndpointComparator _preferNonSecureEndpointComparator = new EndpointComparator(false);
1736         private static EndpointComparator _preferSecureEndpointComparator = new EndpointComparator(true);
1737         private static EndpointI[] _emptyEndpoints = new EndpointI[0];
1738 
1739         private EndpointI[] _endpoints;
1740         private string _adapterId;
1741         private LocatorInfo _locatorInfo; // Null if no locator is used.
1742         private RouterInfo _routerInfo; // Null if no router is used.
1743         private bool _collocationOptimized;
1744         private bool _cacheConnection;
1745         private bool _preferSecure;
1746         private Ice.EndpointSelectionType _endpointSelection;
1747         private int _locatorCacheTimeout;
1748 
1749         private bool _overrideTimeout;
1750         private int _timeout; // Only used if _overrideTimeout == true
1751         private string _connectionId = "";
1752     }
1753 }
1754