static
This commit is contained in:
@@ -209,17 +209,13 @@ public class ArcNetProvider implements NetProvider{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//TODO remove
|
||||
static AsyncUdp udp = new AsyncUdp();
|
||||
|
||||
@Override
|
||||
public void pingHost(String address, int port, Cons<Host> valid, Cons<Exception> invalid){
|
||||
long time = Time.millis();
|
||||
var socket = new InetSocketAddress(address, port);
|
||||
Log.info("Time to resolve @: @", address, Time.timeSinceMillis(time));
|
||||
|
||||
udp.send(socket, 2000, 512, ByteBuffer.wrap(new byte[]{-2, 1}), data -> {
|
||||
AsyncUdp.send(socket, 2000, 512, ByteBuffer.wrap(new byte[]{-2, 1}), data -> {
|
||||
Host host = NetworkIO.readServerData((int)Time.timeSinceMillis(time), socket.getAddress().getHostAddress(), data);
|
||||
host.port = port;
|
||||
Core.app.post(() -> valid.get(host));
|
||||
|
||||
@@ -10,58 +10,18 @@ import java.nio.channels.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class AsyncUdp implements Runnable{
|
||||
Selector selector;
|
||||
DelayQueue<Request> removals = new DelayQueue<>();
|
||||
TaskQueue tasks = new TaskQueue();
|
||||
int emptySelects;
|
||||
public class AsyncUdp{
|
||||
static Selector selector;
|
||||
static DelayQueue<Request> removals = new DelayQueue<>();
|
||||
static TaskQueue tasks = new TaskQueue();
|
||||
static int emptySelects;
|
||||
|
||||
public AsyncUdp(){
|
||||
static{
|
||||
try{
|
||||
selector = Selector.open();
|
||||
|
||||
Threads.daemon("AsyncUDP", this);
|
||||
Threads.daemon("AsyncUDP-Delay", () -> {
|
||||
while(true){
|
||||
try{
|
||||
var request = removals.take();
|
||||
synchronized(request){
|
||||
request.cancel(new TimeoutException());
|
||||
}
|
||||
}catch(InterruptedException ignored){
|
||||
}
|
||||
}
|
||||
});
|
||||
}catch(IOException e){
|
||||
throw new ArcRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(InetSocketAddress address, int timeout, int bufferSize, ByteBuffer data, Cons<ByteBuffer> received, Cons<Exception> failed){
|
||||
//TODO is it worth posting to the task queue when you can just run it here? shouldn't be very expensive
|
||||
tasks.post(() -> {
|
||||
try{
|
||||
DatagramChannel channel = selector.provider().openDatagramChannel();
|
||||
channel.configureBlocking(false);
|
||||
channel.connect(address);
|
||||
channel.send(data, address);
|
||||
|
||||
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
|
||||
|
||||
Request req = new Request(address, timeout, bufferSize, data, channel, key, received, failed);
|
||||
key.attach(req);
|
||||
|
||||
removals.offer(req);
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
failed.get(e);
|
||||
}
|
||||
});
|
||||
selector.wakeup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(){
|
||||
//handle requests and tasks
|
||||
Threads.daemon("AsyncUDP", () -> {
|
||||
while(true){
|
||||
try{
|
||||
long startTime = Time.millis();
|
||||
@@ -84,10 +44,8 @@ public class AsyncUdp implements Runnable{
|
||||
var key = iter.next();
|
||||
iter.remove();
|
||||
|
||||
if(key.isReadable()){
|
||||
if(key.isReadable() && key.isValid()){
|
||||
var request = (Request)key.attachment();
|
||||
|
||||
synchronized(request){
|
||||
try{
|
||||
var channel = (DatagramChannel)key.channel();
|
||||
var buffer = ByteBuffer.allocate(request.bufferSize);
|
||||
@@ -97,17 +55,54 @@ public class AsyncUdp implements Runnable{
|
||||
request.received.get(buffer);
|
||||
request.close();
|
||||
}catch(IOException error){
|
||||
request.cancel(error);
|
||||
request.fail(error);
|
||||
//TODO remove logging, this is not needed outside of debugging
|
||||
Log.err(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}catch(IOException e){
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//remove requests with the delay queue
|
||||
Threads.daemon("AsyncUDP-Delay", () -> {
|
||||
while(true){
|
||||
try{
|
||||
var request = removals.take();
|
||||
tasks.post(() -> request.fail(new TimeoutException()));
|
||||
selector.wakeup();
|
||||
}catch(InterruptedException ignored){}
|
||||
}
|
||||
});
|
||||
}catch(IOException e){
|
||||
throw new ArcRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void send(InetSocketAddress address, int timeout, int bufferSize, ByteBuffer data, Cons<ByteBuffer> received, Cons<Exception> failed){
|
||||
tasks.post(() -> {
|
||||
try{
|
||||
DatagramChannel channel = selector.provider().openDatagramChannel();
|
||||
channel.configureBlocking(false);
|
||||
channel.connect(address);
|
||||
channel.send(data, address);
|
||||
|
||||
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
|
||||
|
||||
Request req = new Request(address, timeout, bufferSize, data, channel, key, received, failed);
|
||||
key.attach(req);
|
||||
|
||||
removals.offer(req);
|
||||
}catch(Exception e){
|
||||
Log.err(e);
|
||||
failed.get(e);
|
||||
}
|
||||
});
|
||||
selector.wakeup();
|
||||
}
|
||||
|
||||
static class Request implements Delayed{
|
||||
@@ -142,7 +137,7 @@ public class AsyncUdp implements Runnable{
|
||||
}
|
||||
}
|
||||
|
||||
void cancel(Exception error){
|
||||
void fail(Exception error){
|
||||
if(!key.isValid()) return;
|
||||
failed.get(error);
|
||||
close();
|
||||
|
||||
Reference in New Issue
Block a user