PageRenderTime 64ms CodeModel.GetById 13ms app.highlight 41ms RepoModel.GetById 1ms app.codeStats 1ms

/cs/src/Ice/Network.cs

https://bitbucket.org/cleto/zeroc-ice-package
C# | 1443 lines | 1189 code | 107 blank | 147 comment | 217 complexity | fa80e81bdaf4a49a8e3e3adc19cc3aae MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// **********************************************************************
   2//
   3// Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
   4//
   5// This copy of Ice is licensed to you under the terms described in the
   6// ICE_LICENSE file included in this distribution.
   7//
   8// **********************************************************************
   9
  10namespace IceInternal
  11{
  12    using System;
  13    using System.Collections;
  14    using System.Collections.Generic;
  15    using System.ComponentModel;
  16    using System.Diagnostics;
  17    using System.Net;
  18#if !COMPACT && !UNITY
  19    using System.Net.NetworkInformation;
  20#endif
  21    using System.Net.Sockets;
  22    using System.Runtime.InteropServices;
  23    using System.Threading;
  24    using System.Globalization;
  25
  26    public interface NetworkProxy
  27    {
  28        //
  29        // Write the connection request on the connection established
  30        // with the network proxy server. This is called right after
  31        // the connection establishment succeeds.
  32        //
  33        void beginWriteConnectRequest(EndPoint endpoint, Buffer buf);
  34        void endWriteConnectRequest(Buffer buf);
  35
  36        //
  37        // Once the connection request has been sent, this is called
  38        // to prepare and read the response from the proxy server.
  39        //
  40        void beginReadConnectRequestResponse(Buffer buf);
  41        void endReadConnectRequestResponse(Buffer buf);
  42
  43#if !SILVERLIGHT
  44        //
  45        // If the proxy host needs to be resolved, this should return
  46        // a new NetworkProxy containing the IP address of the proxy.
  47        // This is called from the endpoint host resolver thread, so
  48        // it's safe if this this method blocks.
  49        //
  50        NetworkProxy resolveHost();
  51#endif
  52
  53        //
  54        // Returns the IP address of the network proxy. This method
  55        // must not block. It's only called on a network proxy object
  56        // returned by resolveHost().
  57        //
  58        EndPoint getAddress();
  59
  60        //
  61        // Returns the name of the proxy, used for tracing purposes.
  62        //
  63        string getName();
  64    }
  65
  66    public sealed class SOCKSNetworkProxy : NetworkProxy
  67    {
  68        public SOCKSNetworkProxy(string host, int port)
  69        {
  70#if SILVERLIGHT
  71            _address = new DnsEndPoint(host, port, AddressFamily.InterNetwork);
  72#else
  73            _host = host;
  74            _port = port;
  75#endif
  76        }
  77
  78        private SOCKSNetworkProxy(EndPoint address)
  79        {
  80            _address = address;
  81        }
  82
  83        public void beginWriteConnectRequest(EndPoint endpoint, Buffer buf)
  84        {
  85            if(!(endpoint is IPEndPoint))
  86            {
  87                throw new Ice.FeatureNotSupportedException("SOCKS4 does not support domain names");
  88            }
  89            else if(endpoint.AddressFamily != AddressFamily.InterNetwork)
  90            {
  91                throw new Ice.FeatureNotSupportedException("SOCKS4 only supports IPv4 addresses");
  92            }
  93
  94            //
  95            // SOCKS connect request
  96            //
  97            IPEndPoint addr = (IPEndPoint)endpoint;
  98            buf.resize(9, false);
  99            ByteBuffer.ByteOrder order = buf.b.order();
 100            buf.b.order(ByteBuffer.ByteOrder.BIG_ENDIAN); // Network byte order.
 101            buf.b.position(0);
 102            buf.b.put(0x04); // SOCKS version 4.
 103            buf.b.put(0x01); // Command, establish a TCP/IP stream connection
 104            buf.b.putShort((short)addr.Port); // Port
 105            buf.b.put(addr.Address.GetAddressBytes()); // IPv4 address
 106            buf.b.put(0x00); // User ID.
 107            buf.b.position(0);
 108            buf.b.limit(buf.size());
 109            buf.b.order(order);
 110        }
 111
 112        public void endWriteConnectRequest(Buffer buf)
 113        {
 114            buf.reset();
 115        }
 116
 117        public void beginReadConnectRequestResponse(Buffer buf)
 118        {
 119            //
 120            // Read the SOCKS4 response whose size is 8 bytes.
 121            //
 122            buf.resize(8, true);
 123            buf.b.position(0);
 124        }
 125
 126        public void endReadConnectRequestResponse(Buffer buf)
 127        {
 128            buf.b.position(0);
 129            byte b1 = buf.b.get();
 130            byte b2 = buf.b.get();
 131            if(b1 != 0x00 || b2 != 0x5a)
 132            {
 133                throw new Ice.ConnectFailedException();
 134            }
 135            buf.reset();
 136        }
 137
 138#if !SILVERLIGHT
 139        public NetworkProxy resolveHost()
 140        {
 141            Debug.Assert(_host != null);
 142            return new SOCKSNetworkProxy(Network.getAddresses(_host,
 143                                                              _port,
 144                                                              Network.EnableIPv4,
 145                                                              Ice.EndpointSelectionType.Random,
 146                                                              false,
 147                                                              true)[0]);
 148        }
 149#endif
 150
 151        public EndPoint getAddress()
 152        {
 153            Debug.Assert(_address != null); // Host must be resolved.
 154            return _address;
 155        }
 156
 157        public string getName()
 158        {
 159            return "SOCKS";
 160        }
 161
 162#if !SILVERLIGHT
 163        private readonly string _host;
 164        private readonly int _port;
 165#endif
 166        private readonly EndPoint _address;
 167    }
 168
 169    public sealed class Network
 170    {
 171        // ProtocolSupport
 172        public const int EnableIPv4 = 0;
 173        public const int EnableIPv6 = 1;
 174        public const int EnableBoth = 2;
 175
 176#if COMPACT
 177        public static SocketError socketErrorCode(SocketException ex)
 178        {
 179            return (SocketError)ex.ErrorCode;
 180        }
 181#else
 182        public static SocketError socketErrorCode(SocketException ex)
 183        {
 184            return ex.SocketErrorCode;
 185        }
 186#endif
 187
 188#if COMPACT
 189        //
 190        // SocketError enumeration isn't available with Silverlight
 191        //
 192        public enum SocketError
 193        {
 194            Interrupted = 10004,                    // A blocking Socket call was canceled.
 195            //AccessDenied =10013,                  // An attempt was made to access a Socket in a way that is forbidden by its access permissions.
 196            Fault = 10014,                          // An invalid pointer address was detected by the underlying socket provider.
 197            InvalidArgument = 10022,                // An invalid argument was supplied to a Socket member.
 198            TooManyOpenSockets = 10024,             // There are too many open sockets in the underlying socket provider.
 199            WouldBlock = 10035,                     // An operation on a nonblocking socket cannot be completed immediately.
 200            InProgress = 10036,                     // A blocking operation is in progress.
 201            //AlreadyInProgress = 10037,            // The nonblocking Socket already has an operation in progress.
 202            //NotSocket = 10038,                    // A Socket operation was attempted on a non-socket.
 203            //DestinationAddressRequired = 10039,   // A required address was omitted from an operation on a Socket.
 204            MessageSize = 10040,                    // The datagram is too long.
 205            //ProtocolType = 10041,                 // The protocol type is incorrect for this Socket.
 206            //ProtocolOption = 10042,               // An unknown, invalid, or unsupported option or level was used with a Socket.
 207            //ProtocolNotSupported = 10043,         // The protocol is not implemented or has not been configured.
 208            //SocketNotSupported = 10044,           // The support for the specified socket type does not exist in this address family.
 209            //OperationNotSupported = 10045,        // The address family is not supported by the protocol family.
 210            //ProtocolFamilyNotSupported = 10046,   // The protocol family is not implemented or has not been configured.
 211            //AddressFamilyNotSupported = 10047,    // The address family specified is not supported.
 212            //AddressAlreadyInUse = 10048,          // Only one use of an address is normally permitted.
 213            //AddressNotAvailable = 10049,          // The selected IP address is not valid in this context.
 214            NetworkDown = 10050,                    // The network is not available.
 215            NetworkUnreachable = 10051,             // No route to the remote host exists.
 216            NetworkReset = 10052,                   // The application tried to set KeepAlive on a connection that has already timed out.
 217            ConnectionAborted = 10053,              // The connection was aborted by the .NET Framework or the underlying socket provider.
 218            ConnectionReset = 10054,                // The connection was reset by the remote peer.
 219            NoBufferSpaceAvailable = 10055,         // No free buffer space is available for a Socket operation.
 220            //IsConnected = 10056,                  // The Socket is already connected.
 221            NotConnected = 10057,                   // The application tried to send or receive data, and the Socket is not connected.
 222            Shutdown = 10058,                       // A request to send or receive data was disallowed because the Socket has already been closed.
 223            TimedOut = 10060,                       // The connection attempt timed out, or the connected host has failed to respond.
 224            ConnectionRefused = 10061,              // The remote host is actively refusing a connection.
 225            //HostDown = 10064,                     // The operation failed because the remote host is down.
 226            HostUnreachable = 10065,                // There is no network route to the specified host.
 227            //ProcessLimit = 10067,                 // Too many processes are using the underlying socket provider.
 228            //SystemNotReady = 10091,               // The network subsystem is unavailable.
 229            //VersionNotSupported = 10092,          // The version of the underlying socket provider is out of range.
 230            //NotInitialized = 10093,               // The underlying socket provider has not been initialized.
 231            //Disconnecting = 10101,                // A graceful shutdown is in progress.
 232            //TypeNotFound = 10109,                 // The specified class was not found.
 233            //HostNotFound = 11001,                 // No such host is known. The name is not an official host name or alias.
 234            TryAgain = 11002,                       // The name of the host could not be resolved. Try again later.
 235            //NoRecovery = 11003,                   // The error is unrecoverable or the requested database cannot be located.
 236            //NoData = 11004,                       // The requested name or IP address was not found on the name server.
 237            //IOPending = 997,                      // The application has initiated an overlapped operation that cannot be completed immediately.
 238            OperationAborted =995                   // The overlapped operation was aborted due to the closure of the Socket.
 239        }
 240#endif
 241
 242        public static bool interrupted(SocketException ex)
 243        {
 244            return socketErrorCode(ex) == SocketError.Interrupted;
 245        }
 246
 247        public static bool acceptInterrupted(SocketException ex)
 248        {
 249            if(interrupted(ex))
 250            {
 251                return true;
 252            }
 253            SocketError error = socketErrorCode(ex);
 254            return error == SocketError.ConnectionAborted ||
 255                   error == SocketError.ConnectionReset ||
 256                   error == SocketError.TimedOut;
 257        }
 258
 259        public static bool noBuffers(SocketException ex)
 260        {
 261            SocketError error = socketErrorCode(ex);
 262            return error == SocketError.NoBufferSpaceAvailable ||
 263                      error == SocketError.Fault;
 264        }
 265
 266        public static bool wouldBlock(SocketException ex)
 267        {
 268            return socketErrorCode(ex) == SocketError.WouldBlock;
 269        }
 270
 271        public static bool connectFailed(SocketException ex)
 272        {
 273            SocketError error = socketErrorCode(ex);
 274            return error == SocketError.ConnectionRefused ||
 275                   error == SocketError.TimedOut ||
 276                   error == SocketError.NetworkUnreachable ||
 277                   error == SocketError.HostUnreachable ||
 278                   error == SocketError.ConnectionReset ||
 279                   error == SocketError.Shutdown ||
 280                   error == SocketError.ConnectionAborted ||
 281                   error == SocketError.NetworkDown;
 282        }
 283
 284        public static bool connectInProgress(SocketException ex)
 285        {
 286            SocketError error = socketErrorCode(ex);
 287            return error == SocketError.WouldBlock ||
 288                   error == SocketError.InProgress;
 289        }
 290
 291        public static bool connectionLost(SocketException ex)
 292        {
 293            SocketError error = socketErrorCode(ex);
 294            return error == SocketError.ConnectionReset ||
 295                   error == SocketError.Shutdown ||
 296                   error == SocketError.ConnectionAborted ||
 297                   error == SocketError.NetworkDown ||
 298                   error == SocketError.NetworkReset;
 299        }
 300
 301        public static bool connectionLost(System.IO.IOException ex)
 302        {
 303            //
 304            // In some cases the IOException has an inner exception that we can pass directly
 305            // to the other overloading of connectionLost().
 306            //
 307            if(ex.InnerException != null && ex.InnerException is SocketException)
 308            {
 309                return connectionLost(ex.InnerException as SocketException);
 310            }
 311
 312            //
 313            // In other cases the IOException has no inner exception. We could examine the
 314            // exception's message, but that is fragile due to localization issues. We
 315            // resort to extracting the value of the protected HResult member via reflection.
 316            //
 317            int hr = (int)ex.GetType().GetProperty("HResult",
 318                System.Reflection.BindingFlags.Instance |
 319                System.Reflection.BindingFlags.NonPublic |
 320                System.Reflection.BindingFlags.Public).GetValue(ex, null);
 321
 322            //
 323            // This value corresponds to the following errors:
 324            //
 325            // "Authentication failed because the remote party has closed the transport stream"
 326            //
 327            if(hr == -2146232800)
 328            {
 329                return true;
 330            }
 331
 332            return false;
 333        }
 334
 335        public static bool connectionRefused(SocketException ex)
 336        {
 337            return socketErrorCode(ex) == SocketError.ConnectionRefused;
 338        }
 339
 340        public static bool notConnected(SocketException ex)
 341        {
 342            // BUGFIX: SocketError.InvalidArgument because shutdown() under OS X returns EINVAL
 343            // if the server side is gone.
 344            // BUGFIX: shutdown() under Vista might return SocketError.ConnectionReset
 345            SocketError error = socketErrorCode(ex);
 346            return error == SocketError.NotConnected ||
 347                   error == SocketError.InvalidArgument ||
 348                   error == SocketError.ConnectionReset;
 349        }
 350
 351        public static bool recvTruncated(SocketException ex)
 352        {
 353            return socketErrorCode(ex) == SocketError.MessageSize;
 354        }
 355
 356        public static bool operationAborted(SocketException ex)
 357        {
 358            return socketErrorCode(ex) == SocketError.OperationAborted;
 359        }
 360
 361        public static bool timeout(System.IO.IOException ex)
 362        {
 363            //
 364            // TODO: Instead of testing for an English substring, we need to examine the inner
 365            // exception (if there is one).
 366            //
 367            return ex.Message.IndexOf("period of time", StringComparison.Ordinal) >= 0;
 368        }
 369
 370        public static bool noMoreFds(System.Exception ex)
 371        {
 372            try
 373            {
 374                return ex != null && socketErrorCode((SocketException)ex) == SocketError.TooManyOpenSockets;
 375            }
 376            catch(InvalidCastException)
 377            {
 378                return false;
 379            }
 380        }
 381
 382        public static bool isMulticast(IPEndPoint addr)
 383        {
 384#if COMPACT
 385            string ip = addr.Address.ToString().ToUpper();
 386#else
 387            string ip = addr.Address.ToString().ToUpperInvariant();
 388#endif
 389            if(addr.AddressFamily == AddressFamily.InterNetwork)
 390            {
 391                char[] splitChars = { '.' };
 392                string[] arr = ip.Split(splitChars);
 393                try
 394                {
 395                    int i = System.Int32.Parse(arr[0], CultureInfo.InvariantCulture);
 396                    if(i >= 223 && i <= 239)
 397                    {
 398                        return true;
 399                    }
 400                }
 401                catch(System.FormatException)
 402                {
 403                    return false;
 404                }
 405            }
 406            else // AddressFamily.InterNetworkV6
 407            {
 408                if(ip.StartsWith("FF", StringComparison.Ordinal))
 409                {
 410                    return true;
 411                }
 412            }
 413            return false;
 414        }
 415
 416        public static Socket createSocket(bool udp, AddressFamily family)
 417        {
 418            Socket socket;
 419
 420            try
 421            {
 422                if(udp)
 423                {
 424                    socket = new Socket(family, SocketType.Dgram, ProtocolType.Udp);
 425                }
 426                else
 427                {
 428                    socket = new Socket(family, SocketType.Stream, ProtocolType.Tcp);
 429                }
 430            }
 431            catch(SocketException ex)
 432            {
 433                throw new Ice.SocketException(ex);
 434            }
 435            catch(ArgumentException ex)
 436            {
 437                throw new Ice.SocketException(ex);
 438            }
 439
 440
 441            if(!udp)
 442            {
 443                try
 444                {
 445                    setTcpNoDelay(socket);
 446#if !SILVERLIGHT
 447                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
 448#endif
 449                }
 450                catch(SocketException ex)
 451                {
 452                    closeSocketNoThrow(socket);
 453                    throw new Ice.SocketException(ex);
 454                }
 455            }
 456            return socket;
 457        }
 458
 459        public static Socket createServerSocket(bool udp, AddressFamily family, int protocol)
 460        {
 461            Socket socket = createSocket(udp, family);
 462#  if !COMPACT && !UNITY && !__MonoCS__ && !SILVERLIGHT
 463            if(family == AddressFamily.InterNetworkV6 && protocol != EnableIPv4)
 464            {
 465                try
 466                {
 467                    int flag = protocol == EnableIPv6 ? 1 : 0;
 468                    socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, flag);
 469                }
 470                catch(SocketException ex)
 471                {
 472                    closeSocketNoThrow(socket);
 473                    throw new Ice.SocketException(ex);
 474                }
 475            }
 476#endif
 477            return socket;
 478        }
 479
 480        public static void closeSocketNoThrow(Socket socket)
 481        {
 482            if(socket == null)
 483            {
 484                return;
 485            }
 486            try
 487            {
 488                socket.Close();
 489            }
 490            catch(SocketException)
 491            {
 492                // Ignore
 493            }
 494        }
 495
 496        public static void closeSocket(Socket socket)
 497        {
 498            if(socket == null)
 499            {
 500                return;
 501            }
 502            try
 503            {
 504                socket.Close();
 505            }
 506            catch(SocketException ex)
 507            {
 508                throw new Ice.SocketException(ex);
 509            }
 510        }
 511
 512        public static void setTcpNoDelay(Socket socket)
 513        {
 514            try
 515            {
 516#if SILVERLIGHT
 517                socket.NoDelay = true;
 518#else
 519                socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1);
 520#endif
 521            }
 522            catch(System.Exception ex)
 523            {
 524                closeSocketNoThrow(socket);
 525                throw new Ice.SocketException(ex);
 526            }
 527        }
 528
 529#if !SILVERLIGHT
 530        public static void setBlock(Socket socket, bool block)
 531        {
 532            try
 533            {
 534                socket.Blocking = block;
 535            }
 536            catch(SocketException ex)
 537            {
 538                closeSocketNoThrow(socket);
 539                throw new Ice.SocketException(ex);
 540            }
 541        }
 542
 543        public static void setKeepAlive(Socket socket)
 544        {
 545            try
 546            {
 547                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
 548            }
 549            catch(System.Exception ex)
 550            {
 551                closeSocketNoThrow(socket);
 552                throw new Ice.SocketException(ex);
 553            }
 554        }
 555#endif
 556
 557        public static void setSendBufferSize(Socket socket, int sz)
 558        {
 559            try
 560            {
 561#if SILVERLIGHT
 562                socket.SendBufferSize = sz;
 563#else
 564                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, sz);
 565#endif
 566            }
 567            catch(SocketException ex)
 568            {
 569                closeSocketNoThrow(socket);
 570                throw new Ice.SocketException(ex);
 571            }
 572        }
 573
 574        public static int getSendBufferSize(Socket socket)
 575        {
 576            int sz;
 577            try
 578            {
 579#if SILVERLIGHT
 580                sz = socket.SendBufferSize;
 581#else
 582                sz = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
 583#endif
 584            }
 585            catch(SocketException ex)
 586            {
 587                closeSocketNoThrow(socket);
 588                throw new Ice.SocketException(ex);
 589            }
 590            return sz;
 591        }
 592
 593        public static void setRecvBufferSize(Socket socket, int sz)
 594        {
 595            try
 596            {
 597#if SILVERLIGHT
 598                socket.ReceiveBufferSize = sz;
 599#else
 600                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, sz);
 601#endif
 602            }
 603            catch(SocketException ex)
 604            {
 605                closeSocketNoThrow(socket);
 606                throw new Ice.SocketException(ex);
 607            }
 608        }
 609
 610        public static int getRecvBufferSize(Socket socket)
 611        {
 612            int sz = 0;
 613            try
 614            {
 615#if SILVERLIGHT
 616                sz = socket.ReceiveBufferSize;
 617#else
 618                sz = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
 619#endif
 620            }
 621            catch(SocketException ex)
 622            {
 623                closeSocketNoThrow(socket);
 624                throw new Ice.SocketException(ex);
 625            }
 626            return sz;
 627        }
 628
 629#if !SILVERLIGHT
 630        public static void setReuseAddress(Socket socket, bool reuse)
 631        {
 632            try
 633            {
 634                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuse ? 1 : 0);
 635            }
 636            catch(SocketException ex)
 637            {
 638                closeSocketNoThrow(socket);
 639                throw new Ice.SocketException(ex);
 640            }
 641        }
 642
 643        public static void setMcastGroup(Socket socket, IPAddress group, string iface)
 644        {
 645            try
 646            {
 647                if(group.AddressFamily == AddressFamily.InterNetwork)
 648                {
 649                    IPAddress ifaceAddr = IPAddress.Any;
 650                    if(iface.Length != 0)
 651                    {
 652                        ifaceAddr = getInterfaceAddress(iface);
 653                        if(ifaceAddr == IPAddress.Any)
 654                        {
 655                            ifaceAddr = ((IPEndPoint)getAddressForServer(iface, 0, EnableIPv4, false)).Address;
 656                        }
 657                    }
 658                    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
 659                                           new MulticastOption(group, ifaceAddr));
 660                }
 661                else
 662                {
 663                    int ifaceIndex = 0;
 664                    if(iface.Length != 0)
 665                    {
 666                        ifaceIndex = getInterfaceIndex(iface);
 667                        if(ifaceIndex == 0)
 668                        {
 669                            try
 670                            {
 671                                ifaceIndex = System.Int32.Parse(iface, CultureInfo.InvariantCulture);
 672                            }
 673                            catch(System.FormatException ex)
 674                            {
 675                                closeSocketNoThrow(socket);
 676                                throw new Ice.SocketException(ex);
 677                            }
 678                        }
 679                    }
 680                    socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership,
 681                                           new IPv6MulticastOption(group, ifaceIndex));
 682                }
 683            }
 684            catch(SocketException ex)
 685            {
 686                closeSocketNoThrow(socket);
 687                throw new Ice.SocketException(ex);
 688            }
 689        }
 690#endif
 691
 692        public static void setMcastTtl(Socket socket, int ttl, AddressFamily family)
 693        {
 694            try
 695            {
 696#if SILVERLIGHT
 697                socket.Ttl = (short)ttl;
 698#else
 699                if(family == AddressFamily.InterNetwork)
 700                {
 701                    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, ttl);
 702                }
 703                else
 704                {
 705                    socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, ttl);
 706                }
 707#endif
 708            }
 709            catch(SocketException ex)
 710            {
 711                closeSocketNoThrow(socket);
 712                throw new Ice.SocketException(ex);
 713            }
 714        }
 715
 716#if !SILVERLIGHT
 717        public static IPEndPoint doBind(Socket socket, EndPoint addr)
 718        {
 719            try
 720            {
 721                socket.Bind(addr);
 722                return (IPEndPoint)socket.LocalEndPoint;
 723            }
 724            catch(SocketException ex)
 725            {
 726                closeSocketNoThrow(socket);
 727                throw new Ice.SocketException(ex);
 728            }
 729        }
 730
 731        public static void doListen(Socket socket, int backlog)
 732        {
 733        repeatListen:
 734
 735            try
 736            {
 737                socket.Listen(backlog);
 738            }
 739            catch(SocketException ex)
 740            {
 741                if(interrupted(ex))
 742                {
 743                    goto repeatListen;
 744                }
 745
 746                closeSocketNoThrow(socket);
 747                throw new Ice.SocketException(ex);
 748            }
 749        }
 750#endif
 751
 752#if !SILVERLIGHT
 753        public static bool doConnect(Socket fd, EndPoint addr)
 754        {
 755        repeatConnect:
 756            try
 757            {
 758                //
 759                // Even though we are on the client side, the call to Bind()
 760                // is necessary to work around a .NET bug: if a socket is
 761                // connected non-blocking, the LocalEndPoint and RemoteEndPoint
 762                // properties are null. The call to Bind() fixes this.
 763                //
 764                IPAddress any = fd.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any;
 765                fd.Bind(new IPEndPoint(any, 0));
 766                IAsyncResult result = fd.BeginConnect(addr, null, null);
 767                if(!result.CompletedSynchronously)
 768                {
 769                    return false;
 770                }
 771                fd.EndConnect(result);
 772            }
 773            catch(SocketException ex)
 774            {
 775                if(interrupted(ex))
 776                {
 777                    goto repeatConnect;
 778                }
 779
 780                closeSocketNoThrow(fd);
 781
 782                if(connectionRefused(ex))
 783                {
 784                    throw new Ice.ConnectionRefusedException(ex);
 785                }
 786                else
 787                {
 788                    throw new Ice.ConnectFailedException(ex);
 789                }
 790            }
 791
 792            //
 793            // On Windows, we need to set the socket's blocking status again
 794            // after the asynchronous connect. Seems like a bug in .NET.
 795            //
 796            setBlock(fd, fd.Blocking);
 797
 798            if(AssemblyUtil.platform_ == AssemblyUtil.Platform.NonWindows)
 799            {
 800                //
 801                // Prevent self connect (self connect happens on Linux when a client tries to connect to
 802                // a server which was just deactivated if the client socket re-uses the same ephemeral
 803                // port as the server).
 804                //
 805                if(addr.Equals(getLocalAddress(fd)))
 806                {
 807                    throw new Ice.ConnectionRefusedException();
 808                }
 809            }
 810            return true;
 811        }
 812
 813        public static IAsyncResult doConnectAsync(Socket fd, EndPoint addr, AsyncCallback callback, object state)
 814        {
 815            //
 816            // NOTE: It's the caller's responsability to close the socket upon
 817            // failure to connect. The socket isn't closed by this method.
 818            //
 819
 820        repeatConnect:
 821            try
 822            {
 823                //
 824                // Even though we are on the client side, the call to Bind()
 825                // is necessary to work around a .NET bug: if a socket is
 826                // connected non-blocking, the LocalEndPoint and RemoteEndPoint
 827                // properties are null. The call to Bind() fixes this.
 828                //
 829                IPAddress any = fd.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any;
 830                fd.Bind(new IPEndPoint(any, 0));
 831                return fd.BeginConnect(addr,
 832                                       delegate(IAsyncResult result)
 833                                       {
 834                                           if(!result.CompletedSynchronously)
 835                                           {
 836                                               callback(result.AsyncState);
 837                                           }
 838                                       }, state);
 839            }
 840            catch(SocketException ex)
 841            {
 842                if(interrupted(ex))
 843                {
 844                    goto repeatConnect;
 845                }
 846
 847                if(connectionRefused(ex))
 848                {
 849                    throw new Ice.ConnectionRefusedException(ex);
 850                }
 851                else
 852                {
 853                    throw new Ice.ConnectFailedException(ex);
 854                }
 855            }
 856        }
 857
 858        public static void doFinishConnectAsync(Socket fd, IAsyncResult result)
 859        {
 860            //
 861            // NOTE: It's the caller's responsability to close the socket upon
 862            // failure to connect. The socket isn't closed by this method.
 863            //
 864            try
 865            {
 866                fd.EndConnect(result);
 867            }
 868            catch(SocketException ex)
 869            {
 870                if(connectionRefused(ex))
 871                {
 872                    throw new Ice.ConnectionRefusedException(ex);
 873                }
 874                else
 875                {
 876                    throw new Ice.ConnectFailedException(ex);
 877                }
 878            }
 879
 880            //
 881            // On Windows, we need to set the socket's blocking status again
 882            // after the asynchronous connect. Seems like a bug in .NET.
 883            //
 884            setBlock(fd, fd.Blocking);
 885
 886            if(AssemblyUtil.platform_ == AssemblyUtil.Platform.NonWindows)
 887            {
 888                //
 889                // Prevent self connect (self connect happens on Linux when a client tries to connect to
 890                // a server which was just deactivated if the client socket re-uses the same ephemeral
 891                // port as the server).
 892                //
 893                EndPoint remoteAddr = getRemoteAddress(fd);
 894                if(remoteAddr != null && remoteAddr.Equals(getLocalAddress(fd)))
 895                {
 896                    throw new Ice.ConnectionRefusedException();
 897                }
 898            }
 899        }
 900#endif
 901
 902        public static EndPoint getAddressForServer(string host, int port, int protocol, bool preferIPv6)
 903        {
 904            if(host.Length == 0)
 905            {
 906                if(protocol != EnableIPv4)
 907                {
 908                    return new IPEndPoint(IPAddress.IPv6Any, port);
 909                }
 910                else
 911                {
 912                    return new IPEndPoint(IPAddress.Any, port);
 913                }
 914            }
 915            return getAddresses(host, port, protocol, Ice.EndpointSelectionType.Ordered, preferIPv6, true)[0];
 916        }
 917
 918        public static List<EndPoint> getAddresses(string host, int port, int protocol,
 919                                                  Ice.EndpointSelectionType selType, bool preferIPv6, bool blocking)
 920        {
 921            List<EndPoint> addresses = new List<EndPoint>();
 922            if(host.Length == 0)
 923            {
 924                if(protocol != EnableIPv4)
 925                {
 926                    addresses.Add(new IPEndPoint(IPAddress.IPv6Loopback, port));
 927                }
 928
 929                if(protocol != EnableIPv6)
 930                {
 931                    addresses.Add(new IPEndPoint(IPAddress.Loopback, port));
 932                }
 933                return addresses;
 934            }
 935
 936
 937            int retry = 5;
 938
 939            repeatGetHostByName:
 940            try
 941            {
 942                //
 943                // No need for lookup if host is ip address.
 944                //
 945                try
 946                {
 947                    IPAddress addr = IPAddress.Parse(host);
 948                    if((addr.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
 949                       (addr.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
 950                    {
 951                        addresses.Add(new IPEndPoint(addr, port));
 952                        return addresses;
 953                    }
 954                    else
 955                    {
 956                        Ice.DNSException e = new Ice.DNSException();
 957                        e.host = host;
 958                        throw e;
 959                    }
 960                }
 961                catch(FormatException)
 962                {
 963#if !SILVERLIGHT
 964                    if(!blocking)
 965                    {
 966                        return addresses;
 967                    }
 968#endif
 969                }
 970
 971#if SILVERLIGHT
 972                addresses.Add(new DnsEndPoint(host, port));
 973#else
 974# if COMPACT
 975                foreach(IPAddress a in Dns.GetHostEntry(host).AddressList)
 976#  else
 977                foreach(IPAddress a in Dns.GetHostAddresses(host))
 978#  endif
 979                {
 980                    if((a.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
 981                       (a.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
 982                    {
 983                        addresses.Add(new IPEndPoint(a, port));
 984                    }
 985                }
 986#endif
 987
 988                if(selType == Ice.EndpointSelectionType.Random)
 989                {
 990                    IceUtilInternal.Collections.Shuffle(ref addresses);
 991                }
 992
 993                if(protocol == EnableBoth)
 994                {
 995                    if(preferIPv6)
 996                    {
 997                        IceUtilInternal.Collections.Sort(ref addresses, _preferIPv6Comparator);
 998                    }
 999                    else
1000                    {
1001                        IceUtilInternal.Collections.Sort(ref addresses, _preferIPv4Comparator);
1002                    }
1003                }
1004            }
1005            catch(SocketException ex)
1006            {
1007                if(socketErrorCode(ex) == SocketError.TryAgain && --retry >= 0)
1008                {
1009                    goto repeatGetHostByName;
1010                }
1011                Ice.DNSException e = new Ice.DNSException(ex);
1012                e.host = host;
1013                throw e;
1014            }
1015            catch(System.Exception ex)
1016            {
1017                Ice.DNSException e = new Ice.DNSException(ex);
1018                e.host = host;
1019                throw e;
1020            }
1021
1022            //
1023            // No InterNetwork/InterNetworkV6 available.
1024            //
1025            if(addresses.Count == 0)
1026            {
1027                Ice.DNSException e = new Ice.DNSException();
1028                e.host = host;
1029                throw e;
1030            }
1031            return addresses;
1032        }
1033
1034        public static IPAddress[] getLocalAddresses(int protocol)
1035        {
1036#if SILVERLIGHT
1037            return new List<IPAddress>().ToArray();
1038#else
1039            List<IPAddress> addresses;
1040            int retry = 5;
1041
1042            repeatGetHostByName:
1043            try
1044            {
1045                addresses = new List<IPAddress>();
1046#  if !COMPACT && !UNITY
1047                NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
1048                foreach(NetworkInterface ni in nics)
1049                {
1050                    IPInterfaceProperties ipProps = ni.GetIPProperties();
1051                    UnicastIPAddressInformationCollection uniColl = ipProps.UnicastAddresses;
1052                    foreach(UnicastIPAddressInformation uni in uniColl)
1053                    {
1054                        if((uni.Address.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
1055                           (uni.Address.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
1056                        {
1057                            if(!IPAddress.IsLoopback(uni.Address))
1058                            {
1059                                addresses.Add(uni.Address);
1060                            }
1061                        }
1062                    }
1063                }
1064#  else
1065#     if COMPACT
1066                foreach(IPAddress a in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
1067#     else
1068                foreach(IPAddress a in Dns.GetHostAddresses(Dns.GetHostName()))
1069#     endif
1070                {
1071                    if((a.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
1072                       (a.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
1073                    {
1074                        if(!IPAddress.IsLoopback(a))
1075                        {
1076                            addresses.Add(a);
1077                        }
1078                    }
1079                }
1080#  endif
1081            }
1082            catch(SocketException ex)
1083            {
1084                if(socketErrorCode(ex) == SocketError.TryAgain && --retry >= 0)
1085                {
1086                    goto repeatGetHostByName;
1087                }
1088                Ice.DNSException e = new Ice.DNSException(ex);
1089                e.host = "0.0.0.0";
1090                throw e;
1091            }
1092            catch(System.Exception ex)
1093            {
1094                Ice.DNSException e = new Ice.DNSException(ex);
1095                e.host = "0.0.0.0";
1096                throw e;
1097            }
1098
1099            return addresses.ToArray();
1100#endif
1101        }
1102
1103        public static void
1104        setTcpBufSize(Socket socket, Ice.Properties properties, Ice.Logger logger)
1105        {
1106            //
1107            // By default, on Windows we use a 128KB buffer size. On Unix
1108            // platforms, we use the system defaults.
1109            //
1110            int dfltBufSize = 0;
1111            if(AssemblyUtil.platform_ == AssemblyUtil.Platform.Windows)
1112            {
1113                dfltBufSize = 128 * 1024;
1114            }
1115
1116            int sizeRequested = properties.getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
1117            if(sizeRequested > 0)
1118            {
1119                //
1120                // Try to set the buffer size. The kernel will silently adjust
1121                // the size to an acceptable value. Then read the size back to
1122                // get the size that was actually set.
1123                //
1124                setRecvBufferSize(socket, sizeRequested);
1125                int size = getRecvBufferSize(socket);
1126                if(size < sizeRequested) // Warn if the size that was set is less than the requested size.
1127                {
1128                    logger.warning("TCP receive buffer size: requested size of " + sizeRequested + " adjusted to " +
1129                                   size);
1130                }
1131            }
1132
1133            sizeRequested = properties.getPropertyAsIntWithDefault("Ice.TCP.SndSize", dfltBufSize);
1134            if(sizeRequested > 0)
1135            {
1136                //
1137                // Try to set the buffer size. The kernel will silently adjust
1138                // the size to an acceptable value. Then read the size back to
1139                // get the size that was actually set.
1140                //
1141                setSendBufferSize(socket, sizeRequested);
1142                int size = getSendBufferSize(socket);
1143                if(size < sizeRequested) // Warn if the size that was set is less than the requested size.
1144                {
1145                    logger.warning("TCP send buffer size: requested size of " + sizeRequested + " adjusted to " + size);
1146                }
1147            }
1148        }
1149
1150        public static List<string> getHostsForEndpointExpand(string host, int protocol, bool includeLoopback)
1151        {
1152            bool wildcard = host.Length == 0;
1153            if(!wildcard)
1154            {
1155                try
1156                {
1157                    IPAddress addr = IPAddress.Parse(host);
1158                    wildcard = addr.Equals(IPAddress.Any) || addr.Equals(IPAddress.IPv6Any);
1159                }
1160                catch(Exception)
1161                {
1162                }
1163            }
1164
1165            List<string> hosts = new List<string>();
1166            if(wildcard)
1167            {
1168                IPAddress[] addrs = getLocalAddresses(protocol);
1169                foreach(IPAddress a in addrs)
1170                {
1171#if COMPACT
1172                    if(!IPAddress.IsLoopback(a))
1173#else
1174                    if(!a.IsIPv6LinkLocal)
1175#endif
1176                    {
1177                        hosts.Add(a.ToString());
1178                    }
1179                }
1180
1181                if(includeLoopback || hosts.Count == 0)
1182                {
1183                    if(protocol != EnableIPv6)
1184                    {
1185                        hosts.Add("127.0.0.1");
1186                    }
1187                    if(protocol != EnableIPv4)
1188                    {
1189                        hosts.Add("0:0:0:0:0:0:0:1");
1190                    }
1191                }
1192            }
1193            return hosts;
1194        }
1195
1196        public static string fdToString(Socket socket, NetworkProxy proxy, EndPoint target)
1197        {
1198            try
1199            {
1200                if(socket == null)
1201                {
1202                    return "<closed>";
1203                }
1204
1205                EndPoint remote = getRemoteAddress(socket);
1206
1207                System.Text.StringBuilder s = new System.Text.StringBuilder();
1208                s.Append("local address = " + localAddrToString(getLocalAddress(socket)));
1209                if(proxy != null)
1210                {
1211                    if(remote == null)
1212                    {
1213                        remote = proxy.getAddress();
1214                    }
1215                    s.Append("\n" + proxy.getName() + " proxy address = " + remoteAddrToString(remote));
1216                    s.Append("\nremote address = " + remoteAddrToString(target));
1217                }
1218                else
1219                {
1220                    if(remote == null)
1221                    {
1222                        remote = target;
1223                    }
1224                    s.Append("\nremote address = " + remoteAddrToString(remote));
1225                }
1226                return s.ToString();
1227            }
1228            catch(ObjectDisposedException)
1229            {
1230                return "<closed>";
1231            }
1232        }
1233
1234        public static string fdToString(Socket socket)
1235        {
1236            try
1237            {
1238                if(socket == null)
1239                {
1240                    return "<closed>";
1241                }
1242                System.Text.StringBuilder s = new System.Text.StringBuilder();
1243                s.Append("local address = " + localAddrToString(getLocalAddress(socket)));
1244                s.Append("\nremote address = " + remoteAddrToString(getRemoteAddress(socket)));
1245                return s.ToString();
1246            }
1247            catch(ObjectDisposedException)
1248            {
1249                return "<closed>";
1250            }
1251        }
1252
1253        public static string fdLocalAddressToString(Socket socket)
1254        {
1255            return "local address = " + localAddrToString(getLocalAddress(socket));
1256        }
1257
1258        public static string
1259        addrToString(EndPoint addr)
1260        {
1261            return endpointAddressToString(addr) + ":" + endpointPort(addr);
1262        }
1263
1264        public static string
1265        localAddrToString(EndPoint endpoint)
1266        {
1267            if(endpoint == null)
1268            {
1269#if SILVERLIGHT
1270                return "<not available>";
1271#else
1272                return "<not bound>";
1273#endif
1274            }
1275            return endpointAddressToString(endpoint) + ":" + endpointPort(endpoint);
1276        }
1277
1278        public static string
1279        remoteAddrToString(EndPoint endpoint)
1280        {
1281            if(endpoint == null)
1282            {
1283                return "<not connected>";
1284            }
1285            return endpointAddressToString(endpoint) + ":" + endpointPort(endpoint);
1286        }
1287
1288        public static EndPoint
1289        getLocalAddress(Socket socket)
1290        {
1291            // Silverlight socket doesn't exposes a local endpoint
1292#if !SILVERLIGHT
1293            try
1294            {
1295                return socket.LocalEndPoint;
1296            }
1297            catch(SocketException ex)
1298            {
1299                throw new Ice.SocketException(ex);
1300            }
1301#else
1302            return null;
1303#endif
1304        }
1305
1306        public static EndPoint
1307        getRemoteAddress(Socket socket)
1308        {
1309            try
1310            {
1311                return (EndPoint)socket.RemoteEndPoint;
1312            }
1313            catch(SocketException)
1314            {
1315            }
1316            return null;
1317        }
1318
1319        private static int
1320        getInterfaceIndex(string name)
1321        {
1322#if !COMPACT && !SILVERLIGHT && !UNITY
1323            NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
1324            foreach(NetworkInterface ni in nics)
1325            {
1326                if(ni.Name == name)
1327                {
1328                    IPInterfaceProperties ipProps = ni.GetIPProperties();
1329                    try
1330                    {
1331                        IPv6InterfaceProperties ipv6Props = ipProps.GetIPv6Properties();
1332                        if(ipv6Props != null)
1333                        {
1334                            return ipv6Props.Index;
1335                        }
1336                    }
1337                    catch(System.NotImplementedException)
1338                    {
1339                    }
1340                }
1341            }
1342#endif
1343            return 0;
1344        }
1345
1346        private static IPAddress
1347        getInterfaceAddress(string name)
1348        {
1349#if !COMPACT && !SILVERLIGHT && !UNITY
1350            NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
1351            foreach(NetworkInterface ni in nics)
1352            {
1353                if(ni.Name == name)
1354                {
1355                    IPInterfaceProperties ipProps = ni.GetIPProperties();
1356                    UnicastIPAddressInformationCollection uniColl = ipProps.UnicastAddresses;
1357                    foreach(UnicastIPAddressInformation uni in uniColl)
1358                    {
1359                        if(uni.Address.AddressFamily == AddressFamily.InterNetwork)
1360                        {
1361                            return uni.Address;
1362                        }
1363                    }
1364                }
1365            }
1366#endif
1367            return IPAddress.Any;
1368        }
1369
1370        public static string
1371        endpointAddressToString(EndPoint endpoint)
1372        {
1373            if(endpoint != null)
1374            {
1375#if SILVERLIGHT
1376                if(endpoint is DnsEndPoint)
1377                {
1378                    DnsEndPoint dnsEndpoint = (DnsEndPoint)endpoint;
1379                    return dnsEndpoint.Host;
1380                }
1381#endif
1382                if(endpoint is IPEndPoint)
1383                {
1384                    IPEndPoint ipEndpoint = (IPEndPoint) endpoint;
1385                    return ipEndpoint.Address.ToString();
1386                }
1387            }
1388            return "";
1389        }
1390
1391        public static int
1392        endpointPort(EndPoint endpoint)
1393        {
1394            if(endpoint != null)
1395            {
1396#if SILVERLIGHT
1397                if(endpoint is DnsEndPoint)
1398                {
1399                    DnsEndPoint dnsEndpoint = (DnsEndPoint)endpoint;
1400                    return dnsEndpoint.Port;
1401                }
1402#endif
1403                if(endpoint is IPEndPoint)
1404                {
1405                    IPEndPoint ipEndpoint = (IPEndPoint) endpoint;
1406                    return ipEndpoint.Port;
1407                }
1408            }
1409            return -1;
1410        }
1411
1412        private class EndPointComparator : IComparer<EndPoint>
1413        {
1414            public EndPointComparator(bool ipv6)
1415            {
1416                _ipv6 = ipv6;
1417            }
1418
1419            public int Compare(EndPoint lhs, EndPoint rhs)
1420            {
1421                if(lhs.AddressFamily == AddressFamily.InterNetwork &&
1422                   rhs.AddressFamil

Large files files are truncated, but you can click here to view the full file