peerjs-server経由でチャット
概要
チャットとかのログを残すためにサーバ経由でチャットを送るようにしたかった。
それのためにシグナリングサーバに無理やりくっつけた。
実装
クライアント
- peer.chat()でチャットを送り、type:CHATのデータをチャットデータとして受信・処理する。
- ユーザ名とかはいったん毎回送ってる
added chat event · kambayashia/peerjs@f1663c1 · GitHub
サーバ
- _handleTransmission()のハンドリングにCHATを加える
- ログ残すのはまた別途
- ルーム内全員に転送する
- あとはちょっとバグ修正
added chat event · kambayashia/peerjs-server@73c9889 · GitHub
使い方
# 受信側 peer.on('chat', function(src, payload) { /** * payload = { * name: "namae", * message: "hogehoge" * }; */ // DOMにくっつける処理 }); # 送信側 peer.chat(name, message);
まとめ
peerjs-serverいろいろかえてくのやっぱり辛いなと思った。 そして毎回xhr対応忘れてる。
peerjsでping-pong
概要
herokuでpeerjsサーバ動かしたら60秒くらいでWebSocketが切断する問題が起きた。
ドキュメント見たら、30秒?で切れるようなので、しかたなくping−pongを実装した。
WebSockets on Heroku | Heroku Dev Center
実装
クライアント
- 受信したPINGに返答を返す
added ping-pong · kambayashia/peerjs@d2b0a26 · GitHub
サーバ
- サーバ側からPINGを投げる
- PONGが帰って来るか来ないかは検証しない、いったんherokuのタイムアウトを回避したいだけだから added ping-pong · kambayashia/peerjs-server@e9ac7b1 · GitHub
peerjsにルーム機能と切断検知機能をつける
概要
peerjsを使ってWebRTC実装したときに、FireFoxだとcloseイベントが通知されなかったので1meetingのjsを参考に、ルーム管理と切断検知を作ってみた。
コード
サーバ
クライアント
ルーム情報送信
- 最初の接続時に接続ルーム名を送る
- ページ遷移なしでルームをうつることは考えない
クライアント
- アクセスパラメータにルーム名を入れる
added room name · kambayashia/peerjs@0717e2c · GitHub
サーバ
- ルーム名を受け取ってルームごとのリストに分ける
added room list · kambayashia/peerjs-server@0187de5 · GitHub
ルームメンバー取得
- ルームメンバー一覧を返すアクションを作る
クライアント
- ルーム取得時に再度ルーム名送ってるのが気になるけどいったんしょうがない。
added getter of room-member · kambayashia/peerjs@ded674a · GitHub
サーバ
- id一覧をarrayで返す
added handler · kambayashia/peerjs-server@c800802 · GitHub
使い方
- OPENイベントのpayloadに乗っけて返そうとしたけど、自身のMediaStreamが必要だったのでgetUserMedia()のコールバック内で呼ぶようにした。
var peer; //Peerオブジェクト navigator.getUserMedia({audio: true, video: true}, function(stream){ peer.listRoomMemberPeers(function (response) { for(var i in response) { var id = response[i]; if (id != peer.id) { // 自分自身のも含んでるので弾く peer.call(id, stream); } } }); });
切断通知
- 切断した際に相手にLEAVEイベントが行っていなかったので、飛ばすようにした。
クライアント
- 変更なし
サーバ
- removePeer()が呼ばれたら内部で同一ルームのメンバーにLEAVEを投げる
send leave event to room members · kambayashia/peerjs-server@dfb8a63 · GitHub
まとめ
元の実装みると次にpeerjs−server経由で通信しようとしたときに切断されていたらLEAVEイベント投げるっぽいけど、定期的に投げられるものじゃないっぽいので自分で投げるようにした。 FireFoxでは相手の切断イベントがこない問題はいったんこれで解決した。 他の方法がどんなのがあるかわからないけど、1meetingも独自イベント実装してたしまあいいかなと。
あと、動画部分はさておき、テキストチャットその他の操作をルームごとのアーカイブとして残したいので、WebRTCのデータチャンネルを使わずに、サーバクライアント方式でチャットやり取りする機能をpeerjsにつける魔改造をする予定。 1つのページで複数WebSocket作って、別サーバに接続に行くのがスマートなのかよくわからない。
vagrantでdebian wheezyの環境を作る
最近仕事でもvagrantを使うのでいろいろ覚えつつ、個人用環境を作ってみた。
vagrantとは
vagrantの使い方やってるページはいろいろあるのでそのへんで
詰まったところ
chefがインストールできない
とりあえず http://www.vagrantbox.es/ からwheezyのvanillaって書いてあるやつを持ってきて入れた。
chefが入ってないので vagrant-omunibusを使う。
ssl的なエラーが出てインストールできない。
# Vagrantfile Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.omnibus.chef_version = :latest : : :
# ログ Please detail your operating system type, version and any other relevant details Metadata URL: https://www.opscode.com/chef/metadata?v=11.8.2&prerelease=false&p=debian&pv=6&m=x86_64 \nDEBUG OUTPUT FOLLOWS:\n\nSTDERR from wget:\n\n--2013-12-22 09:14:57-- https://www.opscode.com/chef/metadata?v=11.8.2&prerelease=false&p=debian&pv=6&m=x86_64 Resolving www.opscode.com (www.opscode.com)... 184.106.28.90 Connecting to www.opscode.com (www.opscode.com)|184.106.28.90|:443... connected. ERROR: The certificate of `www.opscode.com' is not trusted.
opscodeからもってきたレシピがインストールできない
http://www.vagrantbox.es/ からchefが入ってるwheezy(Debian Wheezy 7.1 amd64 (french) with Chef 11.4.4 and VirtualBox 4.1.18)を持ってきて入れた。
適当にmysql::serverとか入れてみるけどapparmor-utilsがどうとかでインストールできない。
ぶっちゃけこのへんの関係が知りたいわけじゃないから原因は調べてない
================================================================================ Error executing action `install` on resource 'package[apparmor-utils]' ================================================================================ Chef::Exceptions::Exec ---------------------- apt-get -q -y install apparmor-utils=2.7.103-4 returned 100, expected 0 Resource Declaration: --------------------- # In /tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/recipes/_server_debian.rb 28: package name do 29: action :install 30: end 31: end
パッケージのマイナーバージョンが違ってインストールできない
recipe[mysql::server]と書いて実行すると下記のように404になる。
fter this operation, 98.5 MB of additional disk space will be used. Get:1 http://ftp.us.debian.org/debian/ wheezy/main libaio1 amd64 0.3.109-3 [9,150 B] Get:2 http://ftp.us.debian.org/debian/ wheezy/main libnet-daemon-perl all 0.48-1 [46.2 kB] Err http://security.debian.org/ wheezy/updates/main mysql-common all 5.5.31+dfsg-0+wheezy1 404 Not Found [IP: 200.17.202.197 80] Get:3 http://ftp.us.debian.org/debian/ wheezy/main libplrpc-perl all 0.2020-2 [36.0 kB] Get:4 http://ftp.us.debian.org/debian/ wheezy/main libdbi-perl amd64 1.622-1 [898 kB] Err http://security.debian.org/ wheezy/updates/main libmysqlclient18 amd64 5.5.31+dfsg-0+wheezy1 404 Not Found [IP: 200.17.202.197 80] Err http://security.debian.org/ wheezy/updates/main mysql-client-5.5 amd64 5.5.31+dfsg-0+wheezy1 404 Not Found [IP: 200.17.202.197 80] Err http://security.debian.org/ wheezy/updates/main mysql-server-core-5.5 amd64 5.5.31+dfsg-0+wheezy1 404 Not Found [IP: 200.17.202.197 80] Err http://security.debian.org/ wheezy/updates/main mysql-server-5.5 amd64 5.5.31+dfsg-0+wheezy1
実際にサイトに言ってみると5.5.33しかない。
mysqlがdebian7に対応してない
このへんの問題
https://github.com/opscode-cookbooks/mysql/pull/132
下記のようなエラー
Chef::Exceptions::FileNotFound ------------------------------ Cookbook 'mysql' (4.0.14) does not contain a file at any of these locations: templates/debian-7.0/init-mysql.conf.erb templates/debian/init-mysql.conf.erb templates/default/init-mysql.conf.erb This cookbook _does_ contain: ['/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/default/debian.cnf.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/default/grants.sql.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/default/my.cnf.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/default/mysql-server.seed.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/default/port_mysql.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/default/usr.sbin.mysqld.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/ubuntu-10/init-mysql.conf.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/ubuntu-12/init-mysql.conf.erb','/tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/templates/windows/my.ini.erb'] Resource Declaration: --------------------- # In /tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/recipes/_server_debian.rb 77: template '/etc/init/mysql.conf' do 78: source 'init-mysql.conf.erb' 79: end
phpでiisの部分でどうとかいわれる
下記近辺で定義がない感じのエラーが出る。
このへん
https://github.com/opscode-cookbooks/iis/blob/master/libraries/helper.rb#L29
Relevant File Content: ---------------------- /tmp/vagrant-chef-1/chef-solo-1/cookbooks/iis/libraries/helper.rb: 23: require 'chef/win32/version' 24: end 25: 26: module Opscode::IIS 27: class Helper 28: 29: def self.older_than_windows2008r2? 30>> win_version = Chef::ReservedNames::Win32::Version.new
解決方法
opscodeのクックブックの問題かboxファイルの問題かわからなくなるからvanillaに最小限の変更をいれたboxファイルを作ることにした。
まずvanillaをそのまま起動する。
$ vagrant box add debian-wheezy-vanilla https://dl.dropboxusercontent.com/s/xymcvez85i29lym/vagrant-debian-wheezy64.box $ vagrant init debian-wheezy-vanilla $ vagrant up
sshでログインしてssl関係のものをインストールする(最初のchefがインストール出来なかった問題用)
mac$ vagrant ssh vagrant$ sudo apt-get install ca-certificates
ログアウトしてboxファイルを作る
mac$ vagrant package [default] Attempting graceful shutdown of VM... [default] Clearing any previously set forwarded ports... [default] Creating temporary directory for export... [default] Exporting VM... [default] Compressing package to: /Users/kambayashia/projects/vagrant-files/test/package.box
作成したboxをvagrantに登録してそれを使うようにする。
Vagrantfileにaptを加えてrun_listにも加える。
これで最初にapt-get updateされる(マイナーバージョンが違って404になる問題用)
# Vagrantfile : : chef.run_list = [ "recipe[apt::default]", : :
debian7対応がまだマージされてないので、Berksfileのmysqlをいったん独自リポジトリにする。
下記ブランチ、変更点はコミット履歴で
https://github.com/kambayashia/cookbooks-mysql/tree/debian7
cookbook 'mysql', github: "kambayashia/cookbooks-mysql", branch: "debian7"
phpのiisはmetadata.rbにdependsが入ってるから起きてるけど、みんなどうやって解決してるのか知りたい。
https://github.com/opscode-cookbooks/php/blob/master/metadata.rb#L12
とりあえずこれも独自リポジトリにしちゃう
cookbook 'php', github: "kambayashia/cookbooks-php"
これでvagrant upすればとりあえずいけた。
すでにberkshelfのがダウンロードされてたらberks updateも必要かも。
cakephp HttpResponseがクラス名かぶってる
参考
- cakephp2.0のHttpSocket
- 1系からの使い方の変更
サンプルコード
public function index(){ // disable view $this->autoRender = false; App::uses('HttpSocket', 'Network/Http'); $http = new HttpSocket(); $url = "http://cakephp.jp/"; $response = $http->get( $url ); if( ! $response ){ return false; } echo $response->body(); }
画面表示
Fatal error: Call to undefined method HttpResponse::body() in /home/atsushi-kambayashi/www/app/Controller/HogeController.php on line 29
メソッド一覧確認
下記コードでメソッド一覧確認
public function index(){ // disable view $this->autoRender = false; App::uses('HttpSocket', 'Network/Http'); $http = new HttpSocket(); $url = "http://cakephp.jp/"; $response = $http->get( $url ); if( ! $response ){ return false; } echo "<pre>"; var_dump( get_class_methods( $response ) ); echo "</pre>"; echo $response->body(); }
出力はこんな感じ
array(34) { [0]=> string(9) "setHeader" [1]=> string(9) "getHeader" [2]=> string(7) "setETag" [3]=> string(7) "getETag" [4]=> string(15) "setLastModified" [5]=> string(15) "getLastModified" [6]=> string(21) "setContentDisposition" [7]=> string(21) "getContentDisposition" [8]=> string(14) "setContentType" [9]=> string(14) "getContentType" [10]=> string(16) "guessContentType" [11]=> string(8) "setCache" [12]=> string(8) "getCache" [13]=> string(15) "setCacheControl" [14]=> string(15) "getCacheControl" [15]=> string(7) "setGzip" [16]=> string(7) "getGzip" [17]=> string(16) "setThrottleDelay" [18]=> string(16) "getThrottleDelay" [19]=> string(13) "setBufferSize" [20]=> string(13) "getBufferSize" [21]=> string(7) "setData" [22]=> string(7) "getData" [23]=> string(7) "setFile" [24]=> string(7) "getFile" [25]=> string(9) "setStream" [26]=> string(9) "getStream" [27]=> string(4) "send" [28]=> string(7) "capture" [29]=> string(8) "redirect" [30]=> string(6) "status" [31]=> string(17) "getRequestHeaders" [32]=> string(14) "getRequestBody" [33]=> string(20) "getRequestBodyStream" }
cakephpのバグか
クラス名変えて確認
$ ls -la lib/Cake/Network/Http/ 合計 72 drwxr-xr-x 2 atsushi-kambayashi atsushi-kambayashi 4096 2012-09-09 18:13 . drwxr-xr-x 4 atsushi-kambayashi atsushi-kambayashi 4096 2012-09-01 10:28 .. -rw-r--r-- 1 atsushi-kambayashi atsushi-kambayashi 1754 2012-09-01 10:28 BasicAuthentication.php -rw-r--r-- 1 atsushi-kambayashi atsushi-kambayashi 3262 2012-09-01 10:28 DigestAuthentication.php -rw-r--r-- 1 atsushi-kambayashi atsushi-kambayashi 10564 2012-09-09 17:51 HttpResponse.php -rw-r--r-- 1 atsushi-kambayashi atsushi-kambayashi 29381 2012-09-09 18:13 HttpSocket.php
HttpSocketに使用するレスポンスクラスの名称があるので変更
/** * Response classname * * @var string */ public $responseClass = 'CakeHttpResponse'; // 元はHttpResponse
同ディレクトリにクラスコピーして内部のクラス名を変更
$ cp lib/Cake/Network/Http/HttpResponse.php lib/Cake/Network/Http/CakeHttpResponse.php /** * HTTP Response from HttpSocket. * * @package Cake.Network.Http */ class CakeHttpResponse implements ArrayAccess {
メソッド名出力外して確認
とりあえずページ情報はとれた
cocos2d-x タッチイベント取得
概要
- タッチイベントを取得してゲーム中で使用する
参考
- タッチイベント関連のリファレンス(ccTouchで検索)
ブランチ「develop/multi-scene-stack」をベースにする
- 前回サンプルに追加実装した
タッチイベントコールバックをオーバーライド
- cocos2d-xのクラスリファレンスを見るとタッチイベント用関数の仮想関数があるのでそれをアプリ用ヘッダでも宣言する
void registerWithTouchDispatcher(); bool ccTouchBegan( cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent ); void ccTouchEnded( cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent );
タッチイベント実装
- cpp側でオーバーライドした関数の実装を行う
- http://dummyimage.com/ で画像つくってボタンを押したら画像がかわるようにする
- CCSpriteのオブジェクトをメンバ変数で保持してるようにしているが省略
bool Title::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { this->mSprite->initWithFile("background_touch_began.png"); return true; } void Title::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { this->mSprite->initWithFile("background_touch_end.png"); }
タッチイベントをとるオブジェクトの設定
- イベントを検出するオブジェクトとして設定する必要がある
- タッチイベントを処理するオブジェクトを設定する必要があるが公式のリファレンスの呼び方ができなくなってる
- priorityが設定できるがサンプルのままの値を設定したらCCMenuのボタンがイベントをとれなくなったので注意
- CCMenuはデフォルトではpriorityが-128で設定されるようだが、これより大きい数を設定したらCCMenuが優先されるようになった
void Title::registerWithTouchDispatcher() { //CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-129,true); CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-127,true); }
タッチイベントの有効化
- デフォルトでも有効かもしれないが一応initの中で呼んどく
// enable touch event this->setTouchEnabled(true);
動かす
cocos2d-x 別シーンに行って元のシーンに戻る
概要
- 前回のサンプルでは切り替えたら前のシーンには戻れなかったが、ポップアップメニューや設定画面など、完了したら元の画面に戻りたい画面を作る
前回のリポジトリから続ける
scene切り替え処理を変更する
- TitleSceneのreplaceSceneは完全にシーンを置き換える処理だったが、pushSceneにするとシーンのスタックに積まれる
TitleScene.cpp
void Title::menuChangeScene(CCObject *pSender) { //CCDirector::sharedDirector()->replaceScene( HelloWorld::scene()); CCDirector::sharedDirector()->pushScene(HelloWorld::scene()); }
前のシーンに戻る
- 子として作ったHelloWorldから前のTitleSceneに戻る処理を作る
- とりあえず終了ボタンを押した時の処理を戻る機能にして確認してみる
HelloWorld.cpp
void HelloWorld::menuCloseCallback(CCObject* pSender) { /* CCDirector::sharedDirector()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif */ CCDirector::sharedDirector()->popScene(); }
前のシーンに戻るボタンを作る
- 終了ボタンは元の処理に戻して、専用ボタンを作る
- ボタンを作った時の記事を参考にする