package org.exist.irc;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jibble.pircbot.IrcException;
import org.jibble.pircbot.NickAlreadyInUseException;
public class IRCProxy extends HttpServlet {
// private String server = "irc.freenode.net";
private String server = "localhost";
private String channel = "#testaabb";
private boolean modProxyHack = false;
public void init(ServletConfig config) throws ServletException {
super.init(config);
String param = config.getInitParameter("mod-proxy");
if (param != null)
modProxyHack = param.equalsIgnoreCase("true");
param = config.getInitParameter("server");
if (param != null)
server = param;
Map channels = new HashMap();
getServletContext().setAttribute("org.exist.irc.sessions", channels);
}
/**
* The GET method opens a connection to the client and keeps it open, i.e. the
* method will only return if the client does explicitely close the session (via a POST)
* or the session is killed. The server sends all input it receives from the IRC server down
* this stream.
*
* Before calling GET, the client has to create a session by sending a POST request
* with just the channel and the nick as parameters (but no 'session' parameter). After
* the session was created successfully, the client can call GET and start listening.
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String sessionId = request.getParameter("session");
if (sessionId == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "No session specified");
return;
}
Map channels = (Map) getServletContext().getAttribute("org.exist.irc.sessions");
IRCSession session = (IRCSession) channels.get(sessionId);
if (session == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Session " + sessionId + " not found");
return;
}
log("Starting/refreshing session ...");
if (session.started()) {
session.closeTunnel();
}
session.run(response);
}
/**
* The POST method is used to initialize a session and to process
* commands. The client will use POST to pass the user input to the
* server asynchronously.
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sessionId = request.getParameter("session");
String nick = request.getParameter("nick");
String channelParam = request.getParameter("channel");
String close = request.getParameter("close");
String send = request.getParameter("send");
String pong = request.getParameter("pong");
String reconnect = request.getParameter("refresh");
Map channels = (Map) getServletContext().getAttribute("org.exist.irc.sessions");
if (sessionId == null) {
// No session yet: connect and create a new one
if (channelParam != null && channelParam.length() > 0)
channel = channelParam;
try {
IRCSession session = new IRCSession(server, channel, nick, modProxyHack);
sessionId = session.getSessionId();
log("New session created: " + sessionId);
// add the session to the list of channels
synchronized(channels) {
channels.put(sessionId, session);
}
response.setContentType("text/text");
response.setContentLength(0);
response.setHeader("X-IRC-Session", sessionId);
response.setHeader("X-IRC-Nick", session.getName());
} catch (NickAlreadyInUseException e) {
response.sendError(HttpServletResponse.SC_CONFLICT, "Nick is already in use");
} catch (IOException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
} catch (IrcException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
} else {
IRCSession session = (IRCSession) channels.get(sessionId);
if (session == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Session " + sessionId + " not found");
return;
}
// we have a valid session, so check for commands and process them
if (pong != null) {
log("Received pong from client.");
session.pingResponse();
} else if (close != null) {
log("Closing session " + sessionId);
session.quit();
} else if (reconnect != null) {
try {
session.attemptReconnect();
} catch (NickAlreadyInUseException e) {
response.sendError(HttpServletResponse.SC_CONFLICT, "Nick is already in use");
} catch (IOException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
} catch (IrcException e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
} else if (send != null) {
log("Sending message: " + send + "; id: " + sessionId);
session.send(send);
}
}
}
public void destroy() {
Map channels = (Map) getServletContext().getAttribute("org.exist.irc.sessions");
for (Iterator i = channels.values().iterator(); i.hasNext(); ) {
IRCSession session = (IRCSession) i.next();
session.quit();
}
}
}