Index: webkit/plugins/ppapi/ppb_transport_impl.cc |
diff --git a/webkit/plugins/ppapi/ppb_transport_impl.cc b/webkit/plugins/ppapi/ppb_transport_impl.cc |
index 55a46e85ac17ea1a4a41d627e72550dc35badadf..9e814cfa2737ed450ba8ad2c581b995f37cf22e6 100644 |
--- a/webkit/plugins/ppapi/ppb_transport_impl.cc |
+++ b/webkit/plugins/ppapi/ppb_transport_impl.cc |
@@ -4,8 +4,11 @@ |
#include "webkit/plugins/ppapi/ppb_transport_impl.h" |
+#include "base/json/json_reader.h" |
+#include "base/json/json_writer.h" |
#include "base/message_loop.h" |
#include "base/string_util.h" |
+#include "base/values.h" |
#include "net/base/io_buffer.h" |
#include "net/base/net_errors.h" |
#include "net/socket/socket.h" |
@@ -45,6 +48,122 @@ int MapNetError(int result) { |
} |
} |
+std::string FormatJson(Value* value) { |
+ std::string result; |
+ base::JSONWriter::Write(value, false, &result); |
+ return result; |
+} |
+ |
+// ParseConfig() parses JSON blob with P2P Transport |
+// configuration. Example of a valid config: |
+// { |
+// "stunServer": ["stun1.l.google.com:31323", "stun2.l.google.com:54324"], |
+// "relayServer": "relay.google.com", |
+// "relayToken": "34t34f234f12", |
+// "tcpReceiveWindow": 32768, |
+// "tcpSendWindow": 32768, |
+// }; |
+int ParseConfig(const std::string& config_str, P2PTransport::Config* config) { |
+ scoped_ptr<Value> value(base::JSONReader::Read(config_str, true)); |
+ if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) { |
+ return false; |
+ } |
+ |
+ DictionaryValue* dic_value = static_cast<DictionaryValue*>(value.get()); |
+ |
+ // Parse STUN servers list. |
+ config->stun_servers.clear(); |
+ Value* stun_server; |
+ if (dic_value->Get("stunServer", &stun_server)) { |
+ if (stun_server->IsType(Value::TYPE_LIST)) { |
+ ListValue* stun_list = static_cast<ListValue*>(stun_server); |
+ for (ListValue::iterator it = stun_list->begin(); |
+ it != stun_list->end(); ++it) { |
+ std::string server_address; |
+ if ((*it)->GetAsString(&server_address)) { |
+ config->stun_servers.push_back(server_address); |
+ } else { |
+ LOG(ERROR) << "Invalid stun server specification: " << |
+ FormatJson(*it); |
+ return false; |
+ } |
+ } |
+ } else if (stun_server->IsType(Value::TYPE_STRING)) { |
+ std::string server_address; |
+ stun_server->GetAsString(&server_address); |
+ config->stun_servers.push_back(server_address); |
+ } else { |
+ LOG(ERROR) << "Invalid stun server specification: " |
+ << FormatJson(stun_server); |
+ return false; |
+ } |
+ } |
+ |
+ // Parse Relay servers list. |
+ config->relay_servers.clear(); |
+ Value* relay_server; |
+ if (dic_value->Get("relayServer", &relay_server)) { |
+ if (relay_server->IsType(Value::TYPE_LIST)) { |
+ ListValue* relay_list = static_cast<ListValue*>(relay_server); |
+ for (ListValue::iterator it = relay_list->begin(); |
+ it != relay_list->end(); ++it) { |
+ std::string server_address; |
+ if ((*it)->GetAsString(&server_address)) { |
+ config->relay_servers.push_back(server_address); |
+ } else { |
+ LOG(ERROR) << "Invalid relay server specification: " |
+ << FormatJson(*it); |
+ return false; |
+ } |
+ } |
+ } else if (relay_server->IsType(Value::TYPE_STRING)) { |
+ std::string server_address; |
+ relay_server->GetAsString(&server_address); |
+ config->relay_servers.push_back(server_address); |
+ } else { |
+ LOG(ERROR) << "Invalid relay server specification: " |
+ << FormatJson(relay_server); |
+ return false; |
+ } |
+ } |
+ |
+ // Relay token. |
+ Value* relay_token; |
+ if (dic_value->Get("relayToken", &relay_token)) { |
+ if (!relay_token->GetAsString(&config->relay_token)) { |
+ LOG(ERROR) << "Invalid relay token: " |
+ << FormatJson(relay_token); |
+ return false; |
+ } |
+ } else { |
+ config->relay_token = ""; |
+ } |
+ |
+ Value* tcp_receive_window; |
+ if (dic_value->Get("tcpReceiveWindow", &tcp_receive_window)) { |
+ if (!tcp_receive_window->GetAsInteger(&config->tcp_receive_window)) { |
+ LOG(ERROR) << "Invalid TCP receive window value: " |
+ << FormatJson(tcp_receive_window); |
+ return false; |
+ } |
+ } else { |
+ config->tcp_receive_window = 0; |
+ } |
+ |
+ Value* tcp_send_window; |
+ if (dic_value->Get("tcpSendWindow", &tcp_send_window)) { |
+ if (!tcp_send_window->GetAsInteger(&config->tcp_send_window)) { |
+ LOG(ERROR) << "Invalid TCP send window value: " |
+ << FormatJson(tcp_send_window); |
+ return false; |
+ } |
+ } else { |
+ config->tcp_send_window = 0; |
+ } |
+ |
+ return true; |
+} |
+ |
} // namespace |
PPB_Transport_Impl::PPB_Transport_Impl(PluginInstance* instance) |
@@ -97,6 +216,14 @@ PP_Bool PPB_Transport_Impl::IsWritable() { |
return PP_FromBool(writable_); |
} |
+int32_t PPB_Transport_Impl::SetConfig(const char* config) { |
+ // SetConfig() may only be called before Connect(). |
+ if (started_) |
+ return PP_ERROR_FAILED; |
+ |
+ return ParseConfig(config, &config_) ? PP_OK : PP_ERROR_BADARGUMENT; |
+} |
+ |
int32_t PPB_Transport_Impl::Connect(PP_CompletionCallback callback) { |
if (!p2p_transport_.get()) |
return PP_ERROR_FAILED; |
@@ -108,7 +235,7 @@ int32_t PPB_Transport_Impl::Connect(PP_CompletionCallback callback) { |
P2PTransport::Protocol protocol = use_tcp_ ? |
P2PTransport::PROTOCOL_TCP : P2PTransport::PROTOCOL_UDP; |
- if (!p2p_transport_->Init(name_, protocol, "", this)) |
+ if (!p2p_transport_->Init(name_, protocol, config_, this)) |
return PP_ERROR_FAILED; |
started_ = true; |