1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 namespace IceInternal
6 {
7     using System.Diagnostics;
8     using System.Collections;
9     using System.Collections.Generic;
10     using System.Net;
11     using System;
12     using System.Globalization;
13 
14     sealed class UdpEndpointI : IPEndpointI
15     {
UdpEndpointI(ProtocolInstance instance, string ho, int po, EndPoint sourceAddr, string mcastInterface, int mttl, bool conn, string conId, bool co)16         public UdpEndpointI(ProtocolInstance instance, string ho, int po, EndPoint sourceAddr, string mcastInterface,
17                             int mttl, bool conn, string conId, bool co) :
18             base(instance, ho, po, sourceAddr, conId)
19         {
20             _mcastInterface = mcastInterface;
21             _mcastTtl = mttl;
22             _connect = conn;
23             _compress = co;
24         }
25 
UdpEndpointI(ProtocolInstance instance)26         public UdpEndpointI(ProtocolInstance instance) :
27             base(instance)
28         {
29             _connect = false;
30             _compress = false;
31         }
32 
UdpEndpointI(ProtocolInstance instance, Ice.InputStream s)33         public UdpEndpointI(ProtocolInstance instance, Ice.InputStream s) :
34             base(instance, s)
35         {
36             if(s.getEncoding().Equals(Ice.Util.Encoding_1_0))
37             {
38                 s.readByte();
39                 s.readByte();
40                 s.readByte();
41                 s.readByte();
42             }
43             // Not transmitted.
44             //_connect = s.readBool();
45             _connect = false;
46             _compress = s.readBool();
47         }
48 
49         private sealed class InfoI : Ice.UDPEndpointInfo
50         {
InfoI(UdpEndpointI e)51             public InfoI(UdpEndpointI e)
52             {
53                 _endpoint = e;
54             }
55 
type()56             override public short type()
57             {
58                 return _endpoint.type();
59             }
60 
datagram()61             override public bool datagram()
62             {
63                 return _endpoint.datagram();
64             }
65 
secure()66             override public bool secure()
67             {
68                 return _endpoint.secure();
69             }
70 
71             private UdpEndpointI _endpoint;
72         }
73 
74         //
75         // Return the endpoint information.
76         //
getInfo()77         public override Ice.EndpointInfo getInfo()
78         {
79             InfoI info = new InfoI(this);
80             fillEndpointInfo(info);
81             return info;
82         }
83 
84         //
85         // Return the timeout for the endpoint in milliseconds. 0 means
86         // non-blocking, -1 means no timeout.
87         //
timeout()88         public override int timeout()
89         {
90             return -1;
91         }
92 
93         //
94         // Return a new endpoint with a different timeout value, provided
95         // that timeouts are supported by the endpoint. Otherwise the same
96         // endpoint is returned.
97         //
timeout(int timeout)98         public override EndpointI timeout(int timeout)
99         {
100             return this;
101         }
102 
103         //
104         // Return true if the endpoints support bzip2 compress, or false
105         // otherwise.
106         //
compress()107         public override bool compress()
108         {
109             return _compress;
110         }
111 
112         //
113         // Return a new endpoint with a different compression value,
114         // provided that compression is supported by the
115         // endpoint. Otherwise the same endpoint is returned.
116         //
compress(bool compress)117         public override EndpointI compress(bool compress)
118         {
119             if(compress == _compress)
120             {
121                 return this;
122             }
123             else
124             {
125                 return new UdpEndpointI(instance_, host_, port_, sourceAddr_, _mcastInterface, _mcastTtl, _connect,
126                                         connectionId_, compress);
127             }
128         }
129 
130         //
131         // Return true if the endpoint is datagram-based.
132         //
datagram()133         public override bool datagram()
134         {
135             return true;
136         }
137 
138         //
139         // Return a server side transceiver for this endpoint, or null if a
140         // transceiver can only be created by an acceptor.
141         //
transceiver()142         public override Transceiver transceiver()
143         {
144             return new UdpTransceiver(this, instance_, host_, port_, _mcastInterface, _connect);
145         }
146 
147         //
148         // Return an acceptor for this endpoint, or null if no acceptors
149         // is available.
150         //
acceptor(string adapterName)151         public override Acceptor acceptor(string adapterName)
152         {
153             return null;
154         }
155 
initWithOptions(List<string> args, bool oaEndpoint)156         public override void initWithOptions(List<string> args, bool oaEndpoint)
157         {
158             base.initWithOptions(args, oaEndpoint);
159 
160             if(_mcastInterface.Equals("*"))
161             {
162                 if(oaEndpoint)
163                 {
164                     _mcastInterface = "";
165                 }
166                 else
167                 {
168                     throw new Ice.EndpointParseException("`--interface *' not valid for proxy endpoint `" +
169                                                          ToString() + "'");
170                 }
171             }
172         }
173 
endpoint(UdpTransceiver transceiver)174         public UdpEndpointI endpoint(UdpTransceiver transceiver)
175         {
176             int port = transceiver.effectivePort();
177             if(port == port_)
178             {
179                 return this;
180             }
181             else
182             {
183                 return new UdpEndpointI(instance_, host_, port, sourceAddr_, _mcastInterface, _mcastTtl, _connect,
184                                         connectionId_, _compress);
185             }
186         }
187 
options()188         public override string options()
189         {
190             //
191             // WARNING: Certain features, such as proxy validation in Glacier2,
192             // depend on the format of proxy strings. Changes to toString() and
193             // methods called to generate parts of the reference string could break
194             // these features. Please review for all features that depend on the
195             // format of proxyToString() before changing this and related code.
196             //
197             string s = base.options();
198 
199             if(_mcastInterface.Length != 0)
200             {
201                 s += " --interface " + _mcastInterface;
202             }
203 
204             if(_mcastTtl != -1)
205             {
206                 s += " --ttl " + _mcastTtl;
207             }
208 
209             if(_connect)
210             {
211                 s += " -c";
212             }
213 
214             if(_compress)
215             {
216                 s += " -z";
217             }
218 
219             return s;
220         }
221 
222         //
223         // Compare endpoints for sorting purposes
224         //
CompareTo(EndpointI obj)225         public override int CompareTo(EndpointI obj)
226         {
227             if(!(obj is UdpEndpointI))
228             {
229                 return type() < obj.type() ? -1 : 1;
230             }
231 
232             UdpEndpointI p = (UdpEndpointI)obj;
233             if(this == p)
234             {
235                 return 0;
236             }
237 
238             if(!_connect && p._connect)
239             {
240                 return -1;
241             }
242             else if(!p._connect && _connect)
243             {
244                 return 1;
245             }
246 
247             if(!_compress && p._compress)
248             {
249                 return -1;
250             }
251             else if(!p._compress && _compress)
252             {
253                 return 1;
254             }
255 
256             int rc = string.Compare(_mcastInterface, p._mcastInterface, StringComparison.Ordinal);
257             if(rc != 0)
258             {
259                 return rc;
260             }
261 
262             if(_mcastTtl < p._mcastTtl)
263             {
264                 return -1;
265             }
266             else if(p._mcastTtl < _mcastTtl)
267             {
268                 return 1;
269             }
270 
271             return base.CompareTo(p);
272         }
273 
274         //
275         // Marshal the endpoint
276         //
streamWriteImpl(Ice.OutputStream s)277         public override void streamWriteImpl(Ice.OutputStream s)
278         {
279             base.streamWriteImpl(s);
280             if(s.getEncoding().Equals(Ice.Util.Encoding_1_0))
281             {
282                 Ice.Util.Protocol_1_0.ice_writeMembers(s);
283                 Ice.Util.Encoding_1_0.ice_writeMembers(s);
284             }
285             // Not transmitted.
286             //s.writeBool(_connect);
287             s.writeBool(_compress);
288         }
289 
hashInit(ref int h)290         public override void hashInit(ref int h)
291         {
292             base.hashInit(ref h);
293             HashUtil.hashAdd(ref h, _mcastInterface);
294             HashUtil.hashAdd(ref h, _mcastTtl);
295             HashUtil.hashAdd(ref h, _connect);
296             HashUtil.hashAdd(ref h, _compress);
297         }
298 
fillEndpointInfo(Ice.IPEndpointInfo info)299         public override void fillEndpointInfo(Ice.IPEndpointInfo info)
300         {
301             base.fillEndpointInfo(info);
302             if(info is Ice.UDPEndpointInfo)
303             {
304                 Ice.UDPEndpointInfo udpInfo = (Ice.UDPEndpointInfo)info;
305                 udpInfo.timeout = -1;
306                 udpInfo.compress = _compress;
307                 udpInfo.mcastInterface = _mcastInterface;
308                 udpInfo.mcastTtl = _mcastTtl;
309             }
310         }
311 
checkOption(string option, string argument, string endpoint)312         protected override bool checkOption(string option, string argument, string endpoint)
313         {
314             if(base.checkOption(option, argument, endpoint))
315             {
316                 return true;
317             }
318 
319             if(option.Equals("-c"))
320             {
321                 if(argument != null)
322                 {
323                     Ice.EndpointParseException e = new Ice.EndpointParseException();
324                     e.str = "unexpected argument `" + argument + "' provided for -c option in " + endpoint;
325                     throw e;
326                 }
327 
328                 _connect = true;
329             }
330             else if(option.Equals("-z"))
331             {
332                 if(argument != null)
333                 {
334                     Ice.EndpointParseException e = new Ice.EndpointParseException();
335                     e.str = "unexpected argument `" + argument + "' provided for -z option in " + endpoint;
336                     throw e;
337                 }
338 
339                 _compress = true;
340             }
341             else if(option.Equals("-v") || option.Equals("-e"))
342             {
343                 if(argument == null)
344                 {
345                     Ice.EndpointParseException e = new Ice.EndpointParseException();
346                     e.str = "no argument provided for " + option + " option in endpoint " + endpoint;
347                     throw e;
348                 }
349 
350                 try
351                 {
352                     Ice.EncodingVersion v = Ice.Util.stringToEncodingVersion(argument);
353                     if(v.major != 1 || v.minor != 0)
354                     {
355                         instance_.logger().warning("deprecated udp endpoint option: " + option);
356                     }
357                 }
358                 catch(Ice.VersionParseException ex)
359                 {
360                     Ice.EndpointParseException e = new Ice.EndpointParseException();
361                     e.str = "invalid version `" + argument + "' in endpoint " + endpoint + ":\n" + ex.str;
362                     throw e;
363                 }
364             }
365             else if(option.Equals("--ttl"))
366             {
367                 if(argument == null)
368                 {
369                     Ice.EndpointParseException e = new Ice.EndpointParseException();
370                     e.str = "no argument provided for --ttl option in endpoint " + endpoint;
371                     throw e;
372                 }
373 
374                 try
375                 {
376                     _mcastTtl = int.Parse(argument, CultureInfo.InvariantCulture);
377                 }
378                 catch(FormatException ex)
379                 {
380                     Ice.EndpointParseException e = new Ice.EndpointParseException(ex);
381                     e.str = "invalid TTL value `" + argument + "' in endpoint " + endpoint;
382                     throw e;
383                 }
384 
385                 if(_mcastTtl < 0)
386                 {
387                     Ice.EndpointParseException e = new Ice.EndpointParseException();
388                     e.str = "TTL value `" + argument + "' out of range in endpoint " + endpoint;
389                     throw e;
390                 }
391             }
392             else if(option.Equals("--interface"))
393             {
394                 if(argument == null)
395                 {
396                     Ice.EndpointParseException e = new Ice.EndpointParseException();
397                     e.str = "no argument provided for --interface option in endpoint " + endpoint;
398                     throw e;
399                 }
400                 _mcastInterface = argument;
401             }
402             else
403             {
404                 return false;
405             }
406 
407             return true;
408         }
409 
createConnector(EndPoint addr, NetworkProxy proxy)410         protected override Connector createConnector(EndPoint addr, NetworkProxy proxy)
411         {
412             return new UdpConnector(instance_, addr, sourceAddr_, _mcastInterface, _mcastTtl, connectionId_);
413         }
414 
createEndpoint(string host, int port, string connectionId)415         protected override IPEndpointI createEndpoint(string host, int port, string connectionId)
416         {
417             return new UdpEndpointI(instance_, host, port, sourceAddr_, _mcastInterface, _mcastTtl, _connect,
418                                     connectionId, _compress);
419         }
420 
421         private string _mcastInterface = "";
422         private int _mcastTtl = -1;
423         private bool _connect;
424         private bool _compress;
425     }
426 
427     sealed class UdpEndpointFactory : EndpointFactory
428     {
UdpEndpointFactory(ProtocolInstance instance)429         internal UdpEndpointFactory(ProtocolInstance instance)
430         {
431             _instance = instance;
432         }
433 
initialize()434         public void initialize()
435         {
436         }
437 
type()438         public short type()
439         {
440             return _instance.type();
441         }
442 
protocol()443         public string protocol()
444         {
445             return _instance.protocol();
446         }
447 
create(List<string> args, bool oaEndpoint)448         public EndpointI create(List<string> args, bool oaEndpoint)
449         {
450             IPEndpointI endpt = new UdpEndpointI(_instance);
451             endpt.initWithOptions(args, oaEndpoint);
452             return endpt;
453         }
454 
read(Ice.InputStream s)455         public EndpointI read(Ice.InputStream s)
456         {
457             return new UdpEndpointI(_instance, s);
458         }
459 
destroy()460         public void destroy()
461         {
462             _instance = null;
463         }
464 
clone(ProtocolInstance instance)465         public EndpointFactory clone(ProtocolInstance instance)
466         {
467             return new UdpEndpointFactory(instance);
468         }
469 
470         private ProtocolInstance _instance;
471     }
472 
473 }
474