1 package com.realtime.crossfire.jxclient.server.crossfire;
3 import java.io.EOFException;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.OutputStream;
7 import java.net.ServerSocket;
8 import java.net.Socket;
9 import java.net.SocketException;
10 import java.nio.charset.Charset;
11 import java.nio.charset.StandardCharsets;
12 import java.util.concurrent.Semaphore;
13 import org.jetbrains.annotations.NotNull;
14 import org.jetbrains.annotations.Nullable;
15 import org.junit.Assert;
26 private final Charset
charset = StandardCharsets.ISO_8859_1;
32 private final Semaphore
sem =
new Semaphore(0);
38 @SuppressWarnings({
"resource",
"IOResourceOpenedButNotSafelyClosed",
"SocketOpenedButNotSafelyClosed"})
39 private final ServerSocket
server =
new ServerSocket(0);
45 private final Thread
thread =
new Thread(this::run);
51 private final Object
sync =
new Object();
78 public void stop() throws InterruptedException, IOException {
94 return server.getLocalPort();
111 synchronized (
sync) {
122 for (paramsIndex = 0; paramsIndex < data.length; paramsIndex++) {
123 if (data[paramsIndex] == (
byte)
' ') {
127 final String cmd =
new String(data, 0, paramsIndex,
charset);
128 if (paramsIndex < data.length && data[paramsIndex] == (
byte)
' ') {
144 case "toggleextendedtext":
153 Assert.fail(
"received unexpected command: "+cmd);
158 synchronized (
sync) {
164 }
catch (
final IOException ex) {
165 Assert.fail(ex.getMessage());
166 throw new AssertionError(ex);
176 private static byte @Nullable []
readPacket(@NotNull
final InputStream in)
throws EOFException {
180 }
catch (
final EOFException ignored) {
183 final int packetLen = tmp*0x100+
readByte(in);
184 final byte[] data =
new byte[packetLen];
187 while (pos < data.length) {
188 final int len = in.read(data, pos, data.length-pos);
190 throw new EOFException(
"unexpected end of file reached");
194 }
catch (
final IOException ex) {
195 Assert.fail(ex.getMessage());
196 throw new AssertionError(ex);
206 private void processSetup(@NotNull
final String params)
throws IOException {
207 final String[] params2 = params.split(
" ", -1);
208 Assert.assertEquals(0, params2.length%2);
209 final StringBuilder sb =
new StringBuilder(
"setup");
210 for (
int i = 0; i < params2.length; i += 2) {
211 final String key = params2[i];
212 final String value = params2[i+1];
213 if (key.equals(
"map2cmd") || key.equals(
"newmapcmd") || key.equals(
"facecache") || key.equals(
"extendedTextInfos") || key.equals(
"itemcmd") || key.equals(
"spellmon") || key.equals(
"tick") || key.equals(
"num_look_objects") || key.equals(
"mapsize")) {
214 sb.append(
" ").append(key).append(
" ").append(value);
216 sb.append(
" ").append(key).append(
" FALSE");
230 writeBytes(
"replyinfo exp_table \0\1".getBytes(StandardCharsets.US_ASCII));
234 writeBytes(
"replyinfo skill_info ".getBytes(StandardCharsets.US_ASCII));
237 case "skill_extra 1":
238 writeBytes(
"replyinfo skill_extra ".getBytes(StandardCharsets.US_ASCII));
241 case "knowledge_info":
242 writeBytes(
"replyinfo knowledge_info ".getBytes(StandardCharsets.US_ASCII));
246 writeBytes(
"replyinfo image_info 0\n0\n".getBytes(StandardCharsets.US_ASCII));
250 writeBytes(
"replyinfo startingmap ".getBytes(StandardCharsets.US_ASCII));
254 writeBytes(
"replyinfo race_list ".getBytes(StandardCharsets.US_ASCII));
258 writeBytes(
"replyinfo class_list ".getBytes(StandardCharsets.US_ASCII));
262 writeBytes(
"replyinfo newcharinfo ".getBytes(StandardCharsets.US_ASCII));
266 Assert.fail(
"requestinfo "+params+
" not implemented");
288 private static int readByte(@NotNull
final InputStream in)
throws EOFException {
292 }
catch (
final SocketException ex) {
293 final String message = ex.getMessage();
294 if (!message.equals(
"Socket closed")) {
295 Assert.fail(message);
296 throw new AssertionError(ex);
298 final EOFException ex2 =
new EOFException(
"EOF");
301 }
catch (
final IOException ex) {
302 Assert.fail(ex.getMessage());
303 throw new AssertionError(ex);
306 throw new EOFException(
"EOF");
316 public void writeString(@NotNull
final String s)
throws IOException {
325 public void writeBytes(
final byte @NotNull [] b)
throws IOException {
327 final int len = b.length;
328 out.write(len/0x100);
344 }
catch (
final IOException ex) {
345 Assert.fail(ex.getMessage());
346 throw new AssertionError(ex);
358 final InputStream in;
360 in = socket.getInputStream();
361 }
catch (
final IOException ex) {
362 Assert.fail(ex.getMessage());
363 throw new AssertionError(ex);
375 synchronized (
sync) {
379 Assert.fail(
"no client connection");
382 final OutputStream out;
384 out = tmp.getOutputStream();
385 }
catch (
final IOException ex) {
386 Assert.fail(ex.getMessage());
387 throw new AssertionError(ex);