00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.server.crossfire;
00023
00024 import java.io.EOFException;
00025 import java.io.IOException;
00026 import java.io.InputStream;
00027 import java.io.OutputStream;
00028 import java.net.ServerSocket;
00029 import java.net.Socket;
00030 import java.nio.charset.Charset;
00031 import java.util.concurrent.Semaphore;
00032 import org.jetbrains.annotations.NotNull;
00033 import org.jetbrains.annotations.Nullable;
00034 import org.junit.Assert;
00035 import org.junit.Test;
00036
00041 public class DefaultCrossfireServerConnectionTest {
00042
00046 @Nullable
00047 private Semaphore sem;
00048
00055 @Test
00056 public void testNegotiateNumLookObjects1() throws InterruptedException, IOException {
00057 sem = new Semaphore(0);
00058 final Model model = new Model();
00059 final DefaultCrossfireServerConnection connection = new DefaultCrossfireServerConnection(model, null, "version");
00060 final int port = startServer();
00061 connection.start();
00062 try {
00063 connection.connect("localhost", port);
00064 connection.setPreferredNumLookObjects(10);
00065 assert sem != null;
00066 sem.acquire();
00067 Thread.sleep(200);
00068 Assert.assertEquals(10, connection.getCurrentNumLookObjects());
00069 connection.setPreferredNumLookObjects(11);
00070 connection.setPreferredNumLookObjects(12);
00071 connection.setPreferredNumLookObjects(13);
00072 connection.setPreferredNumLookObjects(14);
00073 Thread.sleep(200);
00074 Assert.assertEquals(14, connection.getCurrentNumLookObjects());
00075 } finally {
00076 connection.stop();
00077 }
00078 }
00079
00085 private int startServer() throws IOException {
00086
00087 final ServerSocket server = new ServerSocket(0);
00088 final Thread thread = new Thread(new Runnable() {
00089
00093 @NotNull
00094 private final Charset charset = Charset.forName("ISO-8859-1");
00095
00099 @Override
00100 public void run() {
00101 try {
00102 final Socket client = acceptClient(server);
00103 try {
00104 final InputStream in = getInputStream(client);
00105 final OutputStream out = getOutputStream(client);
00106 while (true) {
00107 final byte[] data = readPacket(in);
00108 if (data == null) {
00109 break;
00110 }
00111 int paramsIndex;
00112 for (paramsIndex = 0; paramsIndex < data.length; paramsIndex++) {
00113 if (data[paramsIndex] == (byte)' ') {
00114 break;
00115 }
00116 }
00117 final String cmd = new String(data, 0, paramsIndex, charset);
00118 if (paramsIndex < data.length && data[paramsIndex] == (byte)' ') {
00119 paramsIndex++;
00120 }
00121 if (cmd.equals("version")) {
00122 writeString(out, "version 1 1 info");
00123 } else if (cmd.equals("setup")) {
00124 processSetup(out, new String(data, paramsIndex, data.length-paramsIndex, charset));
00125 } else if (cmd.equals("requestinfo")) {
00126 processRequestinfo(out, new String(data, paramsIndex, data.length-paramsIndex, charset));
00127 } else if (cmd.equals("toggleextendedtext")) {
00128
00129 } else if (cmd.equals("addme")) {
00130 processAddme(out);
00131 } else {
00132 Assert.fail("received unexpected command: "+cmd);
00133 }
00134 }
00135 } finally {
00136 client.close();
00137 }
00138 } catch (final IOException ex) {
00139 Assert.fail(ex.getMessage());
00140 throw new AssertionError(ex);
00141 }
00142 }
00143
00150 @Nullable
00151 private byte[] readPacket(@NotNull final InputStream in) throws EOFException {
00152 final int tmp;
00153 try {
00154 tmp = readByte(in);
00155 } catch (final EOFException ignored) {
00156 return null;
00157 }
00158 final int packetLen = tmp*0x100+readByte(in);
00159 final byte[] data = new byte[packetLen];
00160 try {
00161 int pos = 0;
00162 while (pos < data.length) {
00163 final int len = in.read(data, pos, data.length-pos);
00164 if (len == -1) {
00165 throw new EOFException("unexpected end of file reached");
00166 }
00167 pos += len;
00168 }
00169 } catch (final IOException ex) {
00170 Assert.fail(ex.getMessage());
00171 throw new AssertionError(ex);
00172 }
00173 return data;
00174 }
00175
00182 private void processSetup(@NotNull final OutputStream out, @NotNull final String params) throws IOException {
00183 final String[] params2 = params.split(" ", -1);
00184 Assert.assertEquals(0, params2.length%2);
00185 final StringBuilder sb = new StringBuilder("setup");
00186 for (int i = 0; i < params2.length; i += 2) {
00187 final String key = params2[i];
00188 final String value = params2[i+1];
00189 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")) {
00190 sb.append(" ").append(key).append(" ").append(value);
00191 } else {
00192 sb.append(" ").append(key).append(" FALSE");
00193 }
00194 }
00195 writeString(out, sb.toString());
00196 }
00197
00204 private void processRequestinfo(@NotNull final OutputStream out, @NotNull final String params) throws IOException {
00205 if (params.equals("exp_table")) {
00206 writeBytes(out, new byte[] {
00207 'r',
00208 'e',
00209 'p',
00210 'l',
00211 'y',
00212 'i',
00213 'n',
00214 'f',
00215 'o',
00216 ' ',
00217 'e',
00218 'x',
00219 'p',
00220 '_',
00221 't',
00222 'a',
00223 'b',
00224 'l',
00225 'e',
00226 ' ',
00227 0,
00228 1,
00229 });
00230 } else {
00231
00232 }
00233 }
00234
00240 private void processAddme(@NotNull final OutputStream out) throws IOException {
00241 writeString(out, "query 0 What is your name?");
00242 writeString(out, "addme_success");
00243 assert sem != null;
00244 sem.release();
00245 }
00246
00253 private int readByte(@NotNull final InputStream in) throws EOFException {
00254 final int ch;
00255 try {
00256 ch = in.read();
00257 } catch (final IOException ex) {
00258 Assert.fail(ex.getMessage());
00259 throw new AssertionError(ex);
00260 }
00261 if (ch == -1) {
00262 throw new EOFException();
00263 }
00264 return ch;
00265 }
00266
00273 private void writeString(@NotNull final OutputStream out, @NotNull final String s) throws IOException {
00274 writeBytes(out, s.getBytes(charset));
00275 }
00276
00283 private void writeBytes(@NotNull final OutputStream out, @NotNull final byte[] b) throws IOException {
00284 final int len = b.length;
00285 out.write(len/0x100);
00286 out.write(len);
00287 out.write(b);
00288 }
00289
00290 });
00291 thread.start();
00292 return server.getLocalPort();
00293 }
00294
00300 @NotNull
00301 private static Socket acceptClient(@NotNull final ServerSocket server) {
00302 final Socket client;
00303 try {
00304 client = server.accept();
00305 } catch (final IOException ex) {
00306 Assert.fail(ex.getMessage());
00307 throw new AssertionError(ex);
00308 }
00309 return client;
00310 }
00311
00317 @NotNull
00318 private static InputStream getInputStream(@NotNull final Socket socket) {
00319 final InputStream in;
00320 try {
00321 in = socket.getInputStream();
00322 } catch (final IOException ex) {
00323 Assert.fail(ex.getMessage());
00324 throw new AssertionError(ex);
00325 }
00326 return in;
00327 }
00328
00334 @NotNull
00335 private static OutputStream getOutputStream(@NotNull final Socket socket) {
00336 final OutputStream out;
00337 try {
00338 out = socket.getOutputStream();
00339 } catch (final IOException ex) {
00340 Assert.fail(ex.getMessage());
00341 throw new AssertionError(ex);
00342 }
00343 return out;
00344 }
00345
00346 }