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