package hudson.plugins.ipmsg.tk.ipmsg;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
/**
* @author Naoki Takezoe
*/
public abstract class IPMessenger extends Thread {
protected String userName;
protected String nickName;
protected String group;
protected String hostName;
protected DatagramSocket socket;
protected boolean absenceMode;
protected String absenceMsg;
protected int in_port;
protected boolean debug;
private boolean loopFlag;
// �z�X�g�ƃ��[�U���̃}�b�s���O���s���}�b�v
private HashMap userNames = new HashMap();
/** ����M�Ɏg�p���镶���R�[�h */
private static String CHARSET = "MS932";
/**
* �f�t�H���g�̃R���X�g���N�^�B
*/
public IPMessenger(){
}
/** �f�o�b�O���[�h��true�̂Ƃ��W���o�͂Ƀf�o�b�O���b�Z�[�W���o�͂��܂��B*/
protected void debugMessage(String message){
if(debug){
System.out.println(message);
}
}
/**
* �R���X�g���N�^�B
*
* @param userName ���[�U��
* @param nickName �j�b�N�l�[��
* @param group �O���[�v��
* @param debug �f�o�b�O���[�h
*/
public IPMessenger(String userName,String nickName,String group,boolean debug) throws IOException {
this.userName = userName;
this.nickName = nickName;
this.group = group;
this.hostName = InetAddress.getLocalHost().getHostName();
this.absenceMode = false;
this.absenceMsg = "";
this.socket = new DatagramSocket(Constants.PORT);
this.in_port = Constants.PORT;
this.debug = debug;
}
/**
* ���O�C�����܂��B
*/
public void login() throws IOException {
broadcastMsg(makeTelegram(Constants.IPMSG_BR_ENTRY|Constants.IPMSG_BROADCASTOPT,
this.nickName+"\0"+this.group));
this.loopFlag = true;
}
/**
* ���O�A�E�g���܂��B
*/
public void logout() throws IOException {
broadcastMsg(makeTelegram(Constants.IPMSG_BR_EXIT|Constants.IPMSG_BROADCASTOPT,
this.nickName+"\0"+this.group));
this.loopFlag = false;
}
/**
* �s�ݎ҃��[�h
*/
public void absence(String msg,boolean mode) throws IOException {
int command;
if(mode){
if(msg==null || msg.equals("")){
this.absenceMsg = "ABSENCE";
} else {
this.absenceMsg = "[" + absenceMsg + "]";
}
this.absenceMode = true;
command = Constants.IPMSG_BR_ABSENCE|Constants.IPMSG_ABSENCEOPT;
} else {
this.absenceMsg = "";
this.absenceMode = false;
command = Constants.IPMSG_BR_ABSENCE;
}
broadcastMsg(makeTelegram(command,this.nickName+this.absenceMsg+"\0"+this.group));
}
/**
* ���b�Z�[�W��M���Ƀt�b�N����钊�ۃ��\�b�h�ł��B
* �A�v���P�[�V�����ŗL�̏������������Ă��������B
*
* @param host ���M�҂̃z�X�g��
* @param user ���[�U��
* @param msg ���b�Z�[�W
* @param lock �������ǂ���
*/
public abstract void receiveMsg(String host,String user,String msg,boolean lock);
/**
* ���b�Z�[�W�𑗐M���܂��B
*/
public void sendMsg(String host,String msg,boolean secret) throws IOException {
int mode = 0;
if(secret){ mode = Constants.IPMSG_SECRETEXOPT; }
send(makeTelegram(Constants.IPMSG_SENDMSG|mode, msg), host, in_port);
}
/**
* �����o�[�lj����Ƀt�b�N����郁�\�b�h�ł��B
* �A�v���P�[�V�����ŗL�̏������������Ă��������B
*
* @param host
* @param nickName
* @param group
* @param addr
* @param absence
*/
public abstract void addMember(String host,String nickName,String group,String addr,int absence);
/**
* �����o�[�폜���Ƀt�b�N����郁�\�b�h�ł��B
* �A�v���P�[�V�����ŗL�̏������������Ă��������B
*
* @param host
*/
public abstract void removeMember(String host);
/**
* �������b�Z�[�W�̊J�����Ƀt�b�N����郁�\�b�h�ł��B
* �A�v���P�[�V�����ŗL�̏������������Ă��������B
*
* @param host
* @param user
*/
public abstract void openMsg(String host,String user);
/**
* �J���ʒm�𑗐M���܂��B
*
* @param host
*/
public void readMsg(String host) throws IOException {
send(makeTelegram(Constants.IPMSG_READMSG|Constants.IPMSG_READCHECKOPT,
String.valueOf(new Date().getTime()/1000)),host, in_port);
}
/**
* �T�[�o�̎��s�B���O�C�����start���\�b�h������s���Ă��������B
*/
public void run(){
try {
while(loopFlag){
byte[] buf = new byte[Constants.BUFSIZE];
DatagramPacket packet = new DatagramPacket(buf,buf.length);
this.socket.receive(packet);
new ChildThread(packet).start();
}
} catch(IOException ex){
ex.printStackTrace();
}
this.socket.close();
}
/**
* ���b�Z�[�W�𑗐M���܂��B
*
* @param msg ���b�Z�[�W
* @param host ���M��̃z�X�g��
* @param port ���M��̃|�[�g�ԍ�
*/
private void send(String msg,String host,int port) throws IOException {
String message = msg;
byte[] byteMsg = message.getBytes(CHARSET);
DatagramPacket packet = new DatagramPacket(byteMsg,byteMsg.length,
InetAddress.getByName(host),port);
socket.send(packet);
}
/**
*
*/
private String makeTelegram(int command,String supplement){
StringBuffer sb = new StringBuffer();
sb.append(Constants.PROTOCOL_VER);
sb.append(":");
sb.append(new Date().getTime()/1000);
sb.append(":");
sb.append(this.userName);
sb.append(":");
sb.append(this.hostName);
sb.append(":");
sb.append(command);
sb.append(":");
sb.append(supplement);
return sb.toString();
}
/**
*
*/
private void broadcastMsg(String msg) throws IOException {
String message = msg;
byte[] byteMsg = message.getBytes(CHARSET);
DatagramPacket packet = new DatagramPacket(byteMsg,byteMsg.length,
InetAddress.getByName("255.255.255.255"),
in_port);
this.socket.send(packet);
}
/**
* ��������w�肵��������ŕ������A�z��ŕԂ��܂��B
*
* @param s1 �����Ώۂ̕�����B
* @param s2 �������̋��Ɏg�p���镶����B
* @return �������ʂ�z��ŕԂ��܂��Bs1��null�̏ꍇ��null��Ԃ��܂��B
*/
private static String[] split(String s1,String s2){
if(s1 == null){
return null;
}
ArrayList v = new ArrayList();
int last = 0;
int index = 0;
while((index=s1.indexOf(s2,last))!=-1){
v.add(s1.substring(last,index));
last = index + s2.length();
}
if(last!=s1.length()){
v.add(s1.substring(last));
}
return (String[])v.toArray(new String[v.size()]);
}
/**
* ��M�����p�P�b�g��������������X���b�h�N���X�B
*/
private class ChildThread extends Thread {
private DatagramPacket packet;
/** �R���X�g���N�^�B*/
public ChildThread(DatagramPacket packet){
this.packet = packet;
}
/** �p�P�b�g���������܂��B*/
public void run(){
try {
String message = new String(packet.getData(),CHARSET);
debugMessage("[MSG]" + message.trim());
String[] telegram = split(message,":");
int command = 0;
command = Integer.parseInt(telegram[4]);
int cmd_no = command & 0x000000ff;
InetAddress from = packet.getAddress();
String fromAddr = split(from.toString(),"/")[1];
String fromHost = fromAddr;
int fromPort = packet.getPort();
int packetNo = Integer.parseInt(telegram[1]);
/* port�ԍ�������Ă����珈�����Ȃ� */
if (fromPort != in_port){
return;
}
switch(cmd_no){
case Constants.IPMSG_ANSENTRY: {
String[] dim = split(telegram[5], "\0");
if (dim[0].equals("")) {
dim[0] = telegram[2];
}
userNames.put(fromHost,dim[0]);
addMember(fromHost, dim[0], dim[1], fromAddr,
Constants.IPMSG_ABSENCEOPT & command);
break;
}
case Constants.IPMSG_BR_ENTRY: {
String[] dim = split(telegram[5], "\0");
userNames.put(fromHost,dim[0]);
addMember(fromHost, dim[0], dim[1], fromAddr,
Constants.IPMSG_ABSENCEOPT & command);
if (absenceMode) {
send(makeTelegram(Constants.IPMSG_ANSENTRY | Constants.IPMSG_ABSENCEOPT,
nickName + absenceMsg + "\0" + group), fromAddr, fromPort);
}
else {
send(makeTelegram(Constants.IPMSG_ANSENTRY,nickName + "\0" + group),
fromAddr, fromPort);
}
break;
}
case Constants.IPMSG_SENDMSG: {
boolean lockFlag = false;
if ( (command & Constants.IPMSG_SENDCHECKOPT) != 0) {
int ack_cmd = Constants.IPMSG_RECVMSG;
send(makeTelegram(ack_cmd,String.valueOf(packetNo)),
fromAddr, in_port);
}
if ( (command & Constants.IPMSG_SECRETOPT) != 0) {
int ack_cmd = Constants.IPMSG_RECVMSG;
send(makeTelegram(ack_cmd,String.valueOf(packetNo)),
fromAddr, in_port);
lockFlag = true;
}
// :�ŋ��ꂽ���̂�߂�
int in_length = telegram.length;
if(telegram.length > 6){
for(int j = 6;j < in_length ;j++){
telegram[5] += ":" + telegram[j];
}
}
String nickName = (String)userNames.get(fromHost);
//receiveMsg(fromHost, telegram[2], telegram[5].trim(),lockFlag);
receiveMsg(fromHost, nickName, telegram[5].trim(),lockFlag);
break;
}
case Constants.IPMSG_READMSG: {
if ( (command & Constants.IPMSG_READCHECKOPT) != 0) {
int ack_cmd = Constants.IPMSG_ANSREADMSG;
send(makeTelegram(ack_cmd,String.valueOf(packetNo)),
fromAddr, in_port);
openMsg(fromHost, telegram[2]);
}
break;
}
case Constants.IPMSG_BR_ABSENCE: {
String[] dim = split(telegram[5], "\0");
addMember(fromHost, dim[0], dim[1], fromAddr,
Constants.IPMSG_ABSENCEOPT & command);
break;
}
case Constants.IPMSG_BR_EXIT: {
userNames.remove(fromHost);
removeMember(fromHost);
break;
}
}
} catch(IOException ex){
ex.printStackTrace();
} finally {
}
}
}
}