public void InjectSelf()
 {
     _Original = this.InjectFunctionPointer<SendToDelegate>(AddressHelper.CodeOffset("gso", 0x1C274), 24);
 }
예제 #2
0
        public LocalMulticast(int port, Action <TMessage> handler = null, string name = null)
        {
            _handler = handler;
            _name    = name ?? String.Empty;

            var msgSize = TypeHelper <TMessage> .FixedSize;

            if (msgSize <= 0)
            {
                throw new ArgumentException($"Type {typeof(TMessage).Name} must be a blittable struct");
            }

            _bufferLength = msgSize;

            _sendArgsPool = new ObjectPool <SocketAsyncEventArgs>(SendArgsFactory, 4);

            var multicastAddress = IPAddress.Parse("239.199.99.9");

            _mcEndPoint = new CachedEndPoint(new IPEndPoint(multicastAddress, port));
            _inEndPoint = new CachedEndPoint(new IPEndPoint(IPAddress.Loopback, port));

            _socket = new Socket(_inEndPoint.AddressFamily,
                                 SocketType.Dgram, ProtocolType.Udp);

            _socket.SetSocketOption(SocketOptionLevel.Socket,
                                    SocketOptionName.ReuseAddress,
                                    true);

            _socket.SetSocketOption(SocketOptionLevel.Udp,
                                    SocketOptionName.NoChecksum,
                                    1);

            _socket.SetSocketOption(SocketOptionLevel.IP,
                                    SocketOptionName.MulticastTimeToLive,
                                    2);

            _socket.ExclusiveAddressUse = false;
            _socket.Blocking            = true;
            _socket.EnableBroadcast     = true;
            // Maybe a fluke, bit perf drops and definitely not improves with this: _socket.UseOnlyOverlappedIO = true;

            _socket.Bind(_inEndPoint);

            // If you are using a connectionless protocol such as UDP,
            // you do not have to call Connect before sending and
            // receiving data. You can use SendTo and ReceiveFrom to
            // synchronously communicate with a remote host.
            // If you do call Connect, any datagrams that arrive from
            // an address other than the specified default will be discarded.
            // _socket.Connect(_mcEndPoint);

            _socket.SetSocketOption(SocketOptionLevel.IP,
                                    SocketOptionName.MulticastLoopback,
                                    true);

            // join on loopback interface
            var mcastOption = new MulticastOption(multicastAddress, NetworkInterface.LoopbackInterfaceIndex);

            _socket.SetSocketOption(SocketOptionLevel.IP,
                                    SocketOptionName.AddMembership,
                                    mcastOption);

            _socket.SetSocketOption(SocketOptionLevel.IP,
                                    SocketOptionName.MulticastInterface,
#pragma warning disable 618
                                    (int)IPAddress.Loopback.Address);
#pragma warning restore 618
            // see https://github.com/dotnet/corefx/issues/25699 if there are issues on non-Windows
            // IPAddress.HostToNetworkOrder(NetworkInterface.LoopbackInterfaceIndex));

            // Another option to limit source to loopback
            //byte[] membershipAddresses = new byte[12]; // 3 IPs * 4 bytes (IPv4)
            //Buffer.BlockCopy(multicastAddress.GetAddressBytes(), 0, membershipAddresses, 0, 4);
            //Buffer.BlockCopy(IPAddress.Loopback.GetAddressBytes(), 0, membershipAddresses, 4, 4);
            //Buffer.BlockCopy(IPAddress.Loopback.GetAddressBytes(), 0, membershipAddresses, 8, 4);
            //_socket.SetSocketOption(SocketOptionLevel.IP,
            //    SocketOptionName.AddSourceMembership,
            //    membershipAddresses);

            StartReceive();

#if NETCOREAPP3_0
            try
            {
                _handle = _socket.SafeHandle;
                var address = _mcEndPoint.Serialize();
                _mcAddressSize   = address.Size;
                _mcAddressBuffer = new byte[_mcAddressSize];
                for (int i = 0; i < _mcAddressSize; i++)
                {
                    _mcAddressBuffer[i] = address[i];
                }

                var assembly      = typeof(Socket).Assembly;
                var socketPalType = assembly.GetTypes().FirstOrDefault(x => x.Name == "SocketPal");
                var method        = socketPalType?.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
                                    .FirstOrDefault(m => m.Name == "SendTo");

                _sendToDelegate = Delegate.CreateDelegate(typeof(SendToDelegate), method) as SendToDelegate;
            }
            catch
            {
                Trace.TraceInformation("Cannot get SocketPal.SendTo method");
            }
#endif
        }