This source file includes following definitions.
- websocket_
 
- ArrayToString
 
- HandleMessage
 
- IsConnected
 
- Open
 
- Close
 
- SendAsBinary
 
- SendAsText
 
- Receive
 
- OnConnectCompletion
 
- OnCloseCompletion
 
- OnReceiveCompletion
 
- OnConnectCompletionCallback
 
- OnCloseCompletionCallback
 
- OnReceiveCompletionCallback
 
- CreateInstance
 
- CreateModule
 
#include <stdio.h>
#include <sstream>
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/cpp/websocket.h"
class WebSocketInstance : public pp::Instance {
 public:
  explicit WebSocketInstance(PP_Instance instance)
      : pp::Instance(instance), websocket_(NULL) {}
  virtual ~WebSocketInstance() {}
  virtual void HandleMessage(const pp::Var& var_message);
 private:
  bool IsConnected();
  void Open(const std::string& url);
  void Close();
  void SendAsBinary(const std::string& message);
  void SendAsText(const std::string& message);
  void Receive();
  void OnConnectCompletion(int32_t result);
  void OnCloseCompletion(int32_t result);
  void OnReceiveCompletion(int32_t result);
  static void OnConnectCompletionCallback(void* user_data, int32_t result);
  static void OnCloseCompletionCallback(void* user_data, int32_t result);
  static void OnReceiveCompletionCallback(void* user_data, int32_t result);
  pp::WebSocket* websocket_;
  pp::Var receive_var_;
};
#define MAX_TO_CONVERT 8
#define BYTES_PER_CHAR 4
#define TAIL_AND_NUL_SIZE 4
static std::string ArrayToString(pp::VarArrayBuffer& array) {
  char tmp[MAX_TO_CONVERT * BYTES_PER_CHAR + TAIL_AND_NUL_SIZE];
  uint32_t offs = 0;
  uint8_t* data = static_cast<uint8_t*>(array.Map());
  for (offs = 0; offs < array.ByteLength() && offs < MAX_TO_CONVERT; offs++)
    sprintf(&tmp[offs * BYTES_PER_CHAR], "%02Xh ", data[offs]);
  sprintf(&tmp[offs * BYTES_PER_CHAR], "...");
  array.Unmap();
  return std::string(tmp);
}
void WebSocketInstance::HandleMessage(const pp::Var& var_message) {
  if (!var_message.is_string())
    return;
  std::string message = var_message.AsString();
  
  
  if (message.length() < 2 || message[1] != ';')
    return;
  switch (message[0]) {
    case 'o':
      
      
      Open(message.substr(2));
      break;
    case 'c':
      
      Close();
      break;
    case 'b':
      
      
      SendAsBinary(message.substr(2));
      break;
    case 't':
      
      
      SendAsText(message.substr(2));
      break;
  }
}
bool WebSocketInstance::IsConnected() {
  if (!websocket_)
    return false;
  if (websocket_->GetReadyState() != PP_WEBSOCKETREADYSTATE_OPEN)
    return false;
  return true;
}
void WebSocketInstance::Open(const std::string& url) {
  pp::CompletionCallback callback(OnConnectCompletionCallback, this);
  websocket_ = new pp::WebSocket(this);
  if (!websocket_)
    return;
  websocket_->Connect(pp::Var(url), NULL, 0, callback);
  PostMessage(pp::Var("connecting..."));
}
void WebSocketInstance::Close() {
  if (!IsConnected())
    return;
  pp::CompletionCallback callback(OnCloseCompletionCallback, this);
  websocket_->Close(
      PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, pp::Var("bye"), callback);
}
void WebSocketInstance::SendAsBinary(const std::string& message) {
  if (!IsConnected())
    return;
  uint32_t size = message.size();
  pp::VarArrayBuffer array_buffer(size);
  char* data = static_cast<char*>(array_buffer.Map());
  for (uint32_t i = 0; i < size; ++i)
    data[i] = message[i];
  array_buffer.Unmap();
  websocket_->SendMessage(array_buffer);
  std::string message_text = ArrayToString(array_buffer);
  PostMessage(pp::Var("send (binary): " + message_text));
}
void WebSocketInstance::SendAsText(const std::string& message) {
  if (!IsConnected())
    return;
  websocket_->SendMessage(pp::Var(message));
  PostMessage(pp::Var("send (text): " + message));
}
void WebSocketInstance::Receive() {
  pp::CompletionCallback callback(OnReceiveCompletionCallback, this);
  
  
  websocket_->ReceiveMessage(&receive_var_, callback);
}
void WebSocketInstance::OnConnectCompletion(int32_t result) {
  if (result != PP_OK) {
    PostMessage(pp::Var("connection failed"));
    return;
  }
  PostMessage(pp::Var("connected"));
  Receive();
}
void WebSocketInstance::OnCloseCompletion(int32_t result) {
  PostMessage(pp::Var(PP_OK == result ? "closed" : "abnormally closed"));
}
void WebSocketInstance::OnReceiveCompletion(int32_t result) {
  if (result == PP_OK) {
    if (receive_var_.is_array_buffer()) {
      pp::VarArrayBuffer array_buffer(receive_var_);
      std::string message_text = ArrayToString(array_buffer);
      PostMessage("receive (binary): " + message_text);
    }
    else {
      PostMessage("receive (text): " + receive_var_.AsString());
    }
  }
  Receive();
}
void WebSocketInstance::OnConnectCompletionCallback(void* user_data,
                                                    int32_t result) {
  WebSocketInstance* instance = static_cast<WebSocketInstance*>(user_data);
  instance->OnConnectCompletion(result);
}
void WebSocketInstance::OnCloseCompletionCallback(void* user_data,
                                                  int32_t result) {
  WebSocketInstance* instance = static_cast<WebSocketInstance*>(user_data);
  instance->OnCloseCompletion(result);
}
void WebSocketInstance::OnReceiveCompletionCallback(void* user_data,
                                                    int32_t result) {
  WebSocketInstance* instance = static_cast<WebSocketInstance*>(user_data);
  instance->OnReceiveCompletion(result);
}
class WebSocketModule : public pp::Module {
 public:
  WebSocketModule() : pp::Module() {}
  virtual ~WebSocketModule() {}
  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new WebSocketInstance(instance);
  }
};
namespace pp {
Module* CreateModule() { return new WebSocketModule(); }
}