package com.pekall.pctool;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import com.pekall.pctool.protos.MsgDefProtos.AppRecord;
import com.pekall.pctool.protos.MsgDefProtos.CmdRequest;
import com.pekall.pctool.protos.MsgDefProtos.CmdResponse;
import com.pekall.pctool.protos.MsgDefProtos.CmdType;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferInputStream;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.buffer.DynamicChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.util.CharsetUtil;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
public class MainServerHandler extends SimpleChannelUpstreamHandler {
private static final int RPC_END_POINT = 1;
private FakeBusinessLogicFacade mLogicFacade;
public MainServerHandler(FakeBusinessLogicFacade facade) {
this.mLogicFacade = facade;
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
HttpRequest request = (HttpRequest) e.getMessage();
String path = request.getUri();
HttpMethod method = request.getMethod();
path = sanitizeUri(path);
Slog.d("path:" + path + ", method: " + method);
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
handleRpc(request, response);
Channel ch = e.getChannel();
// Write the initial line and the header.
ChannelFuture future = ch.write(response);
future.addListener(ChannelFutureListener.CLOSE);
}
private void handleRpc(HttpRequest request, HttpResponse response) {
Slog.d("handleRpc");
Slog.d("content length = " + request.getHeader(CONTENT_LENGTH));
Slog.d("content type = " + request.getHeader(CONTENT_TYPE));
ChannelBuffer content = request.getContent();
Slog.d("content length = " + content.readableBytes());
ChannelBufferInputStream cbis = new ChannelBufferInputStream(content);
try {
CmdRequest cmdRequest = CmdRequest.parseFrom(cbis);
CmdType cmdType = cmdRequest.getType();
Slog.d("cmdType = " + cmdType);
switch (cmdType) {
case CMD_QUERY_APP:
AppRecord appRecord = cmdRequest.getAppParams();
if (appRecord != null) {
Slog.d("type = " + appRecord.getType());
Slog.d("location = " + appRecord.getLocation());
}
CmdResponse cmdResponse = mLogicFacade.queryAppRecordList();
ChannelBuffer buffer = new DynamicChannelBuffer(2048);
buffer.writeBytes(cmdResponse.toByteArray());
response.setContent(buffer);
response.setHeader(CONTENT_TYPE, "application/x-protobuf");
response.setHeader(CONTENT_LENGTH, response.getContent().writerIndex());
break;
default:
break;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void handleNotFound(HttpRequest request, HttpResponse response) {
response.setStatus(NOT_FOUND);
}
private static String sanitizeUri(String uri) {
// Decode the path.
try {
uri = URLDecoder.decode(uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
try {
uri = URLDecoder.decode(uri, "ISO-8859-1");
} catch (UnsupportedEncodingException e1) {
throw new Error();
}
}
return uri;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
Channel ch = e.getChannel();
Throwable cause = e.getCause();
if (cause instanceof TooLongFrameException) {
sendError(ctx, BAD_REQUEST);
return;
}
cause.printStackTrace();
if (ch.isConnected()) {
sendError(ctx, INTERNAL_SERVER_ERROR);
}
}
private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
response.setContent(ChannelBuffers.copiedBuffer(
"Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8));
// Close the connection as soon as the error message is sent.
ctx.getChannel().write(response)
.addListener(ChannelFutureListener.CLOSE);
}
}