SAMv3 : protocol better specified, and small changes in the code reflecting the new protocol
This commit is contained in:
@ -23,7 +23,7 @@ sess = socket.socket(
|
||||
sess.connect(("127.0.0.1",7656));
|
||||
sess.send("HELLO VERSION MIN=3.0 MAX=3.0\n")
|
||||
sys.stdout.write(sess.recv(1000))
|
||||
sess.send("SESSION CREATE STYLE=DATAGRAM PORT="+str(port)+" ID="+name+" DESTINATION=EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHNqwgkhJnBW4ymaRsdVmITAha-ff0UiALfKSlznqp5HcSewgMHbzQ0I01TQytFnW\n")
|
||||
sess.send("SESSION CREATE STYLE=DATAGRAM PORT="+str(port)+" ID="+name+" DESTINATION=EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHNqwgkhJnBW4ymaRsdVmITAha-ff0UiALfKSlznqp5HcSewgMHbzQ0I01TQytFnW outbound.nickname="+name+" inbound.nickname="+name+" outbound.length=0\n")
|
||||
sys.stdout.write(sess.recv(10000))
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
@ -26,6 +26,6 @@ port = 7655
|
||||
host = "localhost"
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.bind(("", 0))
|
||||
s.sendto(name+" tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAA\n"+message, (host, port))
|
||||
s.sendto(name+" EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAA\n"+message, (host, port))
|
||||
s.sendto("3.0 "+name+" tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAA\n"+message, (host, port))
|
||||
s.sendto("3.0 "+name+" EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAA\n"+message, (host, port))
|
||||
|
||||
|
@ -26,6 +26,6 @@ port = 7655
|
||||
host = "localhost"
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.bind(("", 0))
|
||||
s.sendto(name+" tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAA\n"+message, (host, port))
|
||||
s.sendto(name+" EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAA\n"+message, (host, port))
|
||||
s.sendto("3.0 "+name+" tYhjbFlFL38WFuO5eCzTvE0UBr4RfaqWMKlekGeMoB-Ouz7nYaWfiS-9j3jMiZT7FH~pwdmoSREOs2ZbXK84sR59P~pPfeCMxnJrk57f3U9uKzXkesjkKWYco3YAGs-G8sw8Fu2FBx0Do57yBdA9~j8Zq6pMjmgPBXCLuXG3vo0Z8zUWCjApJyFY6OXYopHck9Fz9vKy7YhC6zXFHfEuNHVkAooduiLd~aCoGij0TW3lH2rTVU-lx-DUdi6edxQ5-RvDNkXfikvytoCpRkivbNVytjCJLk~7RNU4FpBD20wTZWNJmEG3OY3cjNjawJVFdNjtgczh9K7gZ7ad-NjVjZVhXEj1lU8mk~vAH-2QE5om8dstWUwWoNDwmVDlvIJNKzQmahG~VrpFexFHXO0n3fKIXcSgWGOHDExM8w9neCt7AxUjxPDtXXuYNW~bRwcfiL-C9~z4K9rmwiTPZX0lmsToSXTF28l7WAoj~TMT9kZAjQeFRRWU5oW5oxVuonVvAAAA\n"+message, (host, port))
|
||||
s.sendto("3.0 "+name+" EYUpJFeW9tiubXR0aOjvCJ~ndj3xN0Wn-ljuGdbpOEttPg7nj0VCTOQDJ~FAolzn9FIDdmR3VjM0OFFDT46Q5HN4vShXFE2VNC8e3~GjzxJfaJhijRC2R9oIOzsNlzKtInD2o9lh0PxPioNMCigwmgWuqlQHs4tjWeaYRAtooHxbrtuoCIhIdGfyVV-nAcPiyYbouKq3leETXE~4kBXm-LfWfyPtrv6OuDk3GBVVcthv19GYBmnl2YI8HpJjc-G-TvNkgYishjzIJyEW-Xrpy43R4ZBXlyQqnheGLlbOEY8NLDbyNHLRMMOGbcr~67SVE3Iw3RqQ3Dhrkq2FCaQwcDucfIUCCbOfCZgu0hlnCkS42xsUvegQeiwMxbdI~h9v7vcR3yFFOrHX6WQvIZSbFLKNGArGJcfmOJVLqw1wTC4AgYXjk3csVDPd-QWbMXOuodyBgrg27Ds2BBYTsVXWskoo6ASsMIQZ6jMfL7PkY9dPLCRParIyzb9aPmf~MntNAAAA\n"+message, (host, port))
|
||||
|
||||
|
@ -55,4 +55,10 @@ while 1 :
|
||||
chunk = sock.recv(100)
|
||||
sys.stdout.write(chunk)
|
||||
if not chunk : break
|
||||
print "Forward socket closed"
|
||||
l=0
|
||||
while 1 :
|
||||
chunk = sess.recv(100)
|
||||
sys.stdout.write(chunk)
|
||||
if not chunk : break
|
||||
|
||||
|
@ -44,16 +44,18 @@ def accept() :
|
||||
sock.send("HELLO VERSION MIN=3.0 MAX=3.0\n")
|
||||
sys.stdout.write(sock.recv(1000))
|
||||
sock.send("STREAM ACCEPT ID=" + name + silent+"\n")
|
||||
print "STREAM ACCEPT ID="+name+silent+"\n"
|
||||
print "STREAM ACCEPT ID="+name+silent
|
||||
if (silent==" SILENT=false") :
|
||||
sys.stdout.write( sock.recv(100) )
|
||||
return sock
|
||||
|
||||
def echo( sock, lines ) :
|
||||
l = 0
|
||||
while lines==-1 or l<lines :
|
||||
chunk = sock.recv(1000)
|
||||
sys.stdout.write(chunk)
|
||||
if lines!=-1 : l = l + 1
|
||||
if not chunk : break
|
||||
print chunk
|
||||
sock.send(chunk)
|
||||
print
|
||||
|
||||
|
@ -280,33 +280,43 @@ public class SAMBridge implements Runnable {
|
||||
+ s.socket().getInetAddress().toString() + ":"
|
||||
+ s.socket().getPort());
|
||||
|
||||
try {
|
||||
SAMHandler handler = SAMHandlerFactory.createSAMHandler(s, i2cpProps);
|
||||
if (handler == null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("SAM handler has not been instantiated");
|
||||
class HelloHandler implements Runnable {
|
||||
SocketChannel s ;
|
||||
SAMBridge parent ;
|
||||
HelloHandler(SocketChannel s, SAMBridge parent) {
|
||||
this.s = s ;
|
||||
}
|
||||
public void run() {
|
||||
try {
|
||||
s.close();
|
||||
} catch (IOException e) {}
|
||||
continue;
|
||||
}
|
||||
handler.setBridge(this);
|
||||
handler.startHandling();
|
||||
} catch (SAMException e) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("SAM error: " + e.getMessage(), e);
|
||||
try {
|
||||
String reply = "HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n";
|
||||
s.write(ByteBuffer.wrap(reply.getBytes("ISO-8859-1")));
|
||||
} catch (IOException ioe) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("SAM Error sending error reply", ioe);
|
||||
}
|
||||
try { s.close(); } catch (IOException ioe) {}
|
||||
} catch (Exception ee) {
|
||||
try { s.close(); } catch (IOException ioe) {}
|
||||
_log.log(Log.CRIT, "Unexpected error handling SAM connection", ee);
|
||||
}
|
||||
SAMHandler handler = SAMHandlerFactory.createSAMHandler(s, i2cpProps);
|
||||
if (handler == null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("SAM handler has not been instantiated");
|
||||
try {
|
||||
s.close();
|
||||
} catch (IOException e) {}
|
||||
return;
|
||||
}
|
||||
handler.setBridge(parent);
|
||||
handler.startHandling();
|
||||
} catch (SAMException e) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("SAM error: " + e.getMessage(), e);
|
||||
try {
|
||||
String reply = "HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n";
|
||||
s.write(ByteBuffer.wrap(reply.getBytes("ISO-8859-1")));
|
||||
} catch (IOException ioe) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("SAM Error sending error reply", ioe);
|
||||
}
|
||||
try { s.close(); } catch (IOException ioe) {}
|
||||
} catch (Exception ee) {
|
||||
try { s.close(); } catch (IOException ioe) {}
|
||||
_log.log(Log.CRIT, "Unexpected error handling SAM connection", ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
new I2PAppThread(new HelloHandler(s,this), "HelloHandler").start();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
|
@ -84,11 +84,13 @@ public class SAMHandlerFactory {
|
||||
}
|
||||
|
||||
String ver = chooseBestVersion(minVer, maxVer);
|
||||
if (ver == null)
|
||||
throw new SAMException("No version specified");
|
||||
|
||||
// Let's answer positively
|
||||
try {
|
||||
if (ver == null) {
|
||||
s.write(ByteBuffer.wrap(("HELLO REPLY RESULT=NOVERSION\n").getBytes("ISO-8859-1")));
|
||||
return null ;
|
||||
}
|
||||
// Let's answer positively
|
||||
s.write(ByteBuffer.wrap(("HELLO REPLY RESULT=OK VERSION="
|
||||
+ ver + "\n").getBytes("ISO-8859-1")));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
|
@ -8,6 +8,7 @@ package net.i2p.sam;
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
@ -19,8 +20,11 @@ import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PClientFactory;
|
||||
import net.i2p.client.naming.NamingService;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.PrivateKey;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -73,6 +77,22 @@ public class SAMUtils {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InvalidDestination extends Exception {
|
||||
static final long serialVersionUID = 0x1 ;
|
||||
}
|
||||
public static void checkPrivateDestination(String dest) throws InvalidDestination {
|
||||
ByteArrayInputStream destKeyStream = new ByteArrayInputStream(Base64.decode(dest));
|
||||
|
||||
try {
|
||||
new Destination().readBytes(destKeyStream);
|
||||
new PrivateKey().readBytes(destKeyStream);
|
||||
new SigningPrivateKey().readBytes(destKeyStream);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidDestination();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolved the specified hostname.
|
||||
@ -108,15 +128,18 @@ public class SAMUtils {
|
||||
*
|
||||
* @return the Destination for the specified hostname, or null if not found
|
||||
*/
|
||||
public static Destination getDest(String s)
|
||||
public static Destination getDest(String s) throws DataFormatException
|
||||
{
|
||||
Destination d = new Destination() ;
|
||||
try {
|
||||
d.fromBase64(s);
|
||||
return d ;
|
||||
} catch (DataFormatException e) {
|
||||
return lookupHost(s, null);
|
||||
}
|
||||
Destination d = new Destination() ;
|
||||
try {
|
||||
d.fromBase64(s);
|
||||
} catch (DataFormatException e) {
|
||||
d = lookupHost(s, null);
|
||||
if ( d==null ) {
|
||||
throw e ;
|
||||
}
|
||||
}
|
||||
return d ;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -327,7 +327,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
return false;
|
||||
}
|
||||
|
||||
Destination dest;
|
||||
Destination dest = null ;
|
||||
if (name.equals("ME")) {
|
||||
if (getRawSession() != null) {
|
||||
dest = getRawSession().getDestination();
|
||||
@ -340,7 +340,10 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
dest = SAMUtils.getDest(name);
|
||||
try {
|
||||
dest = SAMUtils.getDest(name);
|
||||
} catch (DataFormatException e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (dest == null) {
|
||||
|
@ -32,7 +32,6 @@ import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.data.VerifiedDestination;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
@ -182,15 +181,18 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
String header = null ;
|
||||
String nick ;
|
||||
String dest ;
|
||||
String version ;
|
||||
|
||||
try {
|
||||
header = DataHelper.readLine(is).trim();
|
||||
StringTokenizer tok = new StringTokenizer(header, " ");
|
||||
if (tok.countTokens() != 2) {
|
||||
if (tok.countTokens() != 3) {
|
||||
// This is not a correct message, for sure
|
||||
_log.debug("Error in message format");
|
||||
return;
|
||||
}
|
||||
version = tok.nextToken();
|
||||
if (!"3.0".equals(version)) return ;
|
||||
nick = tok.nextToken();
|
||||
dest = tok.nextToken();
|
||||
|
||||
@ -257,14 +259,30 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
{
|
||||
static final long serialVersionUID = 0x1 ;
|
||||
|
||||
class ExistingId extends Exception {
|
||||
static final long serialVersionUID = 0x1 ;
|
||||
}
|
||||
class ExistingDest extends Exception {
|
||||
static final long serialVersionUID = 0x1 ;
|
||||
}
|
||||
|
||||
HashMap<String, SessionRecord> map ;
|
||||
|
||||
public SessionsDB() {
|
||||
map = new HashMap<String, SessionRecord>() ;
|
||||
}
|
||||
|
||||
synchronized public boolean put( String nick, SessionRecord session )
|
||||
synchronized public boolean put( String nick, SessionRecord session ) throws ExistingId, ExistingDest
|
||||
{
|
||||
if ( map.containsKey(nick) ) {
|
||||
throw new ExistingId();
|
||||
}
|
||||
for ( SessionRecord r : map.values() ) {
|
||||
if (r.getDest().equals(session.getDest())) {
|
||||
throw new ExistingDest();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !map.containsKey(nick) ) {
|
||||
session.createThreadGroup("SAM session "+nick);
|
||||
map.put(nick, session) ;
|
||||
@ -455,16 +473,10 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
_log.debug("Custom destination specified [" + dest + "]");
|
||||
}
|
||||
|
||||
boolean good_key = false ;
|
||||
try {
|
||||
good_key = (new VerifiedDestination(dest)).verifyCert(true);
|
||||
} catch (DataFormatException e) {
|
||||
good_key = false ;
|
||||
}
|
||||
if (!good_key)
|
||||
{
|
||||
_log.debug("Bad destination key");
|
||||
return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"bad destination key\"\n");
|
||||
SAMUtils.checkPrivateDestination(dest);
|
||||
} catch ( SAMUtils.InvalidDestination e ) {
|
||||
return writeString("SESSION STATUS RESULT=INVALID_KEY\n");
|
||||
}
|
||||
|
||||
nick = props.getProperty("ID");
|
||||
@ -489,12 +501,17 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
allProps.putAll(i2cpProps);
|
||||
allProps.putAll(props);
|
||||
|
||||
if (! sSessionsHash.put( nick, new SessionRecord(dest, allProps, this) ) ) {
|
||||
|
||||
try {
|
||||
sSessionsHash.put( nick, new SessionRecord(dest, allProps, this) ) ;
|
||||
} catch (SessionsDB.ExistingId e) {
|
||||
_log.debug("SESSION ID parameter already in use");
|
||||
String n = nick ;
|
||||
return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"ID "+n+" already in use\"\n");
|
||||
return writeString("SESSION STATUS RESULT=DUPLICATED_ID\n");
|
||||
} catch (SessionsDB.ExistingDest e) {
|
||||
return writeString("SESSION STATUS RESULT=DUPLICATED_DEST\n");
|
||||
}
|
||||
|
||||
|
||||
// Create the session
|
||||
|
||||
if (style.equals("RAW")) {
|
||||
@ -568,14 +585,19 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
if ( session != null )
|
||||
{
|
||||
_log.error ( "STREAM message received, but this session is a master session" );
|
||||
writeString("STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"master session cannot be used for streams");
|
||||
|
||||
try {
|
||||
notifyStreamResult(true, "I2P_ERROR", "master session cannot be used for streams");
|
||||
} catch (IOException e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
nick = props.getProperty("ID");
|
||||
if (nick == null) {
|
||||
_log.debug("SESSION ID parameter not specified");
|
||||
writeString("STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"ID not specified\"\n");
|
||||
try {
|
||||
notifyStreamResult(true, "I2P_ERROR", "ID not specified");
|
||||
} catch (IOException e) {}
|
||||
return false ;
|
||||
}
|
||||
props.remove("ID");
|
||||
@ -584,7 +606,9 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
|
||||
if ( rec==null ) {
|
||||
_log.debug("STREAM SESSION ID does not exist");
|
||||
writeString("STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"STREAM SESSION ID does not exist\"\n");
|
||||
try {
|
||||
notifyStreamResult(true, "INVALID_ID", "STREAM SESSION ID does not exist");
|
||||
} catch (IOException e) {}
|
||||
return false ;
|
||||
}
|
||||
|
||||
@ -592,7 +616,9 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
|
||||
if (streamSession==null) {
|
||||
_log.debug("specified ID is not a stream session");
|
||||
writeString("STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"specified ID is not a STREAM session\"\n");
|
||||
try {
|
||||
notifyStreamResult(true, "I2P_ERROR", "specified ID is not a STREAM session");
|
||||
} catch (IOException e) {}
|
||||
return false ;
|
||||
}
|
||||
|
||||
@ -612,45 +638,49 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
{
|
||||
_log.debug ( "Unrecognized RAW message opcode: \""
|
||||
+ opcode + "\"" );
|
||||
writeString("STREAM STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized RAW message opcode: \""
|
||||
+ opcode + "\"" );
|
||||
try {
|
||||
notifyStreamResult(true, "I2P_ERROR", "Unrecognized RAW message opcode: "+opcode );
|
||||
} catch (IOException e) {}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean execStreamConnect( Properties props) {
|
||||
if (props == null) {
|
||||
_log.debug("No parameters specified in STREAM CONNECT message");
|
||||
return false;
|
||||
}
|
||||
boolean verbose = props.getProperty("SILENT","false").equals("false");
|
||||
|
||||
String dest = props.getProperty("DESTINATION");
|
||||
if (dest == null) {
|
||||
_log.debug("Destination not specified in RAW SEND message");
|
||||
return false;
|
||||
}
|
||||
props.remove("DESTINATION");
|
||||
|
||||
try {
|
||||
if (props == null) {
|
||||
notifyStreamResult(true,"I2P_ERROR","No parameters specified in STREAM CONNECT message");
|
||||
_log.debug("No parameters specified in STREAM CONNECT message");
|
||||
return false;
|
||||
}
|
||||
boolean verbose = props.getProperty("SILENT","false").equals("false");
|
||||
|
||||
String dest = props.getProperty("DESTINATION");
|
||||
if (dest == null) {
|
||||
notifyStreamResult(verbose, "I2P_ERROR", "Destination not specified in RAW SEND message");
|
||||
_log.debug("Destination not specified in RAW SEND message");
|
||||
return false;
|
||||
}
|
||||
props.remove("DESTINATION");
|
||||
|
||||
try {
|
||||
streamSession.connect( this, dest, props );
|
||||
return true ;
|
||||
} catch (DataFormatException e) {
|
||||
_log.debug("Invalid destination in STREAM CONNECT message");
|
||||
if (verbose) notifyStreamAccept ( "INVALID_KEY" );
|
||||
notifyStreamResult ( verbose, "INVALID_KEY", null );
|
||||
} catch (ConnectException e) {
|
||||
_log.debug("STREAM CONNECT failed: " + e.getMessage());
|
||||
if (verbose) notifyStreamAccept ( "CONNECTION_REFUSED" );
|
||||
notifyStreamResult ( verbose, "CONNECTION_REFUSED", null );
|
||||
} catch (NoRouteToHostException e) {
|
||||
_log.debug("STREAM CONNECT failed: " + e.getMessage());
|
||||
if (verbose) notifyStreamAccept ( "CANT_REACH_PEER" );
|
||||
notifyStreamResult ( verbose, "CANT_REACH_PEER", null );
|
||||
} catch (InterruptedIOException e) {
|
||||
_log.debug("STREAM CONNECT failed: " + e.getMessage());
|
||||
if (verbose) notifyStreamAccept ( "TIMEOUT" );
|
||||
notifyStreamResult ( verbose, "TIMEOUT", null );
|
||||
} catch (I2PException e) {
|
||||
_log.debug("STREAM CONNECT failed: " + e.getMessage());
|
||||
if (verbose) notifyStreamAccept ( "I2P_ERROR" );
|
||||
notifyStreamResult ( verbose, "I2P_ERROR", e.getMessage() );
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
@ -661,11 +691,11 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
try {
|
||||
try {
|
||||
streamSession.startForwardingIncoming(props);
|
||||
notifyStreamAccept("OK");
|
||||
return true ;
|
||||
notifyStreamResult( true, "OK", null );
|
||||
return false ;
|
||||
} catch (SAMException e) {
|
||||
_log.debug("Forwarding STREAM connections failed: " + e.getMessage());
|
||||
notifyStreamAccept ( "FORWARDER_FAILED" );
|
||||
notifyStreamResult ( true, "I2P_ERROR", "Forwarding failed : " + e.getMessage() );
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
@ -677,17 +707,18 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
boolean verbose = props.getProperty( "SILENT", "false").equals("false");
|
||||
try {
|
||||
try {
|
||||
notifyStreamResult(verbose, "OK", null);
|
||||
streamSession.accept(this, verbose);
|
||||
return true ;
|
||||
} catch (InterruptedIOException e) {
|
||||
_log.debug("STREAM ACCEPT failed: " + e.getMessage());
|
||||
if (verbose) notifyStreamAccept( "TIMEOUT" );
|
||||
notifyStreamResult( verbose, "TIMEOUT", e.getMessage() );
|
||||
} catch (I2PException e) {
|
||||
_log.debug("STREAM ACCEPT failed: " + e.getMessage());
|
||||
if (verbose) notifyStreamAccept ( "I2P_ERROR" );
|
||||
notifyStreamResult ( verbose, "I2P_ERROR", e.getMessage() );
|
||||
} catch (SAMException e) {
|
||||
_log.debug("STREAM ACCEPT failed: " + e.getMessage());
|
||||
if (verbose) notifyStreamAccept ( "ALREADY_ACCEPTING" );
|
||||
notifyStreamResult ( verbose, "ALREADY_ACCEPTING", null );
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
@ -695,33 +726,16 @@ public class SAMv3Handler extends SAMv1Handler
|
||||
}
|
||||
|
||||
|
||||
public void notifyStreamAccept(String status) throws IOException
|
||||
public void notifyStreamResult(boolean verbose, String result, String message) throws IOException
|
||||
{
|
||||
if ( streamSession == null )
|
||||
{
|
||||
_log.error ( "BUG! Received stream connection, but session is null!" );
|
||||
throw new NullPointerException ( "BUG! STREAM session is null!" );
|
||||
}
|
||||
|
||||
if ( !writeString ( "STREAM STATUS RESULT="
|
||||
+ status
|
||||
+ "\n" ) )
|
||||
{
|
||||
throw new IOException ( "Error notifying connection to SAM client" );
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyStreamOutgoingConnection(String result) throws IOException
|
||||
{
|
||||
if ( streamSession == null )
|
||||
{
|
||||
_log.error ( "BUG! Received stream connection, but session is null!" );
|
||||
throw new NullPointerException ( "BUG! STREAM session is null!" );
|
||||
}
|
||||
|
||||
if ( !writeString ( "STREAM STATUS RESULT="
|
||||
+ result
|
||||
+ "\n" ) )
|
||||
if (!verbose) return ;
|
||||
|
||||
String out = "STREAM STATUS RESULT="+result;
|
||||
if (message!=null)
|
||||
out = out + " MESSAGE=\"" + message + "\"";
|
||||
out = out + '\n';
|
||||
|
||||
if ( !writeString ( out ) )
|
||||
{
|
||||
throw new IOException ( "Error notifying connection to SAM client" );
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle
|
||||
}
|
||||
|
||||
private void initSAMStreamSession(String login)
|
||||
throws IOException, DataFormatException, SAMException{
|
||||
throws IOException, DataFormatException, SAMException {
|
||||
|
||||
SAMv3Handler.SessionRecord rec = getDB().get(login);
|
||||
String dest = rec.getDest() ;
|
||||
@ -131,8 +131,7 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle
|
||||
public void connect ( SAMv3Handler handler, String dest, Properties props ) throws I2PException, ConnectException, NoRouteToHostException, DataFormatException, InterruptedIOException, IOException {
|
||||
|
||||
boolean verbose = (props.getProperty("SILENT", "false").equals("false"));
|
||||
Destination d = new Destination();
|
||||
d = SAMUtils.getDest(dest);
|
||||
Destination d = SAMUtils.getDest(dest);
|
||||
|
||||
I2PSocketOptions opts = socketMgr.buildOptions(props);
|
||||
if (props.getProperty(I2PSocketOptions.PROP_CONNECT_TIMEOUT) == null)
|
||||
@ -148,7 +147,7 @@ public class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handle
|
||||
|
||||
if ( rec==null ) throw new InterruptedIOException() ;
|
||||
|
||||
if (verbose) handler.notifyStreamOutgoingConnection("OK") ;
|
||||
handler.notifyStreamResult(verbose, "OK", null) ;
|
||||
|
||||
handler.stealSocket() ;
|
||||
|
||||
|
Reference in New Issue
Block a user