AsyncUDPSocket::AsyncUDPSocket(const Environment& env,
absl_nonnull std::unique_ptr<Socket> socket)
: env_(env),
sequence_checker_(SequenceChecker::kDetached),
socket_(std::move(socket)) { // The socket should start out readable but not writable.
socket_->SubscribeReadEvent(this,
[this](Socket* socket) { OnReadEvent(socket); });
socket_->SubscribeWriteEvent( this, [this](Socket* socket) { OnWriteEvent(socket); }); // need to forward that also for UDP case (DTLS) once the SSL handshake is // finished
int AsyncUDPSocket::Send(constvoid* pv,
size_t cb, const AsyncSocketPacketOptions& options) {
SentPacketInfo sent_packet(options.packet_id,
env_.clock().TimeInMilliseconds(),
options.info_signaled_after_sent);
CopySocketInformationToPacketInfo(cb, *this, &sent_packet.info);
int ret = socket_->Send(pv, cb);
NotifySentPacket(this, sent_packet); return ret;
}
int AsyncUDPSocket::SendTo(constvoid* pv,
size_t cb, const SocketAddress& addr, const AsyncSocketPacketOptions& options) {
SentPacketInfo sent_packet(options.packet_id,
env_.clock().TimeInMilliseconds(),
options.info_signaled_after_sent);
CopySocketInformationToPacketInfo(cb, *this, &sent_packet.info);
if (has_set_ect1_options_ != options.ect_1) { // It is unclear what is most efficient, setting options on every sent // packet or when changed. Potentially, can separate send sockets be used? // This is the easier implementation.
if (socket_->SetOption(Socket::Option::OPT_SEND_ECN,
options.ect_1 ? 1 : 0) == 0) {
has_set_ect1_options_ = options.ect_1;
}
}
int ret = socket_->SendTo(pv, cb, addr);
NotifySentPacket(this, sent_packet); return ret;
}
int AsyncUDPSocket::Close() { return socket_->Close();
}
Socket::ReceiveBuffer receive_buffer(buffer_);
int len = socket_->RecvFrom(receive_buffer);
if (len < 0) { // An error here typically means we got an ICMP error in response to our // send datagram, indicating the remote address was unreachable. // When doing ICE, this kind of thing will often happen. // TODO: Do something better like forwarding the error to the user.
SocketAddress local_addr = socket_->GetLocalAddress();
RTC_LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString()
<< "] receive failed with error " << socket_->GetError(); return;
}
if (len == 0) { // Spurios wakeup. return;
}
if (!receive_buffer.arrival_time) { // Timestamp from socket is not available.
receive_buffer.arrival_time = env_.clock().CurrentTime();
} else {
Timestamp current_time = env_.clock().CurrentTime();
if (!socket_time_offset_ ||
*receive_buffer.arrival_time + *socket_time_offset_ > current_time) { // Estimate timestamp offset from first packet arrival time. // This may be wrong if packets have been buffered in the socket before we // read the first packet and `socket_time_offset_` may then have to be set // again to ensure no arrival times are set in the future.
socket_time_offset_ = current_time - *receive_buffer.arrival_time;
}
*receive_buffer.arrival_time += *socket_time_offset_;
RTC_DCHECK_LE(*receive_buffer.arrival_time, current_time);
}
NotifyPacketReceived(
ReceivedIpPacket(receive_buffer.payload, receive_buffer.source_address,
receive_buffer.arrival_time, receive_buffer.ecn));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.