forked from I2P_Developers/i2p.i2p
Move DatagramServer from SAMv3Handler to its own file,
javadocs more changes to follow
This commit is contained in:
217
apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java
Normal file
217
apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
package net.i2p.sam;
|
||||||
|
/*
|
||||||
|
* free (adj.): unencumbered; not under the control of others
|
||||||
|
* Written by human in 2004 and released into the public domain
|
||||||
|
* with no warranty of any kind, either expressed or implied.
|
||||||
|
* It probably won't make your computer catch on fire, or eat
|
||||||
|
* your children, but it might. Use at your own risk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.client.I2PSession;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.util.I2PAppThread;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a singleton listening on 127.0.0.1:7655 or as specified by
|
||||||
|
* sam.udp.host and sam.udp.port properties.
|
||||||
|
* This is used for both repliable and raw datagrams.
|
||||||
|
*
|
||||||
|
* @since 0.9.22 moved from SAMv3Handler
|
||||||
|
*/
|
||||||
|
class SAMv3DatagramServer {
|
||||||
|
|
||||||
|
private static SAMv3DatagramServer _instance;
|
||||||
|
private static DatagramChannel server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the singleton.
|
||||||
|
* If this is the first call, will be instantiated and will listen
|
||||||
|
* on the default host:port 127.0.0.1:7655.
|
||||||
|
*/
|
||||||
|
public static SAMv3DatagramServer getInstance() throws IOException {
|
||||||
|
return getInstance(new Properties());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the singleton.
|
||||||
|
* If this is the first call, will be instantiated and will listen
|
||||||
|
* on the specified host:port, default 127.0.0.1:7655.
|
||||||
|
* Properties are sam.udp.host and sam.udp.port.
|
||||||
|
*
|
||||||
|
* @param props ignored unless this is the first call
|
||||||
|
*/
|
||||||
|
public static SAMv3DatagramServer getInstance(Properties props) throws IOException {
|
||||||
|
synchronized(SAMv3DatagramServer.class) {
|
||||||
|
if (_instance==null)
|
||||||
|
_instance = new SAMv3DatagramServer(props);
|
||||||
|
return _instance ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SAMv3DatagramServer(Properties props) throws IOException {
|
||||||
|
synchronized(SAMv3DatagramServer.class) {
|
||||||
|
if (server==null)
|
||||||
|
server = DatagramChannel.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
String host = props.getProperty(SAMBridge.PROP_DATAGRAM_HOST, SAMBridge.DEFAULT_DATAGRAM_HOST);
|
||||||
|
String portStr = props.getProperty(SAMBridge.PROP_DATAGRAM_PORT, SAMBridge.DEFAULT_DATAGRAM_PORT);
|
||||||
|
int port ;
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt(portStr);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
port = Integer.parseInt(SAMBridge.DEFAULT_DATAGRAM_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
server.socket().bind(new InetSocketAddress(host, port));
|
||||||
|
new I2PAppThread(new Listener(server), "DatagramListener").start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(SocketAddress addr, ByteBuffer msg) throws IOException {
|
||||||
|
server.send(msg, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Listener implements Runnable {
|
||||||
|
|
||||||
|
private final DatagramChannel server;
|
||||||
|
|
||||||
|
public Listener(DatagramChannel server)
|
||||||
|
{
|
||||||
|
this.server = server ;
|
||||||
|
}
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
ByteBuffer inBuf = ByteBuffer.allocateDirect(SAMRawSession.RAW_SIZE_MAX+1024);
|
||||||
|
|
||||||
|
while (!Thread.interrupted())
|
||||||
|
{
|
||||||
|
inBuf.clear();
|
||||||
|
try {
|
||||||
|
server.receive(inBuf);
|
||||||
|
} catch (IOException e) {
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
inBuf.flip();
|
||||||
|
ByteBuffer outBuf = ByteBuffer.wrap(new byte[inBuf.remaining()]);
|
||||||
|
outBuf.put(inBuf);
|
||||||
|
outBuf.flip();
|
||||||
|
// A new thread for every message is wildly inefficient...
|
||||||
|
//new I2PAppThread(new MessageDispatcher(outBuf.array()), "MessageDispatcher").start();
|
||||||
|
// inline
|
||||||
|
// Even though we could be sending messages through multiple sessions,
|
||||||
|
// that isn't a common use case, and blocking should be rare.
|
||||||
|
// Inside router context, I2CP drops on overflow.
|
||||||
|
(new MessageDispatcher(outBuf.array())).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MessageDispatcher implements Runnable {
|
||||||
|
private final ByteArrayInputStream is;
|
||||||
|
|
||||||
|
public MessageDispatcher(byte[] buf) {
|
||||||
|
this.is = new ByteArrayInputStream(buf) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
String header = DataHelper.readLine(is).trim();
|
||||||
|
StringTokenizer tok = new StringTokenizer(header, " ");
|
||||||
|
if (tok.countTokens() < 3) {
|
||||||
|
// This is not a correct message, for sure
|
||||||
|
warn("Bad datagram header received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String version = tok.nextToken();
|
||||||
|
if (!version.startsWith("3.")) {
|
||||||
|
warn("Bad datagram header received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String nick = tok.nextToken();
|
||||||
|
String dest = tok.nextToken();
|
||||||
|
|
||||||
|
SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
|
||||||
|
if (rec!=null) {
|
||||||
|
Properties sprops = rec.getProps();
|
||||||
|
String pr = sprops.getProperty("PROTOCOL");
|
||||||
|
String fp = sprops.getProperty("FROM_PORT");
|
||||||
|
String tp = sprops.getProperty("TO_PORT");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
String t = tok.nextToken();
|
||||||
|
if (t.startsWith("PROTOCOL="))
|
||||||
|
pr = t.substring("PROTOTCOL=".length());
|
||||||
|
else if (t.startsWith("FROM_PORT="))
|
||||||
|
fp = t.substring("FROM_PORT=".length());
|
||||||
|
else if (t.startsWith("TO_PORT="))
|
||||||
|
tp = t.substring("TO_PORT=".length());
|
||||||
|
}
|
||||||
|
int proto = I2PSession.PROTO_UNSPECIFIED;
|
||||||
|
int fromPort = I2PSession.PORT_UNSPECIFIED;
|
||||||
|
int toPort = I2PSession.PORT_UNSPECIFIED;
|
||||||
|
if (pr != null) {
|
||||||
|
try {
|
||||||
|
proto = Integer.parseInt(pr);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
warn("Bad datagram header received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fp != null) {
|
||||||
|
try {
|
||||||
|
fromPort = Integer.parseInt(fp);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
warn("Bad datagram header received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tp != null) {
|
||||||
|
try {
|
||||||
|
toPort = Integer.parseInt(tp);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
warn("Bad datagram header received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO too many allocations and copies. One here and one in Listener above.
|
||||||
|
byte[] data = new byte[is.available()];
|
||||||
|
is.read(data);
|
||||||
|
SAMv3Handler.Session sess = rec.getHandler().getSession();
|
||||||
|
if (sess != null)
|
||||||
|
rec.getHandler().getSession().sendBytes(dest,data, proto, fromPort, toPort);
|
||||||
|
else
|
||||||
|
warn("Dropping datagram, no session for " + nick);
|
||||||
|
} else {
|
||||||
|
warn("Dropping datagram, no session for " + nick);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
warn("Error handling datagram", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9.22 */
|
||||||
|
private static void warn(String s) {
|
||||||
|
warn(s, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9.22 */
|
||||||
|
private static void warn(String s, Throwable t) {
|
||||||
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3DatagramServer.class);
|
||||||
|
if (log.shouldLog(Log.WARN))
|
||||||
|
log.warn(s, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -21,7 +21,7 @@ import java.nio.ByteBuffer;
|
|||||||
class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Handler.Session, SAMDatagramReceiver {
|
class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Handler.Session, SAMDatagramReceiver {
|
||||||
|
|
||||||
private final SAMv3Handler handler;
|
private final SAMv3Handler handler;
|
||||||
private final SAMv3Handler.DatagramServer server;
|
private final SAMv3DatagramServer server;
|
||||||
private final String nick;
|
private final String nick;
|
||||||
private final SocketAddress clientAddress;
|
private final SocketAddress clientAddress;
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Handler.Se
|
|||||||
);
|
);
|
||||||
this.nick = nick ;
|
this.nick = nick ;
|
||||||
this.recv = this ; // replacement
|
this.recv = this ; // replacement
|
||||||
this.server = SAMv3Handler.DatagramServer.getInstance() ;
|
this.server = SAMv3DatagramServer.getInstance() ;
|
||||||
|
|
||||||
SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
|
SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
|
||||||
if ( rec==null ) throw new SAMException("Record disappeared for nickname : \""+nick+"\"") ;
|
if ( rec==null ) throw new SAMException("Record disappeared for nickname : \""+nick+"\"") ;
|
||||||
|
@@ -10,7 +10,6 @@ package net.i2p.sam;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
@@ -18,7 +17,6 @@ import java.net.ConnectException;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.NoRouteToHostException;
|
import java.net.NoRouteToHostException;
|
||||||
import java.nio.channels.DatagramChannel;
|
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
@@ -101,175 +99,6 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
{
|
{
|
||||||
return (verMajor == 3);
|
return (verMajor == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DatagramServer {
|
|
||||||
|
|
||||||
private static DatagramServer _instance;
|
|
||||||
private static DatagramChannel server;
|
|
||||||
|
|
||||||
public static DatagramServer getInstance() throws IOException {
|
|
||||||
return getInstance(new Properties());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DatagramServer getInstance(Properties props) throws IOException {
|
|
||||||
synchronized(DatagramServer.class) {
|
|
||||||
if (_instance==null)
|
|
||||||
_instance = new DatagramServer(props);
|
|
||||||
return _instance ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DatagramServer(Properties props) throws IOException {
|
|
||||||
synchronized(DatagramServer.class) {
|
|
||||||
if (server==null)
|
|
||||||
server = DatagramChannel.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
String host = props.getProperty(SAMBridge.PROP_DATAGRAM_HOST, SAMBridge.DEFAULT_DATAGRAM_HOST);
|
|
||||||
String portStr = props.getProperty(SAMBridge.PROP_DATAGRAM_PORT, SAMBridge.DEFAULT_DATAGRAM_PORT);
|
|
||||||
int port ;
|
|
||||||
try {
|
|
||||||
port = Integer.parseInt(portStr);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
port = Integer.parseInt(SAMBridge.DEFAULT_DATAGRAM_PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
server.socket().bind(new InetSocketAddress(host, port));
|
|
||||||
new I2PAppThread(new Listener(server), "DatagramListener").start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void send(SocketAddress addr, ByteBuffer msg) throws IOException {
|
|
||||||
server.send(msg, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class Listener implements Runnable {
|
|
||||||
|
|
||||||
private final DatagramChannel server;
|
|
||||||
|
|
||||||
public Listener(DatagramChannel server)
|
|
||||||
{
|
|
||||||
this.server = server ;
|
|
||||||
}
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
ByteBuffer inBuf = ByteBuffer.allocateDirect(SAMRawSession.RAW_SIZE_MAX+1024);
|
|
||||||
|
|
||||||
while (!Thread.interrupted())
|
|
||||||
{
|
|
||||||
inBuf.clear();
|
|
||||||
try {
|
|
||||||
server.receive(inBuf);
|
|
||||||
} catch (IOException e) {
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
inBuf.flip();
|
|
||||||
ByteBuffer outBuf = ByteBuffer.wrap(new byte[inBuf.remaining()]);
|
|
||||||
outBuf.put(inBuf);
|
|
||||||
outBuf.flip();
|
|
||||||
// A new thread for every message is wildly inefficient...
|
|
||||||
//new I2PAppThread(new MessageDispatcher(outBuf.array()), "MessageDispatcher").start();
|
|
||||||
// inline
|
|
||||||
// Even though we could be sending messages through multiple sessions,
|
|
||||||
// that isn't a common use case, and blocking should be rare.
|
|
||||||
// Inside router context, I2CP drops on overflow.
|
|
||||||
(new MessageDispatcher(outBuf.array())).run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MessageDispatcher implements Runnable
|
|
||||||
{
|
|
||||||
private final ByteArrayInputStream is;
|
|
||||||
|
|
||||||
public MessageDispatcher(byte[] buf)
|
|
||||||
{
|
|
||||||
this.is = new java.io.ByteArrayInputStream(buf) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
String header = DataHelper.readLine(is).trim();
|
|
||||||
StringTokenizer tok = new StringTokenizer(header, " ");
|
|
||||||
if (tok.countTokens() < 3) {
|
|
||||||
// This is not a correct message, for sure
|
|
||||||
warn("Bad datagram header received");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String version = tok.nextToken();
|
|
||||||
if (!version.startsWith("3.")) {
|
|
||||||
warn("Bad datagram header received");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String nick = tok.nextToken();
|
|
||||||
String dest = tok.nextToken();
|
|
||||||
|
|
||||||
SessionRecord rec = sSessionsHash.get(nick);
|
|
||||||
if (rec!=null) {
|
|
||||||
Properties sprops = rec.getProps();
|
|
||||||
String pr = sprops.getProperty("PROTOCOL");
|
|
||||||
String fp = sprops.getProperty("FROM_PORT");
|
|
||||||
String tp = sprops.getProperty("TO_PORT");
|
|
||||||
while (tok.hasMoreTokens()) {
|
|
||||||
String t = tok.nextToken();
|
|
||||||
if (t.startsWith("PROTOCOL="))
|
|
||||||
pr = t.substring("PROTOTCOL=".length());
|
|
||||||
else if (t.startsWith("FROM_PORT="))
|
|
||||||
fp = t.substring("FROM_PORT=".length());
|
|
||||||
else if (t.startsWith("TO_PORT="))
|
|
||||||
tp = t.substring("TO_PORT=".length());
|
|
||||||
}
|
|
||||||
int proto = I2PSession.PROTO_UNSPECIFIED;
|
|
||||||
int fromPort = I2PSession.PORT_UNSPECIFIED;
|
|
||||||
int toPort = I2PSession.PORT_UNSPECIFIED;
|
|
||||||
if (pr != null) {
|
|
||||||
try {
|
|
||||||
proto = Integer.parseInt(pr);
|
|
||||||
} catch (NumberFormatException nfe) {
|
|
||||||
warn("Bad datagram header received");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fp != null) {
|
|
||||||
try {
|
|
||||||
fromPort = Integer.parseInt(fp);
|
|
||||||
} catch (NumberFormatException nfe) {
|
|
||||||
warn("Bad datagram header received");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tp != null) {
|
|
||||||
try {
|
|
||||||
toPort = Integer.parseInt(tp);
|
|
||||||
} catch (NumberFormatException nfe) {
|
|
||||||
warn("Bad datagram header received");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO too many allocations and copies. One here and one in Listener above.
|
|
||||||
byte[] data = new byte[is.available()];
|
|
||||||
is.read(data);
|
|
||||||
rec.getHandler().session.sendBytes(dest,data, proto, fromPort, toPort);
|
|
||||||
} else {
|
|
||||||
warn("Dropping datagram, no session for " + nick);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
warn("Error handling datagram", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @since 0.9.22 */
|
|
||||||
private static void warn(String s) {
|
|
||||||
warn(s, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @since 0.9.22 */
|
|
||||||
private static void warn(String s, Throwable t) {
|
|
||||||
Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class);
|
|
||||||
if (log.shouldLog(Log.WARN))
|
|
||||||
log.warn(s, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The values in the SessionsDB
|
* The values in the SessionsDB
|
||||||
@@ -408,6 +237,15 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
return bridge;
|
return bridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For SAMv3DatagramServer
|
||||||
|
* @return may be null
|
||||||
|
* @since 0.9.22
|
||||||
|
*/
|
||||||
|
Session getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
public void handle() {
|
public void handle() {
|
||||||
String msg = null;
|
String msg = null;
|
||||||
String domain = null;
|
String domain = null;
|
||||||
@@ -682,12 +520,12 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
// Create the session
|
// Create the session
|
||||||
|
|
||||||
if (style.equals("RAW")) {
|
if (style.equals("RAW")) {
|
||||||
DatagramServer.getInstance(i2cpProps);
|
SAMv3DatagramServer.getInstance(i2cpProps);
|
||||||
SAMv3RawSession v3 = newSAMRawSession(nick);
|
SAMv3RawSession v3 = newSAMRawSession(nick);
|
||||||
rawSession = v3;
|
rawSession = v3;
|
||||||
this.session = v3;
|
this.session = v3;
|
||||||
} else if (style.equals("DATAGRAM")) {
|
} else if (style.equals("DATAGRAM")) {
|
||||||
DatagramServer.getInstance(i2cpProps);
|
SAMv3DatagramServer.getInstance(i2cpProps);
|
||||||
SAMv3DatagramSession v3 = newSAMDatagramSession(nick);
|
SAMv3DatagramSession v3 = newSAMDatagramSession(nick);
|
||||||
datagramSession = v3;
|
datagramSession = v3;
|
||||||
this.session = v3;
|
this.session = v3;
|
||||||
|
@@ -22,7 +22,7 @@ class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Session, SA
|
|||||||
|
|
||||||
private final String nick;
|
private final String nick;
|
||||||
private final SAMv3Handler handler;
|
private final SAMv3Handler handler;
|
||||||
private final SAMv3Handler.DatagramServer server;
|
private final SAMv3DatagramServer server;
|
||||||
private final SocketAddress clientAddress;
|
private final SocketAddress clientAddress;
|
||||||
|
|
||||||
public String getNick() { return nick; }
|
public String getNick() { return nick; }
|
||||||
@@ -43,7 +43,7 @@ class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Session, SA
|
|||||||
);
|
);
|
||||||
this.nick = nick ;
|
this.nick = nick ;
|
||||||
this.recv = this ; // replacement
|
this.recv = this ; // replacement
|
||||||
this.server = SAMv3Handler.DatagramServer.getInstance() ;
|
this.server = SAMv3DatagramServer.getInstance() ;
|
||||||
SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
|
SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
|
||||||
if (rec == null)
|
if (rec == null)
|
||||||
throw new InterruptedIOException() ;
|
throw new InterruptedIOException() ;
|
||||||
|
Reference in New Issue
Block a user