예제 #1
0
 public bool close(UdpSocket fan)
 {
     try
       {
     close();
     return true;
       }
       catch
       {
     return false;
       }
 }
예제 #2
0
 //////////////////////////////////////////////////////////////////////////
 // Communication
 //////////////////////////////////////////////////////////////////////////
 public UdpSocket bind(UdpSocket fan, IpAddr addr, Long port)
 {
     try
       {
     if (m_dotnet == null) m_dotnet = createSocket();
     IPAddress dotnetAddr = (addr == null) ? IPAddress.Any : addr.m_peer.m_dotnet;
     int dotnetPort = (port == null) ? 0 : port.intValue();
     m_dotnet.Bind(new IPEndPoint(dotnetAddr, dotnetPort));
     return fan;
       }
       catch (SocketException e)
       {
     throw IOErr.make(e).val;
       }
 }
        internal UdpSocketReceiveManager(UdpSocket[] receiveSockets, int maxPendingReceivesPerSocket, BufferManager bufferManager, IUdpReceiveHandler receiveHandler)
        {
            Fx.Assert(receiveSockets != null, "receiveSockets parameter is null");
            Fx.Assert(receiveSockets.Length > 0, "receiveSockets parameter is empty");
            Fx.Assert(maxPendingReceivesPerSocket > 0, "maxPendingReceivesPerSocket can't be <= 0");
            Fx.Assert(receiveHandler.MaxReceivedMessageSize > 0, "maxReceivedMessageSize must be > 0");
            Fx.Assert(bufferManager != null, "bufferManager argument should not be null");
            Fx.Assert(receiveHandler != null, "receiveHandler should not be null");

            this.receiveHandler = receiveHandler;
            this.thisLock = new object();
            this.bufferManager = bufferManager;
            this.receiveSockets = receiveSockets;
            this.maxPendingReceivesPerSocket = maxPendingReceivesPerSocket;
            this.messageBufferSize = UdpUtility.ComputeMessageBufferSize(receiveHandler.MaxReceivedMessageSize);

            int maxPendingReceives = maxPendingReceivesPerSocket * receiveSockets.Length;
            this.receiveBufferPool = new ConnectionBufferPool(this.messageBufferSize, maxPendingReceives);
        }
예제 #4
0
 public void setReceiveTimeout(UdpSocket fan, Duration v)
 {
     m_receiveTimeout = (v == null) ? 0 : (int)v.millis();
 }
예제 #5
0
 public void setReuseAddr(UdpSocket fan, bool v)
 {
     m_reuseAddr = v;
 }
 public ServerUdpOutputChannel(ChannelManagerBase factory, MessageEncoder encoder, BufferManager bufferManager, UdpSocket[] sendSockets, UdpRetransmissionSettings retransmissionSettings, Uri via, bool isMulticast)
     : base(factory, encoder, bufferManager, sendSockets, retransmissionSettings, via, isMulticast)
 {
 }
예제 #7
0
 public bool getReuseAddr(UdpSocket fan)
 {
     return m_reuseAddr;
 }
예제 #8
0
 //////////////////////////////////////////////////////////////////////////
 // State
 //////////////////////////////////////////////////////////////////////////
 public bool isBound(UdpSocket fan)
 {
     return (m_dotnet == null) ? false : m_dotnet.IsBound;
 }
            public UdpSocketReceiveState(UdpSocket socket, byte[] receiveBuffer)
            {
                Fx.Assert(socket != null, "UdpSocketReceiveState.ctor: socket should not be null");

                this.Socket = socket;
                this.ReceiveBuffer = receiveBuffer;
            }
예제 #10
0
        public UdpPacket receive(UdpSocket fan, UdpPacket packet)
        {
            // create packet if null
              if (packet == null)
            packet = UdpPacket.make(null, null, new MemBuf(1024));

              // map buf bytes to packet
              MemBuf data = (MemBuf)packet.data();
              byte[] buf = data.m_buf;
              int off = data.m_pos;
              int len = buf.Length - off;
              int recv = 0;
              EndPoint sender = new IPEndPoint(IPAddress.Any, 0);

              // receive
              if (isConnected(fan))
              {
            try
            {
              recv = m_dotnet.Receive(buf, off, len, SocketFlags.None);
              sender = m_dotnet.RemoteEndPoint;
            }
            catch (SocketException e)
            {
              // .NET will truncate contents correctly, but still throws a
              // SocketException, so catch that specific case and allow it
              if (e.Message.StartsWith("A message sent on a datagram socket was larger"))
              {
            recv = len;
            sender = m_dotnet.RemoteEndPoint;
              }
              else
              {
            throw IOErr.make(e).val;
              }
            }
              }
              else
              {
            try
            {
              if (m_dotnet == null) m_dotnet = createSocket();
              recv = m_dotnet.ReceiveFrom(buf, off, len, SocketFlags.None, ref sender);
            }
            catch (SocketException e)
            {
              // .NET will truncate contents correctly, but still throws a
              // SocketException, so catch that specific case and allow it
              if (e.Message.StartsWith("A message sent on a datagram socket was larger"))
            recv = len;
              else
            throw IOErr.make(e).val;
            }
              }

              // update packet with received message
              IPEndPoint endPoint = sender as IPEndPoint;
              packet.addr(IpAddrPeer.make(endPoint.Address));
              packet.port(Long.valueOf(endPoint.Port));
              data.m_pos  += recv;
              data.m_size += recv;

              return packet;
        }
예제 #11
0
 //////////////////////////////////////////////////////////////////////////
 // Peer Factory
 //////////////////////////////////////////////////////////////////////////
 public static UdpSocketPeer make(UdpSocket fan)
 {
     return new UdpSocketPeer();
 }
예제 #12
0
 public Long localPort(UdpSocket fan)
 {
     if (!isBound(fan)) return null;
       IPEndPoint pt = m_dotnet.LocalEndPoint as IPEndPoint;
       if (pt == null) return null;
       // TODO - default port?
       return Long.valueOf(pt.Port);
 }
예제 #13
0
 //////////////////////////////////////////////////////////////////////////
 // Socket Options
 //////////////////////////////////////////////////////////////////////////
 public SocketOptions options(UdpSocket fan)
 {
     if (m_options == null) m_options = SocketOptions.make(fan);
       return m_options;
 }
예제 #14
0
 //////////////////////////////////////////////////////////////////////////
 // End Points
 //////////////////////////////////////////////////////////////////////////
 public IpAddr localAddr(UdpSocket fan)
 {
     if (!isBound(fan)) return null;
       IPEndPoint pt = m_dotnet.LocalEndPoint as IPEndPoint;
       if (pt == null) return null;
       return IpAddrPeer.make(pt.Address);
 }
예제 #15
0
 public bool isConnected(UdpSocket fan)
 {
     return (m_dotnet == null) ? false : m_dotnet.Connected;
 }
예제 #16
0
 public bool isClosed(UdpSocket fan)
 {
     return m_closed;
 }
예제 #17
0
 public void setSendBufferSize(UdpSocket fan, long v)
 {
     m_sendBufferSize = v;
 }
예제 #18
0
 public long getSendBufferSize(UdpSocket fan)
 {
     return m_sendBufferSize;
 }
예제 #19
0
 public void setTrafficClass(UdpSocket fan, long v)
 {
     m_trafficClass = v;
 }
        //returns true if receive completed synchronously, false otherwise
        bool StartAsyncReceive(UdpSocket socket)
        {
            Fx.Assert(socket != null, "UdpSocketReceiveManager.StartAsyncReceive: Socket should never be null");                         
            bool completedSync = false;

            ArraySegment<byte> messageBytes = default(ArraySegment<byte>);
            UdpSocketReceiveState state = null;

            lock (this.thisLock)
            {
                if (!this.IsDisposed && socket.PendingReceiveCount < this.maxPendingReceivesPerSocket)
                {
                    IAsyncResult result = null;
                    byte[] receiveBuffer = this.receiveBufferPool.Take();
                    try
                    {
                        state = new UdpSocketReceiveState(socket, receiveBuffer);
                        EndPoint remoteEndpoint = socket.CreateIPAnyEndPoint();

                        result = socket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, ref remoteEndpoint, onReceiveFrom, state);
                    }
                    catch (Exception e)
                    {
                        if (!Fx.IsFatal(e))
                        {
                            this.receiveBufferPool.Return(receiveBuffer);
                        }
                        throw;
                    }

                    if (result.CompletedSynchronously)
                    {
                        completedSync = true;
                        messageBytes = EndReceiveFrom(result, state);
                    }
                }
            }

            if (completedSync)
            {
                messageBytes = this.CopyMessageIntoBufferManager(messageBytes);
                //if HandleDataReceived returns false, it means that the max pending message count was hit.
                //when receiveHandler.HandleDataReceived is called (whether now or later), it will return the buffer to the buffer manager.
                return this.receiveHandler.HandleDataReceived(messageBytes, state.RemoteEndPoint, state.Socket.InterfaceIndex, this.onMessageDequeued);
            }

            return false;
        }
예제 #21
0
 public IpAddr remoteAddr(UdpSocket fan)
 {
     if (!isConnected(fan)) return null;
       return m_remoteAddr;
 }
예제 #22
0
 public long getTrafficClass(UdpSocket fan)
 {
     return m_trafficClass;
 }
예제 #23
0
 public UdpSocket connect(UdpSocket fan, IpAddr addr, long port)
 {
     try
       {
     if (m_dotnet == null) m_dotnet = createSocket();
     m_dotnet.Connect(addr.m_peer.m_dotnet, (int)port);
     IPEndPoint endPoint = m_dotnet.RemoteEndPoint as IPEndPoint;
     m_remoteAddr = IpAddrPeer.make(endPoint.Address);
     m_remotePort = endPoint.Port;
     return fan;
       }
       catch (SocketException e)
       {
     throw IOErr.make(e).val;
       }
 }
예제 #24
0
 public Long remotePort(UdpSocket fan)
 {
     if (!isConnected(fan)) return null;
       return Long.valueOf(m_remotePort);
 }
예제 #25
0
        public void send(UdpSocket fan, UdpPacket packet)
        {
            // map buf bytes to packet
              MemBuf data = (MemBuf)packet.data();
              byte[] buf = data.m_buf;
              int off = data.m_pos;
              int len = data.m_size - off;

              // map address, port
              IpAddr addr = packet.addr();
              Long port = packet.port();
              if (isConnected(fan))
              {
            if (addr != null || port != null)
              throw ArgErr.make("Address and port must be null to send while connected").val;

            try
            {
              m_dotnet.Send(buf, off, len, SocketFlags.None);
            }
            catch (SocketException e)
            {
              throw IOErr.make(e).val;
            }
              }
              else
              {
            if (addr == null || port == null)
              throw ArgErr.make("Address or port is null").val;

            try
            {
              if (m_dotnet == null) m_dotnet = createSocket();
              IPEndPoint endPoint = new IPEndPoint(addr.m_peer.m_dotnet, port.intValue());
              m_dotnet.SendTo(buf, off, len, SocketFlags.None, endPoint);
            }
            catch (SocketException e)
            {
              throw IOErr.make(e).val;
            }
              }

              // lastly drain buf
              data.m_pos += len;
        }
예제 #26
0
 public void setBroadcast(UdpSocket fan, bool v)
 {
     m_enableBroadcast = v;
 }
예제 #27
0
        //returns the port number used...
        public static int CreateListenSocketsOnUniquePort(IPAddress ipv4Address, IPAddress ipv6Address, int receiveBufferSize, int timeToLive, out UdpSocket ipv4Socket, out UdpSocket ipv6Socket)
        {
            // We need both IPv4 and IPv6 on the same port. We can't atomicly bind for IPv4 and IPv6, 
            // so we try 10 times, which even with a 50% failure rate will statistically succeed 99.9% of the time.
            //
            // We look in the range of 49152-65534 for Vista default behavior parity.
            // http://www.iana.org/assignments/port-numbers
            // 
            // We also grab the 10 random numbers in a row to reduce collisions between multiple people somehow
            // colliding on the same seed.
            const int retries = 10;
            const int lowWatermark = 49152;
            const int highWatermark = 65535;

            ipv4Socket = null;
            ipv6Socket = null;

            int[] portNumbers = new int[retries];

            Random randomNumberGenerator = new Random(AppDomain.CurrentDomain.GetHashCode() | Environment.TickCount);

            for (int i = 0; i < retries; i++)
            {
                portNumbers[i] = randomNumberGenerator.Next(lowWatermark, highWatermark);
            }


            int port = -1;
            for (int i = 0; i < retries; i++)
            {
                port = portNumbers[i];
                try
                {
                    ipv4Socket = UdpUtility.CreateUnicastListenSocket(ipv4Address, ref port, receiveBufferSize, timeToLive);
                    ipv6Socket = UdpUtility.CreateUnicastListenSocket(ipv6Address, ref port, receiveBufferSize, timeToLive);
                    break;
                }
                catch (AddressAlreadyInUseException)
                {
                    if (ipv4Socket != null)
                    {
                        ipv4Socket.Close();
                        ipv4Socket = null;
                    }
                    ipv6Socket = null;
                }
                catch (AddressAccessDeniedException)
                {
                    if (ipv4Socket != null)
                    {
                        ipv4Socket.Close();
                        ipv4Socket = null;
                    }
                    ipv6Socket = null;
                }
            }

            if (ipv4Socket == null)
            {
                throw FxTrace.Exception.AsError(new AddressAlreadyInUseException(SR.UniquePortNotAvailable));
            }

            Fx.Assert(ipv4Socket != null, "An exception should have been thrown if the ipv4Socket socket is null");
            Fx.Assert(ipv6Socket != null, "An exception should have been thrown if the ipv6Socket socket is null");
            Fx.Assert(port > 0, "The port number should have been greater than 0. Actual value was " + port);

            return port;
        }
예제 #28
0
 public void setReceiveBufferSize(UdpSocket fan, long v)
 {
     m_receiveBufferSize = v;
 }
        // Must return non-null/non-empty array unless exceptionToBeThrown is has been set
        protected override UdpSocket[] GetSendSockets(Message message, out IPEndPoint remoteEndPoint, out Exception exceptionToBeThrown)
        {
            Fx.Assert(message != null, "message can't be null");

            UdpSocket[] socketList = null;
            exceptionToBeThrown = null;

            remoteEndPoint = null;
            Uri destination;
            bool isVia = false;

            if (message.Properties.Via != null)
            {
                destination = message.Properties.Via;
                isVia = true;
            }
            else if (message.Headers.To != null)
            {
                destination = message.Headers.To;
            }
            else
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ToOrViaRequired));
            }

            this.ValidateDestinationUri(destination, isVia);

            if (destination.HostNameType == UriHostNameType.IPv4 || destination.HostNameType == UriHostNameType.IPv6)
            {
                remoteEndPoint = new IPEndPoint(IPAddress.Parse(destination.DnsSafeHost), destination.Port);

                if (this.IsMulticast)
                {
                    UdpSocket socket = this.GetSendSocketUsingInterfaceIndex(message.Properties, out exceptionToBeThrown);

                    if (socket != null)
                    {
                        if (socket.AddressFamily == remoteEndPoint.AddressFamily)
                        {
                            socketList = new UdpSocket[] { socket };
                        }
                        else
                        {
                            exceptionToBeThrown = new InvalidOperationException(SR.RemoteAddressUnreachableDueToIPVersionMismatch(destination.DnsSafeHost));
                        }
                    }
                }
                else
                {
                    UdpSocket socket = this.GetSendSocket(remoteEndPoint.Address, destination, out exceptionToBeThrown);
                    if (socket != null)
                    {
                        socketList = new UdpSocket[] { socket };
                    }
                }
            }
            else
            {
                IPAddress[] remoteAddresses = DnsCache.Resolve(destination).AddressList;

                if (this.IsMulticast)
                {
                    UdpSocket socket = this.GetSendSocketUsingInterfaceIndex(message.Properties, out exceptionToBeThrown);

                    if (socket != null)
                    {
                        socketList = new UdpSocket[] { socket };

                        for (int i = 0; i < remoteAddresses.Length; i++)
                        {
                            if (remoteAddresses[i].AddressFamily == socket.AddressFamily)
                            {
                                remoteEndPoint = new IPEndPoint(remoteAddresses[i], destination.Port);
                                break;
                            }
                        }

                        if (remoteEndPoint == null)
                        {
                            // for multicast, we only listen on either IPv4 or IPv6 (not both).
                            // if we didn't find a matching remote endpoint, then it would indicate that
                            // the remote host didn't resolve to an address we can use...
                            exceptionToBeThrown = new InvalidOperationException(SR.RemoteAddressUnreachableDueToIPVersionMismatch(destination.DnsSafeHost));
                        }
                    }
                }
                else
                {
                    bool useIPv4 = true;
                    bool useIPv6 = true;

                    for (int i = 0; i < remoteAddresses.Length; i++)
                    {
                        IPAddress address = remoteAddresses[i];

                        if (address.AddressFamily == AddressFamily.InterNetwork && useIPv4)
                        {
                            UdpSocket socket = this.GetSendSocket(address, destination, out exceptionToBeThrown);
                            if (socket == null)
                            {
                                if (this.State != CommunicationState.Opened)
                                {
                                    // time to exit, the channel is closing down.
                                    break;
                                }
                                else
                                {
                                    // no matching socket on IPv4, so ignore future IPv4 addresses 
                                    // in the remoteAddresses list
                                    useIPv4 = false;
                                }
                            }
                            else
                            {
                                remoteEndPoint = new IPEndPoint(address, destination.Port);
                                socketList = new UdpSocket[] { socket };
                                break;
                            }
                        }
                        else if (address.AddressFamily == AddressFamily.InterNetworkV6 && useIPv6)
                        {
                            UdpSocket socket = this.GetSendSocket(address, destination, out exceptionToBeThrown);
                            if (socket == null)
                            {
                                if (this.State != CommunicationState.Opened)
                                {
                                    // time to exit, the channel is closing down.
                                    break;
                                }
                                else
                                {
                                    // no matching socket on IPv6, so ignore future IPv6 addresses 
                                    // in the remoteAddresses list
                                    useIPv6 = false;
                                }
                            }
                            else
                            {
                                remoteEndPoint = new IPEndPoint(address, destination.Port);
                                socketList = new UdpSocket[] { socket };
                                break;
                            }
                        }
                    }
                }
            }

            return socketList;
        }
예제 #30
0
 public Duration getReceiveTimeout(UdpSocket fan)
 {
     if (m_receiveTimeout <= 0) return null;
       return Duration.makeMillis(m_receiveTimeout);
 }