Native Client(NaCl)をやってみる (7) - pp::WebSocket -

2012-10-23T00:00:00+00:00 C++ HTML5 Native Client

引き続き、Native Clientのサンプル読みつつ進めてみてます。今回はpp::WebSocketを使ってWebSocketサーバーにNative Client側から接続して云々するというサンプルを読んで進めてみました

ちなみに今まで「どのバージョンのpepperを使ってるのか」っていうの書いてなかったような気がしますので、一応検証ではpepper api version22

nacl.html

<html>
  <body>
    <button id="btn1">send</button>
    <embed id="plugin" width="0" height="0" src="/sample.nmf" type="application/x-nacl" />

    <script type="text/javascript">
(function(undefined) {
  var plugin = document.querySelector("#plugin");
  plugin.addEventListener("message", function(msg) {
    var response = msg.data.split(",");

    if (response[0] == 1) {
      console.log(response[1]);
    } else {
      console.log("ERROR: " + response[1]);
    }
  });

  document.querySelector("#btn1").addEventListener("click", function() {
    // Native Client側にメッセージを送る
    plugin.postMessage("fuga");
  });
})();
    </script>
  <body>
</html>

HTMLとNative Client側はメッセージングでのみやりとりをする。WebSocket関係は全てNative Client内部で行う

sample.cc

#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/websocket.h"
#include "ppapi/utility/completion_callback_factory.h"

class WebSocketInstance : public pp::Instance {
  public:
    explicit WebSocketInstance(PP_Instance instance) : pp::Instance(instance), websocket_(NULL), callback_(this) {
    }

    virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
      pp::CompletionCallback callback = callback_.NewCallback(&WebSocketInstance::OnConnect);

      websocket_ = new pp::WebSocket(this);
      websocket_->Connect(
        pp::Var("ws://localhost:3000/echo"),
        NULL,
        0,
        callback
      );

      return true;
    }

    virtual void HandleMessage(const pp::Var &var) {
      if (!isConnected()) {
        return;
      }

      websocket_->SendMessage(var);
    }

  private:
    pp::WebSocket* websocket_;
    pp::CompletionCallbackFactory<WebSocketInstance> callback_;
    pp::Var data;

    bool isConnected() {
      if (websocket_) {
        if (websocket_->GetReadyState() == PP_WEBSOCKETREADYSTATE_OPEN) {
          return true;
        }
      }

      PostMessage(pp::Var("0,disconncted"));

      return false;
    }

    void OnConnect(int32_t result) {
      if (!isConnected() || result != PP_OK) {
        return;
      }

      Receive();
    }

    void Receive() {
      if (!isConnected()) {
        return;
      }

      pp::CompletionCallback callback = callback_.NewCallback(&WebSocketInstance::OnReceive);

      websocket_->ReceiveMessage(&data, callback);
    }

    void OnReceive(int32_t result) {
      if (result == PP_OK) {
        if (data.is_string()) {
          PostMessage(pp::Var("1," + data.AsString()));
        }
      }

      Receive();
    }
};

class WebSocketModule : public pp::Module {
  public:
    WebSocketModule() : pp::Module() {
    }

    virtual pp::Instance* CreateInstance(PP_Instance instance) {
      return new WebSocketInstance(instance);
    }
};

namespace pp {
  Module* CreateModule() {
    return new WebSocketModule();
  }
}

でコンパイルして、上のnacl.htmlを動かすしてボタンを押すとここでもMojolicious側のHTMLな所でもWebSocket通信のメッセージング結果が返ってくる。で一度WebSocketサーバー側を落としちゃって見るとnacl.html側でdisconnectedって返ってくる

Native Client(NaCl)をやってみる (8) - pp::FileSystem - Native Client(NaCl)をやってみる (6) - pp::URLLoader -