/**
*
*/
package com.chamago.cometserver;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import com.chamago.cometserver.connection.CometConnection;
import com.chamago.cometserver.connection.CometConnectionManager;
import com.chamago.cometserver.connection.StreamCometConnection;
import com.chamago.cometserver.connection.StreamMsgPullFactory;
import com.chamago.cometserver.sercret.AppKeyManager;
import com.chamago.cometserver.sercret.CopUtils;
import com.chamago.cometserver.util.Constants;
import com.chamago.cometserver.util.RequestParametersHolder;
import com.chamago.cometserver.util.TaobaoHashMap;
public class CometServlet extends HttpServlet {
private final static Log LOG = LogFactory
.getLog(CometServlet.class);
private StreamMsgPullFactory streamMsgPullFactory;
private CometConnectionManager connectionManager;
private AppKeyManager akm;
private ServletConfig config;
/**
*
*/
private static final long serialVersionUID = 7791301745498733988L;
@Override
public void init(ServletConfig config) {
LOG.info("启动流式长连接服务");
this.streamMsgPullFactory = new StreamMsgPullFactory(
CometServer.MIN_THREADS, CometServer.MAX_THREADS,
CometServer.QUEUE_SIZE, null);
this.connectionManager = new CometConnectionManager();
this.akm = AppKeyManager.getInstance();
config.getServletContext().setAttribute("cometserver.connect.manager", connectionManager);
config.getServletContext().setAttribute("cometserver.connect.factory", streamMsgPullFactory);
this.config = config;
}
@Override
public ServletConfig getServletConfig(){
return this.config;
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
try {
if(secretValidate(request,response)){
postMessage(request, response);
}else{
LOG.warn("校验参数失败");
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 安全验证
* @throws IOException
*/
public boolean secretValidate(HttpServletRequest request, HttpServletResponse response) throws IOException{
String timestamp = request.getParameter("timestamp");
if(!checkTimestamp(timestamp)){
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setHeader(StreamConstants.ERR_MSG_HEADER, URLEncoder.encode("timestamp误差不在服务器允许的15分钟范围内 ,而且不能超过服务器时间","UTF-8"));
return false;
}
String sign = request.getParameter("sign");
request.getParameterValues("");
RequestParametersHolder requestHolder = this.praseReqParams(request);
String appkey = request.getParameter("app_key");
String app_secret = this.akm.findSecret(appkey);
if(app_secret!=null){
String serSign = CopUtils.signCopRequest(requestHolder,app_secret);
if(!sign.equals(serSign)){
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setHeader(StreamConstants.ERR_MSG_HEADER,URLEncoder.encode("签名无效,请检查appkey对应的密钥","UTF-8") );
return false;
}
}else{
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setHeader(StreamConstants.ERR_MSG_HEADER, URLEncoder.encode("appkey["+appkey+"]不存在,请客户端检查","UTF-8"));
return false;
}
return true;
}
public boolean checkTimestamp(String timestamp){
long cts = Long.parseLong(timestamp);
long now = System.currentTimeMillis();
if(now-cts>Constants.VALID_TIMESTAMP){
return false;
}else if(cts-now>0){
return false;
}
return true;
}
public RequestParametersHolder praseReqParams(HttpServletRequest request) throws IOException {
TaobaoHashMap protocalMustParams = new TaobaoHashMap();
Iterator<String> it = request.getParameterMap().keySet().iterator();
while (it.hasNext()) {
String name = it.next();
if(!name.equals("sign")){
String value = URLDecoder.decode(request.getParameter(name), "UTF-8");
protocalMustParams.put(name, value);
}
}
RequestParametersHolder requestHolder = new RequestParametersHolder();
requestHolder.setProtocalMustParams(protocalMustParams);
return requestHolder;
}
private void postMessage(HttpServletRequest request,
HttpServletResponse response) throws IOException {
Continuation continuation = ContinuationSupport
.getContinuation(request);
String appkey = request.getParameter("app_key");
String subject = request.getParameter("id");
CometConnection connect = this.connectionManager.findCometConnection(appkey);
if(connect == null){
connect = new StreamCometConnection(this.streamMsgPullFactory,this.connectionManager);
connect.setAppkey(appkey);
if(subject!=null&&subject.length()>0){
String[] subs = subject.split(",");
for(String sub:subs){
connect.addSubject(sub);
}
}
}
this.connectionManager.registerConnection(connect);
continuation.setTimeout(0);
connect.setContinuation(continuation);
connect.holdingConnection(response,request);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}