PageRenderTime 214ms CodeModel.GetById 129ms app.highlight 75ms RepoModel.GetById 1ms app.codeStats 0ms

/Framework/Tools/Emulator/Sockets.cs

https://bitbucket.org/CW2/netduinofirmware
C# | 1555 lines | 1209 code | 326 blank | 20 comment | 160 complexity | 9a066437ee7a803dc6c21aaba3b46eca MD5 | raw file
   1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   2// Copyright (c) Microsoft Corporation.  All rights reserved.
   3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   4
   5using System;
   6using System.IO;
   7using System.Diagnostics;
   8using System.Runtime.InteropServices;
   9using System.Collections;
  10using System.Collections.Generic;
  11using System.ComponentModel;
  12using System.Threading;
  13using System.Net;
  14using System.Net.Sockets;
  15using System.Net.NetworkInformation;
  16using System.Runtime.CompilerServices;
  17using Microsoft.Win32.SafeHandles;
  18using Microsoft.SPOT.Emulator.Com;
  19
  20namespace Microsoft.SPOT.Emulator.Sockets
  21{
  22    internal class SocketsDriver : HalDriver<ISocketsDriver>, ISocketsDriver
  23    {
  24        internal static class TinyCLRSockets
  25        {
  26            [StructLayout(LayoutKind.Sequential)]
  27            internal class fd_set
  28            {
  29                internal uint count;
  30                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
  31                internal int[] fd_array;
  32            }
  33        }
  34
  35        [StructLayout(LayoutKind.Sequential)]
  36        internal class SockAddr
  37        {
  38            public short  sin_family;
  39            public ushort sin_port;
  40            public uint   sin_addr;
  41            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  42            public byte[] sin_zero = new byte[8];
  43
  44            public void MarshalFromNative(IntPtr native)
  45            {
  46                Marshal.PtrToStructure(native, this);
  47
  48                sin_port = (ushort)(((sin_port & 0xFF) << 8) | ((sin_port >> 8) & 0xFF));
  49            }
  50
  51            public void MarshalToNative(IntPtr native)
  52            {
  53                sin_port = (ushort)(((sin_port & 0xFF) << 8) | ((sin_port >> 8) & 0xFF));
  54
  55                Marshal.StructureToPtr(this, native, true);
  56            }
  57        }
  58
  59        internal static class NativeSockets
  60        {
  61            [StructLayout(LayoutKind.Sequential)]
  62            internal class fd_set
  63            {
  64                const int FD_SETSIZE = 64;
  65
  66                internal uint count;
  67                [MarshalAs(UnmanagedType.ByValArray, SizeConst = FD_SETSIZE)]
  68                internal IntPtr[] fd_array;
  69
  70                public fd_set()
  71                {
  72                    fd_array = new IntPtr[FD_SETSIZE];
  73                }
  74            }
  75
  76            [StructLayout(LayoutKind.Sequential)]
  77            internal struct WSAData
  78            {
  79                internal short wVersion;
  80                internal short wHighVersion;
  81                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
  82                internal string szDescription;
  83                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
  84                internal string szSystemStatus;
  85                internal short iMaxSockets;
  86                internal short iMaxUdpDg;
  87                internal IntPtr lpVendorInfo;
  88            }
  89
  90            public const int FIONREAD = 0x4004667F;
  91            public const int FIONBIO = unchecked((int)0x8004667E);
  92            public const int FIOASYNC = unchecked((int)0x8004667D);
  93            public const int SIOGETEXTENSIONFUNCTIONPOINTER = unchecked((int)0xC8000006);
  94            public const int FD_ALL_EVENTS = (1 << 10) - 1;
  95
  96            private const string WS2_32 = "Ws2_32.dll";
  97
  98
  99            internal class SafeSocketHandle : SafeHandleMinusOneIsInvalid
 100            {
 101                public SafeSocketHandle(IntPtr Handle) : base(false)
 102                {
 103                    this.SetHandle(Handle);
 104                }
 105
 106                protected SafeSocketHandle() : base(true) { }
 107
 108                protected override bool ReleaseHandle()
 109                {
 110                    // handle released by managed socket
 111                    return true;
 112                }
 113            }
 114
 115            [DllImport(WS2_32)]
 116            public extern static int getaddrinfo(IntPtr nodename, IntPtr servname, IntPtr hints, out IntPtr res);
 117
 118            [DllImport(WS2_32)]
 119            public extern static void freeaddrinfo(IntPtr ai);
 120
 121            [DllImport(WS2_32)]
 122            public extern static int ioctlsocket(SafeSocketHandle s, int cmd, ref int argp);
 123
 124            [DllImport(WS2_32)]
 125            public extern static int connect(SafeSocketHandle s, IntPtr name, int namelen);
 126
 127            [DllImport(WS2_32)]
 128            public extern static void WSASetLastError(int iError);
 129
 130            [DllImport(WS2_32)]
 131            public extern static int WSAGetLastError();
 132
 133            [DllImport(WS2_32, CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)]
 134            internal static extern SocketError WSAStartup(
 135                                               [In] short wVersionRequested,
 136                                               [Out] out WSAData lpWSAData
 137                                               );
 138
 139            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 140            internal static extern SafeSocketHandle socket(int af, int type, int protocol);
 141
 142            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 143            internal static extern int bind(SafeSocketHandle s, IntPtr name, int namelen);
 144
 145            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 146            internal static extern int listen(SafeSocketHandle s, int backlog);
 147
 148            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 149            internal static extern int select(int nfds, [In, Out] fd_set readfds, [In, Out] fd_set writefds, [In, Out] fd_set exceptfds, ref TimeVal timeout);
 150
 151            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 152            internal static extern int send(SafeSocketHandle s, IntPtr buf, int len, int flags);
 153
 154            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 155            internal static extern int recv(SafeSocketHandle s, IntPtr buf, int len, int flags);
 156
 157            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 158            internal static extern NativeSockets.SafeSocketHandle accept(SafeSocketHandle s, IntPtr name, int namelen);
 159
 160            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 161            internal static extern int closesocket(IntPtr s);
 162
 163            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 164            internal static extern int shutdown(SafeSocketHandle s, int how);
 165
 166            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 167            internal static extern int getsockopt(SafeSocketHandle s, int level, int optname, IntPtr optval, ref int optlen);
 168
 169            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 170            internal static extern int setsockopt(SafeSocketHandle s, int level, int optname, IntPtr optval, int optlen);
 171
 172            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 173            internal static extern int getpeername(SafeSocketHandle s, IntPtr name, ref int namelen);
 174
 175            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 176            internal static extern int getsockname(SafeSocketHandle s, IntPtr name, ref int namelen);
 177
 178            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 179            internal static extern int sendto(SafeSocketHandle s, IntPtr buf, int len, int flags, IntPtr to, ref int tolen);
 180
 181            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 182            internal static extern int recvfrom(SafeSocketHandle s, IntPtr buf, int len, int flags, IntPtr from, ref int fromlen);
 183
 184            [DllImport(WS2_32, ExactSpelling = true, SetLastError = true)]
 185            internal static extern int WSAEventSelect(SafeSocketHandle S, SafeWaitHandle hEventObject, int lNetworkEvents);
 186        }
 187
 188        private class SocketData
 189        {
 190            internal Socket Socket;
 191            internal bool   IsSelectable = false;
 192            internal bool   IsSsl        = false;
 193            internal bool   IsClosing    = false;
 194
 195            public SocketData(Socket socket)
 196            {                
 197                Socket = socket;
 198            }
 199        }
 200
 201        bool _isInitialized = false;
 202        Dictionary<int, SocketData> _sockets = new Dictionary<int, SocketData>();
 203        int _handleNext;
 204        const int MaxSockets = 62; //for the call to WaitAny
 205        AutoResetEvent _eventSignalThread;
 206        AutoResetEvent _eventSsl = new AutoResetEvent(false);
 207        Thread _threadWaitForEvents;
 208        int _dwLastError = (int)SocketError.SocketError;
 209
 210        private bool GetSocketData(int socketIndex, out SocketData socketData)
 211        {
 212            socketData = null;
 213
 214            lock(_sockets)
 215            {
 216                if(!_sockets.ContainsKey(socketIndex)) return false;
 217
 218                socketData = _sockets[socketIndex];
 219            }
 220            return true;
 221        }
 222
 223        internal bool GetSocket(int socketIndex, out Socket socket)
 224        {
 225            SocketData sd;
 226
 227            socket = null;
 228            
 229            if(!GetSocketData(socketIndex, out sd)) return false;
 230
 231            socket = sd.Socket;
 232
 233            return true;
 234        }
 235
 236        internal void SetSslSocket(int socketIndex)
 237        {
 238            lock(_sockets)
 239            {
 240                if (_sockets.ContainsKey(socketIndex))
 241                {
 242                    _sockets[socketIndex].IsSsl = true;
 243                }
 244            }
 245        }
 246
 247        internal void SignalThread()
 248        {
 249            if (_isInitialized)
 250            {
 251                _evtSocketSend.SendTo(new byte[] { 0 }, _evtSocketRecv.LocalEndPoint);
 252            }
 253        }
 254
 255        Socket _evtSocketRecv;
 256        Socket _evtSocketSend;
 257
 258        internal void ClearSocketEvent(int socket, bool fRead)
 259        {
 260            SocketData sd;
 261            if (_isInitialized)
 262            {
 263                if (GetSocketData(socket, out sd))
 264                {
 265                    if (fRead)
 266                    {
 267                        lock (m_read)
 268                        {
 269                            if (m_read.Contains(sd.Socket))
 270                            {
 271                                m_read.Remove(sd.Socket);
 272                            }
 273                        }
 274                    }
 275                    else
 276                    {
 277                        lock (m_write)
 278                        {
 279                            if (m_write.Contains(sd.Socket))
 280                            {
 281                                m_write.Remove(sd.Socket);
 282                            }
 283                        }
 284                    }
 285                }
 286
 287                SignalThread();
 288            }
 289        }
 290
 291        bool _socketsShuttingDown = false;
 292
 293        List<Socket> m_read = new List<Socket>();
 294        List<Socket> m_write = new List<Socket>();
 295        List<Socket> m_excpt = new List<Socket>();
 296
 297        void WaitForNetworkEvents()
 298        {
 299            List<Socket> read = new List<Socket>();
 300            List<Socket> write = new List<Socket>();
 301            List<Socket> excpt = new List<Socket>();
 302
 303
 304            read.Add(_evtSocketRecv);
 305
 306            //check for emulator exit..
 307            while (!this.Emulator.IsShuttingDown && !_socketsShuttingDown)
 308            {
 309                Socket.Select(read, write, excpt, 0x7fffffff );
 310
 311                if (_socketsShuttingDown) return;
 312
 313                if (read.Contains(_evtSocketRecv))
 314                {
 315                    EndPoint ep = _evtSocketSend.LocalEndPoint;
 316                    byte[] data = new byte[256];
 317
 318                    _evtSocketRecv.ReceiveFrom(data, ref ep);
 319
 320                    read.Remove(_evtSocketRecv);
 321                }
 322
 323                lock (_sockets)
 324                {
 325                    lock (m_read)
 326                    {
 327                        for (int i = 0; i < read.Count; i++)
 328                        {
 329                            m_read.Add(read[i]);
 330                        }
 331                    }
 332                    lock (m_write)
 333                    {
 334                        for (int i = 0; i < write.Count; i++)
 335                        {
 336                            m_write.Add(write[i]);
 337                        }
 338                    }
 339                    lock (m_excpt)
 340                    {
 341                        for (int i = 0; i < excpt.Count; i++)
 342                        {
 343                            m_excpt.Add(excpt[i]);
 344                        }
 345                    }
 346
 347                    List<int> removeList = new List<int>();
 348
 349                    read.Clear();
 350                    write.Clear();
 351                    excpt.Clear();
 352
 353                    read.Add(_evtSocketRecv);
 354
 355                    foreach (int handle in _sockets.Keys)
 356                    {
 357                        SocketData socket = _sockets[handle];
 358
 359                        if (socket.IsClosing)
 360                        {
 361                            removeList.Add(handle);
 362
 363                            Socket sock = socket.Socket;
 364
 365                            lock (m_read)
 366                            {
 367                                if (m_read.Contains(sock))
 368                                {
 369                                    m_read.Remove(sock);
 370                                }
 371                            }
 372                            lock (m_write)
 373                            {
 374                                if (m_write.Contains(sock))
 375                                {
 376                                    m_write.Remove(sock);
 377                                }
 378                            }
 379                            lock (m_excpt)
 380                            {
 381                                if (m_excpt.Contains(sock))
 382                                {
 383                                    m_excpt.Remove(sock);
 384                                }
 385                            }
 386
 387                            continue;
 388                        }
 389
 390                        if (socket.IsSelectable)
 391                        {
 392                            try
 393                            {
 394                                Socket sock = socket.Socket;
 395
 396                                if (!m_read.Contains(sock))
 397                                {
 398                                    read.Add(sock);
 399                                }
 400
 401                                if (!m_write.Contains(sock))
 402                                {
 403                                    write.Add(sock);
 404                                }
 405
 406                                if (!m_excpt.Contains(sock))
 407                                {
 408                                    excpt.Add(sock);
 409                                }
 410                            }
 411                            catch
 412                            {
 413                            }
 414                        }
 415                    }
 416
 417                    foreach (int handle in removeList)
 418                    {
 419                        try
 420                        {
 421                            _sockets[handle].Socket.Close();
 422                        }
 423                        catch
 424                        {
 425                        }
 426                        _sockets.Remove(handle);
 427                    }
 428                }
 429
 430                this.Emulator.SetSystemEvents(Events.SystemEvents.SOCKET);
 431            }
 432        }
 433        
 434        [MethodImplAttribute(MethodImplOptions.Synchronized)]
 435        void EnsureInitialized()
 436        {
 437            if (!_isInitialized)
 438            {
 439                short wVersion = 0x0202;
 440                NativeSockets.WSAData wsaData = new NativeSockets.WSAData();
 441
 442                SocketError err = NativeSockets.WSAStartup(wVersion, out wsaData);
 443
 444                if (err != SocketError.Success)
 445                    throw new SocketException((int)err);
 446
 447                _eventSignalThread = new AutoResetEvent(false);
 448
 449                _evtSocketRecv = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
 450                _evtSocketRecv.Bind(new IPEndPoint(IPAddress.Loopback, 0));
 451
 452                _evtSocketSend = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
 453                _evtSocketSend.Bind(new IPEndPoint(IPAddress.Loopback, 0));
 454
 455                _threadWaitForEvents = new Thread(new ThreadStart(WaitForNetworkEvents));
 456                _threadWaitForEvents.Start();
 457
 458                _isInitialized = true;
 459            }
 460        }
 461
 462        int RegisterSocket(Socket socket)
 463        {
 464            return RegisterSocket(socket, false);
 465        }
 466
 467
 468        [MethodImplAttribute(MethodImplOptions.Synchronized)]
 469        int RegisterSocket( Socket socket, bool isSelectable)
 470        {
 471            if (_sockets.Count == MaxSockets)
 472            {
 473                return ReturnError(SocketError.TooManyOpenSockets);
 474            }
 475
 476            int handle;
 477
 478            lock(_sockets)
 479            {
 480                handle = ++_handleNext;
 481
 482                _sockets[handle] = new SocketData( socket );
 483
 484                _sockets[handle].IsSelectable = (isSelectable || socket.ProtocolType != ProtocolType.Tcp);
 485            }
 486            
 487            SignalThread();
 488
 489            return handle;
 490        }
 491
 492        [MethodImplAttribute(MethodImplOptions.Synchronized)]
 493        internal void UnregisterSocket(int handle)
 494        {
 495            lock(_sockets)
 496            {
 497                if(!_sockets.ContainsKey(handle)) return;
 498
 499                _sockets[handle].IsClosing = true;
 500                
 501                SignalThread();
 502            }
 503        }
 504
 505        internal int ReturnError(SocketError error)
 506        {
 507            _dwLastError = (int)error;
 508            return (int)SocketError.SocketError;
 509        }
 510
 511        void StoreLastError()
 512        {
 513            _dwLastError = NativeSockets.WSAGetLastError();
 514        }
 515
 516        TinyCLRSockets.fd_set IntPtrToTinyCLRFdSet(IntPtr fds)
 517        {
 518            TinyCLRSockets.fd_set fd_set = null;
 519
 520            if (fds != IntPtr.Zero)
 521            {
 522                fd_set = new TinyCLRSockets.fd_set();
 523
 524                Marshal.PtrToStructure(fds, fd_set);
 525            }
 526
 527            return fd_set;
 528        }
 529
 530        bool TinyCLRFdSetToFdSet(TinyCLRSockets.fd_set fd_setsrc, out List<Socket> fd_setDst)
 531        {
 532            bool fRes = true;
 533            fd_setDst = null;
 534
 535            if (fd_setsrc != null)
 536            {
 537                fd_setDst = new List<Socket>();
 538
 539                for (int i = 0; i < fd_setsrc.count; i++)
 540                {
 541                    SocketData sd;
 542
 543                    if(!GetSocketData(fd_setsrc.fd_array[i], out sd))
 544                    {
 545                        fRes = false;
 546                        break;
 547                    }
 548                    
 549                    if(sd.IsSelectable)
 550                    {
 551                        fd_setDst.Add(sd.Socket);
 552                    }
 553                }
 554            }
 555
 556            return fRes;
 557        }
 558
 559        bool FilterFd_set(List<Socket> fdNative, TinyCLRSockets.fd_set fdCLR)
 560        {
 561            if (fdNative != null)
 562            {
 563                Debug.Assert(fdCLR != null);
 564
 565                for (int i = 0; i < fdCLR.count; )
 566                {
 567                    bool fSet = false;
 568                    Socket sock = null;
 569
 570                    if(!GetSocket(fdCLR.fd_array[i], out sock)) return false;
 571
 572                    for (int j = 0; j < fdNative.Count; j++)
 573                    {
 574                        if (fdNative[j] == sock)
 575                        {
 576                            fSet = true;
 577                            break;
 578                        }
 579                    }
 580
 581                    if (!fSet)
 582                    {
 583                        Array.Copy(fdCLR.fd_array, i + 1, fdCLR.fd_array, i, fdCLR.count - i - 1);
 584                        fdCLR.count--;
 585                    }
 586                    else
 587                    {
 588                        i++;
 589                    }
 590                }
 591            }
 592
 593            return true;
 594        }
 595
 596        void TinyCLRFdSetToIntPtr(TinyCLRSockets.fd_set fd_set, IntPtr fds)
 597        {
 598            if (fds != IntPtr.Zero)
 599            {
 600                Marshal.StructureToPtr(fd_set, fds, true);
 601            }
 602        }
 603
 604        private uint IPAddressToUint(IPAddress address)
 605        {
 606            uint ret = 0;
 607
 608            if (address != null)
 609            {
 610                byte[] bytes = address.GetAddressBytes();
 611
 612                Debug.Assert(address.AddressFamily == AddressFamily.InterNetwork);
 613                Debug.Assert(bytes != null);
 614                Debug.Assert(bytes.Length == 4);
 615
 616                ret = BitConverter.ToUInt32(bytes, 0);
 617            }
 618
 619            return ret;
 620        }
 621
 622        private bool IsIPAddressIPv4(IPAddress address)
 623        {
 624            if (address.AddressFamily == AddressFamily.InterNetwork)
 625                return true;
 626
 627            return false;
 628        }
 629
 630        #region ISocketsDriver
 631        
 632        bool ISocketsDriver.Initialize()
 633        {
 634            EnsureInitialized();
 635            return true;
 636        }
 637
 638        bool ISocketsDriver.Uninitialize()
 639        {
 640            if (_isInitialized)
 641            {
 642                _socketsShuttingDown = true;
 643
 644                SignalThread();
 645
 646                lock (_sockets)
 647                {
 648                    foreach (SocketData sd in _sockets.Values)
 649                    {
 650                        try
 651                        {
 652                            sd.Socket.Close();
 653                        }
 654                        catch
 655                        {
 656                        }
 657                    }
 658                    _sockets.Clear();
 659                }
 660                try
 661                {
 662                    _evtSocketRecv.Close();
 663                    _evtSocketSend.Close();
 664                }
 665                catch
 666                {
 667                }
 668                _isInitialized = false;
 669            }
 670            return true;
 671        }
 672
 673        
 674
 675        int ISocketsDriver.socket(int family, int type, int protocol)
 676        {
 677            Socket socket = null;
 678
 679            try
 680            {
 681                socket = new Socket((AddressFamily)family, (SocketType)type, (ProtocolType)protocol);
 682
 683                // always make emulator sockets blocking so that the NetworkStream will work (for SSL)
 684                socket.Blocking = true;
 685            }
 686            catch( SocketException se )
 687            {
 688                return ReturnError(se.SocketErrorCode);
 689            }
 690            catch
 691            {
 692                return ReturnError(SocketError.SocketError);
 693            }
 694
 695            if (socket == null) return ReturnError(SocketError.SocketError);
 696
 697            return RegisterSocket(socket, ((ProtocolType)protocol != ProtocolType.Tcp));
 698        }
 699
 700        int ISocketsDriver.bind(int socket, IntPtr address, int addressLen)
 701        {
 702            SocketData sd = null;
 703            
 704            if (!GetSocketData(socket, out sd)) return ReturnError(SocketError.NotSocket);
 705
 706            try
 707            {
 708                SockAddr sa = new SockAddr();
 709
 710                sa.MarshalFromNative(address);
 711
 712                if (sa.sin_port == 80)
 713                {
 714                    sa.sin_port++;
 715                }
 716
 717                IPEndPoint ep = new IPEndPoint(sa.sin_addr, sa.sin_port);
 718
 719                sd.Socket.Bind(ep);
 720            }
 721            catch (SocketException se)
 722            {
 723                return ReturnError(se.SocketErrorCode);
 724            }
 725            catch
 726            {
 727                return ReturnError(SocketError.SocketError);
 728            }
 729
 730            return (int)SocketError.Success;
 731        }
 732
 733        int ISocketsDriver.connect(int socket, IntPtr address, int addressLen)
 734        {
 735            Socket sock = null;
 736            
 737            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
 738
 739            try
 740            {
 741                SockAddr sa = new SockAddr();
 742
 743                sa.MarshalFromNative(address);
 744
 745                sock.BeginConnect(new IPEndPoint(sa.sin_addr, sa.sin_port), new AsyncCallback(EndSockConnect), socket);
 746            }
 747            catch( SocketException se )
 748            {
 749                return ReturnError(se.SocketErrorCode);
 750            }
 751            catch
 752            {
 753                return ReturnError(SocketError.SocketError);
 754            }
 755
 756            return ReturnError(SocketError.WouldBlock);
 757        }
 758
 759        void EndSockConnect(IAsyncResult iar)
 760        {
 761            int socket = (int)iar.AsyncState;
 762
 763            SocketData sd = null;
 764            
 765            if (!GetSocketData(socket, out sd)) return;
 766
 767            try
 768            {
 769                sd.IsSelectable = true;
 770                sd.Socket.EndConnect(iar);
 771            }
 772            catch
 773            {
 774            }
 775
 776            SignalThread();
 777        }
 778
 779        int ISocketsDriver.send(int socket, IntPtr buf, int len, int flags)
 780        {
 781            SocketData sd = null;
 782            
 783            if (!GetSocketData(socket, out sd)) return ReturnError(SocketError.NotSocket);
 784
 785            try
 786            {
 787                if (sd.Socket.Poll(0, SelectMode.SelectWrite))
 788                {
 789                    byte[] data = new byte[len];
 790                    int sent = 0;
 791
 792                    Marshal.Copy(buf, data, 0, len);
 793
 794                    sent = sd.Socket.Send(data, 0, len, (SocketFlags)flags);
 795
 796                    ClearSocketEvent(socket, false);
 797
 798                    return sent;
 799                }
 800            }
 801            catch (SocketException se)
 802            {
 803                return ReturnError((SocketError)se.ErrorCode);
 804            }
 805
 806            return ReturnError(SocketError.WouldBlock);
 807        }
 808
 809        int ISocketsDriver.recv(int socket, IntPtr buf, int len, int flags)
 810        {
 811            int ret = ReturnError(SocketError.WouldBlock);
 812
 813            SocketData sd = null;
 814            
 815            if (!GetSocketData(socket, out sd)) return ReturnError(SocketError.NotSocket);
 816
 817            try
 818            {
 819                if (sd.Socket.Poll(0, SelectMode.SelectRead))
 820                {
 821                    byte[] data = new byte[len];
 822                    int read = 0;
 823                    read = sd.Socket.Receive(data, 0, len, (SocketFlags)flags);
 824
 825                    Marshal.Copy(data, 0, buf, read);
 826
 827                    return read;
 828                }
 829            }
 830            catch (SocketException se)
 831            {
 832                return ReturnError((SocketError)se.ErrorCode);
 833            }
 834            finally
 835            {
 836                ClearSocketEvent(socket, true);
 837            }
 838
 839            return ReturnError(SocketError.WouldBlock);
 840        }
 841
 842        int ISocketsDriver.close(int socket)
 843        {
 844            int ret = (int)SocketError.Success;
 845
 846            SocketData sd = null;
 847            
 848            if (!GetSocketData(socket, out sd)) return ReturnError(SocketError.NotSocket);
 849
 850            try
 851            {
 852                if (sd.IsSsl)
 853                {
 854                    Hal.Ssl.CloseSocket(socket);
 855                }
 856
 857                UnregisterSocket(socket);
 858            }
 859            catch (SocketException se)
 860            {
 861                ret = ReturnError(se.SocketErrorCode);
 862            }
 863            catch
 864            {
 865                ret = ReturnError(SocketError.SocketError);
 866            }
 867
 868            return ret;
 869        }
 870
 871        int ISocketsDriver.accept(int socket, IntPtr address, ref int addressLen)
 872        {
 873            Socket sock = null;
 874            
 875            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
 876
 877            try
 878            {
 879                IAsyncResult iar = sock.BeginAccept(null, null);
 880
 881                iar.AsyncWaitHandle.WaitOne();
 882
 883                Socket sockAccept = sock.EndAccept(iar);
 884
 885                int newSock = RegisterSocket(sockAccept, true);
 886
 887                ClearSocketEvent(socket, true);
 888
 889                return newSock;
 890            }
 891            catch (SocketException se)
 892            {
 893                return ReturnError(se.SocketErrorCode);
 894            }
 895            catch
 896            {
 897                return ReturnError(SocketError.SocketError);
 898            }
 899        }
 900
 901        int ISocketsDriver.listen(int socket, int backlog)
 902        {
 903            SocketData sd = null;
 904            
 905            if (!GetSocketData(socket, out sd)) return ReturnError(SocketError.NotSocket);
 906
 907            int ret = (int)SocketError.Success;
 908
 909            try
 910            {
 911                sd.Socket.Listen(backlog);
 912
 913                sd.IsSelectable = true;
 914
 915                SignalThread();
 916            }
 917            catch (SocketException se)
 918            {
 919                ret = ReturnError(se.SocketErrorCode);
 920            }
 921            catch
 922            {
 923                ret = ReturnError(SocketError.SocketError);
 924            }
 925
 926            return ret;
 927        }
 928
 929        int ISocketsDriver.shutdown(int socket, int how)
 930        {
 931            int ret = (int)SocketError.Success;
 932
 933            Socket sock = null;
 934            
 935            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
 936
 937            try
 938            {
 939                sock.Shutdown( (SocketShutdown)how );
 940
 941                SignalThread();
 942            }
 943            catch (SocketException se)
 944            {
 945                ret = ReturnError(se.SocketErrorCode);
 946            }
 947            catch
 948            {
 949                ret = ReturnError(SocketError.SocketError);
 950            }
 951
 952            return ret;
 953        }
 954        
 955        int ISocketsDriver.getaddrinfo(IntPtr nodename, IntPtr servname, IntPtr hints, out IntPtr res)
 956        {
 957            res = IntPtr.Zero;
 958
 959            int ret = NativeSockets.getaddrinfo(nodename, servname, hints, out res);
 960
 961            StoreLastError();
 962
 963            return ret;
 964        }
 965
 966        void ISocketsDriver.freeaddrinfo(IntPtr ai)
 967        {
 968            NativeSockets.freeaddrinfo(ai);
 969        }
 970
 971        int ISocketsDriver.ioctl(int socket, int cmd, ref int data)
 972        {
 973            Socket sock = null;
 974            
 975            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
 976
 977            int ret = (int)SocketError.Success;
 978
 979            try
 980            {
 981                if (cmd == NativeSockets.FIONBIO)
 982                {
 983                }
 984                else if (cmd == NativeSockets.FIONREAD)
 985                {
 986                    data = sock.Available;
 987                }
 988                else
 989                {
 990                    ret = (int)SocketError.SocketError;
 991                }
 992            }
 993            catch (SocketException se)
 994            {
 995                ret = ReturnError(se.SocketErrorCode);
 996            }
 997            catch
 998            {
 999                ret = ReturnError(SocketError.SocketError);
1000            }
1001
1002            return ret;
1003        }
1004
1005        int ISocketsDriver.getlasterror()
1006        {
1007            return _dwLastError;
1008        }
1009
1010        private void InternalSelect(List<Socket> read, List<Socket> write, List<Socket> excpt)
1011        {
1012            if (read != null)
1013            {
1014                for (int i = read.Count - 1; i >= 0; i--)
1015                {
1016                    if (!m_read.Contains(read[i]))
1017                    {
1018                        read.RemoveAt(i);
1019                    }
1020                }
1021            }
1022            if (write != null)
1023            {
1024                for (int i = write.Count - 1; i >= 0; i--)
1025                {
1026                    if (!m_write.Contains(write[i]))
1027                    {
1028                        write.RemoveAt(i);
1029                    }
1030                }
1031            }
1032            if (excpt != null)
1033            {
1034                for (int i = excpt.Count - 1; i >= 0; i--)
1035                {
1036                    if (!m_excpt.Contains(excpt[i]))
1037                    {
1038                        excpt.RemoveAt(i);
1039                    }
1040                }
1041            }
1042        }
1043
1044
1045        [MethodImplAttribute(MethodImplOptions.Synchronized)]
1046        int ISocketsDriver.select(int nfds, IntPtr readfds, IntPtr writefds, IntPtr exceptfds, ref TimeVal timeout)
1047        {
1048            List<Socket> readList;
1049            List<Socket> writeList;
1050            List<Socket> exceptList;
1051
1052            int ret = 0;
1053
1054            TinyCLRSockets.fd_set read = IntPtrToTinyCLRFdSet(readfds);
1055            TinyCLRSockets.fd_set write = IntPtrToTinyCLRFdSet(writefds);
1056            TinyCLRSockets.fd_set except = IntPtrToTinyCLRFdSet(exceptfds);
1057
1058            if (!TinyCLRFdSetToFdSet(read, out readList)) return ReturnError(SocketError.NotSocket);
1059            if (!TinyCLRFdSetToFdSet(write, out writeList)) return ReturnError(SocketError.NotSocket);
1060            if (!TinyCLRFdSetToFdSet(except, out exceptList)) return ReturnError(SocketError.NotSocket);
1061
1062            if ((readList   != null && readList.Count   > 0) ||
1063                (writeList  != null && writeList.Count  > 0) ||
1064                (exceptList != null && exceptList.Count > 0))
1065            {
1066                try
1067                {
1068                    //Socket.Select(readList, writeList, exceptList, timeout.tv_usec);
1069                    InternalSelect(readList, writeList, exceptList);
1070                }
1071                catch (SocketException se)
1072                {
1073                    ret = ReturnError(se.SocketErrorCode);
1074                }
1075            }
1076
1077            if (!FilterFd_set(readList, read)) return ReturnError(SocketError.NotSocket);
1078            if (!FilterFd_set(writeList, write)) return ReturnError(SocketError.NotSocket);
1079            if (!FilterFd_set(exceptList, except)) return ReturnError(SocketError.NotSocket);
1080
1081            TinyCLRFdSetToIntPtr(read, readfds);
1082            TinyCLRFdSetToIntPtr(write, writefds);
1083            TinyCLRFdSetToIntPtr(except, exceptfds);
1084
1085            if(ret != (int)SocketError.SocketError)
1086            {
1087                if (readList   != null) ret += readList.Count;
1088                if (writeList  != null) ret += writeList.Count;
1089                if (exceptList != null) ret += exceptList.Count;
1090            }
1091
1092            return ret;
1093        }
1094
1095        int ISocketsDriver.setsockopt(int socket, int level, int optname, IntPtr optval, int optlen)
1096        {
1097            Socket sock = null;
1098            
1099            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
1100
1101            int ret = (int)SocketError.Success;
1102
1103            try
1104            {
1105                byte []data = new byte[optlen];
1106
1107                if (level == (int)SocketOptionLevel.Socket && optname == (int)SocketOptionName.Linger && optlen == 4)
1108                {
1109                    int linger = Marshal.ReadInt32(optval);
1110
1111                    LingerOption li = new LingerOption(linger != -1, linger < 0 ? 10 : linger);
1112
1113                    Array.Copy(BitConverter.GetBytes((UInt16)(li.Enabled ? 1 : 0)), 0, data, 0, 2);
1114                    Array.Copy(BitConverter.GetBytes((UInt16)li.LingerTime       ), 0, data, 2, 2);
1115                }
1116                else
1117                {
1118                    Marshal.Copy(optval, data, 0, optlen);
1119                }
1120
1121                sock.SetSocketOption((SocketOptionLevel)level, (SocketOptionName)optname, data);
1122            }
1123            catch (SocketException se)
1124            {
1125                ret = ReturnError(se.SocketErrorCode);
1126            }
1127
1128            return ret;
1129        }
1130
1131        int ISocketsDriver.getsockopt(int socket, int level, int optname, IntPtr optval, ref int optlen)
1132        {
1133            Socket sock = null;
1134            
1135            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
1136
1137            int ret = (int)SocketError.Success;
1138
1139            try
1140            {
1141                byte[] data = new byte[optlen];
1142
1143                sock.GetSocketOption((SocketOptionLevel)level, (SocketOptionName)optname, data);
1144                
1145                if (level == (int)SocketOptionLevel.Socket && optname == (int)SocketOptionName.Linger && optlen == 4)
1146                {
1147                    // if linger option is off, then we translate to -1 for the MF option
1148                    if(data[0] == 0 && data[1] == 0)
1149                    {
1150                        Marshal.WriteInt32(optval, -1);
1151                    }
1152                    else
1153                    {
1154                        // convert back to a single integer value
1155                        Marshal.WriteInt32(optval, (int)BitConverter.ToInt16(data, 2));
1156                    }
1157                }
1158                else
1159                {
1160                    Marshal.Copy(data, 0, optval, optlen);
1161                }
1162            }
1163            catch (SocketException se)
1164            {
1165                ret = ReturnError(se.SocketErrorCode);
1166            }
1167
1168            return ret;
1169        }
1170
1171        int ISocketsDriver.getpeername(int socket, IntPtr name, ref int namelen)
1172        {
1173            Socket sock = null;
1174            
1175            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
1176
1177            int ret = (int)SocketError.Success;
1178
1179            try
1180            {
1181                IPEndPoint ep = sock.RemoteEndPoint as IPEndPoint;
1182                SockAddr addr = new SockAddr();
1183
1184                addr.sin_addr = IPAddressToUint(ep.Address);
1185                addr.sin_family = (short)ep.AddressFamily;
1186                addr.sin_port   = (ushort)ep.Port;
1187
1188                addr.MarshalToNative(name);
1189            }
1190            catch (SocketException se)
1191            {
1192                ret = ReturnError(se.SocketErrorCode);
1193            }
1194
1195            return ret;
1196        }
1197
1198        int ISocketsDriver.getsockname(int socket, IntPtr name, ref int namelen)
1199        {
1200            Socket sock = null;
1201            
1202            if (!GetSocket(socket, out sock)) return ReturnError(SocketError.NotSocket);
1203
1204            int ret = (int)SocketError.Success;
1205
1206            try
1207            {
1208                IPEndPoint ep = sock.LocalEndPoint as IPEndPoint;
1209                SockAddr addr = new SockAddr();
1210
1211                if (IPAddress.IsLoopback(ep.Address))
1212                {
1213                    addr.sin_addr = IPAddressToUint(ep.Address);
1214                }
1215                else
1216                {
1217                    IPHostEntry ipEntry = Dns.GetHostEntry(ep.Address);
1218
1219                    for (int i = 0; i < ipEntry.AddressList.Length; i++)
1220                    {
1221                        if (ipEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
1222                        {
1223                            addr.sin_addr = IPAddressToUint(ipEntry.AddressList[i]);
1224                        }
1225                    }
1226                }
1227                
1228                addr.sin_family = (short)ep.AddressFamily;
1229                addr.sin_port = (ushort)ep.Port;
1230
1231                addr.MarshalToNative(name);
1232            }
1233            catch (SocketException se)
1234            {
1235                ret = ReturnError(se.SocketErrorCode);
1236            }
1237
1238            return ret;
1239        }
1240
1241        int ISocketsDriver.sendto(int socket, IntPtr buf, int len, int flags, IntPtr to, ref int tolen)
1242        {
1243            SocketData sd = null;
1244            
1245            if (!GetSocketData(socket, out sd)) return ReturnError(SocketError.NotSocket);
1246
1247            try
1248            {
1249                if (sd.Socket.Poll(0, SelectMode.SelectWrite))
1250                {
1251                    byte[] data = new byte[len];
1252                    int sent = 0;
1253
1254                    Marshal.Copy(buf, data, 0, len);
1255
1256                    SockAddr toAddr = new SockAddr();
1257
1258                    toAddr.MarshalFromNative(to);
1259
1260                    IPEndPoint toEP = new IPEndPoint(toAddr.sin_addr, toAddr.sin_port);
1261
1262                    sent = sd.Socket.SendTo(data, 0, len, (SocketFlags)flags, toEP);
1263
1264                    ClearSocketEvent(socket, false);
1265
1266                    return sent;
1267                }
1268            }
1269            catch (SocketException se)
1270            {
1271                return ReturnError((SocketError)se.ErrorCode);
1272            }
1273
1274            return ReturnError(SocketError.WouldBlock);
1275        }
1276
1277        int ISocketsDriver.recvfrom(int socket, IntPtr buf, int len, int flags, IntPtr from, ref int fromlen)
1278        {
1279            SocketData sd = null;
1280            
1281            if (!GetSocketData(socket, out sd)) return ReturnError(SocketError.NotSocket);
1282
1283            try
1284            {
1285                if (sd.Socket.Poll(0, SelectMode.SelectRead))
1286                {
1287                    byte[] data = new byte[len];
1288                    int read = 0;
1289
1290                    SockAddr fromAddr = new SockAddr();
1291
1292                    fromAddr.MarshalFromNative(from);
1293
1294                    EndPoint fromEP = new IPEndPoint(fromAddr.sin_addr, fromAddr.sin_port);
1295
1296
1297                    read = sd.Socket.ReceiveFrom(data, 0, len, (SocketFlags)flags, ref fromEP);
1298
1299                    Marshal.Copy(data, 0, buf, read);
1300
1301                    fromAddr.sin_addr = IPAddressToUint(((IPEndPoint)fromEP).Address);
1302
1303                    fromAddr.sin_port = (ushort)((IPEndPoint)fromEP).Port;
1304
1305                    fromAddr.sin_family = (short)((IPEndPoint)fromEP).AddressFamily;
1306
1307                    fromAddr.MarshalToNative(from);
1308
1309                    return read;
1310                }
1311            }
1312            catch (SocketException se)
1313            {
1314                return ReturnError((SocketError)se.ErrorCode);
1315
1316            }
1317            finally
1318            {
1319                ClearSocketEvent(socket, true);
1320            }
1321
1322            return ReturnError(SocketError.WouldBlock);
1323        }
1324
1325        uint ISocketsDriver.NetworkAdapterCount 
1326        {
1327            get
1328            {
1329                return (uint)NetworkInterface.GetAllNetworkInterfaces().Length;
1330            }
1331        }
1332
1333        int ISocketsDriver.LoadAdapterConfiguration(uint interfaceIndex, ref NetworkAdapterConfiguration config)
1334        {
1335            NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces()[interfaceIndex];
1336            IPInterfaceProperties props = networkInterface.GetIPProperties();
1337            IPv4InterfaceProperties ipv4props = null;
1338
1339            try
1340            {
1341                ipv4props = props.GetIPv4Properties();
1342            }
1343            catch(NetworkInformationException)
1344            {
1345            }
1346
1347            
1348            if (ipv4props != null)
1349            {
1350                if (props.IsDynamicDnsEnabled)
1351                {
1352                    config.flags |= NetworkAdapterConfiguration.FLAGS_DYNAMIC_DNS;
1353                }
1354
1355                if (ipv4props.IsDhcpEnabled)
1356                {
1357                    config.flags |= NetworkAdapterConfiguration.FLAGS_DHCP;
1358                }
1359
1360                for (int iAddress = 0; iAddress < props.UnicastAddresses.Count; iAddress++)
1361                {
1362                    UnicastIPAddressInformation unicastAddress = props.UnicastAddresses[iAddress];
1363
1364                    if (IsIPAddressIPv4(unicastAddress.Address))
1365                    {
1366                        config.ipaddr = this.IPAddressToUint(unicastAddress.Address);
1367                        config.subnetmask = this.IPAddressToUint(unicastAddress.IPv4Mask);
1368
1369                        break;
1370                    }
1371                }
1372
1373                for (int iAddress = 0; iAddress < props.GatewayAddresses.Count; iAddress++)
1374                {
1375                    GatewayIPAddressInformation gatewayAddress = props.GatewayAddresses[iAddress];
1376
1377                    if (IsIPAddressIPv4(gatewayAddress.Address))
1378                    {
1379                        config.gateway = this.IPAddressToUint(gatewayAddress.Address);
1380
1381                        break;
1382                    }
1383                }
1384
1385                int dnsServerIndex = 0;
1386                for (int iAddress = 0; iAddress < props.DnsAddresses.Count && dnsServerIndex < 2; iAddress++)
1387                {
1388                    IPAddress address = props.DnsAddresses[iAddress];
1389
1390                    if (IsIPAddressIPv4(address))
1391                    {
1392                        switch(dnsServerIndex)
1393                        {
1394                            case 0:
1395                                config.dnsServer1 = this.IPAddressToUint(address);
1396                                break;
1397                            case 1:
1398                                config.dnsServer2 = this.IPAddressToUint(address);
1399                                break;
1400                        }
1401
1402                        dnsServerIndex++;
1403                    }
1404                }
1405
1406                PhysicalAddress macAddress = networkInterface.GetPhysicalAddress();
1407                byte[] macBytes = macAddress.GetAddressBytes();
1408                
1409                config.networkInterfaceType = (uint)networkInterface.NetworkInterfaceType;                
1410                config.networkAddressLen = (uint)macBytes.Length;
1411
1412                unsafe
1413                {
1414                    fixed (byte* p = config.networkAddressBuf)
1415                    {
1416                        Marshal.Copy(macBytes, 0, new IntPtr(p), macBytes.Length);
1417                    }
1418                }
1419            }
1420        
1421            return 0;
1422        }
1423
1424        int ISocketsDriver.UpdateAdapterConfiguration(uint interfaceIndex, uint updateFlags, ref NetworkAdapterConfiguration config)
1425        {
1426            //CLR_E_FAIL.  Update with better error?
1427            unchecked { return (int)(uint)CLR_ERRORCODE.CLR_E_FAIL; }
1428        }
1429
1430        #endregion
1431    }
1432
1433    internal class ComPortSocket : ComPortToAsyncStream
1434    {
1435        Socket _socket;
1436
1437        public ComPortSocket(Socket socket)
1438            : base(new NetworkStream(socket))
1439        {
1440            _socket = socket;         
1441        }
1442
1443        public override int AvailableBytes
1444        {
1445            get
1446            {
1447                return _socket.Available;
1448            }
1449        }
1450    }
1451
1452    internal class TcpListenerForDebugAPI : EmulatorComponent
1453    {
1454        //defined in unmanaged code somewhere??
1455        //also in debugger.dll somewhere??
1456        //Should Emulator depend on Debugger.dll?  Can then use PortDefinition_Tcp.DefaultPort
1457        //and use Streams, instead of copy/pasted code?
1458        const int DEBUG_PORT = 26000;
1459
1460        TcpListener _tcpListener;
1461        TcpClient _tcpClient;
1462        int _port = DEBUG_PORT;
1463        ComPortHandle _comPortHandle = ComPortHandle.DebugPort;
1464
1465        public override void SetupComponent()
1466        {
1467            //Is this right???
1468            base.SetupComponent();
1469
1470            _tcpListener = new TcpListener(IPAddress.Any, _port);
1471
1472            this.Emulator.ComPortCollection.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(OnComPortCollectionChanged);
1473
1474            StartListener();
1475        }
1476
1477        private void OnComPortCollectionChanged(object sender, CollectionChangeEventArgs args)
1478        {
1479            if (args.Action == CollectionChangeAction.Remove)
1480            {
1481                ComPort comPort = (ComPort)args.Element;
1482                ComPortHandle handle = comPort.ComPortHandle;
1483
1484                if (handle == _comPortHandle)
1485                {
1486                    StartListener();
1487                }
1488            }
1489        }
1490
1491        [MethodImplAttribute(MethodImplOptions.Synchronized)]
1492        void StartListener()
1493        {
1494            try
1495            {
1496                //should this support both debug ports? Or just one per port?
1497                _tcpListener.Start(1);
1498
1499                _tcpListener.BeginAcceptSocket(new AsyncCallback(AcceptSocket), null);
1500            }
1501            catch
1502            {
1503            }
1504        }
1505
1506        [MethodImplAttribute(MethodImplOptions.Synchronized)]
1507        public override void UninitializeComponent()
1508        {
1509            base.UninitializeComponent();
1510
1511            try
1512            {
1513                _tcpListener.Stop();
1514
1515                if (_tcpClient != null)
1516                {
1517                    _tcpClient.Close();
1518                    _tcpClient = null;
1519                }
1520            }
1521            catch
1522            {
1523            }
1524        }
1525
1526        [MethodImplAttribute(MethodImplOptions.Synchronized)]
1527        private void AcceptSocket(IAsyncResult ar)
1528        {
1529            try
1530            {
1531                // End the operation and display the received data on 
1532                // the console.
1533                Socket client = _tcpListener.EndAcceptSocket(ar);
1534
1535                client.NoDelay = true;
1536
1537                ComPortSocket comPortSocket = new ComPortSocket(client/*, this*/);
1538
1539                comPortSocket.ComPortHandle = _comPortHandle;
1540
1541                //This doesn't seem right.  ComPort should have an Initialize that starts read? 
1542                //who cares if the Device calls initialize??????
1543
1544                comPortSocket.DeviceInitialize();
1545
1546                this.Emulator.RegisterComponent(comPortSocket);
1547
1548                _tcpListener.Stop();
1549            }
1550            catch
1551            {
1552            }
1553        }
1554    }    
1555}