package com.ruoyi.device.bts;
|
|
import java.io.ByteArrayOutputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.net.ServerSocket;
|
import java.net.Socket;
|
import java.nio.charset.StandardCharsets;
|
import java.util.List;
|
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.Executors;
|
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.TimeUnit;
|
|
final class ScriptedBtsTcpSimulator implements AutoCloseable
|
{
|
private static final byte[] FRAME_END = "#\r\n".getBytes(StandardCharsets.UTF_8);
|
|
private final ServerSocket serverSocket;
|
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
private final BlockingQueue<String> responses = new LinkedBlockingQueue<>();
|
private final List<String> requests = new CopyOnWriteArrayList<>();
|
|
ScriptedBtsTcpSimulator() throws IOException
|
{
|
serverSocket = new ServerSocket(0);
|
executor.submit(this::serve);
|
}
|
|
int port()
|
{
|
return serverSocket.getLocalPort();
|
}
|
|
void enqueue(String response)
|
{
|
responses.add(response);
|
}
|
|
List<String> requests()
|
{
|
return List.copyOf(requests);
|
}
|
|
private void serve()
|
{
|
try (Socket socket = serverSocket.accept())
|
{
|
while (!socket.isClosed())
|
{
|
String request = readFrame(socket.getInputStream());
|
requests.add(request);
|
String response = responses.poll(5, TimeUnit.SECONDS);
|
if (response == null) throw new IOException("No scripted BTS response available");
|
socket.getOutputStream().write(response.getBytes(StandardCharsets.UTF_8));
|
socket.getOutputStream().write(FRAME_END);
|
socket.getOutputStream().flush();
|
}
|
}
|
catch (Exception ignored)
|
{
|
}
|
}
|
|
private String readFrame(InputStream input) throws IOException
|
{
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
int matched = 0;
|
while (true)
|
{
|
int value = input.read();
|
if (value < 0) throw new IOException("Client disconnected");
|
if ((byte) value == FRAME_END[matched])
|
{
|
matched++;
|
if (matched == FRAME_END.length) return buffer.toString(StandardCharsets.UTF_8);
|
continue;
|
}
|
if (matched > 0)
|
{
|
buffer.write(FRAME_END, 0, matched);
|
matched = 0;
|
}
|
buffer.write(value);
|
}
|
}
|
|
@Override
|
public void close() throws Exception
|
{
|
serverSocket.close();
|
executor.shutdownNow();
|
executor.awaitTermination(2, TimeUnit.SECONDS);
|
}
|
}
|