1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file. 4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <stdio.h> 6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <string.h> 7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <sstream> 8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "echo_server.h" 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/host_resolver.h" 12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/instance.h" 13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/module.h" 14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/tcp_socket.h" 15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/udp_socket.h" 16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/var.h" 17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h" 18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#ifdef WIN32 20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#undef PostMessage 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Allow 'this' in initializer list 22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#pragma warning(disable : 4355) 23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class ExampleInstance : public pp::Instance { 26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public: 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) explicit ExampleInstance(PP_Instance instance) 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) : pp::Instance(instance), 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_factory_(this), 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) send_outstanding_(false), 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) echo_server_(NULL) {} 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual ~ExampleInstance() { 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delete echo_server_; 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual void HandleMessage(const pp::Var& var_message); 38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private: 40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool IsConnected(); 41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool IsUDP(); 42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Connect(const std::string& host, bool tcp); 44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Close(); 45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Send(const std::string& message); 46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void Receive(); 47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnConnectCompletion(int32_t result); 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnResolveCompletion(int32_t result); 50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnReceiveCompletion(int32_t result); 51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnReceiveFromCompletion(int32_t result, pp::NetAddress source); 52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnSendCompletion(int32_t result); 53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::CompletionCallbackFactory<ExampleInstance> callback_factory_; 55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::TCPSocket tcp_socket_; 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::UDPSocket udp_socket_; 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::HostResolver resolver_; 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::NetAddress remote_host_; 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) char receive_buffer_[kBufferSize]; 61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool send_outstanding_; 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EchoServer* echo_server_; 63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}; 64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#define MSG_CREATE_TCP 't' 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#define MSG_CREATE_UDP 'u' 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#define MSG_SEND 's' 68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#define MSG_CLOSE 'c' 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define MSG_LISTEN 'l' 70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::HandleMessage(const pp::Var& var_message) { 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!var_message.is_string()) 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::string message = var_message.AsString(); 75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // This message must contain a command character followed by ';' and 76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // arguments like "X;arguments". 77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (message.length() < 2 || message[1] != ';') 78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) switch (message[0]) { 80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case MSG_CREATE_UDP: 81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // The command 'b' requests to create a UDP connection the 82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // specified HOST. 83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // HOST is passed as an argument like "t;HOST". 84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Connect(message.substr(2), false); 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case MSG_CREATE_TCP: 87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // The command 'o' requests to connect to the specified HOST. 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // HOST is passed as an argument like "u;HOST". 89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Connect(message.substr(2), true); 90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case MSG_CLOSE: 92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // The command 'c' requests to close without any argument like "c;" 93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Close(); 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case MSG_LISTEN: 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) { 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The command 'l' starts a listening socket (server). 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int port = atoi(message.substr(2).c_str()); 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) echo_server_ = new EchoServer(this, port); 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) case MSG_SEND: 103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // The command 't' requests to send a message as a text frame. The 104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // message passed as an argument like "t;message". 105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Send(message.substr(2)); 106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::ostringstream status; 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status << "Unhandled message from JavaScript: " << message; 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PostMessage(status.str()); 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool ExampleInstance::IsConnected() { 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!tcp_socket_.is_null()) 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!udp_socket_.is_null()) 119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return true; 120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return false; 122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool ExampleInstance::IsUDP() { 125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return !udp_socket_.is_null(); 126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::Connect(const std::string& host, bool tcp) { 129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (IsConnected()) { 130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Already connected."); 131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (tcp) { 135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!pp::TCPSocket::IsAvailable()) { 136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("TCPSocket not available"); 137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) tcp_socket_ = pp::TCPSocket(this); 141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (tcp_socket_.is_null()) { 142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Error creating TCPSocket."); 143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!pp::UDPSocket::IsAvailable()) { 147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("UDPSocket not available"); 148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) udp_socket_ = pp::UDPSocket(this); 152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (udp_socket_.is_null()) { 153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Error creating UDPSocket."); 154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!pp::HostResolver::IsAvailable()) { 159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("HostResolver not available"); 160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) resolver_ = pp::HostResolver(this); 164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (resolver_.is_null()) { 165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Error creating HostResolver."); 166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int port = 80; 170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::string hostname = host; 171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) size_t pos = host.rfind(':'); 172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (pos != std::string::npos) { 173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) hostname = host.substr(0, pos); 174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) port = atoi(host.substr(pos+1).c_str()); 175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::CompletionCallback callback = 178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_factory_.NewCallback(&ExampleInstance::OnResolveCompletion); 179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PP_HostResolver_Hint hint = { PP_NETADDRESS_FAMILY_UNSPECIFIED, 0 }; 180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) resolver_.Resolve(hostname.c_str(), port, hint, callback); 181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Resolving ..."); 182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::OnResolveCompletion(int32_t result) { 185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result != PP_OK) { 186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Resolve failed."); 187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::NetAddress addr = resolver_.GetNetAddress(0); 191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(std::string("Resolved: ") + 192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) addr.DescribeAsString(true).AsString()); 193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::CompletionCallback callback = 195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_factory_.NewCallback(&ExampleInstance::OnConnectCompletion); 196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (IsUDP()) { 198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Binding ..."); 199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) remote_host_ = addr; 200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PP_NetAddress_IPv4 ipv4_addr = { 0, { 0 } }; 201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) udp_socket_.Bind(pp::NetAddress(this, ipv4_addr), callback); 202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Connecting ..."); 204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) tcp_socket_.Connect(addr, callback); 205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::Close() { 209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!IsConnected()) { 210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Not connected."); 211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (tcp_socket_.is_null()) { 215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) udp_socket_.Close(); 216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) udp_socket_ = pp::UDPSocket(); 217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) tcp_socket_.Close(); 219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) tcp_socket_ = pp::TCPSocket(); 220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Closed connection."); 223a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::Send(const std::string& message) { 226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!IsConnected()) { 227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Not connected."); 228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (send_outstanding_) { 232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Already sending."); 233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) uint32_t size = message.size(); 237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const char* data = message.c_str(); 2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::CompletionCallback callback = 239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_factory_.NewCallback(&ExampleInstance::OnSendCompletion); 240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int32_t result; 241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (IsUDP()) 242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result = udp_socket_.SendTo(data, size, remote_host_, callback); 243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) else 244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) result = tcp_socket_.Write(data, size, callback); 245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::ostringstream status; 246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result < 0) { 247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result == PP_OK_COMPLETIONPENDING) { 248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status << "Sending bytes: " << size; 249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(status.str()); 250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) send_outstanding_ = true; 251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status << "Send returned error: " << result; 253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(status.str()); 254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status << "Sent bytes synchronously: " << result; 257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(status.str()); 258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::Receive() { 2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) memset(receive_buffer_, 0, kBufferSize); 263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (IsUDP()) { 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::CompletionCallbackWithOutput<pp::NetAddress> callback = 265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_factory_.NewCallbackWithOutput( 266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) &ExampleInstance::OnReceiveFromCompletion); 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) udp_socket_.RecvFrom(receive_buffer_, kBufferSize, callback); 268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) pp::CompletionCallback callback = 270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_factory_.NewCallback(&ExampleInstance::OnReceiveCompletion); 2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tcp_socket_.Read(receive_buffer_, kBufferSize, callback); 272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::OnConnectCompletion(int32_t result) { 276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result != PP_OK) { 277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::ostringstream status; 278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status << "Connection failed: " << result; 279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(status.str()); 280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (IsUDP()) { 284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::NetAddress addr = udp_socket_.GetBoundAddress(); 285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(std::string("Bound to: ") + 286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) addr.DescribeAsString(true).AsString()); 287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage("Connected"); 289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Receive(); 292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::OnReceiveFromCompletion(int32_t result, 295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) pp::NetAddress source) { 296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OnReceiveCompletion(result); 297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::OnReceiveCompletion(int32_t result) { 300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result < 0) { 301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::ostringstream status; 302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status << "Receive failed with: " << result; 303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(status.str()); 304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PostMessage(std::string("Received: ") + std::string(receive_buffer_, result)); 308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Receive(); 309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExampleInstance::OnSendCompletion(int32_t result) { 312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::ostringstream status; 313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (result < 0) { 314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status << "Send failed with: " << result; 315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) status << "Sent bytes: " << result; 317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) send_outstanding_ = false; 319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PostMessage(status.str()); 320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// The ExampleModule provides an implementation of pp::Module that creates 323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// ExampleInstance objects when invoked. 324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class ExampleModule : public pp::Module { 325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public: 326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ExampleModule() : pp::Module() {} 327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual ~ExampleModule() {} 328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual pp::Instance* CreateInstance(PP_Instance instance) { 330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return new ExampleInstance(instance); 331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}; 333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Implement the required pp::CreateModule function that creates our specific 335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// kind of Module. 336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace pp { 337a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Module* CreateModule() { return new ExampleModule(); } 338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} // namespace pp 339