Send a crash report when a hung process is detected.
[chromium-blink-merge.git] / native_client_sdk / src / examples / api / websocket / websocket.cc
blobbe994c5817fefd92f60974c415998f251314efa1
1 // Copyright (c) 2012 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.
5 #include <stdio.h>
6 #include <sstream>
8 #include "ppapi/cpp/completion_callback.h"
9 #include "ppapi/cpp/instance.h"
10 #include "ppapi/cpp/module.h"
11 #include "ppapi/cpp/var.h"
12 #include "ppapi/cpp/var_array_buffer.h"
13 #include "ppapi/cpp/websocket.h"
15 class WebSocketInstance : public pp::Instance {
16 public:
17 explicit WebSocketInstance(PP_Instance instance)
18 : pp::Instance(instance), websocket_(NULL) {}
19 virtual ~WebSocketInstance() {}
20 virtual void HandleMessage(const pp::Var& var_message);
22 private:
23 bool IsConnected();
25 void Open(const std::string& url);
26 void Close();
27 void SendAsBinary(const std::string& message);
28 void SendAsText(const std::string& message);
29 void Receive();
31 void OnConnectCompletion(int32_t result);
32 void OnCloseCompletion(int32_t result);
33 void OnReceiveCompletion(int32_t result);
35 static void OnConnectCompletionCallback(void* user_data, int32_t result);
36 static void OnCloseCompletionCallback(void* user_data, int32_t result);
37 static void OnReceiveCompletionCallback(void* user_data, int32_t result);
39 pp::WebSocket* websocket_;
40 pp::Var receive_var_;
43 #define MAX_TO_CONVERT 8
44 #define BYTES_PER_CHAR 4
45 #define TAIL_AND_NUL_SIZE 4
47 static std::string ArrayToString(pp::VarArrayBuffer& array) {
48 char tmp[MAX_TO_CONVERT * BYTES_PER_CHAR + TAIL_AND_NUL_SIZE];
49 uint32_t offs = 0;
50 uint8_t* data = static_cast<uint8_t*>(array.Map());
52 for (offs = 0; offs < array.ByteLength() && offs < MAX_TO_CONVERT; offs++)
53 sprintf(&tmp[offs * BYTES_PER_CHAR], "%02Xh ", data[offs]);
55 sprintf(&tmp[offs * BYTES_PER_CHAR], "...");
56 array.Unmap();
57 return std::string(tmp);
60 void WebSocketInstance::HandleMessage(const pp::Var& var_message) {
61 if (!var_message.is_string())
62 return;
63 std::string message = var_message.AsString();
64 // This message must contain a command character followed by ';' and
65 // arguments like "X;arguments".
66 if (message.length() < 2 || message[1] != ';')
67 return;
68 switch (message[0]) {
69 case 'o':
70 // The command 'o' requests to open the specified URL.
71 // URL is passed as an argument like "o;URL".
72 Open(message.substr(2));
73 break;
74 case 'c':
75 // The command 'c' requests to close without any argument like "c;"
76 Close();
77 break;
78 case 'b':
79 // The command 'b' requests to send a message as a binary frame. The
80 // message is passed as an argument like "b;message".
81 SendAsBinary(message.substr(2));
82 break;
83 case 't':
84 // The command 't' requests to send a message as a text frame. The message
85 // is passed as an argument like "t;message".
86 SendAsText(message.substr(2));
87 break;
91 bool WebSocketInstance::IsConnected() {
92 if (!websocket_)
93 return false;
94 if (websocket_->GetReadyState() != PP_WEBSOCKETREADYSTATE_OPEN)
95 return false;
96 return true;
99 void WebSocketInstance::Open(const std::string& url) {
100 pp::CompletionCallback callback(OnConnectCompletionCallback, this);
101 websocket_ = new pp::WebSocket(this);
102 if (!websocket_)
103 return;
104 websocket_->Connect(pp::Var(url), NULL, 0, callback);
105 PostMessage(pp::Var("connecting..."));
108 void WebSocketInstance::Close() {
109 if (!IsConnected())
110 return;
111 pp::CompletionCallback callback(OnCloseCompletionCallback, this);
112 websocket_->Close(
113 PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var("bye"), callback);
116 void WebSocketInstance::SendAsBinary(const std::string& message) {
117 if (!IsConnected())
118 return;
119 uint32_t size = message.size();
120 pp::VarArrayBuffer array_buffer(size);
121 char* data = static_cast<char*>(array_buffer.Map());
122 for (uint32_t i = 0; i < size; ++i)
123 data[i] = message[i];
124 array_buffer.Unmap();
125 websocket_->SendMessage(array_buffer);
126 std::string message_text = ArrayToString(array_buffer);
127 PostMessage(pp::Var("send (binary): " + message_text));
130 void WebSocketInstance::SendAsText(const std::string& message) {
131 if (!IsConnected())
132 return;
133 websocket_->SendMessage(pp::Var(message));
134 PostMessage(pp::Var("send (text): " + message));
137 void WebSocketInstance::Receive() {
138 pp::CompletionCallback callback(OnReceiveCompletionCallback, this);
139 // |receive_var_| must be valid until |callback| is invoked.
140 // Just use a member variable.
141 websocket_->ReceiveMessage(&receive_var_, callback);
144 void WebSocketInstance::OnConnectCompletion(int32_t result) {
145 if (result != PP_OK) {
146 PostMessage(pp::Var("connection failed"));
147 return;
149 PostMessage(pp::Var("connected"));
150 Receive();
153 void WebSocketInstance::OnCloseCompletion(int32_t result) {
154 PostMessage(pp::Var(PP_OK == result ? "closed" : "abnormally closed"));
157 void WebSocketInstance::OnReceiveCompletion(int32_t result) {
158 if (result == PP_OK) {
159 if (receive_var_.is_array_buffer()) {
160 pp::VarArrayBuffer array_buffer(receive_var_);
161 std::string message_text = ArrayToString(array_buffer);
162 PostMessage("receive (binary): " + message_text);
164 else {
165 PostMessage("receive (text): " + receive_var_.AsString());
168 Receive();
171 void WebSocketInstance::OnConnectCompletionCallback(void* user_data,
172 int32_t result) {
173 WebSocketInstance* instance = static_cast<WebSocketInstance*>(user_data);
174 instance->OnConnectCompletion(result);
177 void WebSocketInstance::OnCloseCompletionCallback(void* user_data,
178 int32_t result) {
179 WebSocketInstance* instance = static_cast<WebSocketInstance*>(user_data);
180 instance->OnCloseCompletion(result);
183 void WebSocketInstance::OnReceiveCompletionCallback(void* user_data,
184 int32_t result) {
185 WebSocketInstance* instance = static_cast<WebSocketInstance*>(user_data);
186 instance->OnReceiveCompletion(result);
189 // The WebSocketModule provides an implementation of pp::Module that creates
190 // WebSocketInstance objects when invoked.
191 class WebSocketModule : public pp::Module {
192 public:
193 WebSocketModule() : pp::Module() {}
194 virtual ~WebSocketModule() {}
196 virtual pp::Instance* CreateInstance(PP_Instance instance) {
197 return new WebSocketInstance(instance);
201 // Implement the required pp::CreateModule function that creates our specific
202 // kind of Module.
203 namespace pp {
204 Module* CreateModule() { return new WebSocketModule(); }
205 } // namespace pp