PageRenderTime 54ms CodeModel.GetById 2ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Languages/Ruby/Libraries.LCA_RESTRICTED/socket/Socket.cs

#
C# | 739 lines | 595 code | 105 blank | 39 comment | 29 complexity | 75ab0179dd3a908766da76613fecf82a MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
  8 * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16#if !SILVERLIGHT
 17
 18using System;
 19using System.Net;
 20using System.Net.Sockets;
 21using System.Reflection;
 22using System.Runtime.InteropServices;
 23using Microsoft.Scripting;
 24using Microsoft.Scripting.Runtime;
 25using IronRuby.Builtins;
 26using IronRuby.Compiler;
 27using IronRuby.Runtime;
 28using System.IO;
 29using Microsoft.Scripting.Math;
 30
 31namespace IronRuby.StandardLibrary.Sockets {
 32    [RubyClass("Socket", BuildConfig = "!SILVERLIGHT")]
 33    [Includes(typeof(SocketConstants), Copy = true)]
 34    public class RubySocket : RubyBasicSocket {
 35
 36        #region Construction
 37
 38        public RubySocket(RubyContext/*!*/ context, Socket/*!*/ socket)
 39            : base(context, socket) {
 40        }
 41
 42        [RubyConstructor]
 43        public static RubySocket/*!*/ CreateSocket(ConversionStorage<MutableString>/*!*/ stringCast, ConversionStorage<int>/*!*/ fixnumCast, 
 44            RubyClass/*!*/ self, [NotNull]object/*!*/ domain, [DefaultProtocol]int/*!*/ type, [DefaultProtocol]int protocol) {
 45
 46            AddressFamily addressFamily = ConvertToAddressFamily(stringCast, fixnumCast, domain);
 47            return new RubySocket(self.Context, new Socket(addressFamily, (SocketType)type, (ProtocolType)protocol));
 48        }
 49
 50        #endregion
 51
 52        #region Public Singleton Methods
 53
 54        [RubyMethod("getaddrinfo", RubyMethodAttributes.PublicSingleton)]
 55        public static RubyArray GetAddressInfo(
 56            ConversionStorage<MutableString>/*!*/ stringCast, ConversionStorage<int>/*!*/ fixnumCast, 
 57            RubyClass/*!*/ self, object hostNameOrAddress, object port,
 58            [DefaultParameterValue(null)]object family,
 59            [DefaultParameterValue(0)]object socktype,
 60            [DefaultParameterValue(0)]object protocol,
 61            [DefaultParameterValue(null)]object flags) {
 62
 63            RubyContext context = self.Context;
 64
 65            IPHostEntry entry = (hostNameOrAddress != null) ?
 66                GetHostEntry(ConvertToHostString(stringCast, hostNameOrAddress), DoNotReverseLookup(context).Value) : 
 67                MakeEntry(IPAddress.Any, DoNotReverseLookup(context).Value);
 68
 69            int iPort = ConvertToPortNum(stringCast, fixnumCast, port);
 70
 71            // TODO: ignore family, the only supported families are InterNetwork and InterNetworkV6
 72            ConvertToAddressFamily(stringCast, fixnumCast, family);
 73            int socketType = Protocols.CastToFixnum(fixnumCast, socktype);
 74            int protocolType = Protocols.CastToFixnum(fixnumCast, protocol);
 75
 76            RubyArray results = new RubyArray(entry.AddressList.Length);
 77            for (int i = 0; i < entry.AddressList.Length; ++i) {
 78                IPAddress address = entry.AddressList[i];
 79
 80                RubyArray result = new RubyArray(9);
 81                result.Add(ToAddressFamilyString(address.AddressFamily));
 82                result.Add(iPort);
 83                result.Add(HostNameToMutableString(context, IPAddressToHostName(address, DoNotReverseLookup(context).Value)));
 84                result.Add(MutableString.CreateAscii(address.ToString()));
 85                result.Add((int)address.AddressFamily);
 86                result.Add(socketType);
 87
 88                // TODO: protocol type:
 89                result.Add(protocolType);
 90
 91                results.Add(result);
 92            }
 93            return results;
 94        }
 95
 96        [RubyMethod("gethostbyaddr", RubyMethodAttributes.PublicSingleton)]
 97        public static RubyArray GetHostByAddress(ConversionStorage<MutableString>/*!*/ stringCast, ConversionStorage<int>/*!*/ fixnumCast, 
 98            RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ address, [DefaultParameterValue(null)]object type) {
 99
100            // TODO: ignore family, the only supported families are InterNetwork and InterNetworkV6
101            ConvertToAddressFamily(stringCast, fixnumCast, type);
102            IPHostEntry entry = GetHostEntry(new IPAddress(address.ConvertToBytes()), DoNotReverseLookup(self.Context).Value);
103
104            return CreateHostEntryArray(self.Context, entry, true);
105        }
106
107        [RubyMethod("gethostbyname", RubyMethodAttributes.PublicSingleton)]
108        public static RubyArray/*!*/ GetHostByName(RubyClass/*!*/ self, int address) {
109            return GetHostByName(self.Context, ConvertToHostString(address), true);
110        }
111
112        [RubyMethod("gethostbyname", RubyMethodAttributes.PublicSingleton)]
113        public static RubyArray/*!*/ GetHostByName(RubyClass/*!*/ self, [NotNull]BigInteger/*!*/ address) {
114            return GetHostByName(self.Context, ConvertToHostString(address), true);
115        }
116
117        [RubyMethod("gethostbyname", RubyMethodAttributes.PublicSingleton)]
118        public static RubyArray/*!*/ GetHostByName(RubyClass/*!*/ self, [DefaultProtocol]MutableString name) {
119            return GetHostByName(self.Context, ConvertToHostString(name), true);
120        }
121
122        [RubyMethod("gethostname", RubyMethodAttributes.PublicSingleton)]
123        public static MutableString GetHostname(RubyClass/*!*/ self) {
124            return HostNameToMutableString(self.Context, Dns.GetHostName());
125        }
126
127        private static readonly MutableString/*!*/ _DefaultProtocol = MutableString.CreateAscii("tcp").Freeze();
128
129        [RubyMethod("getservbyname", RubyMethodAttributes.PublicSingleton)]
130        public static int GetServiceByName(RubyClass/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ name, 
131            [DefaultProtocol, Optional]MutableString protocol) {
132            
133            if (protocol == null) {
134                protocol = _DefaultProtocol;
135            }
136
137            ServiceName service = SearchForService(name, protocol);
138            if (service != null) {
139                return service.Port;
140            } 
141
142            // Cannot use: object port = Protocols.TryConvertToInteger(context, name);
143            // Since the conversion process returns 0 if the string is not a valid number
144            try {
145                return ParseInteger(self.Context, name.ConvertToString());
146            } catch (InvalidOperationException) {
147                throw SocketErrorOps.Create(MutableString.FormatMessage("no such service {0} {1}", name, protocol));
148            }
149        }
150
151        /// <summary>
152        /// Returns a pair of connected sockets
153        /// [Not Implemented]
154        /// </summary>
155        [RubyMethod("socketpair", RubyMethodAttributes.PublicSingleton)]
156        [RubyMethod("pair", RubyMethodAttributes.PublicSingleton)]
157        public static RubyArray/*!*/ CreateSocketPair(RubyClass/*!*/ self, object domain, object type, object protocol) {
158            throw new NotImplementedError();
159        }
160
161        [RubyMethod("getnameinfo", RubyMethodAttributes.PublicSingleton)]
162        public static RubyArray/*!*/ GetNameInfo(ConversionStorage<MutableString>/*!*/ stringCast, ConversionStorage<int>/*!*/ fixnumCast, 
163            RubyClass/*!*/ self, [NotNull]RubyArray/*!*/ hostInfo, [Optional]object flags) {
164            if (hostInfo.Count < 3 || hostInfo.Count > 4) {
165                throw RubyExceptions.CreateArgumentError("First parameter must be a 3 or 4 element array");
166            }
167
168            RubyContext context = self.Context;
169
170            // We only support AF_INET (IP V4) family
171            AddressFamily addressFamily = ConvertToAddressFamily(stringCast, fixnumCast, hostInfo[0]);
172            if (addressFamily != AddressFamily.InterNetwork) {
173                throw new SocketException((int)SocketError.AddressFamilyNotSupported);
174            }
175
176            // Lookup the service name for the given port.
177            int port = ConvertToPortNum(stringCast, fixnumCast, hostInfo[1]);
178            ServiceName service = SearchForService(port);
179
180            // hostInfo[2] should have a host name
181            // if it exists and is not null hostInfo[3] should have an IP address
182            // in that case we use that rather than the host name.
183            object hostName =  (hostInfo.Count > 3 && hostInfo[3] != null) ? hostInfo[3] : hostInfo[2];
184            IPHostEntry entry = GetHostEntry(ConvertToHostString(stringCast, hostName), false);
185
186            RubyArray result = new RubyArray(2);
187            result.Add(HostNameToMutableString(context, entry.HostName));
188            if (service != null) {
189                result.Add(MutableString.Create(service.Name));
190            } else {
191                result.Add(port);
192            }
193            return result;
194        }
195
196        [RubyMethod("getnameinfo", RubyMethodAttributes.PublicSingleton)]
197        public static RubyArray/*!*/ GetNameInfo(RubyClass/*!*/ self, 
198            [DefaultProtocol, NotNull]MutableString/*!*/ address, [Optional]object flags) {
199
200            IPEndPoint ep = UnpackSockAddr(address);
201            IPHostEntry entry = GetHostEntry(ep.Address, false);
202            ServiceName service = SearchForService(ep.Port);
203
204            RubyArray result = new RubyArray(2);
205            result.Add(HostNameToMutableString(self.Context, entry.HostName));
206            if (service != null) {
207                result.Add(MutableString.Create(service.Name));
208            } else {
209                result.Add(ep.Port);
210            }
211            return result;
212        }
213
214        /// <summary>
215        /// Returns the system dependent sockaddr structure packed into a string
216        /// </summary>
217        [RubyMethod("sockaddr_in", RubyMethodAttributes.PublicSingleton)]
218        [RubyMethod("pack_sockaddr_in", RubyMethodAttributes.PublicSingleton)]
219        public static MutableString/*!*/ PackInetSockAddr(ConversionStorage<MutableString>/*!*/ stringCast, ConversionStorage<int>/*!*/ fixnumCast, 
220            RubyClass/*!*/ self, object port, object hostNameOrAddress) {
221            int iPort = ConvertToPortNum(stringCast, fixnumCast,port);
222
223            IPAddress address = (hostNameOrAddress != null) ?
224                GetHostAddress(ConvertToHostString(stringCast, hostNameOrAddress)) : IPAddress.Loopback;
225
226            SocketAddress socketAddress = new IPEndPoint(address, iPort).Serialize();
227            var result = MutableString.CreateBinary(socketAddress.Size);
228            for (int i = 0; i < socketAddress.Size; i++) {
229                result.Append(socketAddress[i]);
230            }
231            return result;
232        }
233
234        /// <summary>
235        /// Returns the system dependent sockaddr structure packed into a string
236        /// </summary>
237        [RubyMethod("unpack_sockaddr_in", RubyMethodAttributes.PublicSingleton)]
238        public static RubyArray/*!*/ UnPackInetSockAddr(RubyClass/*!*/ self, 
239            [DefaultProtocol, NotNull]MutableString/*!*/ address) {
240
241            IPEndPoint ep = UnpackSockAddr(address);
242            RubyArray result = new RubyArray(2);
243            result.Add(ep.Port);
244            result.Add(MutableString.CreateAscii(ep.Address.ToString()));
245            return result;
246        }
247
248        internal static IPEndPoint/*!*/ UnpackSockAddr(MutableString/*!*/ stringAddress) {
249            byte[] bytes = stringAddress.ConvertToBytes();
250            SocketAddress addr = new SocketAddress(AddressFamily.InterNetwork, bytes.Length);
251            for (int i = 0; i < bytes.Length; ++i) {
252                addr[i] = bytes[i];
253            }
254            IPEndPoint ep = new IPEndPoint(0, 0);
255            return (IPEndPoint)ep.Create(addr);
256        }
257
258        #endregion
259
260        #region Public Instance Methods
261
262        [RubyMethod("accept")]
263        public static RubyArray/*!*/ Accept(RubyContext/*!*/ context, RubySocket/*!*/ self) {
264            RubyArray result = new RubyArray(2);
265            RubySocket s = new RubySocket(context, self.Socket.Accept());
266            result.Add(s);
267            SocketAddress addr = s.Socket.RemoteEndPoint.Serialize();
268            result.Add(MutableString.CreateAscii(addr.ToString()));
269            return result;
270        }
271
272        [RubyMethod("accept_nonblock")]
273        public static RubyArray/*!*/ AcceptNonBlocking(RubyContext/*!*/ context, RubySocket/*!*/ self) {
274            bool blocking = self.Socket.Blocking;
275            try {
276                self.Socket.Blocking = false;
277                return Accept(context, self);
278            } finally {
279                // Reset the blocking
280                self.Socket.Blocking = blocking;
281            }
282        }
283
284        [RubyMethod("bind")]
285        public static int Bind(RubyContext/*!*/ context, RubySocket/*!*/ self, MutableString sockaddr) {
286            IPEndPoint ep = UnpackSockAddr(sockaddr);
287            self.Socket.Bind(ep);
288            return 0;
289        }
290
291        [RubyMethod("connect")]
292        public static int Connect(RubyContext/*!*/ context, RubySocket/*!*/ self, MutableString sockaddr) {
293            IPEndPoint ep = UnpackSockAddr(sockaddr);
294            self.Socket.Connect(ep);
295            return 0;
296        }
297
298        [RubyMethod("connect_nonblock")]
299        public static int ConnectNonBlocking(RubyContext/*!*/ context, RubySocket/*!*/ self, MutableString sockaddr) {
300            bool blocking = self.Socket.Blocking;
301            try {
302                self.Socket.Blocking = false;
303                return Connect(context, self, sockaddr);
304            } finally {
305                // Reset the blocking
306                self.Socket.Blocking = blocking;
307            }
308        }
309
310        [RubyMethod("listen")]
311        public static int Listen(RubyContext/*!*/ context, RubySocket/*!*/ self, int backlog) {
312            self.Socket.Listen(backlog);
313            return 0;
314        }
315
316        [RubyMethod("recvfrom")]
317        public static RubyArray/*!*/ ReceiveFrom(ConversionStorage<int>/*!*/ fixnumCast, RubySocket/*!*/ self, int length) {
318            return ReceiveFrom(fixnumCast, self, length, null);
319        }
320
321        [RubyMethod("recvfrom")]
322        public static RubyArray/*!*/ ReceiveFrom(ConversionStorage<int>/*!*/ fixnumCast, RubySocket/*!*/ self, 
323            int length, object/*Numeric*/ flags) {
324            SocketFlags sFlags = ConvertToSocketFlag(fixnumCast, flags);
325            byte[] buffer = new byte[length];
326            EndPoint fromEP = new IPEndPoint(IPAddress.Any, 0);
327            int received = self.Socket.ReceiveFrom(buffer, sFlags, ref fromEP);
328            MutableString str = MutableString.CreateBinary();
329            str.Append(buffer, 0, received);
330            str.IsTainted = true;
331            return RubyOps.MakeArray2(str, self.GetAddressArray(fromEP));
332        }
333
334
335        [RubyMethod("sysaccept")]
336        public static RubyArray/*!*/ SysAccept(RubyContext/*!*/ context, RubySocket/*!*/ self) {
337            RubyArray result = new RubyArray(2);
338            // TODO: Do we need some kind of strong reference to the socket
339            // here to stop the RubySocket from being garbage collected?
340            RubySocket s = new RubySocket(context, self.Socket.Accept());
341            result.Add(s.GetFileDescriptor());
342            SocketAddress addr = s.Socket.RemoteEndPoint.Serialize();
343            result.Add(MutableString.CreateAscii(addr.ToString()));
344            return result;
345        }
346
347        #endregion
348
349        #region Constants
350
351        [RubyModule("Constants", BuildConfig ="!SILVERLIGHT")]
352        public class SocketConstants {
353            #region Address Family
354
355            [RubyConstant]
356            public const int AF_APPLETALK = (int)AddressFamily.AppleTalk;
357            [RubyConstant]
358            public const int AF_ATM = (int)AddressFamily.Atm;
359            [RubyConstant]
360            public const int AF_CCITT = (int)AddressFamily.Ccitt;
361            [RubyConstant]
362            public const int AF_CHAOS = (int)AddressFamily.Chaos;
363            [RubyConstant]
364            public const int AF_DATAKIT = (int)AddressFamily.DataKit;
365            [RubyConstant]
366            public const int AF_DLI = (int)AddressFamily.DataLink;
367            [RubyConstant]
368            public const int AF_ECMA = (int)AddressFamily.Ecma;
369            [RubyConstant]
370            public const int AF_HYLINK = (int)AddressFamily.HyperChannel;
371            [RubyConstant]
372            public const int AF_IMPLINK = (int)AddressFamily.ImpLink;
373            [RubyConstant]
374            public const int AF_INET = (int)AddressFamily.InterNetwork;
375            [RubyConstant]
376            public const int AF_INET6 = (int)AddressFamily.InterNetworkV6;
377            [RubyConstant]
378            public const int AF_IPX = (int)AddressFamily.Ipx;
379            [RubyConstant]
380            public const int AF_ISO = (int)AddressFamily.Iso;
381            [RubyConstant]
382            public const int AF_LAT = (int)AddressFamily.Lat;
383            [RubyConstant]
384            public const int AF_MAX = (int)AddressFamily.Max;
385            [RubyConstant]
386            public const int AF_NETBIOS = (int)AddressFamily.NetBios;
387            [RubyConstant]
388            public const int AF_NS = (int)AddressFamily.NS;
389            [RubyConstant]
390            public const int AF_OSI = (int)AddressFamily.Osi;
391            [RubyConstant]
392            public const int AF_PUP = (int)AddressFamily.Pup;
393            [RubyConstant]
394            public const int AF_SNA = (int)AddressFamily.Sna;
395            [RubyConstant]
396            public const int AF_UNIX = (int)AddressFamily.Unix;
397            [RubyConstant]
398            public const int AF_UNSPEC = (int)AddressFamily.Unspecified;
399
400            #endregion
401
402            #region Flag Options for GetAddressInfo
403
404            [RubyConstant]
405            public const int AI_PASSIVE = 1;
406            [RubyConstant]
407            public const int AI_CANONNAME = 2;
408            [RubyConstant]
409            public const int AI_NUMERICHOST = 4;
410
411            #endregion
412
413            #region Error Return Codes from GetAddressInfo
414
415            [RubyConstant]
416            public const int EAI_AGAIN = 2;
417            [RubyConstant]
418            public const int EAI_BADFLAGS = 3;
419            [RubyConstant]
420            public const int EAI_FAIL = 4;
421            [RubyConstant]
422            public const int EAI_FAMILY = 5;
423            [RubyConstant]
424            public const int EAI_MEMORY = 6;
425            [RubyConstant]
426            public const int EAI_NODATA = 7;
427            [RubyConstant]
428            public const int EAI_NONAME = 8;
429            [RubyConstant]
430            public const int EAI_SERVICE = 9;
431            [RubyConstant]
432            public const int EAI_SOCKTYPE = 10;
433
434            #endregion
435
436            #region Addresses
437
438            [RubyConstant]
439            public const int IPPORT_RESERVED = 1024;
440            [RubyConstant]
441            public const int IPPORT_USERRESERVED = 5000;
442
443            [RubyConstant]
444            public const int INET_ADDRSTRLEN = 16;
445            [RubyConstant]
446            public const int INET6_ADDRSTRLEN = 46;
447
448            [RubyConstant]
449            public const uint INADDR_ALLHOSTS_GROUP = 0xe0000001;
450            [RubyConstant]
451            public const int INADDR_ANY = 0;
452            [RubyConstant]
453            public const uint INADDR_BROADCAST = 0xffffffff;
454            [RubyConstant]
455            public const int INADDR_LOOPBACK = 0x7F000001;
456            [RubyConstant]
457            public const uint INADDR_MAX_LOCAL_GROUP = 0xe00000ff;
458            [RubyConstant]
459            public const uint INADDR_NONE = 0xffffffff;
460            [RubyConstant]
461            public const uint INADDR_UNSPEC_GROUP = 0xe0000000;
462
463            #endregion
464
465            #region IP Protocol Constants
466
467            [RubyConstant]
468            public const int IP_DEFAULT_MULTICAST_TTL = 1;
469            [RubyConstant]
470            public const int IP_DEFAULT_MULTICAST_LOOP = 1;
471
472            [RubyConstant]
473            public const int IP_OPTIONS = 1;
474            [RubyConstant]
475            public const int IP_HDRINCL = 2;
476            [RubyConstant]
477            public const int IP_TOS = 3;
478            [RubyConstant]
479            public const int IP_TTL = 4;
480            [RubyConstant]
481            public const int IP_MULTICAST_IF = 9;
482            [RubyConstant]
483            public const int IP_MULTICAST_TTL = 10;
484            [RubyConstant]
485            public const int IP_MULTICAST_LOOP = 11;
486            [RubyConstant]
487            public const int IP_ADD_MEMBERSHIP = 12;
488            [RubyConstant]
489            public const int IP_DROP_MEMBERSHIP = 13;
490            [RubyConstant]
491            public const int IP_ADD_SOURCE_MEMBERSHIP = 15;
492            [RubyConstant]
493            public const int IP_DROP_SOURCE_MEMBERSHIP = 16;
494            [RubyConstant]
495            public const int IP_BLOCK_SOURCE = 17;
496            [RubyConstant]
497            public const int IP_UNBLOCK_SOURCE = 18;
498            [RubyConstant]
499            public const int IP_PKTINFO = 19;
500            [RubyConstant]
501            public const int IP_MAX_MEMBERSHIPS = 20;
502
503            [RubyConstant]
504            public const int IPPROTO_GGP = 3;
505            [RubyConstant]
506            public const int IPPROTO_ICMP = 1;
507            [RubyConstant]
508            public const int IPPROTO_IDP = 22;
509            [RubyConstant]
510            public const int IPPROTO_IGMP = 2;
511            [RubyConstant]
512            public const int IPPROTO_IP = 0;
513            [RubyConstant]
514            public const int IPPROTO_MAX = 256;
515            [RubyConstant]
516            public const int IPPROTO_ND = 77;
517            [RubyConstant]
518            public const int IPPROTO_PUP = 12;
519            [RubyConstant]
520            public const int IPPROTO_RAW = 255;
521            [RubyConstant]
522            public const int IPPROTO_TCP = 6;
523            [RubyConstant]
524            public const int IPPROTO_UDP = 17;
525            [RubyConstant]
526            public const int IPPROTO_AH = 51;
527            [RubyConstant]
528            public const int IPPROTO_DSTOPTS = 60;
529            [RubyConstant]
530            public const int IPPROTO_ESP = 50;
531            [RubyConstant]
532            public const int IPPROTO_FRAGMENT = 44;
533            [RubyConstant]
534            public const int IPPROTO_HOPOPTS = 0;
535            [RubyConstant]
536            public const int IPPROTO_ICMPV6 = 58;
537            [RubyConstant]
538            public const int IPPROTO_IPV6 = 41;
539            [RubyConstant]
540            public const int IPPROTO_NONE = 59;
541            [RubyConstant]
542            public const int IPPROTO_ROUTING = 43;
543
544            [RubyConstant]
545            public const int IPV6_JOIN_GROUP = 12;
546            [RubyConstant]
547            public const int IPV6_LEAVE_GROUP = 13;
548            [RubyConstant]
549            public const int IPV6_MULTICAST_HOPS = 10;
550            [RubyConstant]
551            public const int IPV6_MULTICAST_IF = 9;
552            [RubyConstant]
553            public const int IPV6_MULTICAST_LOOP = 11;
554            [RubyConstant]
555            public const int IPV6_UNICAST_HOPS = 4;
556            [RubyConstant]
557            public const int IPV6_PKTINFO = 19;
558
559
560
561            #endregion
562
563            #region Message Options
564            [RubyConstant]
565            public const int MSG_DONTROUTE = 4;
566            [RubyConstant]
567            public const int MSG_OOB = 1;
568            [RubyConstant]
569            public const int MSG_PEEK = 2;
570            [RubyConstant]
571            #endregion
572
573            #region Name Info
574            public const int NI_DGRAM = 16;
575            [RubyConstant]
576            public const int NI_MAXHOST = 1025;
577            [RubyConstant]
578            public const int NI_MAXSERV = 32;
579            [RubyConstant]
580            public const int NI_NAMEREQD = 4;
581            [RubyConstant]
582            public const int NI_NOFQDN = 1;
583            [RubyConstant]
584            public const int NI_NUMERICHOST = 2;
585            [RubyConstant]
586            public const int NI_NUMERICSERV = 8;
587            #endregion
588
589            #region Protocol Family
590
591            [RubyConstant]
592            public const int PF_APPLETALK = (int)ProtocolFamily.AppleTalk;
593            [RubyConstant]
594            public const int PF_ATM = (int)ProtocolFamily.Atm;
595            [RubyConstant]
596            public const int PF_CCITT = (int)ProtocolFamily.Ccitt;
597            [RubyConstant]
598            public const int PF_CHAOS = (int)ProtocolFamily.Chaos;
599            [RubyConstant]
600            public const int PF_DATAKIT = (int)ProtocolFamily.DataKit;
601            [RubyConstant]
602            public const int PF_DLI = (int)ProtocolFamily.DataLink;
603            [RubyConstant]
604            public const int PF_ECMA = (int)ProtocolFamily.Ecma;
605            [RubyConstant]
606            public const int PF_HYLINK = (int)ProtocolFamily.HyperChannel;
607            [RubyConstant]
608            public const int PF_IMPLINK = (int)ProtocolFamily.ImpLink;
609            [RubyConstant]
610            public const int PF_INET = (int)ProtocolFamily.InterNetwork;
611            [RubyConstant]
612            public const int PF_INET6 = (int)ProtocolFamily.InterNetworkV6;
613            [RubyConstant]
614            public const int PF_IPX = (int)ProtocolFamily.Ipx;
615            [RubyConstant]
616            public const int PF_ISO = (int)ProtocolFamily.Iso;
617            [RubyConstant]
618            public const int PF_LAT = (int)ProtocolFamily.Lat;
619            [RubyConstant]
620            public const int PF_MAX = (int)ProtocolFamily.Max;
621            [RubyConstant]
622            public const int PF_NS = (int)ProtocolFamily.NS;
623            [RubyConstant]
624            public const int PF_OSI = (int)ProtocolFamily.Osi;
625            [RubyConstant]
626            public const int PF_PUP = (int)ProtocolFamily.Pup;
627            [RubyConstant]
628            public const int PF_SNA = (int)ProtocolFamily.Sna;
629            [RubyConstant]
630            public const int PF_UNIX = (int)ProtocolFamily.Unix;
631            [RubyConstant]
632            public const int PF_UNSPEC = (int)ProtocolFamily.Unspecified;
633
634            #endregion
635
636            #region Socket Shutdown
637
638            [RubyConstant]
639            public const int SHUT_RD = (int)SocketShutdown.Receive;
640            [RubyConstant]
641            public const int SHUT_RDWR = (int)SocketShutdown.Both;
642            [RubyConstant]
643            public const int SHUT_WR = (int)SocketShutdown.Send;
644
645            #endregion
646
647            #region Socket Type
648
649            [RubyConstant]
650            public const int SOCK_DGRAM = (int)SocketType.Dgram;
651            [RubyConstant]
652            public const int SOCK_RAW = (int)SocketType.Raw;
653            [RubyConstant]
654            public const int SOCK_RDM = (int)SocketType.Rdm;
655            [RubyConstant]
656            public const int SOCK_SEQPACKET = (int)SocketType.Seqpacket;
657            [RubyConstant]
658            public const int SOCK_STREAM = (int)SocketType.Stream;
659
660            #endregion
661
662            #region Socket Option
663
664            [RubyConstant]
665            public const int SO_ACCEPTCONN = (int)SocketOptionName.AcceptConnection;
666            [RubyConstant]
667            public const int SO_BROADCAST = (int)SocketOptionName.Broadcast;
668            [RubyConstant]
669            public const int SO_DEBUG = (int)SocketOptionName.Debug;
670            [RubyConstant]
671            public const int SO_DONTROUTE = (int)SocketOptionName.DontRoute;
672            [RubyConstant]
673            public const int SO_ERROR = (int)SocketOptionName.Error;
674            [RubyConstant]
675            public const int SO_KEEPALIVE = (int)SocketOptionName.KeepAlive;
676            [RubyConstant]
677            public const int SO_LINGER = (int)SocketOptionName.Linger;
678            [RubyConstant]
679            public const int SO_OOBINLINE = (int)SocketOptionName.OutOfBandInline;
680            [RubyConstant]
681            public const int SO_RCVBUF = (int)SocketOptionName.ReceiveBuffer;
682            [RubyConstant]
683            public const int SO_RCVLOWAT = (int)SocketOptionName.ReceiveLowWater;
684            [RubyConstant]
685            public const int SO_RCVTIMEO = (int)SocketOptionName.ReceiveTimeout;
686            [RubyConstant]
687            public const int SO_REUSEADDR = (int)SocketOptionName.ReuseAddress;
688            [RubyConstant]
689            public const int SO_SNDBUF = (int)SocketOptionName.SendBuffer;
690            [RubyConstant]
691            public const int SO_SNDLOWAT = (int)SocketOptionName.SendLowWater;
692            [RubyConstant]
693            public const int SO_SNDTIMEO = (int)SocketOptionName.SendTimeout;
694            [RubyConstant]
695            public const int SO_TYPE = (int)SocketOptionName.Type;
696            [RubyConstant]
697            public const int SO_USELOOPBACK = (int)SocketOptionName.UseLoopback;
698
699            #endregion
700
701            [RubyConstant]
702            public const int SOL_SOCKET = 65535;
703
704            [RubyConstant]
705            public const int SOMAXCONN = Int32.MaxValue;
706
707            [RubyConstant]
708            public const int TCP_NODELAY = 1;
709        }
710
711        #endregion
712
713        #region Private Helpers
714
715        private static int ParseInteger(RubyContext/*!*/ context, string/*!*/ str) {
716            bool isNegative = false;
717            if (str[0] == '-') {
718                isNegative = true;
719                str = str.Remove(0, 1);
720            }
721
722            Tokenizer tokenizer = new Tokenizer();
723            tokenizer.Initialize(new StringReader(str));
724            Tokens token = tokenizer.GetNextToken();
725            TokenValue value = tokenizer.TokenValue;
726            Tokens nextToken = tokenizer.GetNextToken();
727
728            // We are only interested in the whole string being a valid Integer
729            if (token == Tokens.Integer && nextToken == Tokens.Integer) {
730                return isNegative ? -value.Integer1 : value.Integer1;
731            } else {
732                throw RubyExceptions.CreateTypeConversionError("String", "Integer");
733            }
734        }
735
736        #endregion
737    }
738}
739#endif