1 package net.sourceforge.rconed;
2
3 import java.io.IOException;
4 import java.net.DatagramPacket;
5 import java.net.DatagramSocket;
6 import java.net.InetAddress;
7 import java.net.SocketTimeoutException;
8
9 import net.sourceforge.rconed.exception.BadRcon;
10 import net.sourceforge.rconed.exception.ResponseEmpty;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 public abstract class Rcon {
29
30 private static final int RESPONSE_TIMEOUT = 2000;
31 private static final int MULTIPLE_PACKETS_TIMEOUT = 300;
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public static String send(int localPort, String ipStr, int port, String password, String command)
46 throws SocketTimeoutException, BadRcon, ResponseEmpty {
47
48 RconPacket[] requested = sendRequest(localPort, ipStr, port, password, command);
49
50 String response = assemblePacket(requested);
51
52 if (response.matches("Bad rcon_password.\n")) {
53 throw new BadRcon();
54 }
55 if (response.length() == 0) {
56 throw new ResponseEmpty();
57 }
58
59 return response;
60 }
61
62 private static DatagramPacket getDatagramPacket(String request, InetAddress inet, int port) {
63 byte first = -1;
64 byte last = 0;
65 byte[] buffer = request.getBytes();
66 byte[] commandBytes = new byte[buffer.length + 5];
67 commandBytes[0] = first;
68 commandBytes[1] = first;
69 commandBytes[2] = first;
70 commandBytes[3] = first;
71 for (int i = 0; i < buffer.length; i++) {
72 commandBytes[i + 4] = buffer[i];
73 }
74 commandBytes[buffer.length + 4] = last;
75
76 return new DatagramPacket(commandBytes, commandBytes.length, inet, port);
77 }
78
79 private static RconPacket[] sendRequest(int localPort, String ipStr, int port, String password,
80 String command) throws SocketTimeoutException {
81
82 DatagramSocket socket = null;
83 RconPacket[] resp = new RconPacket[128];
84
85 try {
86 socket = new DatagramSocket(localPort);
87 int packetSize = 1400;
88
89 InetAddress address = InetAddress.getByName(ipStr);
90 byte[] ip = address.getAddress();
91 InetAddress inet = InetAddress.getByAddress(ip);
92 String msg = "challenge rcon\n";
93
94 DatagramPacket out = getDatagramPacket(msg, inet, port);
95 socket.send(out);
96
97
98 byte[] data = new byte[packetSize];
99 DatagramPacket inPacket = new DatagramPacket(data, packetSize);
100
101 socket.setSoTimeout(RESPONSE_TIMEOUT);
102 socket.receive(inPacket);
103
104
105 String challenge = parseResponse(inPacket.getData());
106 String challengeNumber = challenge.substring(challenge.indexOf("rcon") + 5).trim();
107 String commandStr = "rcon " + challengeNumber + " \"" + password + "\" " + command;
108 DatagramPacket out2 = getDatagramPacket(commandStr, inet, port);
109 socket.send(out2);
110
111
112 byte[] data2 = new byte[packetSize];
113 DatagramPacket inPacket2 = new DatagramPacket(data2, packetSize);
114 socket.setSoTimeout(RESPONSE_TIMEOUT);
115 socket.receive(inPacket2);
116
117 resp[0] = new RconPacket(inPacket2);
118 try {
119
120 socket.setSoTimeout(MULTIPLE_PACKETS_TIMEOUT);
121 int i = 1;
122 while (true) {
123 socket.receive(inPacket2);
124 resp[i++] = new RconPacket(inPacket2);
125 }
126 } catch (SocketTimeoutException sex) {
127
128 }
129
130 } catch (SocketTimeoutException sex) {
131 throw sex;
132 } catch (IOException ex) {
133 ex.printStackTrace();
134 } finally {
135 if (socket != null) {
136 socket.close();
137 }
138 }
139
140 return resp;
141 }
142
143 private static String parseResponse(byte[] buf) {
144 String retVal = "";
145
146 if (buf[0] != -1 || buf[1] != -1 || buf[2] != -1 || buf[3] != -1) {
147 retVal = "ERROR";
148 } else {
149 int off = 5;
150 StringBuffer challenge = new StringBuffer(20);
151 while (buf[off] != 0) {
152 challenge.append((char) (buf[off++] & 255));
153 }
154 retVal = challenge.toString();
155 }
156
157 return retVal;
158 }
159
160 private static String assemblePacket(RconPacket[] respPacket) {
161
162 String resp = "";
163
164
165
166 for (int i = 0; i < respPacket.length; i++) {
167 if (respPacket[i] != null) {
168 resp = resp.concat(respPacket[i].data);
169 }
170 }
171 return resp;
172 }
173
174 }
175
176 class RconPacket {
177
178
179
180
181 public String ascii = "";
182
183
184
185
186 public String data = "";
187
188
189
190
191 public byte[] bytes = new byte[1400];
192
193
194
195
196 public int length = 0;
197
198
199
200
201
202
203
204 public RconPacket(DatagramPacket packet) {
205
206 this.ascii = new String(packet.getData(), 0, packet.getLength());
207 this.bytes = ascii.getBytes();
208 this.length = packet.getLength();
209
210
211 if (bytes[0] == -2) {
212
213 if (bytes[13] == 108) {
214 this.data = new String(packet.getData(), 14, packet.getLength() - 16);
215 } else {
216 this.data = new String(packet.getData(), 11, packet.getLength() - 13);
217 }
218 } else {
219
220 this.data = new String(packet.getData(), 5, packet.getLength() - 7);
221 }
222 }
223 }