OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/net/udp_transport.h" | 5 #include "media/cast/net/udp_transport.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 weak_factory_(this) { | 59 weak_factory_(this) { |
60 DCHECK(!IsEmpty(local_end_point) || !IsEmpty(remote_end_point)); | 60 DCHECK(!IsEmpty(local_end_point) || !IsEmpty(remote_end_point)); |
61 } | 61 } |
62 | 62 |
63 UdpTransport::~UdpTransport() {} | 63 UdpTransport::~UdpTransport() {} |
64 | 64 |
65 void UdpTransport::StartReceiving( | 65 void UdpTransport::StartReceiving( |
66 const PacketReceiverCallbackWithStatus& packet_receiver) { | 66 const PacketReceiverCallbackWithStatus& packet_receiver) { |
67 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); | 67 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); |
68 | 68 |
| 69 if (!udp_socket_) { |
| 70 status_callback_.Run(TRANSPORT_SOCKET_ERROR); |
| 71 return; |
| 72 } |
| 73 |
69 packet_receiver_ = packet_receiver; | 74 packet_receiver_ = packet_receiver; |
70 udp_socket_->SetMulticastLoopbackMode(true); | 75 udp_socket_->SetMulticastLoopbackMode(true); |
71 if (!IsEmpty(local_addr_)) { | 76 if (!IsEmpty(local_addr_)) { |
72 if (udp_socket_->Open(local_addr_.GetFamily()) < 0 || | 77 if (udp_socket_->Open(local_addr_.GetFamily()) < 0 || |
73 udp_socket_->AllowAddressReuse() < 0 || | 78 udp_socket_->AllowAddressReuse() < 0 || |
74 udp_socket_->Bind(local_addr_) < 0) { | 79 udp_socket_->Bind(local_addr_) < 0) { |
75 udp_socket_->Close(); | 80 udp_socket_->Close(); |
| 81 udp_socket_.reset(); |
76 status_callback_.Run(TRANSPORT_SOCKET_ERROR); | 82 status_callback_.Run(TRANSPORT_SOCKET_ERROR); |
77 LOG(ERROR) << "Failed to bind local address."; | 83 LOG(ERROR) << "Failed to bind local address."; |
78 return; | 84 return; |
79 } | 85 } |
80 } else if (!IsEmpty(remote_addr_)) { | 86 } else if (!IsEmpty(remote_addr_)) { |
81 if (udp_socket_->Open(remote_addr_.GetFamily()) < 0 || | 87 if (udp_socket_->Open(remote_addr_.GetFamily()) < 0 || |
82 udp_socket_->AllowAddressReuse() < 0 || | 88 udp_socket_->AllowAddressReuse() < 0 || |
83 udp_socket_->Connect(remote_addr_) < 0) { | 89 udp_socket_->Connect(remote_addr_) < 0) { |
84 udp_socket_->Close(); | 90 udp_socket_->Close(); |
| 91 udp_socket_.reset(); |
85 status_callback_.Run(TRANSPORT_SOCKET_ERROR); | 92 status_callback_.Run(TRANSPORT_SOCKET_ERROR); |
86 LOG(ERROR) << "Failed to connect to remote address."; | 93 LOG(ERROR) << "Failed to connect to remote address."; |
87 return; | 94 return; |
88 } | 95 } |
89 client_connected_ = true; | 96 client_connected_ = true; |
90 } else { | 97 } else { |
91 NOTREACHED() << "Either local or remote address has to be defined."; | 98 NOTREACHED() << "Either local or remote address has to be defined."; |
92 } | 99 } |
93 if (udp_socket_->SetSendBufferSize(send_buffer_size_) != net::OK) { | 100 if (udp_socket_->SetSendBufferSize(send_buffer_size_) != net::OK) { |
94 LOG(WARNING) << "Failed to set socket send buffer size."; | 101 LOG(WARNING) << "Failed to set socket send buffer size."; |
95 } | 102 } |
96 | 103 |
97 ScheduleReceiveNextPacket(); | 104 ScheduleReceiveNextPacket(); |
98 } | 105 } |
99 | 106 |
100 void UdpTransport::StopReceiving() { | 107 void UdpTransport::StopReceiving() { |
101 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); | 108 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); |
102 packet_receiver_ = PacketReceiverCallbackWithStatus(); | 109 packet_receiver_ = PacketReceiverCallbackWithStatus(); |
103 } | 110 } |
104 | 111 |
105 | 112 |
106 void UdpTransport::SetDscp(net::DiffServCodePoint dscp) { | 113 void UdpTransport::SetDscp(net::DiffServCodePoint dscp) { |
107 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); | 114 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); |
108 next_dscp_value_ = dscp; | 115 next_dscp_value_ = dscp; |
109 } | 116 } |
110 | 117 |
111 #if defined(OS_WIN) | 118 #if defined(OS_WIN) |
112 void UdpTransport::UseNonBlockingIO() { | 119 void UdpTransport::UseNonBlockingIO() { |
113 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); | 120 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); |
| 121 if (!udp_socket_) |
| 122 return; |
114 udp_socket_->UseNonBlockingIO(); | 123 udp_socket_->UseNonBlockingIO(); |
115 } | 124 } |
116 #endif | 125 #endif |
117 | 126 |
118 void UdpTransport::ScheduleReceiveNextPacket() { | 127 void UdpTransport::ScheduleReceiveNextPacket() { |
119 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); | 128 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); |
120 if (!packet_receiver_.is_null() && !receive_pending_) { | 129 if (!packet_receiver_.is_null() && !receive_pending_) { |
121 receive_pending_ = true; | 130 receive_pending_ = true; |
122 io_thread_proxy_->PostTask(FROM_HERE, | 131 io_thread_proxy_->PostTask(FROM_HERE, |
123 base::Bind(&UdpTransport::ReceiveNextPacket, | 132 base::Bind(&UdpTransport::ReceiveNextPacket, |
124 weak_factory_.GetWeakPtr(), | 133 weak_factory_.GetWeakPtr(), |
125 net::ERR_IO_PENDING)); | 134 net::ERR_IO_PENDING)); |
126 } | 135 } |
127 } | 136 } |
128 | 137 |
129 void UdpTransport::ReceiveNextPacket(int length_or_status) { | 138 void UdpTransport::ReceiveNextPacket(int length_or_status) { |
130 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); | 139 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); |
131 | 140 |
132 if (packet_receiver_.is_null()) | 141 if (packet_receiver_.is_null()) |
133 return; | 142 return; |
| 143 if (!udp_socket_) |
| 144 return; |
134 | 145 |
135 // Loop while UdpSocket is delivering data synchronously. When it responds | 146 // Loop while UdpSocket is delivering data synchronously. When it responds |
136 // with a "pending" status, break and expect this method to be called back in | 147 // with a "pending" status, break and expect this method to be called back in |
137 // the future when a packet is ready. | 148 // the future when a packet is ready. |
138 while (true) { | 149 while (true) { |
139 if (length_or_status == net::ERR_IO_PENDING) { | 150 if (length_or_status == net::ERR_IO_PENDING) { |
140 next_packet_.reset(new Packet(kMaxPacketSize)); | 151 next_packet_.reset(new Packet(kMaxPacketSize)); |
141 recv_buf_ = new net::WrappedIOBuffer( | 152 recv_buf_ = new net::WrappedIOBuffer( |
142 reinterpret_cast<char*>(&next_packet_->front())); | 153 reinterpret_cast<char*>(&next_packet_->front())); |
143 length_or_status = | 154 length_or_status = |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } else { | 191 } else { |
181 next_packet_->resize(length_or_status); | 192 next_packet_->resize(length_or_status); |
182 packet_receiver_.Run(next_packet_.Pass()); | 193 packet_receiver_.Run(next_packet_.Pass()); |
183 } | 194 } |
184 length_or_status = net::ERR_IO_PENDING; | 195 length_or_status = net::ERR_IO_PENDING; |
185 } | 196 } |
186 } | 197 } |
187 | 198 |
188 bool UdpTransport::SendPacket(PacketRef packet, const base::Closure& cb) { | 199 bool UdpTransport::SendPacket(PacketRef packet, const base::Closure& cb) { |
189 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); | 200 DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread()); |
| 201 if (!udp_socket_) |
| 202 return true; |
190 | 203 |
191 // Increase byte count no matter the packet was sent or dropped. | 204 // Increase byte count no matter the packet was sent or dropped. |
192 bytes_sent_ += packet->data.size(); | 205 bytes_sent_ += packet->data.size(); |
193 | 206 |
194 DCHECK(!send_pending_); | 207 DCHECK(!send_pending_); |
195 if (send_pending_) { | 208 if (send_pending_) { |
196 VLOG(1) << "Cannot send because of pending IO."; | 209 VLOG(1) << "Cannot send because of pending IO."; |
197 return true; | 210 return true; |
198 } | 211 } |
199 | 212 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 } | 273 } |
261 ScheduleReceiveNextPacket(); | 274 ScheduleReceiveNextPacket(); |
262 | 275 |
263 if (!cb.is_null()) { | 276 if (!cb.is_null()) { |
264 cb.Run(); | 277 cb.Run(); |
265 } | 278 } |
266 } | 279 } |
267 | 280 |
268 } // namespace cast | 281 } // namespace cast |
269 } // namespace media | 282 } // namespace media |
OLD | NEW |