/* * Copyright 2004 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
// The input buffer will be resized so that at least kMinimumRecvSize bytes can // be received (but it will not grow above the maximum size passed to the // constructor). staticconst size_t kMinimumRecvSize = 128;
int AsyncTCPSocketBase::SendTo(constvoid* pv,
size_t cb, const SocketAddress& addr, const rtc::PacketOptions& options) { const SocketAddress& remote_address = GetRemoteAddress(); if (addr == remote_address) return Send(pv, cb, options); // Remote address may be empty if there is a sudden network change.
RTC_DCHECK(remote_address.IsNil());
socket_->SetError(ENOTCONN); return -1;
}
int AsyncTCPSocketBase::FlushOutBuffer() {
RTC_DCHECK_GT(outbuf_.size(), 0);
rtc::ArrayView<uint8_t> view = outbuf_; int res; while (view.size() > 0) {
res = socket_->Send(view.data(), view.size()); if (res <= 0) { break;
} if (static_cast<size_t>(res) > view.size()) {
RTC_DCHECK_NOTREACHED();
res = -1; break;
}
view = view.subview(res);
} if (res > 0) { // The output buffer may have been written out over multiple partial Send(), // so reconstruct the total written length.
RTC_DCHECK_EQ(view.size(), 0);
res = outbuf_.size();
outbuf_.Clear();
} else { // There was an error when calling Send(), so there will still be data left // to send at a later point.
RTC_DCHECK_GT(view.size(), 0); // In the special case of EWOULDBLOCK, signal that we had a partial write. if (socket_->GetError() == EWOULDBLOCK) {
res = outbuf_.size() - view.size();
} if (view.size() < outbuf_.size()) {
memmove(outbuf_.data(), view.data(), view.size());
outbuf_.SetSize(view.size());
}
} return res;
}
int len = socket_->Recv(inbuf_.data() + inbuf_.size(), free_size, nullptr); if (len < 0) { // TODO(stefan): Do something better like forwarding the error to the // user. if (!socket_->IsBlocking()) {
RTC_LOG(LS_ERROR) << "Recv() returned error: " << socket_->GetError();
} break;
}
if (outbuf_.size() == 0) {
SignalReadyToSend(this);
}
}
void AsyncTCPSocketBase::OnCloseEvent(Socket* socket, int error) {
NotifyClosed(error);
}
// AsyncTCPSocket // Binds and connects `socket` and creates AsyncTCPSocket for // it. Takes ownership of `socket`. Returns null if bind() or // connect() fail (`socket` is destroyed in that case).
AsyncTCPSocket* AsyncTCPSocket::Create(Socket* socket, const SocketAddress& bind_address, const SocketAddress& remote_address) { returnnew AsyncTCPSocket(
AsyncTCPSocketBase::ConnectSocket(socket, bind_address, remote_address));
}
rtc::SocketAddress address;
rtc::Socket* new_socket = socket->Accept(&address); if (!new_socket) { // TODO(stefan): Do something better like forwarding the error // to the user.
RTC_LOG(LS_ERROR) << "TCP accept failed with error " << socket_->GetError(); return;
}
HandleIncomingConnection(new_socket);
// Prime a read event in case data is waiting.
new_socket->SignalReadEvent(new_socket);
}
void AsyncTcpListenSocket::HandleIncomingConnection(Socket* socket) {
SignalNewConnection(this, new AsyncTCPSocket(socket));
}
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.