OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "remoting/protocol/pepper_p2p_channel.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "net/base/io_buffer.h" | |
9 #include "net/base/net_errors.h" | |
10 #include "ppapi/c/pp_errors.h" | |
11 #include "ppapi/cpp/dev/transport_dev.h" | |
12 #include "ppapi/cpp/var.h" | |
13 | |
14 namespace remoting { | |
15 namespace protocol { | |
16 | |
17 namespace { | |
18 | |
19 const char kPepperTransportUdpProtocol[] = "udp"; | |
20 | |
21 // Maps value returned by Recv() and Send() Pepper methods to net::Error. | |
22 int PPErrorToNetError(int result) { | |
23 if (result > 0) | |
24 return result; | |
25 | |
26 switch (result) { | |
27 case PP_OK: | |
28 return net::OK; | |
29 case PP_OK_COMPLETIONPENDING: | |
30 return net::ERR_IO_PENDING; | |
31 default: | |
32 return net::ERR_FAILED; | |
33 } | |
34 } | |
35 | |
36 } // namespace | |
37 | |
38 PepperP2PChannel::PepperP2PChannel( | |
39 pp::Instance* pp_instance, | |
40 const char* name, | |
41 const IncomingCandidateCallback& candidate_callback) | |
42 : candidate_callback_(candidate_callback), | |
43 get_address_pending_(false), | |
44 read_callback_(NULL), | |
45 write_callback_(NULL) { | |
46 transport_.reset( | |
47 new pp::Transport_Dev(pp_instance, name, kPepperTransportUdpProtocol)); | |
48 } | |
49 | |
50 bool PepperP2PChannel::Init() { | |
51 // This will return false when the GetNextAddress() returns an | |
52 // error. Particularly it is useful to detect when the P2P Transport | |
53 // API is not supported. | |
54 return ProcessCandidates(); | |
55 } | |
56 | |
57 PepperP2PChannel::~PepperP2PChannel() { | |
58 } | |
59 | |
60 void PepperP2PChannel::AddRemoteCandidate(const std::string& candidate) { | |
61 DCHECK(CalledOnValidThread()); | |
62 transport_->ReceiveRemoteAddress(candidate); | |
63 } | |
64 | |
65 int PepperP2PChannel::Read(net::IOBuffer* buf, int buf_len, | |
66 net::CompletionCallback* callback) { | |
67 DCHECK(CalledOnValidThread()); | |
68 DCHECK(!read_callback_); | |
69 DCHECK(!read_buffer_); | |
70 | |
71 int result = PPErrorToNetError(transport_->Recv( | |
72 buf->data(), buf_len, | |
73 pp::CompletionCallback(&PepperP2PChannel::ReadCallback, this))); | |
74 | |
75 if (result == net::ERR_IO_PENDING) { | |
76 read_callback_ = callback; | |
77 read_buffer_ = buf; | |
78 } | |
79 | |
80 return result; | |
81 } | |
82 | |
83 int PepperP2PChannel::Write(net::IOBuffer* buf, int buf_len, | |
84 net::CompletionCallback* callback) { | |
85 DCHECK(CalledOnValidThread()); | |
86 DCHECK(!write_callback_); | |
87 DCHECK(!write_buffer_); | |
88 | |
89 int result = PPErrorToNetError(transport_->Send( | |
90 buf->data(), buf_len, | |
91 pp::CompletionCallback(&PepperP2PChannel::WriteCallback, this))); | |
92 | |
93 if (result == net::ERR_IO_PENDING) { | |
94 write_callback_ = callback; | |
95 write_buffer_ = buf; | |
96 } | |
97 | |
98 return result; | |
99 } | |
100 | |
101 bool PepperP2PChannel::SetReceiveBufferSize(int32 size) { | |
102 DCHECK(CalledOnValidThread()); | |
103 NOTIMPLEMENTED(); | |
104 return false; | |
105 } | |
106 | |
107 bool PepperP2PChannel::SetSendBufferSize(int32 size) { | |
108 DCHECK(CalledOnValidThread()); | |
109 NOTIMPLEMENTED(); | |
110 return false; | |
111 } | |
112 | |
113 bool PepperP2PChannel::ProcessCandidates() { | |
114 DCHECK(CalledOnValidThread()); | |
115 DCHECK(!get_address_pending_); | |
116 | |
117 while (true) { | |
118 pp::Var address; | |
119 int result = transport_->GetNextAddress( | |
120 &address, | |
121 pp::CompletionCallback(&PepperP2PChannel::NextAddressCallback, this)); | |
122 if (result == PP_OK_COMPLETIONPENDING) { | |
123 get_address_pending_ = true; | |
124 break; | |
125 } | |
126 | |
127 if (result == PP_OK) { | |
128 candidate_callback_.Run(address.AsString()); | |
129 } else { | |
130 LOG(ERROR) << "GetNextAddress() returned an error " << result; | |
131 return false; | |
132 } | |
133 } | |
134 return true; | |
135 } | |
136 | |
137 // static | |
138 void PepperP2PChannel::NextAddressCallback(void* data, int32_t result) { | |
139 PepperP2PChannel* channel = reinterpret_cast<PepperP2PChannel*>(data); | |
140 DCHECK(channel->CalledOnValidThread()); | |
141 channel->get_address_pending_ = false; | |
142 channel->ProcessCandidates(); | |
143 } | |
144 | |
145 // static | |
146 void PepperP2PChannel::ReadCallback(void* data, int32_t result) { | |
147 PepperP2PChannel* channel = reinterpret_cast<PepperP2PChannel*>(data); | |
148 DCHECK(channel->CalledOnValidThread()); | |
149 DCHECK(channel->read_callback_); | |
150 DCHECK(channel->read_buffer_); | |
151 net::CompletionCallback* callback = channel->read_callback_; | |
152 channel->read_callback_ = NULL; | |
153 channel->read_buffer_ = NULL; | |
154 callback->Run(result); | |
155 } | |
156 | |
157 // static | |
158 void PepperP2PChannel::WriteCallback(void* data, int32_t result) { | |
159 PepperP2PChannel* channel = reinterpret_cast<PepperP2PChannel*>(data); | |
160 DCHECK(channel->CalledOnValidThread()); | |
161 DCHECK(channel->write_callback_); | |
162 DCHECK(channel->write_buffer_); | |
163 net::CompletionCallback* callback = channel->write_callback_; | |
164 channel->write_callback_ = NULL; | |
165 channel->write_buffer_ = NULL; | |
166 callback->Run(result); | |
167 } | |
168 | |
169 } // namespace protocol | |
170 } // namespace remoting | |
OLD | NEW |