- admin can toggle verbose logging of all requests on and off
- admin page shows user hostname - servlets log request and response if logging is enabled
This commit is contained in:
parent
5e95299801
commit
a26221c2bb
|
@ -13,6 +13,19 @@ String remoteAddr = request.getRemoteAddr();
|
||||||
if (!(remoteAddr.equals("0:0:0:0:0:0:0:1") || remoteAddr.equals("127.0.0.1"))) {
|
if (!(remoteAddr.equals("0:0:0:0:0:0:0:1") || remoteAddr.equals("127.0.0.1"))) {
|
||||||
response.sendError(403, "Access is restricted to known hosts");
|
response.sendError(403, "Access is restricted to known hosts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServletContext servletContext = pageContext.getServletContext();
|
||||||
|
|
||||||
|
// process verbose toggle
|
||||||
|
String verboseParam = request.getParameter("verbose");
|
||||||
|
if (verboseParam != null) {
|
||||||
|
if (verboseParam.equals("on")) {
|
||||||
|
servletContext.setAttribute(StartupUtils.VERBOSE_DEBUG, Boolean.TRUE);
|
||||||
|
} else {
|
||||||
|
servletContext.setAttribute(StartupUtils.VERBOSE_DEBUG, Boolean.FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
@ -33,7 +46,6 @@ th, td {
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
ServletContext servletContext = pageContext.getServletContext();
|
|
||||||
Injector injector = (Injector) servletContext.getAttribute(StartupUtils.INJECTOR);
|
Injector injector = (Injector) servletContext.getAttribute(StartupUtils.INJECTOR);
|
||||||
%>
|
%>
|
||||||
|
|
||||||
|
@ -83,17 +95,28 @@ Collection<User> users = connectedUsers.getUsers();
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Username</th>
|
<th>Username</th>
|
||||||
|
<th>Host</th>
|
||||||
</tr>
|
</tr>
|
||||||
<%
|
<%
|
||||||
for (User u : users) {
|
for (User u : users) {
|
||||||
%>
|
%>
|
||||||
<tr>
|
<tr>
|
||||||
<td><% out.print(u.getNickname()); %></td>
|
<td><% out.print(u.getNickname()); %></td>
|
||||||
|
<td><% out.print(u.getHostName()); %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<%
|
<%
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<%
|
||||||
|
Boolean verboseDebugObj = (Boolean) servletContext.getAttribute(StartupUtils.VERBOSE_DEBUG);
|
||||||
|
boolean verboseDebug = verboseDebugObj != null ? verboseDebugObj.booleanValue() : false;
|
||||||
|
%>
|
||||||
|
<p>
|
||||||
|
Verbose logging is currently <strong><% out.print(verboseDebug ? "ON" : "OFF"); %></strong>.
|
||||||
|
<a href="?verbose=on">Turn on.</a> <a href="?verbose=off">Turn off.</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -14,6 +14,8 @@ import net.socialgamer.cah.Constants.AjaxRequest;
|
||||||
import net.socialgamer.cah.Constants.AjaxResponse;
|
import net.socialgamer.cah.Constants.AjaxResponse;
|
||||||
import net.socialgamer.cah.Constants.ErrorCode;
|
import net.socialgamer.cah.Constants.ErrorCode;
|
||||||
import net.socialgamer.cah.Constants.ReturnableData;
|
import net.socialgamer.cah.Constants.ReturnableData;
|
||||||
|
import net.socialgamer.cah.Constants.SessionAttribute;
|
||||||
|
import net.socialgamer.cah.data.User;
|
||||||
import net.socialgamer.cah.handlers.Handler;
|
import net.socialgamer.cah.handlers.Handler;
|
||||||
import net.socialgamer.cah.handlers.Handlers;
|
import net.socialgamer.cah.handlers.Handlers;
|
||||||
|
|
||||||
|
@ -36,19 +38,20 @@ public class AjaxServlet extends CahServlet {
|
||||||
final HttpServletResponse response, final HttpSession hSession) throws ServletException,
|
final HttpServletResponse response, final HttpSession hSession) throws ServletException,
|
||||||
IOException {
|
IOException {
|
||||||
final PrintWriter out = response.getWriter();
|
final PrintWriter out = response.getWriter();
|
||||||
|
final User user = (User) hSession.getAttribute(SessionAttribute.USER);
|
||||||
int serial = -1;
|
int serial = -1;
|
||||||
if (request.getParameter(AjaxRequest.SERIAL.toString()) != null) {
|
if (request.getParameter(AjaxRequest.SERIAL.toString()) != null) {
|
||||||
try {
|
try {
|
||||||
serial = Integer.parseInt(request.getParameter(AjaxRequest.SERIAL.toString()));
|
serial = Integer.parseInt(request.getParameter(AjaxRequest.SERIAL.toString()));
|
||||||
} catch (final NumberFormatException nfe) {
|
} catch (final NumberFormatException nfe) {
|
||||||
returnError(out, ErrorCode.BAD_REQUEST);
|
returnError(user, out, ErrorCode.BAD_REQUEST);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final String op = request.getParameter(AjaxRequest.OP.toString());
|
final String op = request.getParameter(AjaxRequest.OP.toString());
|
||||||
if (op == null || op.equals("")) {
|
if (op == null || op.equals("")) {
|
||||||
returnError(out, ErrorCode.OP_NOT_SPECIFIED, serial);
|
returnError(user, out, ErrorCode.OP_NOT_SPECIFIED, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,12 +61,12 @@ public class AjaxServlet extends CahServlet {
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
System.err.println("Exception creating handler for " + op);
|
System.err.println("Exception creating handler for " + op);
|
||||||
e.printStackTrace(System.err);
|
e.printStackTrace(System.err);
|
||||||
returnError(out, ErrorCode.BAD_OP, serial);
|
returnError(user, out, ErrorCode.BAD_OP, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Map<ReturnableData, Object> data = handler.handle(new RequestWrapper(request), hSession);
|
final Map<ReturnableData, Object> data = handler.handle(new RequestWrapper(request), hSession);
|
||||||
data.put(AjaxResponse.SERIAL, serial);
|
data.put(AjaxResponse.SERIAL, serial);
|
||||||
returnData(out, data);
|
returnData(user, out, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ package net.socialgamer.cah;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -23,6 +25,7 @@ import org.json.simple.JSONObject;
|
||||||
import org.json.simple.JSONValue;
|
import org.json.simple.JSONValue;
|
||||||
|
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
import com.sun.istack.internal.Nullable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,13 +35,7 @@ import com.google.inject.Injector;
|
||||||
public abstract class CahServlet extends HttpServlet {
|
public abstract class CahServlet extends HttpServlet {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
private final boolean debugLog = false;
|
||||||
* @see HttpServlet#HttpServlet()
|
|
||||||
*/
|
|
||||||
public CahServlet() {
|
|
||||||
super();
|
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
|
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
@ -50,6 +47,21 @@ public abstract class CahServlet extends HttpServlet {
|
||||||
response.setCharacterEncoding("UTF-8");
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
final HttpSession hSession = request.getSession(true);
|
final HttpSession hSession = request.getSession(true);
|
||||||
|
final User user = (User) hSession.getAttribute(SessionAttribute.USER);
|
||||||
|
|
||||||
|
if (verboseDebug()) {
|
||||||
|
// TODO if we have any sort of authentication later, we need to make sure to not log passwords!
|
||||||
|
// I could use getParameterMap, but that returns an array, and getting pretty strings out of
|
||||||
|
// array values is a lot of work.
|
||||||
|
final Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
final Enumeration<String> paramNames = request.getParameterNames();
|
||||||
|
while (paramNames.hasMoreElements()) {
|
||||||
|
final String name = paramNames.nextElement();
|
||||||
|
params.put(name, request.getParameter(name));
|
||||||
|
}
|
||||||
|
log(user, "Request: " + JSONValue.toJSONString(params));
|
||||||
|
}
|
||||||
|
|
||||||
final String op = request.getParameter(AjaxRequest.OP.toString());
|
final String op = request.getParameter(AjaxRequest.OP.toString());
|
||||||
final boolean skipSessionUserCheck = op != null
|
final boolean skipSessionUserCheck = op != null
|
||||||
&& (op.equals(AjaxOperation.REGISTER.toString())
|
&& (op.equals(AjaxOperation.REGISTER.toString())
|
||||||
|
@ -57,24 +69,31 @@ public abstract class CahServlet extends HttpServlet {
|
||||||
if (hSession.isNew()) {
|
if (hSession.isNew()) {
|
||||||
// they should have gotten a session from the index page.
|
// they should have gotten a session from the index page.
|
||||||
// they probably don't have cookies on.
|
// they probably don't have cookies on.
|
||||||
returnError(response.getWriter(), ErrorCode.NO_SESSION);
|
returnError(user, response.getWriter(), ErrorCode.NO_SESSION);
|
||||||
} else if (!skipSessionUserCheck && hSession.getAttribute(SessionAttribute.USER) == null) {
|
} else if (!skipSessionUserCheck && hSession.getAttribute(SessionAttribute.USER) == null) {
|
||||||
returnError(response.getWriter(), ErrorCode.NOT_REGISTERED);
|
returnError(user, response.getWriter(), ErrorCode.NOT_REGISTERED);
|
||||||
} else if (hSession.getAttribute(SessionAttribute.USER) != null
|
} else if (user != null && !user.isValid()) {
|
||||||
&& !(((User) hSession.getAttribute(SessionAttribute.USER)).isValid())) {
|
|
||||||
// user probably pinged out
|
// user probably pinged out
|
||||||
hSession.invalidate();
|
hSession.invalidate();
|
||||||
returnError(response.getWriter(), ErrorCode.SESSION_EXPIRED);
|
returnError(user, response.getWriter(), ErrorCode.SESSION_EXPIRED);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
handleRequest(request, response, hSession);
|
handleRequest(request, response, hSession);
|
||||||
} catch (final AssertionError ae) {
|
} catch (final AssertionError ae) {
|
||||||
|
log("Assertion failed", ae);
|
||||||
getServletContext().log(ae.toString());
|
getServletContext().log(ae.toString());
|
||||||
ae.printStackTrace();
|
ae.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean verboseDebug() {
|
||||||
|
final Boolean verboseDebugObj = (Boolean) getServletContext().getAttribute(
|
||||||
|
StartupUtils.VERBOSE_DEBUG);
|
||||||
|
final boolean verboseDebug = verboseDebugObj != null ? verboseDebugObj.booleanValue() : false;
|
||||||
|
return verboseDebug;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a request from a CAH client. A session is guaranteed to exist at this point.
|
* Handles a request from a CAH client. A session is guaranteed to exist at this point.
|
||||||
*
|
*
|
||||||
|
@ -96,8 +115,9 @@ public abstract class CahServlet extends HttpServlet {
|
||||||
* @param code
|
* @param code
|
||||||
* Error code that the js code knows how to handle.
|
* Error code that the js code knows how to handle.
|
||||||
*/
|
*/
|
||||||
protected void returnError(final PrintWriter writer, final ErrorCode code) {
|
protected void returnError(@Nullable final User user, final PrintWriter writer,
|
||||||
returnError(writer, code, -1);
|
final ErrorCode code) {
|
||||||
|
returnError(user, writer, code, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +127,9 @@ public abstract class CahServlet extends HttpServlet {
|
||||||
* @param serial
|
* @param serial
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void returnError(final PrintWriter writer, final ErrorCode code, final int serial) {
|
protected void returnError(@Nullable final User user, final PrintWriter writer,
|
||||||
|
final ErrorCode code,
|
||||||
|
final int serial) {
|
||||||
final JSONObject ret = new JSONObject();
|
final JSONObject ret = new JSONObject();
|
||||||
ret.put(AjaxResponse.ERROR, Boolean.TRUE);
|
ret.put(AjaxResponse.ERROR, Boolean.TRUE);
|
||||||
ret.put(AjaxResponse.ERROR_CODE, code.toString());
|
ret.put(AjaxResponse.ERROR_CODE, code.toString());
|
||||||
|
@ -122,8 +144,9 @@ public abstract class CahServlet extends HttpServlet {
|
||||||
* @param data
|
* @param data
|
||||||
* Key-value data to return as the response.
|
* Key-value data to return as the response.
|
||||||
*/
|
*/
|
||||||
protected void returnData(final PrintWriter writer, final Map<ReturnableData, Object> data) {
|
protected void returnData(@Nullable final User user, final PrintWriter writer,
|
||||||
returnObject(writer, data);
|
final Map<ReturnableData, Object> data) {
|
||||||
|
returnObject(user, writer, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,18 +157,28 @@ public abstract class CahServlet extends HttpServlet {
|
||||||
* @param data_list
|
* @param data_list
|
||||||
* List of key-value data to return as the response.
|
* List of key-value data to return as the response.
|
||||||
*/
|
*/
|
||||||
protected void returnArray(final PrintWriter writer,
|
protected void returnArray(@Nullable final User user, final PrintWriter writer,
|
||||||
final List<Map<ReturnableData, Object>> data_list) {
|
final List<Map<ReturnableData, Object>> data_list) {
|
||||||
returnObject(writer, data_list);
|
returnObject(user, writer, data_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void returnObject(final PrintWriter writer, final Object object) {
|
private void returnObject(@Nullable final User user, final PrintWriter writer, final Object object) {
|
||||||
final String ret = JSONValue.toJSONString(object);
|
final String ret = JSONValue.toJSONString(object);
|
||||||
writer.println(ret);
|
writer.println(ret);
|
||||||
// System.out.println(">>>> " + ret + " <<<<");
|
if (verboseDebug()) {
|
||||||
|
log(user, "Response: " + ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Injector getInjector() {
|
protected Injector getInjector() {
|
||||||
return (Injector) getServletContext().getAttribute(StartupUtils.INJECTOR);
|
return (Injector) getServletContext().getAttribute(StartupUtils.INJECTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void log(@Nullable final User user, final String message) {
|
||||||
|
String userStr = "unknown user";
|
||||||
|
if (user != null) {
|
||||||
|
userStr = user.getNickname();
|
||||||
|
}
|
||||||
|
log("For " + userStr + ": " + message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class LongPollServlet extends CahServlet {
|
||||||
for (final QueuedMessage qm : msgs) {
|
for (final QueuedMessage qm : msgs) {
|
||||||
data.add(qm.getData());
|
data.add(qm.getData());
|
||||||
}
|
}
|
||||||
returnArray(out, data);
|
returnArray(user, out, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,6 @@ public class LongPollServlet extends CahServlet {
|
||||||
final Map<ReturnableData, Object> data = new HashMap<ReturnableData, Object>();
|
final Map<ReturnableData, Object> data = new HashMap<ReturnableData, Object>();
|
||||||
data.put(LongPollResponse.EVENT, LongPollEvent.NOOP.toString());
|
data.put(LongPollResponse.EVENT, LongPollEvent.NOOP.toString());
|
||||||
data.put(LongPollResponse.TIMESTAMP, System.currentTimeMillis());
|
data.put(LongPollResponse.TIMESTAMP, System.currentTimeMillis());
|
||||||
returnData(out, data);
|
returnData(user, out, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,4 +22,12 @@ public class RequestWrapper {
|
||||||
public String getParameter(final AjaxRequest parameter) {
|
public String getParameter(final AjaxRequest parameter) {
|
||||||
return request.getParameter(parameter.toString());
|
return request.getParameter(parameter.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRemoteAddr() {
|
||||||
|
return request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemoteHost() {
|
||||||
|
return request.getRemoteHost();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ public class StartupUtils extends GuiceServletContextListener {
|
||||||
|
|
||||||
public static final String DATE_NAME = "started_at";
|
public static final String DATE_NAME = "started_at";
|
||||||
|
|
||||||
|
public static final String VERBOSE_DEBUG = "verbose_debug";
|
||||||
|
|
||||||
private Date serverStarted;
|
private Date serverStarted;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,13 +17,16 @@ public class User {
|
||||||
|
|
||||||
private Game currentGame;
|
private Game currentGame;
|
||||||
|
|
||||||
|
private final String hostName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset when this user object is no longer valid, most likely because it pinged out.
|
* Reset when this user object is no longer valid, most likely because it pinged out.
|
||||||
*/
|
*/
|
||||||
private boolean valid = true;
|
private boolean valid = true;
|
||||||
|
|
||||||
public User(final String nickname) {
|
public User(final String nickname, final String hostName) {
|
||||||
this.nickname = nickname;
|
this.nickname = nickname;
|
||||||
|
this.hostName = hostName;
|
||||||
queuedMessages = new PriorityBlockingQueue<QueuedMessage>();
|
queuedMessages = new PriorityBlockingQueue<QueuedMessage>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +82,10 @@ public class User {
|
||||||
return nickname;
|
return nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHostName() {
|
||||||
|
return hostName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getNickname();
|
return getNickname();
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class RegisterHandler extends Handler {
|
||||||
} else if (users.hasUser(nick)) {
|
} else if (users.hasUser(nick)) {
|
||||||
return error(ErrorCode.NICK_IN_USE);
|
return error(ErrorCode.NICK_IN_USE);
|
||||||
} else {
|
} else {
|
||||||
final User user = new User(nick);
|
final User user = new User(nick, request.getRemoteHost());
|
||||||
users.newUser(user);
|
users.newUser(user);
|
||||||
session.setAttribute(SessionAttribute.USER, user);
|
session.setAttribute(SessionAttribute.USER, user);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue