1 package net.sourceforge.rconed;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.io.OutputStream;
8 import java.net.InetAddress;
9 import java.net.InetSocketAddress;
10 import java.net.Socket;
11 import java.net.SocketTimeoutException;
12 import java.net.UnknownHostException;
13 import java.security.MessageDigest;
14 import java.security.NoSuchAlgorithmException;
15
16 import net.sourceforge.rconed.exception.BadRcon;
17 import net.sourceforge.rconed.exception.ResponseEmpty;
18
19
20
21
22
23
24
25
26
27
28
29
30 public class BF2Rcon {
31
32 final static int RESPONSE_TIMEOUT = 2000;
33
34 static Socket rconSocket = null;
35 static InputStream in = null;
36 static OutputStream out = null;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public static String send(String ipStr, int port, String password, String command) throws SocketTimeoutException, BadRcon, ResponseEmpty {
52 return send(ipStr, port, password, command, 0);
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public static String send(String ipStr, int port, String password, String command, int localPort) throws SocketTimeoutException, BadRcon, ResponseEmpty {
69 return send(ipStr, port, password, command, null, localPort);
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public static String send(String ipStr, int port, String password, String command, InetAddress localhost, int localPort) throws SocketTimeoutException, BadRcon, ResponseEmpty {
87 StringBuffer response = new StringBuffer();
88
89 try {
90 rconSocket = new Socket();
91
92
93
94
95
96
97 rconSocket.bind(new InetSocketAddress(localhost, localPort));
98 rconSocket.connect(new InetSocketAddress(ipStr, port), RESPONSE_TIMEOUT);
99
100 out = rconSocket.getOutputStream();
101 in = rconSocket.getInputStream();
102 BufferedReader buffRead = new BufferedReader(new InputStreamReader(in));
103
104 rconSocket.setSoTimeout(RESPONSE_TIMEOUT);
105
106 String digestSeed = "";
107 boolean loggedIn = false;
108 boolean keepGoing = true;
109 while(keepGoing) {
110 String receivedContent = buffRead.readLine();
111 if(receivedContent.startsWith("### Digest seed: ")) {
112 digestSeed = receivedContent.substring(17, receivedContent.length());
113 try {
114 MessageDigest md5 = MessageDigest.getInstance("MD5");
115 md5.update(digestSeed.getBytes());
116 md5.update(password.getBytes());
117 String digestStr = "login "+ digestedToHex(md5.digest()) +"\n";
118 out.write(digestStr.getBytes());
119 } catch (NoSuchAlgorithmException e1) {
120 response.append("MD5 algorithm not available - unable to complete RCON request.");
121 keepGoing = false;
122 }
123 } else if(receivedContent.startsWith("error: not authenticated: you can only invoke 'login'")) {
124 throw new BadRcon();
125 } else if(receivedContent.startsWith("Authentication failed.")) {
126 throw new BadRcon();
127 } else if(receivedContent.startsWith("Authentication successful, rcon ready.")) {
128 keepGoing = false;
129 loggedIn = true;
130 }
131 }
132 if(loggedIn) {
133
134 String cmd = "\u0002exec "+ command +"\n";
135 out.write(cmd.getBytes());
136
137 readResponse(buffRead, response);
138 if(response.length() == 0) {
139 throw new ResponseEmpty();
140 }
141 }
142
143 } catch (SocketTimeoutException timeout) {
144 throw timeout;
145 } catch (UnknownHostException e) {
146 response.append("UnknownHostException: "+ e.getMessage());
147 } catch (IOException e) {
148 response.append("Couldn't get I/O for the connection: "+ e.getMessage());
149 e.printStackTrace();
150 } finally {
151 try {
152 if(out != null) {
153 out.close();
154 }
155 if(in != null) {
156 in.close();
157 }
158 if(rconSocket != null) {
159 rconSocket.close();
160 }
161 } catch (IOException e1) {
162
163 }
164 }
165
166 return response.toString();
167 }
168
169
170
171
172
173
174 private static void readResponse(BufferedReader buffRead, StringBuffer sb) throws IOException {
175 int ch;
176 while(true) {
177 ch = buffRead.read();
178 if(ch == -1 || ch == 4) {
179 return;
180 }
181 sb.append((char)ch);
182 }
183 }
184
185 private static String digestedToHex(byte digest[]) {
186 StringBuffer store = new StringBuffer();
187 for(int x=0; x < digest.length; x++) {
188 byte bite = digest[x];
189 String val = Integer.toHexString(bite & 255);
190 if(val.length() == 1) {
191 store.append("0");
192 }
193 store.append(val);
194 }
195 return store.toString();
196 }
197 }