OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 "webkit/plugins/ppapi/ppb_transport_impl.h" | 5 #include "webkit/plugins/ppapi/ppb_transport_impl.h" |
6 | 6 |
| 7 #include "base/json/json_reader.h" |
| 8 #include "base/json/json_writer.h" |
7 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
8 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "base/values.h" |
9 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
10 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
11 #include "net/socket/socket.h" | 14 #include "net/socket/socket.h" |
12 #include "ppapi/c/dev/ppb_transport_dev.h" | 15 #include "ppapi/c/dev/ppb_transport_dev.h" |
13 #include "ppapi/c/pp_completion_callback.h" | 16 #include "ppapi/c/pp_completion_callback.h" |
14 #include "ppapi/c/pp_errors.h" | 17 #include "ppapi/c/pp_errors.h" |
15 #include "ppapi/shared_impl/var.h" | 18 #include "ppapi/shared_impl/var.h" |
16 #include "webkit/plugins/ppapi/common.h" | 19 #include "webkit/plugins/ppapi/common.h" |
17 #include "webkit/plugins/ppapi/plugin_module.h" | 20 #include "webkit/plugins/ppapi/plugin_module.h" |
18 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 21 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
(...skipping 19 matching lines...) Expand all Loading... |
38 return PP_OK; | 41 return PP_OK; |
39 case net::ERR_IO_PENDING: | 42 case net::ERR_IO_PENDING: |
40 return PP_OK_COMPLETIONPENDING; | 43 return PP_OK_COMPLETIONPENDING; |
41 case net::ERR_INVALID_ARGUMENT: | 44 case net::ERR_INVALID_ARGUMENT: |
42 return PP_ERROR_BADARGUMENT; | 45 return PP_ERROR_BADARGUMENT; |
43 default: | 46 default: |
44 return PP_ERROR_FAILED; | 47 return PP_ERROR_FAILED; |
45 } | 48 } |
46 } | 49 } |
47 | 50 |
| 51 std::string FormatJson(Value* value) { |
| 52 std::string result; |
| 53 base::JSONWriter::Write(value, false, &result); |
| 54 return result; |
| 55 } |
| 56 |
| 57 // ParseConfig() parses JSON blob with P2P Transport |
| 58 // configuration. Example of a valid config: |
| 59 // { |
| 60 // "stunServer": ["stun1.l.google.com:31323", "stun2.l.google.com:54324"], |
| 61 // "relayServer": "relay.google.com", |
| 62 // "relayToken": "34t34f234f12", |
| 63 // "tcpReceiveWindow": 32768, |
| 64 // "tcpSendWindow": 32768, |
| 65 // }; |
| 66 int ParseConfig(const std::string& config_str, P2PTransport::Config* config) { |
| 67 scoped_ptr<Value> value(base::JSONReader::Read(config_str, true)); |
| 68 if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) { |
| 69 return false; |
| 70 } |
| 71 |
| 72 DictionaryValue* dic_value = static_cast<DictionaryValue*>(value.get()); |
| 73 |
| 74 // Parse STUN servers list. |
| 75 config->stun_servers.clear(); |
| 76 Value* stun_server; |
| 77 if (dic_value->Get("stunServer", &stun_server)) { |
| 78 if (stun_server->IsType(Value::TYPE_LIST)) { |
| 79 ListValue* stun_list = static_cast<ListValue*>(stun_server); |
| 80 for (ListValue::iterator it = stun_list->begin(); |
| 81 it != stun_list->end(); ++it) { |
| 82 std::string server_address; |
| 83 if ((*it)->GetAsString(&server_address)) { |
| 84 config->stun_servers.push_back(server_address); |
| 85 } else { |
| 86 LOG(ERROR) << "Invalid stun server specification: " << |
| 87 FormatJson(*it); |
| 88 return false; |
| 89 } |
| 90 } |
| 91 } else if (stun_server->IsType(Value::TYPE_STRING)) { |
| 92 std::string server_address; |
| 93 stun_server->GetAsString(&server_address); |
| 94 config->stun_servers.push_back(server_address); |
| 95 } else { |
| 96 LOG(ERROR) << "Invalid stun server specification: " |
| 97 << FormatJson(stun_server); |
| 98 return false; |
| 99 } |
| 100 } |
| 101 |
| 102 // Parse Relay servers list. |
| 103 config->relay_servers.clear(); |
| 104 Value* relay_server; |
| 105 if (dic_value->Get("relayServer", &relay_server)) { |
| 106 if (relay_server->IsType(Value::TYPE_LIST)) { |
| 107 ListValue* relay_list = static_cast<ListValue*>(relay_server); |
| 108 for (ListValue::iterator it = relay_list->begin(); |
| 109 it != relay_list->end(); ++it) { |
| 110 std::string server_address; |
| 111 if ((*it)->GetAsString(&server_address)) { |
| 112 config->relay_servers.push_back(server_address); |
| 113 } else { |
| 114 LOG(ERROR) << "Invalid relay server specification: " |
| 115 << FormatJson(*it); |
| 116 return false; |
| 117 } |
| 118 } |
| 119 } else if (relay_server->IsType(Value::TYPE_STRING)) { |
| 120 std::string server_address; |
| 121 relay_server->GetAsString(&server_address); |
| 122 config->relay_servers.push_back(server_address); |
| 123 } else { |
| 124 LOG(ERROR) << "Invalid relay server specification: " |
| 125 << FormatJson(relay_server); |
| 126 return false; |
| 127 } |
| 128 } |
| 129 |
| 130 // Relay token. |
| 131 Value* relay_token; |
| 132 if (dic_value->Get("relayToken", &relay_token)) { |
| 133 if (!relay_token->GetAsString(&config->relay_token)) { |
| 134 LOG(ERROR) << "Invalid relay token: " |
| 135 << FormatJson(relay_token); |
| 136 return false; |
| 137 } |
| 138 } else { |
| 139 config->relay_token = ""; |
| 140 } |
| 141 |
| 142 Value* tcp_receive_window; |
| 143 if (dic_value->Get("tcpReceiveWindow", &tcp_receive_window)) { |
| 144 if (!tcp_receive_window->GetAsInteger(&config->tcp_receive_window)) { |
| 145 LOG(ERROR) << "Invalid TCP receive window value: " |
| 146 << FormatJson(tcp_receive_window); |
| 147 return false; |
| 148 } |
| 149 } else { |
| 150 config->tcp_receive_window = 0; |
| 151 } |
| 152 |
| 153 Value* tcp_send_window; |
| 154 if (dic_value->Get("tcpSendWindow", &tcp_send_window)) { |
| 155 if (!tcp_send_window->GetAsInteger(&config->tcp_send_window)) { |
| 156 LOG(ERROR) << "Invalid TCP send window value: " |
| 157 << FormatJson(tcp_send_window); |
| 158 return false; |
| 159 } |
| 160 } else { |
| 161 config->tcp_send_window = 0; |
| 162 } |
| 163 |
| 164 return true; |
| 165 } |
| 166 |
48 } // namespace | 167 } // namespace |
49 | 168 |
50 PPB_Transport_Impl::PPB_Transport_Impl(PluginInstance* instance) | 169 PPB_Transport_Impl::PPB_Transport_Impl(PluginInstance* instance) |
51 : Resource(instance), | 170 : Resource(instance), |
52 started_(false), | 171 started_(false), |
53 writable_(false), | 172 writable_(false), |
54 ALLOW_THIS_IN_INITIALIZER_LIST( | 173 ALLOW_THIS_IN_INITIALIZER_LIST( |
55 channel_write_callback_(this, &PPB_Transport_Impl::OnWritten)), | 174 channel_write_callback_(this, &PPB_Transport_Impl::OnWritten)), |
56 ALLOW_THIS_IN_INITIALIZER_LIST( | 175 ALLOW_THIS_IN_INITIALIZER_LIST( |
57 channel_read_callback_(this, &PPB_Transport_Impl::OnRead)) { | 176 channel_read_callback_(this, &PPB_Transport_Impl::OnRead)) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 return p2p_transport_.get() != NULL; | 209 return p2p_transport_.get() != NULL; |
91 } | 210 } |
92 | 211 |
93 PP_Bool PPB_Transport_Impl::IsWritable() { | 212 PP_Bool PPB_Transport_Impl::IsWritable() { |
94 if (!p2p_transport_.get()) | 213 if (!p2p_transport_.get()) |
95 return PP_FALSE; | 214 return PP_FALSE; |
96 | 215 |
97 return PP_FromBool(writable_); | 216 return PP_FromBool(writable_); |
98 } | 217 } |
99 | 218 |
| 219 int32_t PPB_Transport_Impl::SetConfig(const char* config) { |
| 220 // SetConfig() may only be called before Connect(). |
| 221 if (started_) |
| 222 return PP_ERROR_FAILED; |
| 223 |
| 224 return ParseConfig(config, &config_) ? PP_OK : PP_ERROR_BADARGUMENT; |
| 225 } |
| 226 |
100 int32_t PPB_Transport_Impl::Connect(PP_CompletionCallback callback) { | 227 int32_t PPB_Transport_Impl::Connect(PP_CompletionCallback callback) { |
101 if (!p2p_transport_.get()) | 228 if (!p2p_transport_.get()) |
102 return PP_ERROR_FAILED; | 229 return PP_ERROR_FAILED; |
103 | 230 |
104 // Connect() has already been called. | 231 // Connect() has already been called. |
105 if (started_) | 232 if (started_) |
106 return PP_ERROR_INPROGRESS; | 233 return PP_ERROR_INPROGRESS; |
107 | 234 |
108 P2PTransport::Protocol protocol = use_tcp_ ? | 235 P2PTransport::Protocol protocol = use_tcp_ ? |
109 P2PTransport::PROTOCOL_TCP : P2PTransport::PROTOCOL_UDP; | 236 P2PTransport::PROTOCOL_TCP : P2PTransport::PROTOCOL_UDP; |
110 | 237 |
111 if (!p2p_transport_->Init(name_, protocol, "", this)) | 238 if (!p2p_transport_->Init(name_, protocol, config_, this)) |
112 return PP_ERROR_FAILED; | 239 return PP_ERROR_FAILED; |
113 | 240 |
114 started_ = true; | 241 started_ = true; |
115 | 242 |
116 connect_callback_ = new TrackedCompletionCallback( | 243 connect_callback_ = new TrackedCompletionCallback( |
117 instance()->module()->GetCallbackTracker(), pp_resource(), callback); | 244 instance()->module()->GetCallbackTracker(), pp_resource(), callback); |
118 return PP_OK_COMPLETIONPENDING; | 245 return PP_OK_COMPLETIONPENDING; |
119 } | 246 } |
120 | 247 |
121 int32_t PPB_Transport_Impl::GetNextAddress(PP_Var* address, | 248 int32_t PPB_Transport_Impl::GetNextAddress(PP_Var* address, |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 void PPB_Transport_Impl::OnWritten(int result) { | 373 void PPB_Transport_Impl::OnWritten(int result) { |
247 DCHECK(send_callback_.get() && !send_callback_->completed()); | 374 DCHECK(send_callback_.get() && !send_callback_->completed()); |
248 | 375 |
249 scoped_refptr<TrackedCompletionCallback> callback; | 376 scoped_refptr<TrackedCompletionCallback> callback; |
250 callback.swap(send_callback_); | 377 callback.swap(send_callback_); |
251 callback->Run(MapNetError(result)); | 378 callback->Run(MapNetError(result)); |
252 } | 379 } |
253 | 380 |
254 } // namespace ppapi | 381 } // namespace ppapi |
255 } // namespace webkit | 382 } // namespace webkit |
OLD | NEW |