AnonymousLANChat

From Usipedia
Jump to: navigation, search

LAN内のみで使える匿名性を高めたピュアP2Pのチャットソフトです.

同じPC教室にいる人同士で,同じオフィスにいる人同士で,学会で同じ発表を聞いている人同士で・・・匿名のチャットが出来たら便利だと思いませんか.匿名というと聞こえが悪いですが,講義・講演へのフィードバックなど有用な状況は色々と考えられます.

PC教室やオフィスでは室内のPCに規則的なプライベートIPアドレスが割り当てられています.また,学会・イベント会場に用意されているWIFIルーターに接続しているときは個人のプライベートIPアドレスはコロコロ変わります.そういった状況では(ルーターなどの設定に依りますが)UDPのブロードキャストを使ったノード検索が可能です.誰がチャットのネットワークに参加しているのか,LAN内のPCにブロードキャストするだけで調べられます.ピュア型P2Pを使い始めるときに必ず必要だった初期ノードの交換の手間を省略できる点がいいなと思って,このソフトを作成しました.

私は高校の卒業研究でマルチプラットフォーム対応のP2Pファイル共有ソフトの開発に関わっていましたが,Rubyではなくjavaで実装する事になってからは全てtondolが開発していました.私がjavaで実装したのは確かSwingのGUI部分くらいです(余談ですが「クリックしようとすると逃げるShareのようなSwingのダイアログ」なんかも作りました).AnonymousLANChatではそこでの経験が活きているものの,ソースコードなどは一切引用していません(後述の#ソースコードの概要のようにこれの機能自体はすごく単純です).

Contents

特徴

  • Windows/Max/Linux/Android 1.6以上 の4OSに対応
  • 起動したら設定なしで即使い始められる
    • LAN内だけで完結しているのでポート開放・初期ノード設定などの手間が必要ありません
  • 発言に多段プロキシと同等の匿名性が保証される
  • 通信内容は全てAESで暗号化

スクリーンショット

左から順にWindows7/Max OS X Lion/Ubuntu 11.04 Desktop/Nexus S(Android 2.3.4)/Xperia X10(Android 2.1-update1 で動作している様子.

on Windows7on Max OS X Lionon Ubuntu 11.04 Desktopon Nexus S(Android 2.3.4)on Xperia X10(Android 2.1-update1)

ダウンロード

それぞれスクリーンショットに載っている環境で動作確認済みです

使い方

起動したら1行の方のテキストエリアに何か書きこんでSendボタンを押して下さい. 他に参加しているノードがいなかったら投稿が反映されません.

問題点

  • 参加者が4人以下だと中継ノードがいないため匿名性が確保できない
  • UDPのブロードキャストを監視し続ければチャットの参加者リストが作れる

オーバーレイの様子

非構造化オーバーレイで,メッセージは伝搬させて伝えます.一つのノードの同時接続数が多いとchurn耐性は強くなりますが,発言者の特定が簡単になってしまいます.そこで,最大接続数は4つまでにしました.端末同士のつながり方は次の画像の通りです(アルファベットはAから順に参加した順,矢印の元がconnectして先がaccept).

左:実際の様子 右:きれいに整列させた様子

一気に4つ以上のノードが離脱しないと孤立ノードが生まれません.また,孤立した際には自動で繋ぎ直します.

ソースコードの概要

環境依存のGUI部分

AndroidのMainActivity.javaやSwingのMainFrame.javaからP2Pクラスのインスタンスとそのリスナーを通して

  • Sendボタンが押されたらテキストボックスの内容をp2p.send
  • P2PListenerのonStatusChangedにP2Pクラスの動向が流れてくるのでそれをログとしてGUIに流す
  • 終了時はp2p.shutdown

などの処理をしています.

共通ライブラリ:P2P.java

public class P2P implements ConnectionListener {
	private UDPBroadcast broadcast; // ブロードキャストの送信と受信を担当
	private P2PListener p2pListener;
	private Set<Connection> clients; // ノード間の接続の間には必ずConnectionクラス
 
	private Thread acceptThread; //他のノードからのconnectを待ってacceptしたりしなかったりするスレッド
	private ServerSocket serverSocket; // acceptThread用
	private boolean destroyed; // // acceptThread用
	private ScheduledExecutorService keepConnectedService; // 他のノードとの接続を保ち続けるための10sに1回色々する
 
	// P2Pクラスの動向は分かりやすく P2PListener を通して呼び出し元に伝える
	public P2P(final P2PListener listener)
 
	public boolean connect(String ip)
	public void send(String message) // 全ての clients にメッセージ送信
	public void checkConnection() // clientsの接続確認
	public void delete(String ip) // 接続が切れた接続を削除
	public void shutdown() // ソフトの終了時に呼ぶ
 
	// ConnectionListener, clientsやbroadcastが受信した情報は全てここに集められる
	@Override public void onReceive(String message, String ip, int port) 
}
  • Connection.java

Socketのラッパーのようなものです.

public class Connection {
	private Socket socket;
	private BufferedOutputStream out;
	private BufferedInputStream in;
 
	private P2PListener p2pListener;
	private ConnectionListener connectionListener;
 
	private Thread receiveThread; // 接続先からの返信を受け取るスレッド
 
	// acceptで得られるSocketのインスタンスを元にConnectionを作る
	public Connection(Socket socket, P2PListener p2pListener, ConnectionListener connectionListener)
	// ipとportを元にConnectionを作る
	public Connection(String ip, int port, P2PListener listener, ConnectionListener connectionListener)
	// リスナーを2つも渡していて気持ち悪いけどしょうがない・・・
 
	public void start() // receiveThread開始
	public boolean send(String message) // outにメッセージを書きこむ.
	public boolean isConnected() // 接続先と本当につながっているか?
	public String getIP() // socketから接続先のIPアドレスを取得して返す
 
	public void shutdown() // 終了時に呼ぶ
}
  • StringCrypt.java

シングルトンで,AESを使った暗号化と復号化を担当しています.ConnectionやUDPBroadcastの送受信部分では全てこのStringCryptをかまします.

public class StringCrypt {
	private static StringCrypt me;
 
	public StringCrypt()
	public static StringCrypt getInstance()
	public byte[] encrypt(String text)
	public String decrypt(byte[] encrypted, int size)
}
Namespaces
Variants
Views
Actions
Categories