Esempio n. 1
0
 public ConnectionInfo(ChannelRegistration registration, IActorRef handler, bool keepOpenOnPeerClosed, bool useResumeWriting)
 {
     Registration         = registration;
     Handler              = handler;
     KeepOpenOnPeerClosed = keepOpenOnPeerClosed;
     UseResumeWriting     = useResumeWriting;
 }
Esempio n. 2
0
        private void DoReceive(ChannelRegistration registration, IActorRef handler)
        {
            Action <int, ByteBuffer> innerReceive = null;

            innerReceive = (readsLeft, buffer) =>
            {
                buffer.Clear();
                buffer.Limit(_udp.Setting.DirectBufferSize);

                var sender = Channel.Receive(buffer);
                if (sender != null)
                {
                    buffer.Flip();
                    handler.Tell(new Udp.Received(ByteString.Create(buffer), sender));
                    if (readsLeft > 0)
                    {
                        innerReceive(readsLeft - 1, buffer);
                    }
                }
            };

            var buffr = _udp.BufferPool.Acquire();

            try
            {
                innerReceive(_udp.Setting.BatchReceiveLimit, buffr);
            }
            finally
            {
                _udp.BufferPool.Release(buffr);
                registration.EnableInterest(SocketAsyncOperation.Receive);
            }
        }
Esempio n. 3
0
        // AUXILIARIES and IMPLEMENTATION

        /** used in subclasses to start the common machinery above once a channel is connected */
        protected void CompleteConnect(ChannelRegistration registration, IActorRef commander,
                                       IEnumerable <Inet.SocketOption> options)
        {
            // Turn off Nagle's algorithm by default
            try
            {
                Channel.Socket.NoDelay = true;
            }
            catch (SocketException e)
            {
                _log.Debug("Could not enable TcpNoDelay: {0}", e.Message);
            }
            options.ForEach(x => x.AfterConnect(Channel.Socket));

            commander.Tell(new Tcp.Connected(
                               Channel.Socket.RemoteEndPoint,
                               Channel.Socket.LocalEndPoint));

            Context.SetReceiveTimeout(_tcp.Settings.RegisterTimeout);

            // TODO: Not ported. The following need to be investigated before porting
            //if (WindowsConnectionAbortWorkaroundEnabled)
            //    registration.EnableInterest(SocketAsyncOperation.Connect);

            Context.Become(WaitingForRegistration(registration, commander));
        }
Esempio n. 4
0
        private void DoRead(ChannelRegistration registration, IActorRef handler)
        {
            Action <int, ByteBuffer> innerRead = null;

            innerRead = (readsLeft, buffer) =>
            {
                buffer.Clear();
                buffer.Limit(_udpConn.Settings.DirectBufferSize);
                if (_channel.Read(buffer) > 0)
                {
                    buffer.Flip();
                    handler.Tell(new UdpConnected.Received(ByteString.Create(buffer)));
                    innerRead(readsLeft - 1, buffer);
                }
            };
            var buffr = _udpConn.BufferPool.Acquire();

            try
            {
                innerRead(_udpConn.Settings.BatchReceiveLimit, buffr);
            }
            finally
            {
                registration.EnableInterest(SocketAsyncOperation.Receive);
                _udpConn.BufferPool.Release(buffr);
            }
        }
Esempio n. 5
0
        // STATES

        /** connection established, waiting for registration from user handler */
        private Receive WaitingForRegistration(ChannelRegistration registration, IActorRef commander)
        {
            return(message =>
            {
                var register = message as Tcp.Register;
                if (register != null)
                {
                    // up to this point we've been watching the commander,
                    // but since registration is now complete we only need to watch the handler from here on
                    if (register.Handler != commander)
                    {
                        Context.Unwatch(commander);
                        Context.Watch(register.Handler);
                    }
                    if (_tcp.Settings.TraceLogging)
                    {
                        _log.Debug("[{0}] registered as connection handler", register.Handler);
                    }

                    var info = new ConnectionInfo(registration, register.Handler, register.KeepOpenonPeerClosed, register.UseResumeWriting);

                    // if we have resumed reading from pullMode while waiting for Register then register OP_READ interest
                    if (_pullMode && !_readingSuspended)
                    {
                        ResumeReading(info);
                    }
                    DoRead(info, null); // immediately try reading, pullMode is handled by readingSuspended
                    Context.SetReceiveTimeout(null);
                    Context.Become(Connected(info));
                    return true;
                }
                if (message is Tcp.ResumeReading)
                {
                    _readingSuspended = false;
                    return true;
                }
                if (message is Tcp.SuspendReading)
                {
                    _readingSuspended = true;
                    return false;
                }
                var cmd = message as Tcp.CloseCommand;
                if (cmd != null)
                {
                    var info = new ConnectionInfo(registration, commander, keepOpenOnPeerClosed: false, useResumeWriting: false);
                    HandleClose(info, Sender, cmd.Event);
                    return true;
                }
                if (message is ReceiveTimeout)
                {
                    // after sending `Register` user should watch this actor to make sure
                    // it didn't die because of the timeout
                    _log.Debug("Configured registration timeout of [{0}] expired, stopping", _tcp.Settings.RegisterTimeout);
                    Context.Stop(Self);
                    return true;
                }
                return false;
            });
        }
Esempio n. 6
0
 private Receive Resolving(DnsEndPoint remoteAddress, ChannelRegistration registration)
 {
     return(message =>
     {
         var resolved = message as Dns.Resolved;
         if (resolved != null)
         {
             ReportConnectFailure(() => Register(new IPEndPoint(resolved.Addr, remoteAddress.Port), registration));
             return true;
         }
         return false;
     });
 }
Esempio n. 7
0
 private Receive Connecting(ChannelRegistration registration, int remainingFinishConnectRetries)
 {
     return(message =>
     {
         if (message is SelectionHandler.ChannelConnectable)
         {
             ReportConnectFailure(() =>
             {
                 if (Channel.FinishConnect())
                 {
                     if (_connect.Timeout.HasValue)
                     {
                         Context.SetReceiveTimeout(null);
                     }
                     Log.Debug("Connection established to [{0}]", _connect.RemoteAddress);
                     CompleteConnect(registration, _commander, _connect.Options);
                 }
                 else
                 {
                     if (remainingFinishConnectRetries > 0)
                     {
                         var self = Self;
                         Context.System.Scheduler.Advanced.ScheduleOnce(1, () => _channelRegistry.Register(Channel, SocketAsyncOperation.Connect, self));
                         Context.Become(Connecting(registration, remainingFinishConnectRetries - 1));
                     }
                     else
                     {
                         Log.Debug("Could not establish connection because finishConnect " +
                                   "never returned true (consider increasing akka.io.tcp.finish-connect-retries)");
                         Stop();
                     }
                 }
             });
             return true;
         }
         if (message is ReceiveTimeout)
         {
             if (_connect.Timeout.HasValue)
             {
                 Context.SetReceiveTimeout(null);                             // Clear the timeout
             }
             Log.Debug("Connect timeout expired, could not establish connection to [{0}]", _connect.RemoteAddress);
             Stop();
             return true;
         }
         return false;
     });
 }
Esempio n. 8
0
 private void Register(EndPoint address, ChannelRegistration registration)
 {
     ReportConnectFailure(() =>
     {
         Log.Debug("Attempting connection to [{0}]", address);
         if (Channel.Connect(address))
         {
             CompleteConnect(registration, _commander, _connect.Options);
         }
         else
         {
             registration.EnableInterest(SocketAsyncOperation.Connect);
             Become(Connecting(registration, Tcp.Settings.FinishConnectRetries));
         }
     });
 }
Esempio n. 9
0
        private void DoSend(ChannelRegistration registration)
        {
            var buffer = Udp.BufferPool.Acquire();

            try
            {
                buffer.Clear();
                _pendingSend.Payload.CopyToBuffer(buffer);
                buffer.Flip();
                var writtenBytes = Channel.Send(buffer, _pendingSend.Target);
                if (Udp.Setting.TraceLogging)
                {
                    _log.Debug("Wrote [{0}] bytes to channel", writtenBytes);
                }

                // Datagram channel either sends the whole message, or nothing
                if (writtenBytes == 0)
                {
                    if (_retriedSend)
                    {
                        _pendingCommander.Tell(new Udp.CommandFailed(_pendingSend));
                        _retriedSend      = false;
                        _pendingSend      = null;
                        _pendingCommander = null;
                    }
                    else
                    {
                        registration.EnableInterest(SocketAsyncOperation.Send);
                        _retriedSend = true;
                    }
                }
                else
                {
                    if (_pendingSend.WantsAck)
                    {
                        _pendingCommander.Tell(_pendingSend.Ack);
                    }
                    _retriedSend      = false;
                    _pendingSend      = null;
                    _pendingCommander = null;
                }
            }
            finally
            {
                Udp.BufferPool.Release(buffer);
            }
        }
Esempio n. 10
0
        private Receive ReadHandlers(ChannelRegistration registration)
        {
            return(message =>
            {
                if (message is Udp.SuspendReading)
                {
                    registration.DisableInterest(SocketAsyncOperation.Receive);
                    return true;
                }
                if (message is Udp.ResumeReading)
                {
                    registration.EnableInterest(SocketAsyncOperation.Receive);
                    return true;
                }
                if (message is SelectionHandler.ChannelReadable)
                {
                    DoReceive(registration, _bind.Handler);
                    return true;
                }

                if (message is Udp.Unbind)
                {
                    _log.Debug("Unbinding endpoint [{0}]", _bind.LocalAddress);
                    try
                    {
                        Channel.Close();
                        Sender.Tell(IO.Udp.Unbound.Instance);
                        _log.Debug("Unbound endpoint [{0}], stopping listener", _bind.LocalAddress);
                    }
                    finally
                    {
                        Context.Stop(Self);
                    }
                    return true;
                }
                return false;
            });
        }
Esempio n. 11
0
        public Receive SendHandlers(ChannelRegistration registration)
        {
            return(message =>
            {
                var send = message as Udp.Send;
                if (send != null && HasWritePending)
                {
                    if (Udp.Setting.TraceLogging)
                    {
                        _log.Debug("Dropping write because queue is full");
                    }
                    Sender.Tell(new Udp.CommandFailed(send));
                    return true;
                }
                if (send != null && send.Payload.IsEmpty)
                {
                    if (send.WantsAck)
                    {
                        Sender.Tell(send.Ack);
                    }
                    return true;
                }
                if (send != null)
                {
                    _pendingSend = send;
                    _pendingCommander = Sender;

                    var dns = send.Target as DnsEndPoint;
                    if (dns != null)
                    {
                        var resolved = Dns.ResolveName(dns.Host, Context.System, Self);
                        if (resolved != null)
                        {
                            try
                            {
                                _pendingSend = new Udp.Send(_pendingSend.Payload, new IPEndPoint(resolved.Addr, dns.Port), _pendingSend.Ack);
                                DoSend(registration);
                            }
                            catch (Exception ex)
                            {
                                Sender.Tell(new Udp.CommandFailed(send));
                                _log.Debug("Failure while sending UDP datagram to remote address [{0}]: {1}", send.Target, ex);
                                _retriedSend = false;
                                _pendingSend = null;
                                _pendingCommander = null;
                            }
                        }
                    }
                    else
                    {
                        DoSend(registration);
                    }
                    return true;
                }
                if (message is SelectionHandler.ChannelWritable && HasWritePending)
                {
                    DoSend(registration);
                    return true;
                }
                return false;
            });
        }
Esempio n. 12
0
        private Receive Connected(ChannelRegistration registration)
        {
            return(message =>
            {
                if (message is UdpConnected.SuspendReading)
                {
                    registration.DisableInterest(SocketAsyncOperation.Receive);
                    return true;
                }
                if (message is UdpConnected.ResumeReading)
                {
                    registration.EnableInterest(SocketAsyncOperation.Receive);
                    return true;
                }
                if (message is SelectionHandler.ChannelReadable)
                {
                    DoRead(registration, _connect.Handler);
                    return true;
                }

                if (message is UdpConnected.Disconnect)
                {
                    _log.Debug("Closing UDP connection to [{0}]", _connect.RemoteAddress);
                    _channel.Close();
                    Sender.Tell(UdpConnected.Disconnected.Instance);
                    _log.Debug("Connection closed to [{0}], stopping listener", _connect.RemoteAddress);
                    Context.Stop(Self);
                    return true;
                }

                var send = message as UdpConnected.Send;
                if (send != null && WritePending)
                {
                    if (_udpConn.Settings.TraceLogging)
                    {
                        _log.Debug("Dropping write because queue is full");
                    }
                    Sender.Tell(new UdpConnected.CommandFailed(send));
                    return true;
                }
                if (send != null && send.Payload.IsEmpty)
                {
                    if (send.WantsAck)
                    {
                        Sender.Tell(send.Ack);
                    }
                    return true;
                }
                if (send != null)
                {
                    _pendingSend = Tuple.Create(send, Sender);
                    registration.EnableInterest(SocketAsyncOperation.Send);
                    return true;
                }
                if (message is SelectionHandler.ChannelWritable)
                {
                    DoWrite();
                    return true;
                }
                return false;
            });
        }