I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit 673c1428 authored by zzz's avatar zzz
Browse files

* SusiMail:

   - Rework in POP3 in prep for more pipelining
parent b4a0ffdb
No related branches found
No related tags found
No related merge requests found
......@@ -51,6 +51,7 @@ public class POP3MailBox {
private int mails;
private boolean connected;
private boolean supportsPipelining;
/** ID to size */
private final HashMap<Integer, Integer> sizes;
......@@ -362,15 +363,17 @@ public class POP3MailBox {
try {
// pipeline 2 commands
lastError = "";
List<String> cmds = new ArrayList(2);
List<SendRecv> cmds = new ArrayList<SendRecv>(3);
// TODO APOP (unsupported by postman)
cmds.add("USER " + user);
cmds.add("PASS " + pass);
cmds.add(new SendRecv(null, Mode.A1));
// TODO CAPA
cmds.add(new SendRecv("USER " + user, Mode.A1));
cmds.add(new SendRecv("PASS " + pass, Mode.A1));
// We can't pipleline the STAT because we must
// enter the transaction state first.
//cmds.add("STAT");
// wait for 3 +OK lines since the connect generates one
if (sendCmds(cmds, 3) && sendCmd1a("STAT")) {
if (sendCmds(cmds) && sendCmd1a("STAT")) {
int i = lastLine.indexOf(" ", 5);
mails =
Integer.parseInt(
......@@ -431,7 +434,7 @@ public class POP3MailBox {
}
return result;
}
/**
* Send commands to pop3 server all at once (and expect answers).
* Sets lastError to the FIRST error.
......@@ -441,29 +444,70 @@ public class POP3MailBox {
* @param rcvLines lines to receive
* @return true if ALL received lines were successful (+OK)
* @throws IOException
* @since 0.9.13
* @since 0.9.13
*/
private boolean sendCmds(List<String> cmds, int rcvLines) throws IOException {
private boolean sendCmds(List<SendRecv> cmds) throws IOException {
boolean result = true;
for (String cmd : cmds) {
sendCmd1aNoWait(cmd);
}
boolean pipe = supportsPipelining;
if (pipe) {
Debug.debug(Debug.DEBUG, "POP3 pipelining " + cmds.size() + " commands");
for (SendRecv sr : cmds) {
String cmd = sr.send;
if (cmd != null)
sendCmd1aNoWait(cmd);
}
} // else we will do it below
socket.getOutputStream().flush();
InputStream in = socket.getInputStream();
for (int i = 0; i < rcvLines; i++) {
int i = 0;
for (SendRecv sr : cmds) {
if (!pipe) {
String cmd = sr.send;
if (cmd != null) {
sendCmd1aNoWait(cmd);
socket.getOutputStream().flush();
}
}
String foo = DataHelper.readLine(in);
if (foo == null) {
lastError = _("No response from server");
throw new IOException(lastError);
}
//foo = foo.trim(); // readLine() doesn't strip \r
sr.response = foo.trim();
i++;
if (!foo.startsWith("+OK")) {
Debug.debug(Debug.DEBUG, "Fail after " + (i+1) + " of " + rcvLines + " responses: \"" + foo.trim() + '"');
Debug.debug(Debug.DEBUG, "Fail after " + i + " of " + cmds.size() + " responses: \"" + foo.trim() + '"');
if (result)
lastError = foo; // actually the first error, for better info to the user
result = false;
sr.result = false;
} else {
Debug.debug(Debug.DEBUG, "OK after " + (i+1) + " of " + rcvLines + " responses: \"" + foo.trim() + '"');
Debug.debug(Debug.DEBUG, "OK after " + i + " of " + cmds.size() + " responses: \"" + foo.trim() + '"');
switch (sr.mode) {
case A1:
sr.result = true;
break;
case RB:
try {
sr.rb = getResultNa();
sr.result = true;
} catch (IOException ioe) {
result = false;
sr.result = false;
}
break;
case LS:
try {
sr.ls = getResultNl();
sr.result = true;
} catch (IOException ioe) {
result = false;
sr.result = false;
}
break;
}
}
lastLine = foo;
}
......@@ -474,7 +518,7 @@ public class POP3MailBox {
* send command to pop3 server. Does NOT flush or read or wait.
* Caller must sync.
*
* @param cmd command to send
* @param cmd command to send non-null
* @throws IOException
* @since 0.9.13
*/
......@@ -532,32 +576,7 @@ public class POP3MailBox {
private ReadBuffer sendCmdNa(String cmd) throws IOException
{
if (sendCmd1a(cmd)) {
InputStream input = socket.getInputStream();
StringBuilder buf = new StringBuilder(512);
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
while (DataHelper.readLine(input, buf)) {
int len = buf.length();
if (len == 0)
break; // huh? no \r?
if (len == 2 && buf.charAt(0) == '.' && buf.charAt(1) == '\r')
break;
String line;
// RFC 1939 sec. 3 de-byte-stuffing
if (buf.charAt(0) == '.')
line = buf.substring(1);
else
line = buf.toString();
baos.write(DataHelper.getASCII(line));
if (buf.charAt(len - 1) != '\r')
baos.write((byte) '\n');
baos.write((byte) '\n');
buf.setLength(0);
}
ReadBuffer readBuffer = new ReadBuffer();
readBuffer.content = baos.toByteArray();
readBuffer.offset = 0;
readBuffer.length = baos.size();
return readBuffer;
return getResultNa();
} else {
Debug.debug( Debug.DEBUG, "sendCmd1a returned false" );
return null;
......@@ -577,35 +596,87 @@ public class POP3MailBox {
private List<String> sendCmdNl(String cmd) throws IOException
{
if (sendCmd1a(cmd)) {
List<String> rv = new ArrayList<String>(16);
long timeOut = 120*1000;
InputStream input = socket.getInputStream();
long startTime = System.currentTimeMillis();
StringBuilder buf = new StringBuilder(512);
while (DataHelper.readLine(input, buf)) {
int len = buf.length();
if (len == 0)
break; // huh? no \r?
if (len == 2 && buf.charAt(0) == '.' && buf.charAt(1) == '\r')
break;
if( System.currentTimeMillis() - startTime > timeOut )
throw new IOException( "Timeout while waiting on server response." );
String line;
// RFC 1939 sec. 3 de-byte-stuffing
if (buf.charAt(0) == '.')
line = buf.substring(1);
else
line = buf.toString();
rv.add(line);
buf.setLength(0);
}
return rv;
return getResultNl();
} else {
Debug.debug( Debug.DEBUG, "sendCmd1a returned false" );
return null;
}
}
/**
* No total timeout (result could be large)
* Caller must sync.
*
* @return buffer non-null
* @throws IOException
*/
private ReadBuffer getResultNa() throws IOException
{
InputStream input = socket.getInputStream();
StringBuilder buf = new StringBuilder(512);
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
while (DataHelper.readLine(input, buf)) {
int len = buf.length();
if (len == 0)
break; // huh? no \r?
if (len == 2 && buf.charAt(0) == '.' && buf.charAt(1) == '\r')
break;
String line;
// RFC 1939 sec. 3 de-byte-stuffing
if (buf.charAt(0) == '.')
line = buf.substring(1);
else
line = buf.toString();
baos.write(DataHelper.getASCII(line));
if (buf.charAt(len - 1) != '\r')
baos.write((byte) '\n');
baos.write((byte) '\n');
buf.setLength(0);
}
ReadBuffer readBuffer = new ReadBuffer();
readBuffer.content = baos.toByteArray();
readBuffer.offset = 0;
readBuffer.length = baos.size();
return readBuffer;
}
/**
* Like getResultNa but returns a list of strings, one per line.
* Strings will have trailing \r but not \n.
* Total timeout 2 minutes.
* Caller must sync.
*
* @return the lines non-null
* @throws IOException on timeout
* @since 0.9.13
*/
private List<String> getResultNl() throws IOException
{
List<String> rv = new ArrayList<String>(16);
long timeOut = 120*1000;
InputStream input = socket.getInputStream();
long startTime = System.currentTimeMillis();
StringBuilder buf = new StringBuilder(512);
while (DataHelper.readLine(input, buf)) {
int len = buf.length();
if (len == 0)
break; // huh? no \r?
if (len == 2 && buf.charAt(0) == '.' && buf.charAt(1) == '\r')
break;
if( System.currentTimeMillis() - startTime > timeOut )
throw new IOException( "Timeout while waiting on server response." );
String line;
// RFC 1939 sec. 3 de-byte-stuffing
if (buf.charAt(0) == '.')
line = buf.substring(1);
else
line = buf.toString();
rv.add(line);
buf.setLength(0);
}
return rv;
}
/**
* Warning - forces a connection.
*
......@@ -739,6 +810,34 @@ public class POP3MailBox {
}
}
private enum Mode {
/** no extra lines (sendCmd1a) */
A1,
/** return extra lines in ReadBuffer (sendCmdNa) */
RB,
/** return extra lines in List of Strings (sendCmdNl) */
LS
}
/**
* A command to send and a mode to receive and return the results
* @since 0.9.13
*/
private static class SendRecv {
public final String send;
public final Mode mode;
public String response;
public boolean result;
public ReadBuffer rb;
public List<String> ls;
/** @param s may be null */
public SendRecv(String s, Mode m) {
send = s;
mode = m;
}
}
/** translate */
private static String _(String s) {
return Messages.getString(s);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment