Hatena::ブログ(Diary)

bushimichiの日記 RSSフィード

この日記のはてなブックマーク数

2016-09-21

Apache稼働中のサーバにnginxを追加する場合のポート設定

| 09:51 |  Apache稼働中のサーバにnginxを追加する場合のポート設定を含むブックマーク

前程として1台のサーバのport80で既にApacheが稼働している状態で

nginxを追加して、nginxをフロントにバックにApacheを置いてproxyでつなぎたい場合。

Apacheがport80をListenしている状態では、nginxはどうしても別ポートにする必要がある。

nginx(8080) -> Apache(80)

ただ、これだと通常のWebでは使いずらい。

nginx(80) -> Apache(8080)

こっちのほうが一般的だと思うが、Apacheの再設定の必要が出てくる。

特にバーチャル設定で複数ホスト設定している場合は変更が結構手間になる。

そこで、iptables のPREROUTINGを使う。


iptables(80) -> nginx(8080) -> Apache(80)

こういう形にするとApacheに手を入れずにnginxをフロントに置ける。


# /etc/sysconf/iptables

*nat
:PREROUTING ACCEPT [466:35427]
:POSTROUTING ACCEPT [27:3255]
:OUTPUT ACCEPT [27:3255]
-A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
COMMIT


# /etc/nginx/conf.d/default.conf

    listen       8080 default_server;
    listen       [::]:8080 default_server;


    #proxy_set
      proxy_set_header Host                   $host;
      proxy_set_header X-Real-IP              $remote_addr;
      proxy_set_header X-Forwarded-Host       $host;
      proxy_set_header X-Forwarded-Server     $host;
      proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;


    location / {
      proxy_pass http://{サーバのIP}:80;
    }

2016-09-20

WebSocket Node.js用にnginx proxyの設定

| 15:41 |  WebSocket Node.js用にnginx proxyの設定を含むブックマーク

WebSocketNode.jsで実装する場合の、port 80 に対するproxy設定

Apache2.4でもよかったけど、nginx のほうが簡単そうなので。


# nginx/conf.d/default.conf

    proxy_set_header Host                   $host;
    proxy_set_header X-Real-IP              $remote_addr;
    proxy_set_header X-Forwarded-Host       $host;
    proxy_set_header X-Forwarded-Server     $host;
    proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;


    location /ws/ {
      proxy_set_header Upgrade     $http_upgrade;
      proxy_set_header Connection  "Upgrade";

      proxy_pass http://127.0.0.1:8080;
    }

2016-09-16

websocket を Lua から利用する時の注意

| 11:52 | websocket を Lua から利用する時の注意を含むブックマーク

cocos2d-x-3.13 LuaWebsocketを利用する際に、以前にはでてなかったと思うエラーが出た。

いつのバージョンからかは不明だが、3.6くらいの時は出てなかったと思う(曖昧な記憶)


  local ws = cc.WebSocket:create("ws://example.com")

  ws:registerScriptHandler(function(msg)
      -- なんらかの処理...
    end,
    cc.WEBSOCKET_MESSAGE)

上記を実行すると、registerScriptHandler の第4の引数が無いとエラーが出る。



以下のbindingファイルがその該当箇所のようなので398行目 のエラーチェックに引っかかってたようだ。

# Lua_web_socket.cpp line 390

int tolua_Cocos2d_WebSocket_registerScriptHandler00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
    tolua_Error tolua_err;
    if (
        !tolua_isusertype(tolua_S,1,"cc.WebSocket",0,&tolua_err) ||
        !toluafix_isfunction(tolua_S,2,"LUA_FUNCTION",0,&tolua_err) ||
        !tolua_isnumber(tolua_S,3,0,&tolua_err) || 
        !tolua_isnoobj(tolua_S,4,&tolua_err)    // ここにひっかかってる
        )
        goto tolua_lerror;
    else
#endif
    {
        LuaWebSocket* self    = (LuaWebSocket*)  tolua_tousertype(tolua_S,1,0);
        if (NULL != self ) {
            int handler = (  toluafix_ref_function(tolua_S,2,0));
            ScriptHandlerMgr::HandlerType handlerType = (ScriptHandlerMgr::HandlerType)((int)tolua_tonumber(tolua_S,3,0) + (int)ScriptHandlerMgr::HandlerType::WEBSOCKET_OPEN);
            ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, handlerType);
        }
    }
    return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
    tolua_error(tolua_S,"#ferror in function 'registerScriptHandler'.",&tolua_err);
    return 0;
#endif
}

ただ、tolua_toobject(tolua_S,4,0) と、この第4の引数を利用している箇所が関数内には存在しないので

このチェックは無視しても問題なさそう。

以下の部分をfalseに変更

- !tolua_isnoobj(tolua_S,4,&tolua_err)
+ false

エラーは出なくなりました。

2016-09-13

AsyncTaskPoolが便利

| 12:03 |  AsyncTaskPoolが便利を含むブックマーク

バックで非同期実行する際などに利用。

AssetsManager とか Download 関係のソースに実装されてるので見様見真似で使ってみる。

Luaからも利用できるように luabinding もさせておくとなおよし。


# 自前のSQLを実行する関数に適用

void Wx::execSqlAsync(const std::string& sql, ResCallback callback)
{
	struct AsyncData
	{
		bool res;
		std::string sql;
	};

	AsyncData* asyncData = new AsyncData;
	asyncData->sql = sql;

	std::function<void(void*)> mainThread = [this, callback, sql](void* param) {
		auto asyncDataInner = reinterpret_cast<AsyncData*>(param);
		callback(asyncDataInner->res, sql);

		delete asyncDataInner;
	};

	AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_OTHER, mainThread, (void*)asyncData, [this, asyncData] {
		asyncData->res = execSql(asyncData->sql);
	});
}



static int lua_cocos2dx_Wx_execSqlAsync(lua_State* L)
{
	if (nullptr == L)
		return 0;

	int argc = 0;
	Wx* self = nullptr;
	bool ok = true;

#if COCOS2D_DEBUG >= 1
	tolua_Error tolua_err;
	if (!tolua_isusertype(L, 1, "Wx", 0, &tolua_err)) goto tolua_lerror;
#endif

	self = static_cast<Wx*>(tolua_tousertype(L, 1, 0));

#if COCOS2D_DEBUG >= 1
	if (nullptr == self) {
		tolua_error(L, "invalid 'self' in function 'lua_cocos2dx_Wx_execSqlAsync'\n", NULL);
		return 0;
	}
#endif
	argc = lua_gettop(L) - 1;
	if (2 == argc)
	{

		std::string arg0;
		ok &= luaval_to_std_string(L, 2, &arg0, "Wx:execSqlAsync");
		if (!ok)
		{
			tolua_error(L, "invalid arguments in function 'lua_cocos2dx_custom_Wx_execSqlAsync'", nullptr);
			return 0;
		}


#if COCOS2D_DEBUG >= 1
		if (!toluafix_isfunction(L, 3, "LUA_FUNCTION", 0, &tolua_err)) { goto tolua_lerror; }
#endif

		LUA_FUNCTION handler = (toluafix_ref_function(L, 3, 0));

		std::function<void(bool b, const std::string sql)> callback = [L, handler](bool b, const std::string sql) {
			LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
			stack->pushBoolean(b);
			stack->pushString(sql.c_str());
			stack->executeFunctionByHandler(handler, 2);
		};

		self->execSqlAsync(arg0, callback);

		return 0;

	}

	luaL_error(L, "'execSqlAsync' function of Wx has wrong number of arguments: %d, was expecting %d\n", argc, 2);

	return 0;

#if COCOS2D_DEBUG >= 1
	tolua_lerror:
				tolua_error(L, "#ferror in function 'execSqlAsync'.", &tolua_err);
				return 0;
#endif
}

cocos2d-x アプリのバージョン取得

| 11:59 |  cocos2d-x アプリのバージョン取得を含むブックマーク

以前は、自前でネイティブコード実装してましたが、cocos2d-x 3.10 からは、標準装備になったみたい。



cc.Application:getInstance():getVersion()

備忘録

2016-09-06

Google Playで課金テストをするときに、テストアカウントが認識されない

| 10:52 |  Google Playで課金テストをするときに、テストアカウントが認識されないを含むブックマーク

新しくテストアカウントGoogleアカウント)を作って課金テストをした時の失敗。

1.Google Play console で、APKファイルをアルファー版で公開。
2.クローズドアルファ版テストとして、テスターをリストに追加
3.オプトインURLを該当者に送付
4.メールに届いたURLをクリックしてインストール
5.起動

ここまでは、よかった。

この後、やりたかった課金テストに進むわけだが、どういうわけか課金処理に入ると

テストなのに、クレジット情報が表示されて正規の課金フローのように。。。

テスト課金なら「これはテスト用の注文です。。。」と表示されてくれるはず。。。

仕様が変わったのかなぁ。。と半信半疑でポチってしまったのが運の尽き。

普通に課金されてしまった。。。。

どうも、テスターの設定だけでなく、

DeveloperConsoleの設定 -> 「テスト用のアクセス権がある Gmail アカウント」

この設定が抜けていたのが問題だったらしい。

テスター登録だけでOKだと勘違いしていた。

以前作ったアプリではちゃんと登録していたみたいで、完全に忘却していました。

今回のように新しくテストアカウント作った時には注意が必要。

2016-09-05

現在サンドボックスでInApp購入を行う権限がありません

| 15:22 | 現在サンドボックスでInApp購入を行う権限がありませんを含むブックマーク

iPhone5S 端末でテストをしようとしたら、「現在サンドボックスでInApp購入を行う権限がありません」とエラーメッセージ。AppleIDをitunes-connectで設定したSandboxユーザに変更してなかっただけ。

端末のAppstoreのトップページを下のほうにスクロールすると「サインアウト」できるので、いったんサインアウトして、改めてテストアプリを起動。課金をしようとするとアカウント入力から求められるのでSandboxに設定したユーザでサインインして課金を行うとOK

cocos2d-x sdkbox とかの問題じゃないので混同しないように注意。

Xcodeでテストビルド用にパッケージを分ける方法

12:18 | Xcodeでテストビルド用にパッケージを分ける方法を含むブックマーク

単純にSchemaとTargetに追加すると新しい設定が追加できるのでパッケージ名を変えた設定でビルドすると幸せになれる。

TARGETS [+]ボタンでターゲットの追加
Product -> Scheme -> ManageSchemes で、適当に編集

※Info.plist も別になるはずなので、設定に追加されているか確認すること

XcodeからTestflightへアップロード時に Error ITMS-90032 No image found ...

| 11:38 |  XcodeからTestflightへアップロード時に Error ITMS-90032 No image found ...を含むブックマーク

cocos2d-x 3.13 のinfo.plistにiconの設定が増えているようなのだが、

Xcodeのプロジェクトにはリソース追加設定がされていないようでArch時にエラーになった。


# Xcodeのプロジェクトがリソースと認識するように以下を追加
# Build Phases -> Copy Bundle Resources +(add) 

ios/icons/icno-87.png
ios/icons/icon-180.png


2016-09-01

XORでジャミング済みのPNGファイルを読み込む

| 21:33 |  XORでジャミング済みのPNGファイルを読み込むを含むブックマーク

XORでbitshiftさせたPNGをcocos2d-x側で読み込む際にデコードする。

PNGの処理については割愛


# cocos/platform/CCImage.h 
# 
# XOR_SEED と XOR_SEED_CNT は任意の値
#
	const char* XOR_SEED = "ABCDE12345";
	const int XOR_SEED_CNT = 10;


# cocos/platform/CCImage.cpp line 515
#
# 画像データを扱うImage関数 (cocos2d-x 3.13)
#
#
bool Image::initWithImageData(const unsigned char * data, ssize_t dataLen)
{
    bool ret = false;
    
    do
    {
        CC_BREAK_IF(! data || dataLen <= 0);
        
        unsigned char* unpackedData = nullptr;
        ssize_t unpackedLen = 0;
        
        //detect and unzip the compress file
        if (ZipUtils::isCCZBuffer(data, dataLen))
        {
            unpackedLen = ZipUtils::inflateCCZBuffer(data, dataLen, &unpackedData);
        }
        else if (ZipUtils::isGZipBuffer(data, dataLen))
        {
            unpackedLen = ZipUtils::inflateMemory(const_cast<unsigned char*>(data), dataLen, &unpackedData);
        }
        else
        {
            unpackedData = const_cast<unsigned char*>(data);
            unpackedLen = dataLen;
        }

        _fileType = detectFormat(unpackedData, unpackedLen);

        switch (_fileType)
        {
        case Format::PNG:
            ret = initWithPngData(unpackedData, unpackedLen);
            break;
        case Format::JPG:
            ret = initWithJpgData(unpackedData, unpackedLen);
            break;
        case Format::TIFF:
            ret = initWithTiffData(unpackedData, unpackedLen);
            break;
        case Format::WEBP:
            ret = initWithWebpData(unpackedData, unpackedLen);
            break;
        case Format::PVR:
            ret = initWithPVRData(unpackedData, unpackedLen);
            break;
        case Format::ETC:
            ret = initWithETCData(unpackedData, unpackedLen);
            break;
        case Format::S3TC:
            ret = initWithS3TCData(unpackedData, unpackedLen);
            break;
        case Format::ATITC:
            ret = initWithATITCData(unpackedData, unpackedLen);
            break;
        default:
            {

            // ここから -------------------------------------------
                // XOR/PNG
                int ci = XOR_SEED_CNT; 
                unpackedData = const_cast<unsigned char*>(data);

                for (int i = 0; i < unpackedLen; i++) {
                    int idx = i % ci;
                    int key = XOR_SEED[idx] % 256;
                    unpackedData[i] = unpackedData[i] ^ key;
                }

                _fileType = detectFormat(unpackedData, unpackedLen);
                //
                if (_fileType == Format::PNG) {
                    ret = initWithPngData(unpackedData, unpackedLen);
                    break;
                }
           // ここまで ---------------------------------------------

                // load and detect image format
                tImageTGA* tgaData = tgaLoadBuffer(unpackedData, unpackedLen);
                
                if (tgaData != nullptr && tgaData->status == TGA_OK)
                {
                    ret = initWithTGAData(tgaData);
                }
                else
                {

                    CCLOG("cocos2d: unsupported image format!");
                }
                
                free(tgaData);
                break;
            }
        }
        
        if(unpackedData != data)
        {
            free(unpackedData);
        }
    } while (0);
    
    return ret;
}


cocos2d-x 3.13 テキストラベルが白くなる

| 10:27 |  cocos2d-x 3.13 テキストラベルが白くなるを含むブックマーク

8月末にバージョンアップされたcocos2d-xを早速使ってみると

いままで cocos studio で色を付けていたラベルの部分が全部白くなってしまう不具合があった。

# cocos/2d/CCLabel.cpp line 1894

void Label::updateDisplayedColor(const Color3B& parentColor)
{
    Node::updateDisplayedColor(parentColor);

    if (_currentLabelType == LabelType::TTF || _currentLabelType == LabelType::STRING_TEXTURE)
    // ここをコメントアウト    setTextColor(Color4B(_displayedColor));


とりあえず、上記をコメントアウトすることで対応。

ラベルのタイプで色を初期化するみたいなことしてると思うのだけれども

必要あると分かるまではコメントアウトでいいでしょう。

2016-08-24

Lua5.1 用 metatable のマジックメソッド __next を実装する

| 09:59 |  Lua5.1 用 metatable のマジックメソッド __next を実装するを含むブックマーク

Lua5.1には、metatableで利用できる、__next が無いらしいので独自に拡張する。


以下を参考

GeneralizedPairsAndIpairs


-- next関数の拡張
rawnext = next
function next(t,k)
  local m = getmetatable(t)
  local n = m and m.__next or rawnext
  return n(t,k)
end

-- nextの拡張だけで以下のようにできる
local priv = {a = 1, b = 2, c = 3}
local mt = {
  __next = function(t, k) 
    --
    -- ここに適当な処理を追加できる
    --
    return next(priv, k) 
  end
}
local t = setmetatable({}, mt)

for k,v in next, t do print(k,v) end

すばらしい。


cocos2d-x Lua メモリ改竄チート対策でデータをジャミングしたい時などに、このmetatable使って処理するとやりやすいかも。

--
--
--
function encodeXXX()
  return -- デコード処理
end
--
--
--
function decodeXXX()
  return -- デコード処理
end
--
--
--
function createEncTable()
  local t1 = {}
  
  local t2 = setmetatable({},{
    __index = function(t, key)
      return decodeXXX(t1[key])
    end,
    __newindex = function(t, key, val)
      t1[key] = encodeXXX(val)
    end,
    __next = function(t, k)
      local t2 = {}
      for k,v in pairs(t1) do
        t2[k] = decodeXXX(v)
      end
      return next(t2,k)
    end
  })

  return t2
end

基本的な対策としてはジャミングが目的なので

エンコード部分は適当なXORとかの簡易なものでもいいと思う。

2016-08-23

CocosCreator 以前のツールのダウンロード

| 22:26 | CocosCreator 以前のツールのダウンロードを含むブックマーク

Cocos CocosForWin CocosForMac CocosStudio CocosCodeIDE など公式からダウンロードできなくなったソフトは以下からまだダウンロードできるみたいです。


https://github.com/fusijie/Cocos-Resource#cocos-studio-%E4%B8%8B%E8%BD%BD

ccui.EditBox に、openKeyboard closeKeyboard がなかったので追加

| 15:25 |  ccui.EditBox に、openKeyboard closeKeyboard がなかったので追加を含むブックマーク

なぜか、C++のファイルにキーボードをON/OFFする関数が定義されてなかったので追加した。

Implファイルにはあるのでプラットフォームごとの定義はある。

ただ、Lua-bindings を利用している場合は、UIEditBox.h UIEditBox.cpp から、

bindを自動生成しているのでこちらに記述がないとLuaから使えないので追加した。



cocos2d-x/cocos/ui/UIEditBox/UIEditBox.h

public: 

 virtual void openKeyboard();
 virtual void closeKeyboard();




cocos2d-x/cocos/ui/UIEditBox/UIEditBox.cpp

void EditBox::openKeyboard()
{
	if (_editBoxImpl != nullptr)
	{
		_editBoxImpl->openKeyboard();
	}
}

void EditBox::closeKeyboard()
{
	if (_editBoxImpl != nullptr)
	{
		_editBoxImpl->closeKeyboard();
	}
}

2016-08-18

wxSqlite3で暗号化 sqlite3をセキュアに利用する

| 14:09 | wxSqlite3で暗号化 sqlite3をセキュアに利用するを含むブックマーク

環境 Centos6


wsqlite3をダウンロードして解凍コンパイルする。

https://sourceforge.net/projects/wxcode/files/Components/wxSQLite3/


cd [wxSqlite3 dir]/sqlite3/secure/src/

gcc -o sqlite3 -DSQLITE_HAS_CODEC=1 -DSQLITE_USER_AUTHENTICATION=0 shell.c sqlite3secure.c -ldl -lpthread

使い方


./sqlite3  test.db

>PRAGMA KEY='passcode';  # 最初にパスコードを指定する
>create table test(a,b);
>insert into test(a,b)values(1,2);
>select * from test;
>1|2
>.q # 終了

./sqlite3 test.db 
># パスコードを指定しない
>select * from test;
>Error: file is encrypted or is not a database
>.q #終了

./sqlite3 test.db
>PRAGMA KEY='passcode'; #  最初にパスコードを指定する
>select * from test;
>1|2
>.q #終了

これを利用するとcocos2d-xでwxsqlite3を利用するときに、外部でwxsqlite3を暗号化したデータベースを読み込ませることができる。