package com.codecronch.util.net.websocket;
import java.security.MessageDigest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import com.codecronch.util.net.http.HttpUtil;
http://yueyang.uz.taobao.com/
http://www.huihui.cn/share/32960004
http://www.huihui.cn/share/32958280
http://www.huihui.cn/share/32957358
http://www.huihui.cn/share/32956760
http://www.huihui.cn/share/32955260
http://www.huihui.cn/share/32954604
http://www.huihui.cn/share/32954146
http://www.huihui.cn/share/32953522
http://www.huihui.cn/share/32952548
http://www.huihui.cn/share/32950878
http://www.huihui.cn/share/32949902
http://www.huihui.cn/share/32949532
http://www.huihui.cn/share/32948930
http://www.huihui.cn/share/32252372
http://www.huihui.cn/share/32251552
http://www.huihui.cn/share/32251048
http://www.huihui.cn/share/32250130
http://www.huihui.cn/share/32249588
http://www.huihui.cn/share/29997150
http://www.huihui.cn/share/29996422
http://www.huihui.cn/share/29995536
http://www.huihui.cn/share/29994856
http://www.huihui.cn/share/29993976
http://www.kingmoke.cn
http://www.lvsenvshen.cn
http://www.shmcauto.com.cn
http://www.tsjqwj.com.cn
http://www.ptsbw.com.cn
http://www.sonqi.net.cn
http://www.tzcxdd.com
http://www.gongneihzp.com
http://www.aivino.com.cn
http://www.xycarpet.cn
http://yueyang.uz.taobao.com/
http://yueyang.uz.taobao.com/
/**
*
* @author lzrzhao
* 2014-2-10
*/
public class WebSocketDecoder extends CumulativeProtocolDecoder {
private static final int SESSION_TAG_SHAKE_HANDS=1;//会话握手标识 用来标识是否握手
private static final String WEBSOCKET_GUID="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
public static final byte FIN = 0x1; // 1000 0000
public static final byte OPCODE = 0x0F;// 0000 1111
public static final byte MASK = 0x1;// 1000 0000
public static final byte PAYLOADLEN = 0x7F;// 0111 1111
public static final byte HAS_EXTEND_DATA = 126;
public static final byte HAS_EXTEND_DATA_CONTINUE = 127;
@Override
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
Object attribute = session.getAttribute(SESSION_TAG_SHAKE_HANDS);
if(attribute==null){
//握手
byte[] bytes=new byte[in.limit()];
in.get(bytes);
String m = new String(bytes);
//TODO 验证是否握手请求
String secKey = getSecWebSocketKey(m);
secKey += WEBSOCKET_GUID;
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(secKey.getBytes("iso-8859-1"), 0, secKey.length());
byte[] sha1Hash = md.digest();
secKey = base64Encode(sha1Hash);
String rtn = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "+ secKey + "\r\n\r\n";
byte[] rtnbytes = rtn.getBytes("utf-8");
IoBuffer resp = IoBuffer.allocate(rtnbytes.length);
resp.put(rtnbytes);
resp.flip();
session.write(resp);
session.setAttribute(SESSION_TAG_SHAKE_HANDS,true);
return false;
}
//不够一个消息
if(in.remaining()<2){
//消息头不完整
return false;
}
in.mark();
byte head1 = in.get();
byte head2 = in.get();
// int isend =head1>>7&FIN;
int opcode=head1 & OPCODE;
if(opcode==8){
session.close(true);
return false;
}
int ismask=head2>>7&MASK;
int length=0;
byte datalength= (byte) (head2& PAYLOADLEN);
if(datalength<has_extend_data){< p="">
length=datalength;
}else if (datalength==HAS_EXTEND_DATA){
if(in.remaining()<2){
//消息头不完整
in.reset();
return false;
}
byte[] extended = new byte[2];
in.get(extended);
int shift = 0;
length = 0;
for (int i = extended.length - 1; i >= 0; i--) {
length = length + ((extended[i] & 0xFF) << shift);
shift += 8;
}
}else if(datalength==HAS_EXTEND_DATA_CONTINUE){
if(in.remaining()<2){
//消息头不完整
in.reset();
return false;
}
byte[] extended = new byte[2];
in.get(extended);
int shift = 0;
length = 0;
for (int i = extended.length - 1; i >= 0; i--) {
length = length + ((extended[i] & 0xFF) << shift);
shift += 8;
}
}
byte[] date=new byte[length];
if(ismask==1){
if(in.remaining()<4+length){
in.reset();
return false;
}
// 利用掩码对org-data进行异或
byte[] mask =new byte[4];
in.get(mask);
in.get(date);
for (int i = 0; i < date.length; i++) {
// 吧数据进行异或运算
date[i] = (byte) (date[i] ^ mask[i % 4]);
}
}else{
if(in.remaining()<length){< p="">
in.reset();
return false;
}
in.get(date);
}
return true;
}