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; }; }
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; }; }
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)); } }); }
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; }; }
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); } }