ニュース

tarボールからインストールしたものを管理

最近はほとんどのものがパッケージで提供されており、ソースからわざわざインストールする機会もずいぶん減った気がします。
しかし、中にはソースからインストールしないといけない場合もあるかと思います。
自分はApachePHPなど主要なソフトは、ソースからインストールする事が多いです。

今までは、バージョンアップさせる度にバカの一つ覚えと言わんばかりに、make && make installをひたすら叩きまくっていたわけです。
バージョアップしたはいいけど、おかしくなったらすぐ戻せる環境がベストだと思い、ちょっと色々調べてみました。

僕が理想とする機能は、

  • ソースから入れたファイル群を管理できる
  • バージョン毎にインストールしたものが管理できる
  • 前のバージョンに戻せる
  • コマンドから削除ができる

paco

まず最初に見つけたのがpacoです。
これはほぼ理想通りで、欲しい機能がほとんど揃っていました。なにより、使っている人が多くて、実績という点でも安心できそうです。
一つ気になった点は、前のバージョンに戻すような履歴管理が簡単ではなかった点です。
軽く調べた感じだと、pacoballというコマンドで、今のバージョンをtarボール化し、新しいバージョンの物を入れるという感じになりそうです。

インストール

## -Dオプションでカレントディレクトをパッケージ名として利用します
# paco -D make install
## -pオプションでパッケージ名の指定が可能
# paco -p "app-1.4.1" make install

アンインストール

# paco -r app-1.4.1

その他

## インストール済みソフトの一覧表示
# paco -a
## 共有ファイルの表示
# paco -fc app
app-1.4.1:
/usr/local/app/conf/local.conf
## インストールした日を表示
# paco -dd app
01-Sep-2008 18:46  app-1.4.1
## configureオプションの表示
# paco -o app
--disable-hoge --enable-extension
## 現在のバージョンをtarボール化
# pacoball -b app-1.4.1
app-1.4.1.paco.tar.bz2
## tarボール化したものに戻す
# tar jtvf app-1.4.1.paco.tar.bz2

参考
Pacoでソースからインストールした物を管理する – WapBox
paco – a source code pacKAGE oRGANIZER for Unix/Linux
pacoでソースから導入したパッケージを管理する | Glide Note – グライドノート

Graft

次に見つけたのがこのGraftです。
pacoより機能面では劣るものの、ずいぶん昔から存在していたようです。
しかし、使ってる人の情報がほとんどない・・・。非常にシンプルが故に簡単に使うことができます。
衝突回避のためのPruneという機能がユニークです。

インストール

# graft -i app-1.4.1

アンインストール

# graft -d app-1.4.1

その他

## 衝突回避のためのPrune機能。既存ファイルが.pruned拡張子にリネームされる
# graft -p app-1.4.1

Graftの詳細記事はこちら
tarボールソースからインストールしたソフトを管理する「Graft」を使ってみる – フタなしカンヅメ

Stow

次は、Stow(すとーんと読むのかな?)です。
これもけっこう有名な物のようで、色々なサイトで紹介されていました。
モデルとしてはGraftと似ているようですが、Graftより機能が少ないようです。
たぶんこっちのStowのほうが古い。

インストール

# stow -t /usr/local/bin app-1.4.1

アンインストール

# stow -D app-1.4.1

その他

## 既存のファイルを更新した時の再処理(再読込)
# stow -R app-1.4.1

調べてみた感じだと、paco >> Graft >> Stowという印象です。後発であるpocoは機能面で優れており、色々便利な機能がたくさんあるので、新しく使うならpocoが良さそうです。
シンプルで最小限の機能だけで十分ということであれば、Graftがよさそうです。

RPMのDBがぶっ壊れた

いつものようにyumでパッケージを更新しようとしたらハングしてしまう。

# yum update
Loaded plugins: fastestmirror ## ここで止まってしまう

再起動して、またアップデートを実行してみたら、今度は次のようなエラーが表示された。

# yum update
error: rpmdb: damaged header #1304 retrieved -- skipping.
エラー: rpmdbNextIterator: スキップします。 h#    1304 タグ[60]: 異常です。tag 33281 type 4 offset 42564 count 1

またyumのキャッシュがおかしくなったのかと思い、yum clean allを実行してみたが同様にハングしてしまう。調べてみた所、RPMのDBが壊れているようで、DBを再構築することで対応できました。

# rpm --rebuilddb
zsh: segmentation fault  rpm --rebuilddb ## 一度目はこんなエラーがだた。
## /var/lib/rpm/ 以下のファイルをバックアップして、削除後にもう一度実行。
# rm /var/lib/rpm/*
# rpm --rebuilddb

参考サイト
RPM DB リビルド – まーのすけRoom
404 Not Found | Web、スマートフォンのオフショア開発 バイタリフィ

iptablesのセッション管理テーブルの上限を上げる

下記のようなログが出るようになったので、調べてみるとiptablesのセッション管理テーブルを使い果たすと出てくるエラーみたいです。

Jul 24 19:25:44 www-02 kernel: printk: 39 messages suppressed.
Jul 24 19:25:44 www-02 kernel: ip_conntrack: table full, dropping packet.

下記のURLを参考にnet.ipv4.ip_conntrack_maxの上限を上げてみたところ、エラーは出なくなった。とりあえず、これで様子見。

処理するセッション数が増えると、突然通信できなくなる(又は検査できなくなる。)(ip_conntrack数の変更) – 覚え書き Plus!

fon2405EルータにDD-WRTを入れる

iPadを買った時にfonという無線ルータをもらいました。どうせなので、色々いじってみたいと思い、改造ファームウェアを入れてみることにしました。

ファームウェアを書き換えるには、シリアルケーブルで接続する必要があるようで、fonの基盤に直接ケーブルをハンダ付けします。
SSHやtelnetなどの接続も試みましたが、このfonでは無理なようでした。
下記サイトを参考にしました。
unix is mine oyster, which I with code will open!: FON2405Eの中身
FONルータ復旧大作戦 | このいえ
DD-WRT – FoNまとめwiki
[FON] –  
Hot Tuna Labs

今回用意したのは、9-KEというシリアルケーブルと、fon本体のみです。9-KEは、ネット通販で送料込み数百円くらいでした。
ちなみにハンダ付けは今回が初めてで、以前から電子工作に興味があったので、これを機会にやってみようと思ったわけです。

なんとか取り付けることができ、シリアル経由でコンソールに繋いでみた所、起動ログがちゃんと流れてきました。ちょっと感動。

こんなログが流れてきました。

U-Boot 1.1.3 (Jan  6 2010 - 07:10:30)
Board: Fonera
DRAM:  32 MB
relocate_code Pointer at: 81fac000
spi_wait_nsec: 3e
spi deice id: c2 20 15 c2 20 (2015c220)
find flash: mx25l1605d
raspi_read: from:41030000 len:1000
Using default environment
##### The CPU freq = 320 MHZ ####
SDRAM bus set to 16 bit
SDRAM size =32 Mbytes
Please choose the operation:
1: Boot system code via Flash (default).
2: Load system code then write to Flash via TFTP.
3: Entr boot command line interface.
booting from flash
## Booting image at bf020000 ...
raspi_read: from:20000 len:40
Image Name:   MIPS OpenWrt Linux-2.6.21
Created:      2010-02-11   8:09:34 UTC
Image Type:   MIPS Linux Kernel Image (lzma compressed)
Data Size:    613723 Bytes = 599.3 kB
Load Address: 80000000
Entry Point:  80000000
raspi_read: from:20040 len:95d5b
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 32
Starting kernel ...
LINUX started...
THIS IS ASIC
Linux version 2.6.21 (blogic@blap4) (gcc version 4.1.2) #143 Thu Feb 11 09:09:18 CET 2010
The CPU feqenuce set to 320 MHz
CPU revision is: 0001964c
Determined physical RAM map:
memory: 02000000 @ 00000000 (usable)
Built 1 zonelists.  Total pages: 8128
Kernel command line: console=ttyS1,57600n8 root=/dev/mtdblock4 init=/sbin/preinit
Primary instruction cache 32kB, physically tagged, 4-way, linesize 32 bytes.
Primary data cache 16kB, 4-way, linesize 32 bytes.
Synthesized TLB refill handler (20 instructions).
Synthesized TLB load handler fastpath (32 instructions).
Synthesized TLB store handler fastpath (32 instructions).
Synthesized TLB modify handler fastpath (31 instructions).
Cache parity protection disabled
cause = 80800000, status = 1100ff00
PID hash table entries: 128 (order: 7, 512 bytes)
calculating r4koff... 0030d400(3200000)
CPU frequency 320.00 MHz
Using 160.000 MHz high precision timer.
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 30416k/32768k available (1689k kernel code, 2352k reserved, 186k data, 100k init, 0k highmem)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
Generic PHY: Registered new driver
NET: Registered protocol family 2
Time: MIPS clocksource has been installed.
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
was not able to assign mahjor 200 to button chardev
ramips_gpio: done
squashfs: version 3.2-r2 (2007/01/15) Phillip Lougher
squashfs: LZMA suppport for slax.org by jro
io scheduler noop registered
io scheduler deadline registered (default)
ramips_wdt: loaded
Serial: 8250/16550 driver $Revision: 1.3 $ 2 ports, IRQ sharing disabled
serial8250: ttyS0 at I/O 0xb0000500 (irq = 37) is a 16550A
serial8250: ttyS1 at I/O 0xb0000c00 (irq = 12) is a 16550A
PPP generic driver version 2.4.2
NET: Registered protocol family 24
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky <[email protected]>
deice id : c2 20 15 c2 20 (2015c220)
mx25l3205d(c2 20160000) (4096 Kbytes)
mtd .name = raspi, .size = 0x00400000 (4M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
ramips_mtd: kernel size is 613787
padded kernel is 00096000
Creating 6 MTD partitions on "raspi":
0x00000000-0x00010000 : "uboot"
0x00010000-0x00020000 : "boardconfig"
0x00020000-0x00200000 : "image"
0x00020000-0x000b6000 : "linux"
mtd: partition "linux" doesn't end on an erase block -- force read-only
0x000b6000-0x001f0000 : "rootfs"
mtd: partition "rootfs" doesn't start on an erase block boundary -- force read-only
mtd: partition "rootfs" set to be root filesystem
0x001f0000-0x00200000 : "uci_overlay"
Registered led device: power
Registered led device: wps
Registered led device: wlan
nf_conntrack version 0.5.0 (256 buckets, 2048 max)
IPv4 over IPv4 tunneling driver
ip_tables: (C) 2000-2006 Netfilter Core Team, Type=Linux
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
802.1Q VLAN Support v1.8 Ben Greear <[email protected]>
All bugs added by David S. Miller <[email protected]>
ramips: ethernet loaded
ramips_eth: loaded
VFS: Mounted root (squashfs filesystem) readonly.
Freeing unused kernel memory: 100k freed
Warning: unable to open an initial console.
Preinit complete, spawning microd
found uci_overlay -> /dev/mtd5
i found OPENWRT_UCI_OVERLAY inside /dev/mtd5
loading file zepttho 275
loading file wireless 696
loading file user 70
loading file system 72
loading file reg 16
loading file network 473
loading file led 342
loading file lang 33
loading file form 4768
loading file fonsmcd 290
loading file fon 4Algorithmics/MIPS FPU Emulator v1.5
07
loading file firewall 907
loading file passwd 149
loading file chilli.conf 566
loading fon config
Spawning syslogd
registering led wps -> /sys/class/leds/wps/
registering led wlan -> /sys/class/leds/wlan/
registering led power -> /sys/class/leds/power/
loading base firewall ...iptables: Chain already exists
done
adding zone wannet
adding zone lan
adding zone wan
adding zone hotspotwifi
adding zone hotspot
adding forwarding lan->wan
adding forwarding hotspot->wan
interface loopback
proto = static
ipaddr = 127.0.0.1
netmask = 255.0.0.0
ifname = lo
interface lan
proto = static
ipaddr = 192.168.10.1
netmask = 255.255.255.0
ifname = eth0.1
type = bridge
interface wan
proto = dhcp
ifname = eth0.2
interface hotspot
ifname = tun0
interface hotspotwifi
proto = none
ifname = ra1
net event up loopback ...bringing up lo
done
net event up lan ...bringing ueth0.1: dev_set_promiscuity(master, 1)
p eth0.1
device eth0 entered promiscuous mode
device eth0.1 entered promiscuous mode
br-lan: port 1(eth0.1) entering learning state
adding br-lan to zone lan
done
net event up wan ...bringing up eth0.2
Spawning udhcpc for eth0.2
udhcpc (v0.9.9-pre) started
Trying to connect...
sending -> "udhcpc|deconfig|eth0.2|"
adding eth0.2 to zone wan
Sending discover...
done
wifi device rt305x
type = rt305x
channel = 11
mode = 9
wifi interface public
ifname = ra1
ssid = FON_FREE_INTERNET
encryption = none
network = hotspotwifi
device = rt305x
isolate = 1
auto = 1
wifi interface private
ifname = ra0
ssid = MyPlace
encryption = wpa-wpa2
key = 4141414141
password = ueriehaeph
wpa_crypto = mixed
network = lan
device = rt305x
channel = 0
mode = bgn
txpower = 100
br-lan: topology change detected, propagating
br-lan: port 1(eth0.1) entering forwarding state
rt2860v2_ap: module license 'unspecified' taints kernel.
Sending discover...
WSending discover...
0x1300 = 00064380
bringing up rt30device ra0 entered promiscuous mode
5x ...done
br-lan: port 2(ra0) entering learning state
Terminate the task(RtmpCmdQTask) with pid(202)!
Terminate the task(RtmpWscTask) with pid(203)!
br-lan: port 2(ra0) entering disabled state

しかし、入力を一切受け付けてくれません。どうやら制限が入っているようで、こちらの操作を受け付けないようになっているようです。
これではファームウェアの更新はできません…。色々試してみたものの、結局解決には至りませんでした。残念。

f:id:happytar0:20100719003100j:image

配線を4本ハンダ付けしてしまったり、他の線と干渉?しちゃったりで、電子工作はやっぱりたいへんだなという感じでしたが、面白かったのでこれからもいじっていきたいです。

mixiアプリでRESTful APIを使う

今さらながらmixiアプリでRESTful APIが使えることに気づいたわけで、早速試してみました。

mixiデベロッパー向けサイトに、サンプルコードも付いて詳しく説明されているので、これを参考にして書いていけば問題なさそうです。

実際のリクエストには、「Consumer Key」と「Consumer Secret」を使い、2-legged OAuthによって適切に署名をする必要があります。
「Consumer Key」と「Consumer Secret」は、アプリごとに割り当てられており、mixiアプリ設定画面より、確認することができます。

注意する点は「xoauth_requestor_id」をリクエストに付加する必要があるということです。公式サイトから引用です。

RESTful APIにアクセスする際に、xoauth_requestor_idパラメータによって、誰の権限でアクセスを行うかを指定することが必要になります。パラメータ値は、対象ユーザのIDとなります。このユーザIDについて、「一定時間内にWebブラウザで対象のmixiアプリを起動したユーザ」のIDのみ指定することが可能です。

対象ユーザが対象のmixiアプリを起動していない、もしくは起動から一定時間が経過した後にRESTful APIにアクセスを行った際には、HTTPレスポンスコードとして「401 Unauthorized」が返却されます。

対象ユーザのID、すなわちコンテナから送られてくる「opensocial_viewer_id」を指定することになります。

下記のようなコードで動かすことが出来ました。署名にはoauthライブラリを使います。

  require 'oauth'
consumer = OAuth::Consumer.new(「アプリのConsumer Key」,
「アプリのConsumer Secret」,
{:site => 'http://api.mixi-platform.com'})
end_point = 'http://api.mixi-platform.com/os/0.8'
req = consumer.request(:get, end_point + '/people/@me/@self' + '?xoauth_requestor_id=' + opensocial_viewer_id)
JSON.parse(req.body) # JSONデータをオブジェクト化

公式にはRubyのコードがなかったようなので載せておきます。

PHP版Shindigが上手く動かない

オープンソーシャルのアプリを開発する上で、必須といえるShindigShindigでコンテナを構築すればローカルでオープンソーシャルの開発をすることが出来ます。
そこでちょっとハマったことを記録として残しておきます。

まずShindigには、色々なバージョンがある上にJava版とPHP版の二種類が存在します。
以前開発に使っていたのはJava版で、PHPで上手く動かすことが出来なかったため使っていました。が、、、HAS_APPフィルタがなぜか上手く動かない事に気づき、調べてみたもののJavaがほとんど分からず、これを機会にPHP版を新たにインストールしてみた訳です。

Shindigをインストールする

ShindigApacheの所で開発されているようで、下記からダウンロードできます。
Shindig – Download
今回は、Currentの「shindig-1.1-BETA5-incubating-php.zip」を使いました。SVNリポジトリから落とすと、Java版も含まれているため、ディレクトリパスの設定がちょっとめんどうだと思います。

zipを展開し、Webからアクセス出来るように各々で設定してください。注意点は、.htaccessも含まれており、mod_rewriteも必要になるということです。

<VirtualHost *:80>
ServerName shindig.localhost.man
DocumentRoot /home/wwww/shindig # zipを展開したディレクトリ
<Directory />
AllowOverride All # .htaccessを読み込めるようにする
</Directory>
</VirtualHost>

URLパラメータ付きでも動くようにする

上記のようにインストールすれば、とりあえずは動くのですが、僕が使う上でちょっと不便な部分があったので修正しました。
それは、コンテナのURLにパラメータが指定されている場合に上手く動かなかった事です。
正しくパラメータを処理できず、「400 – Bad Request」となってしまいます。

http://shindig.localhost.man/gadgets/files/container/container.html?view=canvas
こんな感じで引数で画面を切り替えていました。

# src/gadgets/servlet/FileServlet.php
# 40行目の下にパラメータを無視するようなコード追加
#
$file = str_replace(Config::get('web_prefix') . '/gadgets/files/', '', $_SERVER["REQUEST_URI"]);
$file = Config::get('javascript_path') . $file;
// ここを追加
$file = substr($file, 0, strlen($file) - strlen(strstr($file, '?')));
// make sure that the real path name is actually in the javascript_path, so people can't abuse this to read
// your private data from disk .. otherwise this would be a huge privacy and security issue
if (substr(realpath($file), 0, strlen(realpath(Config::get('javascript_path')))) != realpath(Config::get('javascript_path'))) {

署名付きリクエストに対応する

署名付きリクエストとは何か、それはオープンソーシャル開発をする上、外部サーバを呼び出したい場合にとても重要になってきます。「makeRequest」というJavaScript関数を使用し、外部サーバに非同期にリクエストを送るわけですが、ここで重要なのは、リクエストが改ざんされないように署名するということです。

Shindigで署名付きリクエストを使うために、opensslで秘密鍵と証明書を作成します。

$ openssl req -newkey rsa:1024 -days 365 -nodes -x509 -keyout test.pem -out test.pem -subj '/CN=mytestke
$ openssl pkcs8 -in test.pem -out private.key -topk8 -nocrypt -outform PEM

とりあえず: [Apache Shindig][お勉強][OpenSocial] メモ118 gadgets.io.makeRequest 認証認可タイプSIGNEDをやってみる(RSA-SHA1で署名)

出来た証明書と鍵をcertsディレクトリに保存し、Shindigの設定ファイルを書き換えます。

# config/container.php
'private_key_file' => realpath(dirname(__FILE__) . '/../certs') . '/private.key',
'public_key_file' => realpath(dirname(__FILE__) . '/../certs') . '/test.pem',
'private_key_phrase' => '',

これで問題なしと思われたのですが、上手く署名付きリクエストをおこなう事が出来ませんでした。

パラメータ付きURLから上手くmakeRequestがおこなえない

makeRequestで外部サーバを呼び出すときに、パラメータを付加すると上手く動かないという現象が発生しました。

var url = 'http://localhost/gadget/canvas?ts=1277893054';
gadgets.io.makeRequest(url, null, this.makeParams(data));

タイムスタンプ値を末尾に付加してリクエストを送っていたのですが、「?ts=1277893054」が問題で、このパラメータを上手く処理出来ていないために失敗しているようでした。

# src/gadgets/oauth/OAuth.php
# 186行目のbuild_signatureが実際に署名をおこなっている箇所になります。
public function build_signature(&$request, OAuthConsumer $consumer, $token) {
$base_string = $request->get_signature_base_string();
// Fetch the private key cert based on the request
$cert = $consumer->getProperty(OAuthSignatureMethod_RSA_SHA1::$PRIVATE_KEY);
// Pull the private key ID from the certificate
//FIXME this function seems to be called both for a oauth.json action where
// there is no phrase required, but for signed requests too, which do require it
// this is a dirty hack to make it work .. kinda
if (! $privatekeyid = @openssl_pkey_get_private($cert)) {
if (! $privatekeyid = @openssl_pkey_get_private($cert, Config::get('private_key_phrase') != '' ? (Config::get('private_key_phrase')) : null)) {
throw new Exception("Could not load private key");
}
}
// Sign using the key
$signature = '';
if (($ok = openssl_sign($base_string, $signature, $privatekeyid)) === false) {
throw new OAuthException("Could not create signature");
}
// Release the key resource
@openssl_free_key($privatekeyid);
return base64_encode($signature);
}

openssl_pkey_get_private関数によって、秘密鍵を取得し、$base_stringに対して署名していることが分かります。この$base_stringの中身はこうなっていました。

POST&http%3A%2F%2Flocalhost%3A3000%2Fgadget%2Fcanvas&dummy%3D1%26oauth_consumer_key%3Dcont%26oauth_nonce%3D96bd6e6d4103d3c5197f26d5dd6e3463%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1277893517%26oauth_token%3D%26opensocial_app_id%3Dappid%26opensocial_app_url%3Durl%26opensocial_owner_id%3Djohn.doe%26opensocial_viewer_id%3Djohn.doe%26ts%3D1277893516%26xoauth_public_key%3Dhttp%253A%252F%252Fshindig.localhost.man%252Fpublic.cer%26xoauth_signature_publickey%3Dhttp%253A%252F%252Fshindig.localhost.man%252Fpublic.cer

この時に「ts%3D1277893516」の文字列があり、パラメータ「ts」も含めて署名されている事が分かります。

続いて実際に外部サーバにリクエストを送る部分です。

# src/gadgets/SigningFetcher.php
# 111行目のsignRequestが送信リクエストを作成します。
# 174行目にクエリーストリングを処理する箇所があり、送信先リクエストにパラメータを追加して渡しています
$newQuery = '';
foreach ($req_req->get_parameters() as $key => $param) {
if (! isset($forPost[$key])) {
$newQuery .= urlencode($key) . '=' . urlencode($param) . '&';
}
}
# 問題の箇所
// and stick on the original query params too
if (isset($parsedUri['query']) && ! empty($parsedUri['query'])) {
$oldQuery = array();
parse_str($parsedUri['query'], $oldQuery);
foreach ($oldQuery as $key => $val) {
$newQuery .= urlencode($key) . '=' . urlencode($val) . '&';
}
}

一見問題ないように見えますが、$req_req->get_parameters関数が返す値には、既にクエリーストリングも処理されており、二重でクエリーストリングが処理されていることになります。
パラメータの二重化によって、署名されたリクエストと異なる値になってしまい、外部サーバでの署名確認時にエラーとなってしまいます。

パラメータが二重処理されたリクエストです。パラメータ「ts」が二つあることが分かります。

http://localhost/gadget/canvas?oauth_nonce=0c8c8040978beed7b0221f655ef50303&oauth_timestamp=1277893863&oauth_consumer_key=cont&ts=1277893863&opensocial_owner_id=john.doe&opensocial_viewer_id=john.doe&opensocial_app_id=appid&opensocial_app_url=url&oauth_token=&xoauth_signature_publickey=http%3A%2F%2Fshindig.localhost.man%2Fpublic.cer&xoauth_public_key=http%3A%2F%2Fshindig.localhost.man%2Fpublic.cer&oauth_signature_method=RSA-SHA1&oauth_signature=KTo5X7QxKg8mSpDiaGjljeyKAlmdMLO%2BbPrAr0qYycqAzqTSw8t44p2lXmdRZendFwEpbKLPZy9tAoJ98X9YVkOHjXsp6D19%2BtFBCgSQDJzuvWxHC6xKiRnw2iR0M0HcKSNeMf6x45W%2FJM9rwxT%2BdUYrDZ%2BO4IKbq1etvQj6nWs%3D&ts=1277893863&

src/gadgets/SigningFetcher.phpの181行目〜187行目までをコメントアウトすることで回避できます。

html_sanitize is not defined

これでようやく署名付きリクエストに対応出来たかと思われましたが、次に新たな問題が発生しました。
コンテナ内で「Tabs」Featureを利用した時に「html_sanitize is not defined」というJavaScriptエラーが出ることです。
どうやら、core Featureでhtml-sanitizer.jsというのを読み込むコードが足りないようです。

# src/gadgets/GadgetFeatureRegistry.php
// Make html-santitization work see SHINDIG-346
if ($content == 'res://com/google/caja/plugin/html-sanitizer.js') {
$content= 'http://google-caja.googlecode.com/svn/trunk/src/com/google/caja/plugin/html-sanitizer.js';
} 

このような記述があり、html-sanitizer.jsだけ特別な処置がされているようです。
今回は、Tabs Featureにhtml-sanitizer.jsを読み込ませるコードを追加します。具体的には、feature.xmlに以下のように追加します。

# features/src/main/javascript/features/tabs/feature.xml
<feature>
<name>tabs</name>
<gadget>
<!-- for gadgets.util.sanitizeHtml -->
<script src="res://com/google/caja/plugin/html-sanitizer.js"/>
<script src="tabs.js"/>
<script src="taming.js"/>
</gadget>
</feature>

これでまともに使えるようになりました。PHP版Shindigは地雷が多いのでJava版を使ったほうが簡単ということでしょうか。それともやり方がおかしいのか・・・?

ブラウザでP2P通信、ファイル転送が出来るのか

P2Pと聞くとマイナスのイメージを持ってしまいますが、P2P技術が使われているプロダクトは意外に多いのではないかと思います。

もちろん、P2Pを利用する上での長所・短所はあります。
長所は、通信帯域を多く使うアプリケーションの場合、サーバを介さずに通信が出来るためコストを抑えることができ、Winnyに代表されるように匿名性やスケーラビリティといった耐障害性の観点からもメリットがあります。
逆に短所は、実装が困難な点やノード管理の複雑さ、接続先のネットワーク環境に左右されうる点などがあると思います。

特に通信帯域を多く使うような場面での効果は絶大です。動画や音声配信などの通信帯域を使う場面はどんどん増えていっています。
この状況下(1年くらい前?)で、FlashPlayer1.0から実装されたのがRTMFP(Real Time Media Flow Protocol)というプロトコルです。
これはUDPを使い、ユーザ間同士で直接通信することができるような夢のような機能です。

少し気になるのはUDP?というわけですが、これにはいくつか理由があるようです。動画や音声送信などのリアルタイム性(遅延が少ない)を求める場面で有利ということや、NAT越えもし易いってこともあるんじゃないでしょうか。

コネクションレスUDPでは、遅延が少ないといってもちゃんと届いている不安な感じですが、信頼性を上げるために輻輳処理や暗号化などが取り入れられているそうです。詳しくは下記参照。
Flash Player 10.1 と RTMFP – akihiro kamijo

あともう一つ、このプロトコルではStratusという中央サーバが必要であり、ハイブリッドP2Pであるということが言えます。Stratusは現在Adobeのサイトにて無償開放されていますが、将来的にはFMSに取り込まれるのではないかと思います。
Cirrus | Real Time Media Flow Protocol (RTMFP) – Adobe Labs

NAT越えは、UDPホールパンチングという方法を使っているそうで、最初に中央サーバに接続する事で実現しているようです。アウトバウンドのUDPが使える環境で、なおかつルータがNATトラバーサルに対応している必要があるという条件は限られますが、多くの環境では使えるのではないかと思います。信頼性を重視するサービスの場合、既存のRTMP等のプロトコルと併用します。

そして6月になり、FlashPlayer10.1が正式リリースされました。新たに10.1で導入された機能にピアアシストネットワークというものがあります。
これはノード同士をグループ化することができ、自律したネットワークを構成してくれるという優れものです。詳しくは下記参照。
Flash Player 10.1 と RTMFP (ピアアシストネットワーク) – akihiro kamijo

そんなこんなでFlashでP2Pを利用できる環境がばっちり整ってきた訳で、早速何か作ろうかと考えて出来たのが、ブラウザ間でファイルをP2P転送することが出来るWebサービスです。
We're sorry, but something went wrong (500)

まだ公開したばかりですが、上に書いたようにビアアシストネットワークを使ったりすれば、もう少し便利になるのではないかという感じです。他のサービスにも応用出来そうなので色々作れればいいなーと思います。

ひかりone(BL190HW)でYAMAHAのルータ(RTX1200)を使う

ひかりoneで他のルータを使う方法をまとめてみます。

付属のルータ(HGW)は「BL190HW」というもので、ひかりone自体はDHCPによってグローバルIPアドレスを割り振っているようです。この時にHGWのMACアドレスを参照しているため、他のルータなどに置き換えた場合、正常にIPアドレスが割り振られません。

MACアドレスをHGWのものに書き換えることが出来るルータならば、恐らくそのまま置き換えることが出来るのではないかと思います。
ひかりoneギガ得プランでRTX1200 – フタなしカンヅメ

今回は手持ちのRTX1200を使いたいので、MACアドレス書き換えなどは使えません。
ですので、RTX系ルータを使う場合はHGWを間に接続する必要があります。

+-----+    +-----+    +-----+
| ONU +----+ HGW +----+ RTX +
+-----+    +-----+    +-----+
DHCP(*1)   DMZ(*2)

*1) DHCPでグローバルIP割り当て
*2) HGWのDMZを使ってRTXにそのまま流す

上の図のように各機器を接続します。
HGWの代わりにRTX1200を使いたいので、HGWのDMZ機能を使って全てのパケットをRTX1200にそのまま流します。

BL190HWのDMZ機能ついてはこちら
DMZホスト機能

以下のようなローカルネットワークを構築することにします。

HGWとRTX間のネットワークは、192.168.99.0/24
HGWのDMZホスト機能をオンに設定し、192.168.99.2をDMZのIPアドレスとして設定
---
DMZで設定した「192.168.99.2」を使ってHGW-RTX間で通信
RTXにぶら下がってるネットワークは、129.168.101.0/24
RTXの下に「192.168.101.2」としてサーバを1台設置
「192.168.99.2」と「192.168.101.2」を静的NATを設定
                    192.168.99.2
|
+-----+    +-----+    +-----+    +-----+
| ONU +----+ HGW +----+ RTX +----+ P C | 192.168.101.2
+-----+    +-----+    +-----+    +-----+
192.168.99.0/24   192.168.101.0/24

RTX1200には以下のような設定をします。

ip route default gateway 192.168.99.1 filter 1001
lan type lan1 auto port-based-option=divide-network
ip vlan1 address 192.168.101.1/24
ip lan3 address 192.168.99.2/24
ip lan3 nat descriptor 1
ip filter 1001 pass 192.168.101.0/24 * * * *
nat descriptor type 1 nat
nat descriptor address outer 1 192.168.99.2
nat descriptor address inner 1 192.168.101.2
nat descriptor static 1 1 192.168.99.2=192.168.101.2 1

LAN3ポートにHGWを接続し、LAN1ポートのvlan1にサーバ側のLANを接続します。
フィルタリングは何もしていませんので、各自環境にあった正しい設定をおこなったほうがいいと思います。
ど素人なので参考程度にということでお願いします。

海外VPSや専用サーバの比較

ずいぶん更新していなかったので久しぶりに記事を・・・。
海外のサーバをいくつか借りてみたので詳細をまとめてみます。

金額やスペック

種類 名前 金額 CPU HDD メモリ OS 備考
専用サーバ The Planet $89 Celeron2.0GHz 80GB 512MB Linux全般、FreeBSD、WindowsServer クレジットの審査が厳しい。サポートは早くてすごい。
専用サーバ XLhost $69 DualCoreE2200 80GB 1GB LinuxFreeBSD、Windows。めっちゃ多い 一日で使える。PayPalも使える。
専用サーバ SH3LLS $69 DualCoreAtom 500GB 1GB LinuxFreeBSD、Windows。 サポートが遅い。三日くらいで使える。めっちゃ怪しいがちゃんと使えた。
VPS IX Web Hosting $39.95 XeonE5400 10GB 384MB Linuxちょい少ない Virtuozzo。三日くらいかかる。
VPS Known Host $25 不明 10GB 192MB CentOS5、選択できない? Virtuozzo。即日で使える。
VPS Linode $19.45 不明 16GB 360MB 管理画面から自分で選択 Xen。即日。
VPS PhotonVPS $10.95 8コアCPU 20GB 512MB Linuxのみ Virtuozzo、Xen。即日。サポートが感じ悪い。
VPS VPSLink $7.95 不明 2.5GB 64MB Linuxのみ Virtuozzo、Xen。金を払うと即使える。全てオートメーション化されてる。

海外だと専用サーバもけっこう安いけど、さくらインターネットでも7800円ほどなのでどうだろう?
日本だとまともなところが少ないVPSも海外だといい所がたくさんある印象。VirtuozzoのVPSはカーネルが更新できない?っぽいのでちょっと不便な気がする。

VirtuozzoのVPSはいずれも audit_log_user_command() のようなエラーが出てくる。カーネルを更新すれば直るっぽいけど、出来ないようので直せない・・・問題ないっぽいけど・・・。(再起動すると元に戻る?)
あとはiptablesを使うときにちょっと問題があった。ip_conntrack_ftp モジュールが入ってなくて、入れるにはどうやらカーネルを入れなおす必要があったけど、これも無理っぽかった。この辺りが使っていく上で問題になってくるかも。他にやり方があったら教えてくださいでござる。

各サーバのレスポンス(PING)

名前 応答時間
The Planet 172 ms
XLhost 162 ms
SH3LLS 141 ms
IX Web Hosting 181 ms
Known Host 111 ms
Linode 121 ms
PhotonVPS 110 ms
VPSLink 135 ms

どこもものすごく差があるわけではなさそうです。ちなみに一番長いLinodeのサーバを半年程度使っていますが特にトラブルなく使えてます。

lsyncdがおかしい

lsyncdをしばらく使っていて妙なエラーが出るようになった。

Mon Nov 23 07:51:34 2009: ERROR: Cannot add watch /home/www/hogehoge (28:No space left on device)

どうやらinotifyの監視対象ファイルが多くなったせいで、上限に引っかかってエラーになっていたみたい。
404 – エラー: 404
今の設定はどうなっているのだろうと、調べて見ると以下のような感じになっていた。

$ cat /proc/sys/fs/inotify/max_user_watches
8192

以下のサイトを参考に上限を変更した所、無事にエラーも消えました。
lsyncdの制限 – kame-tの日記