format (shendaras)
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
package net.i2p.phttprelay;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
@ -44,70 +45,70 @@ import javax.servlet.http.HttpServletResponse;
|
||||
*/
|
||||
public class CheckSendStatusServlet extends PHTTPRelayServlet {
|
||||
/* URL parameters on the check */
|
||||
|
||||
|
||||
/** H(routerIdent).toBase64() of the target to receive the message */
|
||||
public final static String PARAM_SEND_TARGET = "target";
|
||||
public final static String PARAM_SEND_TARGET = "target";
|
||||
/** msgId parameter */
|
||||
public final static String PARAM_MSG_ID = "msgId";
|
||||
|
||||
public final static String PROP_STATUS = "status";
|
||||
public final static String STATUS_PENDING = "pending";
|
||||
public final static String STATUS_UNKNOWN = "unknown";
|
||||
|
||||
|
||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String target = req.getParameter(PARAM_SEND_TARGET);
|
||||
String msgIdStr = req.getParameter(PARAM_MSG_ID);
|
||||
|
||||
log("Checking status of [" + target + "] message [" + msgIdStr + "]");
|
||||
if (!isKnownMessage(target, msgIdStr)) {
|
||||
log("Not known - its not pending");
|
||||
notPending(req, resp);
|
||||
return;
|
||||
} else {
|
||||
log("Known - its still pending");
|
||||
pending(req, resp);
|
||||
return;
|
||||
}
|
||||
String target = req.getParameter(PARAM_SEND_TARGET);
|
||||
String msgIdStr = req.getParameter(PARAM_MSG_ID);
|
||||
|
||||
log("Checking status of [" + target + "] message [" + msgIdStr + "]");
|
||||
if (!isKnownMessage(target, msgIdStr)) {
|
||||
log("Not known - its not pending");
|
||||
notPending(req, resp);
|
||||
return;
|
||||
} else {
|
||||
log("Known - its still pending");
|
||||
pending(req, resp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isKnownMessage(String target, String msgId) throws IOException {
|
||||
if ( (target == null) || (target.trim().length() <= 0) ) return false;
|
||||
if ( (msgId == null) || (msgId.trim().length() <= 0) ) return false;
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
File msgFile = new File(identDir, "msg" + msgId + ".dat");
|
||||
if (msgFile.exists())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if ((target == null) || (target.trim().length() <= 0)) return false;
|
||||
if ((msgId == null) || (msgId.trim().length() <= 0)) return false;
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
File msgFile = new File(identDir, "msg" + msgId + ".dat");
|
||||
if (msgFile.exists())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void pending(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_PENDING).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
out.close();
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_PENDING).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
private void notPending(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
out.close();
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
package net.i2p.phttprelay;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
@ -18,23 +19,26 @@ import java.util.Set;
|
||||
*/
|
||||
class LockManager {
|
||||
private volatile static Set _locks = new HashSet(); // target
|
||||
|
||||
|
||||
public static void lockIdent(String target) {
|
||||
while (true) {
|
||||
synchronized (_locks) {
|
||||
if (!_locks.contains(target)) {
|
||||
_locks.add(target);
|
||||
return;
|
||||
}
|
||||
try { _locks.wait(1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
synchronized (_locks) {
|
||||
if (!_locks.contains(target)) {
|
||||
_locks.add(target);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
_locks.wait(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void unlockIdent(String target) {
|
||||
synchronized (_locks) {
|
||||
_locks.remove(target);
|
||||
_locks.notifyAll();
|
||||
}
|
||||
synchronized (_locks) {
|
||||
_locks.remove(target);
|
||||
_locks.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
package net.i2p.phttprelay;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
@ -25,49 +26,50 @@ abstract class PHTTPRelayServlet extends HttpServlet {
|
||||
/* config params */
|
||||
/*public final static String PARAM_BASEDIR = "baseDir";*/
|
||||
public final static String ENV_BASEDIR = "phttpRelay.baseDir";
|
||||
|
||||
|
||||
/** match the clock fudge factor on the router, rather than importing the entire router cvs module */
|
||||
public final static long CLOCK_FUDGE_FACTOR = 1*60*1000;
|
||||
|
||||
public final static long CLOCK_FUDGE_FACTOR = 1 * 60 * 1000;
|
||||
|
||||
protected String buildURL(HttpServletRequest req, String path) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(req.getScheme()).append("://");
|
||||
buf.append(req.getServerName()).append(":").append(req.getServerPort());
|
||||
buf.append(req.getContextPath());
|
||||
buf.append(path);
|
||||
log("URL built: " + buf.toString());
|
||||
return buf.toString();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(req.getScheme()).append("://");
|
||||
buf.append(req.getServerName()).append(":").append(req.getServerPort());
|
||||
buf.append(req.getContextPath());
|
||||
buf.append(path);
|
||||
log("URL built: " + buf.toString());
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
protected File getIdentDir(String target) throws IOException {
|
||||
if ( (_baseDir == null) || (target == null) ) throw new IOException("dir not specified to deal with");
|
||||
File baseDir = new File(_baseDir);
|
||||
if (!baseDir.exists()) {
|
||||
boolean created = baseDir.mkdirs();
|
||||
log("Creating PHTTP Relay Base Directory: " + baseDir.getAbsolutePath() + " - ok? " + created);
|
||||
}
|
||||
File identDir = new File(baseDir, target);
|
||||
log("Ident dir: " + identDir.getAbsolutePath());
|
||||
return identDir;
|
||||
if ((_baseDir == null) || (target == null)) throw new IOException("dir not specified to deal with");
|
||||
File baseDir = new File(_baseDir);
|
||||
if (!baseDir.exists()) {
|
||||
boolean created = baseDir.mkdirs();
|
||||
log("Creating PHTTP Relay Base Directory: " + baseDir.getAbsolutePath() + " - ok? " + created);
|
||||
}
|
||||
File identDir = new File(baseDir, target);
|
||||
log("Ident dir: " + identDir.getAbsolutePath());
|
||||
return identDir;
|
||||
}
|
||||
|
||||
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
String dir = System.getProperty(ENV_BASEDIR);
|
||||
if (dir == null) {
|
||||
_log.warn("Base directory for the polling http relay system not in the environment [" + ENV_BASEDIR +"]");
|
||||
_log.warn("Setting the base directory to ./relayDir for " + getServletName());
|
||||
_baseDir = ".relayDir";
|
||||
} else {
|
||||
_baseDir = dir;
|
||||
log("Loaded up " + getServletName() + " with base directory " + _baseDir);
|
||||
}
|
||||
super.init(config);
|
||||
String dir = System.getProperty(ENV_BASEDIR);
|
||||
if (dir == null) {
|
||||
_log.warn("Base directory for the polling http relay system not in the environment [" + ENV_BASEDIR + "]");
|
||||
_log.warn("Setting the base directory to ./relayDir for " + getServletName());
|
||||
_baseDir = ".relayDir";
|
||||
} else {
|
||||
_baseDir = dir;
|
||||
log("Loaded up " + getServletName() + " with base directory " + _baseDir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void log(String msg) {
|
||||
_log.debug(msg);
|
||||
_log.debug(msg);
|
||||
}
|
||||
|
||||
public void log(String msg, Throwable t) {
|
||||
_log.debug(msg, t);
|
||||
_log.debug(msg, t);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
package net.i2p.phttprelay;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
@ -55,209 +56,208 @@ import net.i2p.util.Clock;
|
||||
* baseDir is the directory under which registrants and their pending messages are stored
|
||||
*
|
||||
*/
|
||||
public class PollServlet extends PHTTPRelayServlet {
|
||||
public class PollServlet extends PHTTPRelayServlet {
|
||||
/* URL parameters on the check */
|
||||
|
||||
|
||||
/** H(routerIdent).toBase64() of the target to receive the message */
|
||||
public final static String PARAM_SEND_TARGET = "target";
|
||||
|
||||
public final static String PARAM_SEND_TARGET = "target";
|
||||
|
||||
/** HTTP error code if the target is not known*/
|
||||
public final static int CODE_UNKNOWN = HttpServletResponse.SC_NOT_FOUND;
|
||||
/** HTTP error code if the signature failed */
|
||||
public final static int CODE_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED;
|
||||
/** HTTP error code if everything is ok */
|
||||
public final static int CODE_OK = HttpServletResponse.SC_OK;
|
||||
|
||||
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
byte data[] = getData(req);
|
||||
if (data == null) return;
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
String target = getTarget(bais);
|
||||
if (target == null) {
|
||||
log("Target not specified");
|
||||
resp.sendError(CODE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isKnown(target)) {
|
||||
resp.sendError(CODE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAuthorized(target, bais)) {
|
||||
resp.sendError(CODE_UNAUTHORIZED);
|
||||
return;
|
||||
} else {
|
||||
log("Authorized access for target " + target);
|
||||
}
|
||||
|
||||
sendMessages(resp, target);
|
||||
byte data[] = getData(req);
|
||||
if (data == null) return;
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
String target = getTarget(bais);
|
||||
if (target == null) {
|
||||
log("Target not specified");
|
||||
resp.sendError(CODE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isKnown(target)) {
|
||||
resp.sendError(CODE_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAuthorized(target, bais)) {
|
||||
resp.sendError(CODE_UNAUTHORIZED);
|
||||
return;
|
||||
} else {
|
||||
log("Authorized access for target " + target);
|
||||
}
|
||||
|
||||
sendMessages(resp, target);
|
||||
}
|
||||
|
||||
|
||||
private byte[] getData(HttpServletRequest req) throws ServletException, IOException {
|
||||
ServletInputStream in = req.getInputStream();
|
||||
int len = req.getContentLength();
|
||||
byte data[] = new byte[len];
|
||||
int cur = 0;
|
||||
int read = DataHelper.read(in, data);
|
||||
if (read != len) {
|
||||
log("Size read is incorrect [" + read + " instead of expected " + len + "]");
|
||||
return null;
|
||||
} else {
|
||||
log("Read data length: " + data.length + " in base64: " + Base64.encode(data));
|
||||
return data;
|
||||
}
|
||||
ServletInputStream in = req.getInputStream();
|
||||
int len = req.getContentLength();
|
||||
byte data[] = new byte[len];
|
||||
int cur = 0;
|
||||
int read = DataHelper.read(in, data);
|
||||
if (read != len) {
|
||||
log("Size read is incorrect [" + read + " instead of expected " + len + "]");
|
||||
return null;
|
||||
} else {
|
||||
log("Read data length: " + data.length + " in base64: " + Base64.encode(data));
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getTarget(InputStream in) throws IOException {
|
||||
StringBuffer buf = new StringBuffer(64);
|
||||
int numBytes = 0;
|
||||
int c = 0;
|
||||
while ( (c = in.read()) != -1) {
|
||||
if (c == (int)'&') break;
|
||||
buf.append((char)c);
|
||||
numBytes++;
|
||||
if (numBytes > 128) {
|
||||
log("Target didn't find the & after 128 bytes [" + buf.toString() + "]");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (buf.toString().indexOf("target=") != 0) {
|
||||
log("Did not start with target= [" + buf.toString() + "]");
|
||||
return null;
|
||||
}
|
||||
return buf.substring("target=".length());
|
||||
StringBuffer buf = new StringBuffer(64);
|
||||
int numBytes = 0;
|
||||
int c = 0;
|
||||
while ((c = in.read()) != -1) {
|
||||
if (c == (int) '&') break;
|
||||
buf.append((char) c);
|
||||
numBytes++;
|
||||
if (numBytes > 128) {
|
||||
log("Target didn't find the & after 128 bytes [" + buf.toString() + "]");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (buf.toString().indexOf("target=") != 0) {
|
||||
log("Did not start with target= [" + buf.toString() + "]");
|
||||
return null;
|
||||
}
|
||||
return buf.substring("target=".length());
|
||||
}
|
||||
|
||||
|
||||
private void sendMessages(HttpServletResponse resp, String target) throws IOException {
|
||||
log("Before lock " + target);
|
||||
LockManager.lockIdent(target);
|
||||
log("Locked " + target);
|
||||
try {
|
||||
File identDir = getIdentDir(target);
|
||||
expire(identDir);
|
||||
File messageFiles[] = identDir.listFiles();
|
||||
resp.setStatus(CODE_OK);
|
||||
log("Sending back " + (messageFiles.length -1) + " messages");
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
DataHelper.writeDate(out, new Date(Clock.getInstance().now()));
|
||||
DataHelper.writeLong(out, 2, messageFiles.length -1);
|
||||
for (int i = 0; i < messageFiles.length; i++) {
|
||||
if ("identity.dat".equals(messageFiles[i].getName())) {
|
||||
// skip
|
||||
} else {
|
||||
log("Message file " + messageFiles[i].getName() + " is " + messageFiles[i].length() + " bytes");
|
||||
DataHelper.writeLong(out, 4, messageFiles[i].length());
|
||||
writeFile(out, messageFiles[i]);
|
||||
boolean deleted = messageFiles[i].delete();
|
||||
if (!deleted) {
|
||||
log("!!!Error removing message file " + messageFiles[i].getAbsolutePath() + " - please delete!");
|
||||
}
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Error sending message", dfe);
|
||||
} finally {
|
||||
LockManager.unlockIdent(target);
|
||||
log("Unlocked " + target);
|
||||
}
|
||||
log("Before lock " + target);
|
||||
LockManager.lockIdent(target);
|
||||
log("Locked " + target);
|
||||
try {
|
||||
File identDir = getIdentDir(target);
|
||||
expire(identDir);
|
||||
File messageFiles[] = identDir.listFiles();
|
||||
resp.setStatus(CODE_OK);
|
||||
log("Sending back " + (messageFiles.length - 1) + " messages");
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
DataHelper.writeDate(out, new Date(Clock.getInstance().now()));
|
||||
DataHelper.writeLong(out, 2, messageFiles.length - 1);
|
||||
for (int i = 0; i < messageFiles.length; i++) {
|
||||
if ("identity.dat".equals(messageFiles[i].getName())) {
|
||||
// skip
|
||||
} else {
|
||||
log("Message file " + messageFiles[i].getName() + " is " + messageFiles[i].length() + " bytes");
|
||||
DataHelper.writeLong(out, 4, messageFiles[i].length());
|
||||
writeFile(out, messageFiles[i]);
|
||||
boolean deleted = messageFiles[i].delete();
|
||||
if (!deleted) {
|
||||
log("!!!Error removing message file " + messageFiles[i].getAbsolutePath() + " - please delete!");
|
||||
}
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Error sending message", dfe);
|
||||
} finally {
|
||||
LockManager.unlockIdent(target);
|
||||
log("Unlocked " + target);
|
||||
}
|
||||
}
|
||||
|
||||
private final static long EXPIRE_DELAY = 60*1000; // expire messages every minute
|
||||
|
||||
|
||||
private final static long EXPIRE_DELAY = 60 * 1000; // expire messages every minute
|
||||
|
||||
private void expire(File identDir) throws IOException {
|
||||
File files[] = identDir.listFiles();
|
||||
long now = System.currentTimeMillis();
|
||||
for (int i = 0 ; i < files.length; i++) {
|
||||
if ("identity.dat".equals(files[i].getName())) {
|
||||
continue;
|
||||
}
|
||||
if (files[i].lastModified() + EXPIRE_DELAY < now) {
|
||||
log("Expiring " + files[i].getAbsolutePath());
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
File files[] = identDir.listFiles();
|
||||
long now = System.currentTimeMillis();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if ("identity.dat".equals(files[i].getName())) {
|
||||
continue;
|
||||
}
|
||||
if (files[i].lastModified() + EXPIRE_DELAY < now) {
|
||||
log("Expiring " + files[i].getAbsolutePath());
|
||||
files[i].delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void writeFile(ServletOutputStream out, File file) throws IOException {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
try {
|
||||
byte buf[] = new byte[4096];
|
||||
while (true) {
|
||||
int read = DataHelper.read(fis, buf);
|
||||
if (read > 0)
|
||||
out.write(buf, 0, read);
|
||||
else
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
fis.close();
|
||||
}
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
try {
|
||||
byte buf[] = new byte[4096];
|
||||
while (true) {
|
||||
int read = DataHelper.read(fis, buf);
|
||||
if (read > 0)
|
||||
out.write(buf, 0, read);
|
||||
else
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
fis.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private boolean isKnown(String target) throws IOException {
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isAuthorized(String target, InputStream in) throws IOException {
|
||||
RouterIdentity ident = null;
|
||||
try {
|
||||
ident = getRouterIdentity(target);
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Identity was not valid", dfe);
|
||||
}
|
||||
|
||||
if (ident == null) {
|
||||
log("Identity not registered");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
long val = DataHelper.readLong(in, 4);
|
||||
Signature sig = new Signature();
|
||||
sig.readBytes(in);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataHelper.writeLong(baos, 4, val);
|
||||
if (DSAEngine.getInstance().verifySignature(sig, baos.toByteArray(), ident.getSigningPublicKey())) {
|
||||
return true;
|
||||
} else {
|
||||
log("Signature does NOT match");
|
||||
return false;
|
||||
}
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Format error reading the nonce and signature", dfe);
|
||||
return false;
|
||||
}
|
||||
RouterIdentity ident = null;
|
||||
try {
|
||||
ident = getRouterIdentity(target);
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Identity was not valid", dfe);
|
||||
}
|
||||
|
||||
if (ident == null) {
|
||||
log("Identity not registered");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
long val = DataHelper.readLong(in, 4);
|
||||
Signature sig = new Signature();
|
||||
sig.readBytes(in);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataHelper.writeLong(baos, 4, val);
|
||||
if (DSAEngine.getInstance().verifySignature(sig, baos.toByteArray(), ident.getSigningPublicKey())) {
|
||||
return true;
|
||||
} else {
|
||||
log("Signature does NOT match");
|
||||
return false;
|
||||
}
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Format error reading the nonce and signature", dfe);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private RouterIdentity getRouterIdentity(String target) throws IOException, DataFormatException {
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
RouterIdentity ident = new RouterIdentity();
|
||||
ident.readBytes(new FileInputStream(identFile));
|
||||
return ident;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
RouterIdentity ident = new RouterIdentity();
|
||||
ident.readBytes(new FileInputStream(identFile));
|
||||
return ident;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
package net.i2p.phttprelay;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
@ -66,89 +67,92 @@ public class RegisterServlet extends PHTTPRelayServlet {
|
||||
/* config params */
|
||||
public final static String PARAM_POLL_PATH = "pollPath";
|
||||
public final static String PARAM_SEND_PATH = "sendPath";
|
||||
|
||||
|
||||
/* key=val keys sent back on registration */
|
||||
public final static String PROP_STATUS = "status";
|
||||
public final static String PROP_STATUS = "status";
|
||||
public final static String PROP_POLL_URL = "pollURL";
|
||||
public final static String PROP_SEND_URL = "sendURL";
|
||||
public final static String PROP_TIME_OFFSET = "timeOffset"; // ms (local-remote)
|
||||
|
||||
/* values for the PROP_STATUS */
|
||||
public final static String STATUS_FAILED = "failed";
|
||||
public final static String STATUS_FAILED = "failed";
|
||||
public final static String STATUS_REGISTERED = "registered";
|
||||
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
ServletInputStream in = req.getInputStream();
|
||||
RouterIdentity ident = new RouterIdentity();
|
||||
try {
|
||||
Date remoteTime = DataHelper.readDate(in);
|
||||
long skew = getSkew(remoteTime);
|
||||
ident.readBytes(in);
|
||||
boolean ok = registerIdent(ident);
|
||||
sendURLs(req, resp, skew, ok);
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Invalid format for router identity posted", dfe);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
private long getSkew(Date remoteDate) {
|
||||
if (remoteDate == null) {
|
||||
log("*ERROR: remote date was null");
|
||||
return Long.MAX_VALUE;
|
||||
} else {
|
||||
long diff = Clock.getInstance().now() - remoteDate.getTime();
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean registerIdent(RouterIdentity ident) throws DataFormatException, IOException {
|
||||
File identDir = getIdentDir(ident.getHash().toBase64());
|
||||
boolean created = identDir.mkdirs();
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(identFile);
|
||||
ident.writeBytes(fos);
|
||||
} finally {
|
||||
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
log("Identity registered into " + identFile.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendURLs(HttpServletRequest req, HttpServletResponse resp, long skew, boolean ok) throws IOException {
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
|
||||
log("*Debug: clock skew of " + skew + "ms (local-remote)");
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
if (ok) {
|
||||
buf.append(PROP_POLL_URL).append("=").append(buildURL(req, _pollPath)).append("\n");
|
||||
buf.append(PROP_SEND_URL).append("=").append(buildURL(req, _sendPath)).append("\n");
|
||||
buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n");
|
||||
buf.append(PROP_STATUS).append("=").append(STATUS_REGISTERED).append("\n");
|
||||
} else {
|
||||
buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n");
|
||||
buf.append(PROP_STATUS).append("=").append(STATUS_FAILED).append("\n");
|
||||
}
|
||||
out.write(buf.toString().getBytes());
|
||||
out.close();
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
ServletInputStream in = req.getInputStream();
|
||||
RouterIdentity ident = new RouterIdentity();
|
||||
try {
|
||||
Date remoteTime = DataHelper.readDate(in);
|
||||
long skew = getSkew(remoteTime);
|
||||
ident.readBytes(in);
|
||||
boolean ok = registerIdent(ident);
|
||||
sendURLs(req, resp, skew, ok);
|
||||
} catch (DataFormatException dfe) {
|
||||
log("Invalid format for router identity posted", dfe);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private long getSkew(Date remoteDate) {
|
||||
if (remoteDate == null) {
|
||||
log("*ERROR: remote date was null");
|
||||
return Long.MAX_VALUE;
|
||||
} else {
|
||||
long diff = Clock.getInstance().now() - remoteDate.getTime();
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean registerIdent(RouterIdentity ident) throws DataFormatException, IOException {
|
||||
File identDir = getIdentDir(ident.getHash().toBase64());
|
||||
boolean created = identDir.mkdirs();
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(identFile);
|
||||
ident.writeBytes(fos);
|
||||
} finally {
|
||||
if (fos != null) try {
|
||||
fos.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
log("Identity registered into " + identFile.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendURLs(HttpServletRequest req, HttpServletResponse resp, long skew, boolean ok) throws IOException {
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
|
||||
log("*Debug: clock skew of " + skew + "ms (local-remote)");
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
if (ok) {
|
||||
buf.append(PROP_POLL_URL).append("=").append(buildURL(req, _pollPath)).append("\n");
|
||||
buf.append(PROP_SEND_URL).append("=").append(buildURL(req, _sendPath)).append("\n");
|
||||
buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n");
|
||||
buf.append(PROP_STATUS).append("=").append(STATUS_REGISTERED).append("\n");
|
||||
} else {
|
||||
buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n");
|
||||
buf.append(PROP_STATUS).append("=").append(STATUS_FAILED).append("\n");
|
||||
}
|
||||
out.write(buf.toString().getBytes());
|
||||
out.close();
|
||||
}
|
||||
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
|
||||
String pollPath = config.getInitParameter(PARAM_POLL_PATH);
|
||||
if (pollPath == null)
|
||||
throw new ServletException("Polling path for the registration servlet required [" + PARAM_POLL_PATH + "]");
|
||||
else
|
||||
_pollPath = pollPath;
|
||||
String sendPath = config.getInitParameter(PARAM_SEND_PATH);
|
||||
if (sendPath == null)
|
||||
throw new ServletException("Sending path for the registration servlet required [" + PARAM_SEND_PATH + "]");
|
||||
else
|
||||
_sendPath = sendPath;
|
||||
super.init(config);
|
||||
|
||||
String pollPath = config.getInitParameter(PARAM_POLL_PATH);
|
||||
if (pollPath == null)
|
||||
throw new ServletException("Polling path for the registration servlet required [" + PARAM_POLL_PATH + "]");
|
||||
else
|
||||
_pollPath = pollPath;
|
||||
String sendPath = config.getInitParameter(PARAM_SEND_PATH);
|
||||
if (sendPath == null)
|
||||
throw new ServletException("Sending path for the registration servlet required [" + PARAM_SEND_PATH + "]");
|
||||
else
|
||||
_sendPath = sendPath;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
package net.i2p.phttprelay;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
@ -63,256 +64,261 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class SendServlet extends PHTTPRelayServlet {
|
||||
private String _checkPath;
|
||||
private int _maxMessagesPerIdent;
|
||||
|
||||
|
||||
/* config params */
|
||||
public final static String PARAM_CHECK_PATH = "checkPath";
|
||||
public final static String PARAM_MAX_MESSAGES_PER_IDENT = "maxMessagesPerIdent";
|
||||
|
||||
|
||||
/* URL parameters on the send */
|
||||
|
||||
|
||||
/** H(routerIdent).toBase64() of the target to receive the message */
|
||||
public final static String PARAM_SEND_TARGET = "target";
|
||||
public final static String PARAM_SEND_TARGET = "target";
|
||||
/** # ms to wait for the message to be delivered before failing it */
|
||||
public final static String PARAM_SEND_TIMEOUTMS = "timeoutMs";
|
||||
/** # bytes to be sent in the message */
|
||||
public final static String PARAM_SEND_DATA_LENGTH = "dataLength";
|
||||
/** sending router's time in ms */
|
||||
public final static String PARAM_SEND_TIME = "localTime";
|
||||
|
||||
|
||||
/** msgId parameter to access the check path servlet with (along side PARAM_SEND_TARGET) */
|
||||
public final static String PARAM_MSG_ID = "msgId";
|
||||
|
||||
|
||||
/* key=val keys sent back on registration */
|
||||
public final static String PROP_CHECK_URL = "statusCheckURL";
|
||||
public final static String PROP_STATUS = "status";
|
||||
public final static String STATUS_OK = "accepted";
|
||||
public final static String STATUS_UNKNOWN = "unknown";
|
||||
private final static String STATUS_CLOCKSKEW = "clockSkew_"; /** prefix for (local-remote) */
|
||||
|
||||
private final static String STATUS_CLOCKSKEW = "clockSkew_";
|
||||
|
||||
/** prefix for (local-remote) */
|
||||
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
ServletInputStream in = req.getInputStream();
|
||||
try {
|
||||
int contentLen = req.getContentLength();
|
||||
String firstLine = getFirstLine(in, contentLen);
|
||||
if (firstLine == null) {
|
||||
return;
|
||||
}
|
||||
Map params = getParameters(firstLine);
|
||||
String target = (String)params.get(PARAM_SEND_TARGET);
|
||||
String timeoutStr = (String)params.get(PARAM_SEND_TIMEOUTMS);
|
||||
String lenStr = (String)params.get(PARAM_SEND_DATA_LENGTH);
|
||||
String remoteTimeStr = (String)params.get(PARAM_SEND_TIME);
|
||||
long skew = 0;
|
||||
try {
|
||||
long remTime = Long.parseLong(remoteTimeStr);
|
||||
skew = System.currentTimeMillis() - remTime;
|
||||
} catch (Throwable t) {
|
||||
skew = Long.MAX_VALUE;
|
||||
log("*ERROR could not parse the remote time from [" + remoteTimeStr + "]");
|
||||
}
|
||||
ServletInputStream in = req.getInputStream();
|
||||
try {
|
||||
int contentLen = req.getContentLength();
|
||||
String firstLine = getFirstLine(in, contentLen);
|
||||
if (firstLine == null) { return; }
|
||||
Map params = getParameters(firstLine);
|
||||
String target = (String) params.get(PARAM_SEND_TARGET);
|
||||
String timeoutStr = (String) params.get(PARAM_SEND_TIMEOUTMS);
|
||||
String lenStr = (String) params.get(PARAM_SEND_DATA_LENGTH);
|
||||
String remoteTimeStr = (String) params.get(PARAM_SEND_TIME);
|
||||
long skew = 0;
|
||||
try {
|
||||
long remTime = Long.parseLong(remoteTimeStr);
|
||||
skew = System.currentTimeMillis() - remTime;
|
||||
} catch (Throwable t) {
|
||||
skew = Long.MAX_VALUE;
|
||||
log("*ERROR could not parse the remote time from [" + remoteTimeStr + "]");
|
||||
}
|
||||
|
||||
log("Target [" + target + "] timeout [" + timeoutStr + "] length [" + lenStr + "] skew [" + skew + "]");
|
||||
log("Target [" + target + "] timeout [" + timeoutStr + "] length [" + lenStr + "] skew [" + skew + "]");
|
||||
|
||||
if ( (skew > CLOCK_FUDGE_FACTOR) || (skew < 0 - CLOCK_FUDGE_FACTOR) ) {
|
||||
log("Attempt to send by a skewed router: skew = " + skew + "ms (local-remote)");
|
||||
failSkewed(req, resp, skew);
|
||||
}
|
||||
|
||||
if (!isValidTarget(target)) {
|
||||
log("Attempt to send to an invalid target [" + target + "]");
|
||||
fail(req, resp, "Unknown or invalid target");
|
||||
return;
|
||||
}
|
||||
if ((skew > CLOCK_FUDGE_FACTOR) || (skew < 0 - CLOCK_FUDGE_FACTOR)) {
|
||||
log("Attempt to send by a skewed router: skew = " + skew + "ms (local-remote)");
|
||||
failSkewed(req, resp, skew);
|
||||
}
|
||||
|
||||
long len = -1;
|
||||
try {
|
||||
len = Long.parseLong(lenStr);
|
||||
} catch (Throwable t) {
|
||||
log("Unable to parse length parameter [" + PARAM_SEND_DATA_LENGTH + "] (" + lenStr + ")");
|
||||
fail(req, resp, "Invalid length parameter");
|
||||
return;
|
||||
}
|
||||
if (!isValidTarget(target)) {
|
||||
log("Attempt to send to an invalid target [" + target + "]");
|
||||
fail(req, resp, "Unknown or invalid target");
|
||||
return;
|
||||
}
|
||||
|
||||
int msgId = saveFile(in, resp, target, len);
|
||||
if (msgId >= 0) {
|
||||
sendSuccess(req, resp, target, msgId);
|
||||
} else {
|
||||
fail(req, resp, "Unable to queue up the message for delivery");
|
||||
}
|
||||
} finally {
|
||||
try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
long len = -1;
|
||||
try {
|
||||
len = Long.parseLong(lenStr);
|
||||
} catch (Throwable t) {
|
||||
log("Unable to parse length parameter [" + PARAM_SEND_DATA_LENGTH + "] (" + lenStr + ")");
|
||||
fail(req, resp, "Invalid length parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
int msgId = saveFile(in, resp, target, len);
|
||||
if (msgId >= 0) {
|
||||
sendSuccess(req, resp, target, msgId);
|
||||
} else {
|
||||
fail(req, resp, "Unable to queue up the message for delivery");
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String getFirstLine(ServletInputStream in, int len) throws ServletException, IOException {
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
int numBytes = 0;
|
||||
int c = 0;
|
||||
while ( (c = in.read()) != -1) {
|
||||
if (c == (int)'\n') break;
|
||||
buf.append((char)c);
|
||||
numBytes++;
|
||||
if (numBytes > 512) {
|
||||
log("First line is > 512 bytes [" + buf.toString() + "]");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
log("First line: " + buf.toString());
|
||||
return buf.toString();
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
int numBytes = 0;
|
||||
int c = 0;
|
||||
while ((c = in.read()) != -1) {
|
||||
if (c == (int) '\n') break;
|
||||
buf.append((char) c);
|
||||
numBytes++;
|
||||
if (numBytes > 512) {
|
||||
log("First line is > 512 bytes [" + buf.toString() + "]");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
log("First line: " + buf.toString());
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
private static Map getParameters(String line) {
|
||||
//StringTokenizer tok = new StringTokenizer(line, "&=", true);
|
||||
Map params = new HashMap();
|
||||
while (line != null) {
|
||||
String key = null;
|
||||
String val = null;
|
||||
int firstAmp = line.indexOf('&');
|
||||
int firstEq = line.indexOf('=');
|
||||
if (firstAmp > 0) {
|
||||
key = line.substring(0, firstEq);
|
||||
val = line.substring(firstEq+1, firstAmp);
|
||||
line = line.substring(firstAmp+1);
|
||||
params.put(key, val);
|
||||
} else {
|
||||
line = null;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
//StringTokenizer tok = new StringTokenizer(line, "&=", true);
|
||||
Map params = new HashMap();
|
||||
while (line != null) {
|
||||
String key = null;
|
||||
String val = null;
|
||||
int firstAmp = line.indexOf('&');
|
||||
int firstEq = line.indexOf('=');
|
||||
if (firstAmp > 0) {
|
||||
key = line.substring(0, firstEq);
|
||||
val = line.substring(firstEq + 1, firstAmp);
|
||||
line = line.substring(firstAmp + 1);
|
||||
params.put(key, val);
|
||||
} else {
|
||||
line = null;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
private boolean isValidTarget(String target) throws IOException {
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
String files[] = identDir.list();
|
||||
// we skip 1 because of identity.dat
|
||||
if (files.length -1 > _maxMessagesPerIdent) {
|
||||
log("Too many messages pending for " + target + ": " + (files.length-1));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
log("Ident directory exists, but identity does not... corrupt for " + target);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
log("Unknown ident " + target);
|
||||
return false;
|
||||
}
|
||||
File identDir = getIdentDir(target);
|
||||
if (identDir.exists()) {
|
||||
File identFile = new File(identDir, "identity.dat");
|
||||
if (identFile.exists()) {
|
||||
// known and valid (maybe we need to check the file format... naw, fuck it
|
||||
String files[] = identDir.list();
|
||||
// we skip 1 because of identity.dat
|
||||
if (files.length - 1 > _maxMessagesPerIdent) {
|
||||
log("Too many messages pending for " + target + ": " + (files.length - 1));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
log("Ident directory exists, but identity does not... corrupt for " + target);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
log("Unknown ident " + target);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int saveFile(InputStream in, HttpServletResponse resp, String target, long len) throws IOException {
|
||||
File identDir = getIdentDir(target);
|
||||
if (!identDir.exists()) return -1;
|
||||
try {
|
||||
LockManager.lockIdent(target);
|
||||
int i = 0;
|
||||
while (true) {
|
||||
File curFile = new File(identDir, "msg" + i + ".dat");
|
||||
if (!curFile.exists()) {
|
||||
boolean ok = writeFile(curFile, in, len);
|
||||
if (ok)
|
||||
return i;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
} finally {
|
||||
LockManager.unlockIdent(target);
|
||||
}
|
||||
File identDir = getIdentDir(target);
|
||||
if (!identDir.exists()) return -1;
|
||||
try {
|
||||
LockManager.lockIdent(target);
|
||||
int i = 0;
|
||||
while (true) {
|
||||
File curFile = new File(identDir, "msg" + i + ".dat");
|
||||
if (!curFile.exists()) {
|
||||
boolean ok = writeFile(curFile, in, len);
|
||||
if (ok)
|
||||
return i;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
} finally {
|
||||
LockManager.unlockIdent(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean writeFile(File file, InputStream in, long len) throws IOException {
|
||||
long remaining = len;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(file);
|
||||
byte buf[] = new byte[4096];
|
||||
while (remaining > 0) {
|
||||
int read = in.read(buf);
|
||||
if (read == -1)
|
||||
break;
|
||||
remaining -= read;
|
||||
if (read > 0)
|
||||
fos.write(buf, 0, read);
|
||||
}
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try { fos.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
if (remaining != 0) {
|
||||
log("Invalid remaining bytes [" + remaining + " out of " + len + "] - perhaps message was cancelled partway through delivery? deleting " + file.getAbsolutePath());
|
||||
boolean deleted = file.delete();
|
||||
if (!deleted)
|
||||
log("!!!Error deleting temporary file " + file.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
long remaining = len;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(file);
|
||||
byte buf[] = new byte[4096];
|
||||
while (remaining > 0) {
|
||||
int read = in.read(buf);
|
||||
if (read == -1) break;
|
||||
remaining -= read;
|
||||
if (read > 0) fos.write(buf, 0, read);
|
||||
}
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
if (remaining != 0) {
|
||||
log("Invalid remaining bytes [" + remaining + " out of " + len
|
||||
+ "] - perhaps message was cancelled partway through delivery? deleting " + file.getAbsolutePath());
|
||||
boolean deleted = file.delete();
|
||||
if (!deleted) log("!!!Error deleting temporary file " + file.getAbsolutePath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendSuccess(HttpServletRequest req, HttpServletResponse resp, String target, int msgId) throws IOException {
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_OK).append('\n');
|
||||
buf.append(PROP_CHECK_URL).append('=').append(buildURL(req, _checkPath));
|
||||
buf.append('?');
|
||||
buf.append(PARAM_SEND_TARGET).append('=').append(target).append("&");
|
||||
buf.append(PARAM_MSG_ID).append('=').append(msgId).append("\n");
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
|
||||
private void sendSuccess(HttpServletRequest req, HttpServletResponse resp, String target, int msgId)
|
||||
throws IOException {
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_OK).append('\n');
|
||||
buf.append(PROP_CHECK_URL).append('=').append(buildURL(req, _checkPath));
|
||||
buf.append('?');
|
||||
buf.append(PARAM_SEND_TARGET).append('=').append(target).append("&");
|
||||
buf.append(PARAM_MSG_ID).append('=').append(msgId).append("\n");
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
||||
private void fail(HttpServletRequest req, HttpServletResponse resp, String err) throws IOException {
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
||||
private void failSkewed(HttpServletRequest req, HttpServletResponse resp, long skew) throws IOException {
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_CLOCKSKEW).append(skew).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
ServletOutputStream out = resp.getOutputStream();
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(PROP_STATUS).append('=').append(STATUS_CLOCKSKEW).append(skew).append('\n');
|
||||
out.write(buf.toString().getBytes());
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
|
||||
String checkPath = config.getInitParameter(PARAM_CHECK_PATH);
|
||||
if (checkPath == null)
|
||||
throw new ServletException("Check status path for the sending servlet required [" + PARAM_CHECK_PATH + "]");
|
||||
else
|
||||
_checkPath = checkPath;
|
||||
|
||||
String maxMessagesPerIdentStr = config.getInitParameter(PARAM_MAX_MESSAGES_PER_IDENT);
|
||||
if (maxMessagesPerIdentStr == null)
|
||||
throw new ServletException("Max messages per ident for the sending servlet required [" + PARAM_MAX_MESSAGES_PER_IDENT + "]");
|
||||
try {
|
||||
_maxMessagesPerIdent = Integer.parseInt(maxMessagesPerIdentStr);
|
||||
} catch (Throwable t) {
|
||||
throw new ServletException("Valid max messages per ident for the sending servlet required [" + PARAM_MAX_MESSAGES_PER_IDENT + "]");
|
||||
}
|
||||
super.init(config);
|
||||
|
||||
String checkPath = config.getInitParameter(PARAM_CHECK_PATH);
|
||||
if (checkPath == null)
|
||||
throw new ServletException("Check status path for the sending servlet required [" + PARAM_CHECK_PATH + "]");
|
||||
else
|
||||
_checkPath = checkPath;
|
||||
|
||||
String maxMessagesPerIdentStr = config.getInitParameter(PARAM_MAX_MESSAGES_PER_IDENT);
|
||||
if (maxMessagesPerIdentStr == null)
|
||||
throw new ServletException("Max messages per ident for the sending servlet required ["
|
||||
+ PARAM_MAX_MESSAGES_PER_IDENT + "]");
|
||||
try {
|
||||
_maxMessagesPerIdent = Integer.parseInt(maxMessagesPerIdentStr);
|
||||
} catch (Throwable t) {
|
||||
throw new ServletException("Valid max messages per ident for the sending servlet required ["
|
||||
+ PARAM_MAX_MESSAGES_PER_IDENT + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String args[]) {
|
||||
String line = "target=pp0ARjQiB~IKC-0FsMUsPEMrwR3gxVBZGRYfEr1IzHI=&timeoutMs=52068&dataLength=2691&";
|
||||
Map props = getParameters(line);
|
||||
for (java.util.Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
||||
String key = (String)iter.next();
|
||||
String val = (String)props.get(key);
|
||||
System.out.println("[" + key + "] = [" + val + "]");
|
||||
}
|
||||
String line = "target=pp0ARjQiB~IKC-0FsMUsPEMrwR3gxVBZGRYfEr1IzHI=&timeoutMs=52068&dataLength=2691&";
|
||||
Map props = getParameters(line);
|
||||
for (java.util.Iterator iter = props.keySet().iterator(); iter.hasNext();) {
|
||||
String key = (String) iter.next();
|
||||
String val = (String) props.get(key);
|
||||
System.out.println("[" + key + "] = [" + val + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user