├── .classpath
├── .gitignore
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── README.md
└── src
├── AutoBot.java
├── ImageSender.java
├── RemoteDataServer.java
├── ServerListener.java
├── ServerWindow.java
└── messages
└── Constants.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/*
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | DesktopRemoteServer
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | #Mon Jan 03 22:35:30 PST 2011
2 | eclipse.preferences.version=1
3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
6 | org.eclipse.jdt.core.compiler.compliance=1.6
7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
12 | org.eclipse.jdt.core.compiler.source=1.6
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Remote Desktop Server v1.5
2 |
3 | Copyright 2010 Justin Taylor
4 | This software can be distributed under the terms of the
5 | GNU General Public License.
6 |
7 | Receives messages via UDP socket alowing a remote device to control any
8 | computer's peripherals.
9 |
10 | The server has a UI that allows the user the specify a port to listen on,
11 | then waits for a connection from the Andoird device. There are two classes
12 | to the server.
13 |
14 | ## Deliverables
15 | What's that? You just want to use the app!?! You don't want to mess with the
16 | hassle of eclipse? In that case just download
17 | http://central.tayloredapps.org/server.jar and run it on any desktop that has
18 | JRE installed. Then mosy on over and download
19 | http://central.tayloredapps.org/Android-remote-client.apk to your android
20 | device.
21 |
22 | Now that you have everything you need, open the server on the Desktop you are
23 | trying to connect to and click connect. Then open up the app on your mobile
24 | deivce. Make sure the IP address field matches the IP listed on your desktop
25 | server. Then click connect. Now, you are ready to control your dekstop.
26 |
27 | 1. ServerWindow
28 | This class contains both the GUI and the server. Messages from
29 | the Android device is received on the server thread then passed
30 | to and AutoBot object (See section 1.b below).
31 |
32 | 1. AutoBot
33 | Receives messages from the server thread and translates them to
34 | I/O interactions (Move Mouse, Keyboard key stroke). The messages constant file
35 | defines what messages are recognized.
36 |
--------------------------------------------------------------------------------
/src/AutoBot.java:
--------------------------------------------------------------------------------
1 | // Copyright 2010 Justin Taylor
2 | // This software can be distributed under the terms of the
3 | // GNU General Public License.
4 |
5 | /*
6 | * TODO:
7 | * an AutoBot Listener class will need to be made to listen
8 | * for events to send images back and forth
9 | */
10 |
11 | import java.awt.*;
12 |
13 | import java.awt.Robot;
14 | import java.awt.MouseInfo;
15 | import java.awt.event.InputEvent;
16 | import java.awt.event.KeyEvent;
17 | import java.awt.Rectangle;
18 | import java.awt.image.BufferedImage;
19 |
20 | import messages.Constants;
21 |
22 | public class AutoBot {
23 |
24 | private Robot robot;
25 |
26 | int lastXpos = 0;
27 | int lastYpos = 0;
28 |
29 | int lastScrollY;
30 |
31 | public AutoBot(){
32 | try{ robot = new Robot(); }
33 | catch(Exception e){ System.out.println("Couldn't Create robot");}
34 | }
35 |
36 | public void handleMessage(String event){
37 |
38 | try{
39 | char eventcode = event.charAt(0);
40 | switch(eventcode){
41 | case Constants.LEFTCLICK: robot.mousePress( InputEvent.BUTTON1_MASK );
42 | robot.mouseRelease( InputEvent.BUTTON1_MASK ); break;
43 | case Constants.LEFTMOUSEDOWN: robot.mousePress( InputEvent.BUTTON1_MASK ); break;
44 | case Constants.LEFTMOUSEUP: robot.mouseRelease( InputEvent.BUTTON1_MASK ); break;
45 |
46 | case Constants.RIGHTMOUSEDOWN: robot.mousePress( InputEvent.BUTTON3_MASK ); break;
47 | case Constants.RIGHTMOUSEUP: robot.mouseRelease( InputEvent.BUTTON3_MASK ); break;
48 |
49 | case Constants.SCROLLUP: robot.mouseWheel(1); break;
50 | case Constants.SCROLLDOWN: robot.mouseWheel(-1); break;
51 |
52 | case Constants.MOVEMOUSE: Point p = Constants.parseMoveMouseMessage(event);
53 | moveMouse(p.x, p.y); break;
54 |
55 | case Constants.KEYBOARD: type(event.charAt(1)); break;
56 | case Constants.KEYCODE: specialKey(Integer.parseInt(event.substring(1))); break;
57 |
58 | default: System.out.println("ELSE:" + event); break;
59 | }
60 |
61 | }catch(Exception e){ e.printStackTrace(); System.out.println("error here "+event); }
62 | }
63 |
64 | public void moveMouse(int x, int y){
65 | try{
66 | //get the current position of the mouse cursor
67 | int current_x_local = MouseInfo.getPointerInfo().getLocation().x;
68 | int current_y_local = MouseInfo.getPointerInfo().getLocation().y;
69 |
70 | //move the mouse relative to the current position
71 | robot.mouseMove(current_x_local + x, current_y_local + y);
72 | }catch(NullPointerException e){
73 | // Not sure why this exception occurs
74 | System.out.print("NUll pointer exception on mouse move");
75 | }
76 | }
77 |
78 | public void specialKey(int key_code){
79 | int key;
80 |
81 | switch(key_code){
82 | case 19: key = KeyEvent.VK_UP; break;
83 | case 20: key = KeyEvent.VK_DOWN; break;
84 | case 21: key = KeyEvent.VK_LEFT; break;
85 | case 22: key = KeyEvent.VK_RIGHT; break;
86 |
87 | case 66: key = KeyEvent.VK_ENTER; break;
88 | case 67: key = KeyEvent.VK_BACK_SPACE; break;
89 | default: key = -1; break;
90 | }
91 | keyBoardPress(key);
92 | }
93 |
94 | public void type(char character) {
95 | switch (character) {
96 | case 'a': keyBoardPress(KeyEvent.VK_A); break;
97 | case 'b': keyBoardPress(KeyEvent.VK_B); break;
98 | case 'c': keyBoardPress(KeyEvent.VK_C); break;
99 | case 'd': keyBoardPress(KeyEvent.VK_D); break;
100 | case 'e': keyBoardPress(KeyEvent.VK_E); break;
101 | case 'f': keyBoardPress(KeyEvent.VK_F); break;
102 | case 'g': keyBoardPress(KeyEvent.VK_G); break;
103 | case 'h': keyBoardPress(KeyEvent.VK_H); break;
104 | case 'i': keyBoardPress(KeyEvent.VK_I); break;
105 | case 'j': keyBoardPress(KeyEvent.VK_J); break;
106 | case 'k': keyBoardPress(KeyEvent.VK_K); break;
107 | case 'l': keyBoardPress(KeyEvent.VK_L); break;
108 | case 'm': keyBoardPress(KeyEvent.VK_M); break;
109 | case 'n': keyBoardPress(KeyEvent.VK_N); break;
110 | case 'o': keyBoardPress(KeyEvent.VK_O); break;
111 | case 'p': keyBoardPress(KeyEvent.VK_P); break;
112 | case 'q': keyBoardPress(KeyEvent.VK_Q); break;
113 | case 'r': keyBoardPress(KeyEvent.VK_R); break;
114 | case 's': keyBoardPress(KeyEvent.VK_S); break;
115 | case 't': keyBoardPress(KeyEvent.VK_T); break;
116 | case 'u': keyBoardPress(KeyEvent.VK_U); break;
117 | case 'v': keyBoardPress(KeyEvent.VK_V); break;
118 | case 'w': keyBoardPress(KeyEvent.VK_W); break;
119 | case 'x': keyBoardPress(KeyEvent.VK_X); break;
120 | case 'y': keyBoardPress(KeyEvent.VK_Y); break;
121 | case 'z': keyBoardPress(KeyEvent.VK_Z); break;
122 | case 'A': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_A); break;
123 | case 'B': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_B); break;
124 | case 'C': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_C); break;
125 | case 'D': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_D); break;
126 | case 'E': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_E); break;
127 | case 'F': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_F); break;
128 | case 'G': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_G); break;
129 | case 'H': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_H); break;
130 | case 'I': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_I); break;
131 | case 'J': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_J); break;
132 | case 'K': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_K); break;
133 | case 'L': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_L); break;
134 | case 'M': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_M); break;
135 | case 'N': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_N); break;
136 | case 'O': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_O); break;
137 | case 'P': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_P); break;
138 | case 'Q': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_Q); break;
139 | case 'R': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_R); break;
140 | case 'S': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_S); break;
141 | case 'T': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_T); break;
142 | case 'U': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_U); break;
143 | case 'V': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_V); break;
144 | case 'W': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_W); break;
145 | case 'X': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_X); break;
146 | case 'Y': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_Y); break;
147 | case 'Z': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_Z); break;
148 | case '`': keyBoardPress(KeyEvent.VK_BACK_QUOTE); break;
149 | case '0': keyBoardPress(KeyEvent.VK_0); break;
150 | case '1': keyBoardPress(KeyEvent.VK_1); break;
151 | case '2': keyBoardPress(KeyEvent.VK_2); break;
152 | case '3': keyBoardPress(KeyEvent.VK_3); break;
153 | case '4': keyBoardPress(KeyEvent.VK_4); break;
154 | case '5': keyBoardPress(KeyEvent.VK_5); break;
155 | case '6': keyBoardPress(KeyEvent.VK_6); break;
156 | case '7': keyBoardPress(KeyEvent.VK_7); break;
157 | case '8': keyBoardPress(KeyEvent.VK_8); break;
158 | case '9': keyBoardPress(KeyEvent.VK_9); break;
159 | case '-': keyBoardPress(KeyEvent.VK_MINUS); break;
160 | case '=': keyBoardPress(KeyEvent.VK_EQUALS); break;
161 | case '~': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_QUOTE); break;
162 | case '!': keyBoardPress(KeyEvent.VK_EXCLAMATION_MARK); break;
163 | case '@': keyBoardPress(KeyEvent.VK_AT); break;
164 | case '#': keyBoardPress(KeyEvent.VK_NUMBER_SIGN); break;
165 | case '$': keyBoardPress(KeyEvent.VK_DOLLAR); break;
166 | case '%': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_5); break;
167 | case '^': keyBoardPress(KeyEvent.VK_CIRCUMFLEX); break;
168 | case '&': keyBoardPress(KeyEvent.VK_AMPERSAND); break;
169 | case '*': keyBoardPress(KeyEvent.VK_ASTERISK); break;
170 | case '(': keyBoardPress(KeyEvent.VK_LEFT_PARENTHESIS); break;
171 | case ')': keyBoardPress(KeyEvent.VK_RIGHT_PARENTHESIS); break;
172 | case '_': keyBoardPress(KeyEvent.VK_UNDERSCORE); break;
173 | case '+': keyBoardPress(KeyEvent.VK_PLUS); break;
174 | case '\t': keyBoardPress(KeyEvent.VK_TAB); break;
175 | case '\n': keyBoardPress(KeyEvent.VK_ENTER); break;
176 | case '[': keyBoardPress(KeyEvent.VK_OPEN_BRACKET); break;
177 | case ']': keyBoardPress(KeyEvent.VK_CLOSE_BRACKET); break;
178 | case '\\': keyBoardPress(KeyEvent.VK_BACK_SLASH); break;
179 | case '{': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_OPEN_BRACKET); break;
180 | case '}': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_CLOSE_BRACKET); break;
181 | case '|': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH); break;
182 | case ';': keyBoardPress(KeyEvent.VK_SEMICOLON); break;
183 | case ':': keyBoardPress(KeyEvent.VK_COLON); break;
184 | case '\'': keyBoardPress(KeyEvent.VK_QUOTE); break;
185 | case '"': keyBoardPress(KeyEvent.VK_QUOTEDBL); break;
186 | case ',': keyBoardPress(KeyEvent.VK_COMMA); break;
187 | case '<': keyBoardPress(KeyEvent.VK_LESS); break;
188 | case '.': keyBoardPress(KeyEvent.VK_PERIOD); break;
189 | case '>': keyBoardPress(KeyEvent.VK_GREATER); break;
190 | case '/': keyBoardPress(KeyEvent.VK_SLASH); break;
191 | case '?': keyBoardPress(KeyEvent.VK_SHIFT, KeyEvent.VK_SLASH); break;
192 | case ' ': keyBoardPress(KeyEvent.VK_SPACE); break;
193 | default: System.out.println("Character " + character); break;
194 | }
195 | }
196 |
197 | public void keyBoardPress(int key){
198 | try{
199 | robot.keyPress(key);
200 | robot.keyRelease(key);
201 | }catch(Exception e){}
202 | }
203 |
204 | public void keyBoardPress(int key, int key2){
205 | try{
206 | robot.keyPress(key);
207 | robot.keyPress(key2);
208 | robot.keyRelease(key2);
209 | robot.keyRelease(key);
210 |
211 | }catch(Exception e){}
212 | }
213 |
214 | public BufferedImage getScreenCap(int width, int height){
215 |
216 | // get the current location of the mouse
217 | // this is used to actually draw the mouse
218 | Point mousePosition = MouseInfo.getPointerInfo().getLocation();
219 |
220 | int x = (int) (mousePosition.x - (width * 0.5));
221 | int y = (int) (mousePosition.y - (height * 0.5));
222 |
223 | Rectangle captureSize = new Rectangle(x, y, width, height);
224 | BufferedImage img = robot.createScreenCapture(captureSize);
225 | // start drawing the mouse onto the image;
226 | Polygon pointer = new Polygon(new int[]{0, -4, 4},new int[]{0, 8, 8}, 3);
227 |
228 | Graphics2D grfx = img.createGraphics();
229 | grfx.translate((width * 0.5), (height * 0.5));
230 | grfx.setColor( new Color(100,100,255,255) );
231 | grfx.fillPolygon( pointer );
232 | grfx.setColor( Color.red );
233 | grfx.drawPolygon( pointer );
234 | grfx.dispose();
235 |
236 | return img;
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/src/ImageSender.java:
--------------------------------------------------------------------------------
1 | import java.awt.Graphics2D;
2 | import java.awt.RenderingHints;
3 | import java.awt.geom.AffineTransform;
4 | import java.awt.image.BufferedImage;
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.IOException;
7 | import java.net.DatagramPacket;
8 | import java.net.DatagramSocket;
9 | import java.net.InetAddress;
10 | import java.util.Iterator;
11 |
12 | import javax.imageio.IIOImage;
13 | import javax.imageio.ImageIO;
14 | import javax.imageio.ImageWriteParam;
15 | import javax.imageio.ImageWriter;
16 | import javax.imageio.stream.ImageOutputStream;
17 |
18 | public class ImageSender implements Runnable{
19 |
20 | private InetAddress clientAddr;
21 | private int clientPort;
22 | private DatagramSocket socket;
23 | public boolean connected = false;
24 |
25 | public static final float SIZETHRESHOLD = 100f;
26 |
27 | private BufferedImage img;
28 |
29 | public ImageSender(String ip, int port){
30 | try{
31 | clientAddr = InetAddress.getByName(ip);
32 | }
33 | catch (Exception e){
34 | System.out.print("Exception setting ip address");
35 | }
36 |
37 | clientPort = port;
38 |
39 | try {
40 | socket = new DatagramSocket();
41 | connected = true;
42 |
43 | }
44 | catch (Exception e) {
45 | System.out.print("Could not bind to a port");
46 | }
47 | }
48 |
49 | public ImageSender(InetAddress ip, int port){
50 | clientAddr = ip;
51 | clientPort = port;
52 |
53 | try {
54 | socket = new DatagramSocket();
55 | connected = true;
56 |
57 | }
58 | catch (Exception e) {
59 | System.out.print("Could not bind to a port");
60 | }
61 | }
62 |
63 | public void setImage(BufferedImage image)
64 | {
65 | img = image;
66 | }
67 |
68 | public void setPort(int port)
69 | {
70 | clientPort = port;
71 | }
72 |
73 | public void run(){
74 | ByteArrayOutputStream buffer;
75 |
76 | try{
77 | ByteArrayOutputStream tmp = compressImage(img, 1.0f);
78 | ImageIO.write(img, "jpeg", tmp);
79 | tmp.close();
80 |
81 | int contentLength = tmp.size();
82 | float compress = 64000.0f/contentLength;
83 | System.out.println("Compress size "+compress);
84 |
85 | if(compress > 1.0) {
86 | buffer = tmp;
87 | } else {
88 | buffer = compressImage(img, compress);
89 | }
90 |
91 | }catch(IOException e){
92 | System.out.println(e);
93 | return;
94 | }
95 |
96 | byte[] data = buffer.toByteArray();
97 | DatagramPacket out = new DatagramPacket(data, data.length, clientAddr, clientPort);
98 |
99 | try {
100 | socket.send(out);
101 | buffer.close();
102 | } catch (IOException e) {
103 | System.out.println("Data Length = "+data.length);
104 | e.printStackTrace();
105 | }
106 | }
107 |
108 | private BufferedImage scaleImage(BufferedImage image, int width, int height)
109 | {
110 | BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
111 | // Paint scaled version of image to new image
112 | Graphics2D graphics2D = scaledImage.createGraphics();
113 |
114 | graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
115 | graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
116 | graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
117 |
118 |
119 | graphics2D.drawImage(image, 0, 0, width, height, null);
120 | graphics2D.dispose();
121 | return scaledImage;
122 | }
123 |
124 | private BufferedImage scaleImage(BufferedImage image, int width, int height, float scale)
125 | {
126 | BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
127 | // Paint scaled version of image to new image
128 | Graphics2D graphics2D = scaledImage.createGraphics();
129 | AffineTransform xform = AffineTransform.getScaleInstance(scale, scale);
130 |
131 | graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
132 | graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
133 | graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
134 |
135 |
136 | graphics2D.drawImage(image, xform, null);
137 |
138 | graphics2D.dispose();
139 | return scaledImage;
140 | }
141 |
142 |
143 | /*
144 | *
145 | * Compression
146 | *
147 | */
148 | private ByteArrayOutputStream compressImage(BufferedImage image, float quality) throws IOException
149 | {
150 | // Get a ImageWriter for jpeg format.
151 | Iterator writers = ImageIO.getImageWritersBySuffix("jpeg");
152 | if (!writers.hasNext()) throw new IllegalStateException("No writers found");
153 | ImageWriter writer = (ImageWriter) writers.next();
154 |
155 | while(!writer.getDefaultWriteParam().canWriteCompressed() && writers.next() != null)
156 | {
157 | writer = writers.next();
158 | }
159 |
160 |
161 | // Create the ImageWriteParam to compress the image.
162 | ImageWriteParam param = writer.getDefaultWriteParam();
163 |
164 | param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
165 | param.setCompressionQuality(quality);
166 |
167 | // The output will be a ByteArrayOutputStream (in memory)
168 | ByteArrayOutputStream bos = new ByteArrayOutputStream(32768);
169 | ImageOutputStream ios = ImageIO.createImageOutputStream(bos);
170 | writer.setOutput(ios);
171 | writer.write(null, new IIOImage(image, null, null), param);
172 | ios.flush();
173 |
174 | return bos;
175 |
176 | /*
177 | // otherwise the buffer size will be zero!
178 | // From the ByteArrayOutputStream create a RenderedImage.
179 | ByteArrayInputStream in = new ByteArrayInputStream(bos.toByteArray());
180 | RenderedImage out = ImageIO.read(in);
181 | int size = bos.toByteArray().length;
182 | showImage("Compressed to " + quality + ": " + size + " bytes", out);
183 | */
184 | }
185 |
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/src/RemoteDataServer.java:
--------------------------------------------------------------------------------
1 |
2 | import java.net.BindException;
3 | import java.net.DatagramPacket;
4 | import java.net.DatagramSocket;
5 | import java.net.InetAddress;
6 |
7 | import messages.Constants;
8 |
9 | public class RemoteDataServer implements Runnable{
10 |
11 | // local settings
12 | private int PORT;
13 | private InetAddress ipAddress;
14 |
15 |
16 | //remote settings
17 | private int clientPort;
18 | private InetAddress listenerAddress;
19 |
20 | private DatagramSocket server;
21 | private byte[] buf;
22 | private DatagramPacket dgp;
23 |
24 | private String message;
25 | private AutoBot bot;
26 |
27 | private ServerListener window;
28 |
29 | private ImageSender sender;
30 |
31 |
32 | public RemoteDataServer(int port){
33 | PORT = port;
34 | buf = new byte[1000];
35 | dgp = new DatagramPacket(buf, buf.length);
36 | bot = new AutoBot();
37 | }
38 |
39 | public RemoteDataServer(){
40 | buf = new byte[1000];
41 | dgp = new DatagramPacket(buf, buf.length);
42 | bot = new AutoBot();
43 | }
44 |
45 | public void setPort(int port){ PORT = port; }
46 |
47 | public void setClientPort(int port){ clientPort = port; }
48 |
49 | public void setIP(InetAddress inet){ ipAddress = inet; }
50 |
51 | public void setServerListener(ServerListener listener){ window = listener; }
52 |
53 | public void shutdown(){
54 | try{ server.close(); }
55 | catch(Exception e){}
56 | }
57 |
58 | public void run(){
59 | boolean connected = false;
60 | try {
61 | server = new DatagramSocket(PORT, ipAddress);
62 | connected = true;
63 | }
64 | catch(BindException e){
65 | setListenerMessage("Port "+PORT+" is already in use. Use a different Port");
66 | setConnectButtonEnabled(false);
67 | }
68 | catch(Exception e){
69 | setListenerMessage("Unable to connect");
70 | setConnectButtonEnabled(false);
71 | }
72 |
73 | while(connected){
74 | // get message from sender
75 | try{ server.receive(dgp);
76 |
77 | // store the packets address for sending images out
78 | listenerAddress = dgp.getAddress();
79 | // translate and use the message to automate the desktop
80 | message = new String(dgp.getData(), 0, dgp.getLength());
81 | if (message.equals("Connectivity"))
82 | {
83 | setListenerMessage("Trying to Connect");
84 | server.send(dgp); //echo the message back
85 | }
86 |
87 | else if(message.equals("Connected"))
88 | {
89 | server.send(dgp); //echo the message back
90 | }
91 |
92 | else if(message.equals("Close"))
93 | {
94 | setListenerMessage("Controller has Disconnected. Trying to reconnect."); //echo the message back
95 | }
96 |
97 | else if(message.charAt(0) == Constants.REQUESTIMAGE)
98 | {
99 |
100 | String[] arr = message.split(Constants.DELIMITER+"");
101 | System.out.print(arr[1]+" "+arr[2]+"\n");
102 | sendImage(Integer.parseInt(arr[1]), Integer.parseInt(arr[2]));
103 | }
104 |
105 | else
106 | {
107 | setListenerMessage("Connected to Controller");
108 | bot.handleMessage(message);
109 | }
110 | }catch(Exception e){
111 | System.out.println(e);
112 | setListenerMessage("Disconnected");
113 | setConnectButtonEnabled(false);
114 | connected = false;
115 | }
116 | }
117 | }
118 |
119 | private void setListenerMessage(String msg){
120 | if(window != null){
121 | window.setMessage(msg);
122 | }
123 | }
124 |
125 | private void setConnectButtonEnabled(boolean enable){
126 | if(window != null){
127 | window.setConnectButtonEnabled(enable);
128 | }
129 | }
130 |
131 | public void sendImage(int width, int height){
132 | if(sender == null && listenerAddress != null)
133 | {
134 | sender = new ImageSender(listenerAddress, clientPort);
135 | }
136 |
137 | if(sender != null)
138 | {
139 |
140 | float scale = 0.5f;
141 | if(width > height) {
142 | scale = ImageSender.SIZETHRESHOLD/width;
143 | }else{
144 | scale = ImageSender.SIZETHRESHOLD/height;
145 | }
146 |
147 | sender.setPort(clientPort);
148 | //sender.setImage(bot.getScreenCap((int)Math.round(width*scale), (int)Math.round(height * scale)) );
149 |
150 | sender.setImage(bot.getScreenCap(width, height));
151 |
152 | Thread send_image_thread = new Thread(sender);
153 | send_image_thread.start();
154 | }
155 | }
156 |
157 |
158 | }
--------------------------------------------------------------------------------
/src/ServerListener.java:
--------------------------------------------------------------------------------
1 |
2 | public abstract class ServerListener {
3 | abstract void setMessage(String message);
4 | abstract void setConnectButtonEnabled(boolean enable);
5 | }
--------------------------------------------------------------------------------
/src/ServerWindow.java:
--------------------------------------------------------------------------------
1 | // Copyright 2010 Justin Taylor
2 | // This software can be distributed under the terms of the
3 | // GNU General Public License.
4 |
5 | import javax.swing.*;
6 | import java.awt.*;
7 | import java.awt.event.*;
8 | import java.io.IOException;
9 | import java.net.*;
10 | import java.util.Collections;
11 | import java.util.Enumeration;
12 |
13 | public class ServerWindow extends ServerListener implements ActionListener{
14 |
15 | public RemoteDataServer server;
16 |
17 | private Thread sThread; //server thread
18 |
19 | private static final int WINDOW_HEIGHT = 275;
20 | private static final int WINDOW_WIDTH = 350;
21 |
22 | private String ipAddress;
23 |
24 | private JFrame window = new JFrame("Remote Desktop Server");
25 |
26 | private JLabel addressLabel = new JLabel("");
27 | private JLabel portLabel = new JLabel("PORT: ");
28 | private JLabel clientPortLabel = new JLabel("Outgoing PORT: ");
29 |
30 | private JTextArea[] buffers = new JTextArea[4];
31 | private JTextField portTxt = new JTextField(5);
32 |
33 | private JTextField clientPortTxt = new JTextField(5);
34 | private JTextField ipTxt = new JTextField(10);
35 | private JLabel serverMessages = new JLabel("Not Connected");
36 |
37 | private JButton connectButton = new JButton("Connect");
38 | private JButton disconnectButton = new JButton("Disconnect");
39 | private JButton shutdownButton = new JButton("Shutdown");
40 |
41 |
42 | public ServerWindow(){
43 |
44 | server = new RemoteDataServer();
45 | server.setServerListener( this );
46 |
47 | window.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
48 | window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
49 |
50 | connectButton.addActionListener(this);
51 | disconnectButton.addActionListener(this);
52 | //shutdownButton.addActionListener(this);
53 |
54 | Container c = window.getContentPane();
55 | c.setLayout(new FlowLayout());
56 |
57 | try{
58 | InetAddress ip = getIpAddress();
59 | ipAddress = ip.getHostAddress();
60 | addressLabel.setText("IP Address: ");
61 | ipTxt.setText(ipAddress);
62 | }
63 | catch(Exception e){addressLabel.setText("IP Address Could Not be Resolved, Try typing in the IP address.");}
64 |
65 | int x;
66 | for(x = 0; x < 4; x++){
67 | buffers[x] = new JTextArea("", 1, 30);
68 | buffers[x].setEditable(false);
69 | buffers[x].setBackground(window.getBackground());
70 | }
71 |
72 | c.add(addressLabel);
73 | c.add(ipTxt);
74 | c.add(buffers[0]);
75 | c.add(portLabel);
76 | portTxt.setText("5444");
77 | c.add(portTxt);
78 |
79 | c.add(buffers[3]);
80 |
81 | c.add(clientPortLabel);
82 | clientPortTxt.setText("5555");
83 | c.add(clientPortTxt);
84 |
85 | c.add(buffers[1]);
86 | c.add(connectButton);
87 | c.add(disconnectButton);
88 | c.add(buffers[2]);
89 | c.add(serverMessages);
90 |
91 | //c.add(shutdownButton);
92 | ipTxt.setSize(100, 20);
93 | window.setLocationRelativeTo(null);
94 | window.setVisible(true);
95 | window.setResizable(false);
96 |
97 | int port = Integer.parseInt(portTxt.getText());
98 | int clientPort = Integer.parseInt(clientPortTxt.getText());
99 |
100 | try{
101 | InetAddress ip = InetAddress.getByName(ipTxt.getText());
102 | runServer(port, clientPort, ip);
103 | }catch(UnknownHostException err){
104 | serverMessages.setText("Error: Check that the ip you have entered is correct.");
105 | }
106 | }
107 |
108 |
109 | private InetAddress getIpAddress() throws Exception
110 | {
111 | // this first line generally works on mac and windows
112 | InetAddress ip = InetAddress.getLocalHost();
113 |
114 | // but on linux...
115 | if(ip.isLoopbackAddress())
116 | {
117 | //loop trough all network interfaces
118 | Enumeration nets = NetworkInterface.getNetworkInterfaces();
119 | for (NetworkInterface netint : Collections.list(nets))
120 | {
121 | //loop through the ip address associated with the interface
122 | Enumeration inetAddresses = netint.getInetAddresses();
123 | for (InetAddress inetAddress : Collections.list(inetAddresses)) {
124 |
125 | // if the address is no the loopback and is not ipv6
126 | if(!inetAddress.isLoopbackAddress() && !inetAddress.toString().contains(":"))
127 | return inetAddress;
128 | }
129 | }
130 | }
131 |
132 | return ip;
133 | }
134 |
135 | public void actionPerformed(ActionEvent e){
136 | Object src = e.getSource();
137 |
138 | if(src instanceof JButton){
139 | if((JButton)src == connectButton){
140 | int port = Integer.parseInt(portTxt.getText());
141 | int clientPort = Integer.parseInt(clientPortTxt.getText());
142 | try{
143 | InetAddress ip = InetAddress.getByName(ipTxt.getText());
144 | runServer(port, clientPort, ip);
145 | }catch(UnknownHostException err){
146 | serverMessages.setText("Error: Check that the ip you have entered is correct.");
147 | }
148 | }
149 |
150 | else if((JButton)src == disconnectButton){
151 | closeServer();
152 | setConnectButtonEnabled(true);
153 | }
154 |
155 | else if((JButton)src == shutdownButton){
156 | closeServer();
157 | shutdown();
158 | System.exit(0);
159 | }
160 | }
161 | }
162 |
163 | public void runServer(int port, int listenerPort, InetAddress ip){
164 | if(port < 65535){
165 | server.setPort(port);
166 | server.setClientPort(listenerPort);
167 | server.setIP(ip);
168 | sThread = new Thread(server);
169 | sThread.start();
170 | serverMessages.setText("Waiting for connection on " + ip);
171 | connectButton.setEnabled(false);
172 | }else{
173 | serverMessages.setText("The port Number must be less than 65535");
174 | connectButton.setEnabled(true);
175 | }
176 | }
177 |
178 | public void closeServer(){
179 | server.shutdown();
180 | setMessage("Disconnected");
181 | }
182 |
183 | public void setMessage(String msg){
184 | serverMessages.setText(msg);
185 | }
186 |
187 | public void setConnectButtonEnabled(boolean enable){
188 | connectButton.setEnabled(enable);
189 | }
190 |
191 | private static void shutdown(){
192 | String shutdownCommand;
193 | String operatingSystem = System.getProperty("os.name");
194 |
195 | if ("Linux".equals(operatingSystem) || "Mac OS X".equals(operatingSystem)) {
196 | shutdownCommand = "shutdown -h now";
197 | }
198 | else if ("Windows".equals(operatingSystem)) {
199 | shutdownCommand = "shutdown.exe -s -t 0";
200 | }
201 | else {
202 | shutdownCommand = "null";
203 | }
204 |
205 | Runtime runtime = Runtime.getRuntime();
206 | try {
207 | Process proc = runtime.exec(shutdownCommand);
208 | } catch (IOException e) {
209 | // TODO Auto-generated catch block
210 | e.printStackTrace();
211 | }
212 | }
213 |
214 |
215 | public static void main(String[] args){
216 | new ServerWindow();
217 | }
218 | }
219 |
--------------------------------------------------------------------------------
/src/messages/Constants.java:
--------------------------------------------------------------------------------
1 | package messages;
2 |
3 | import java.awt.Point;
4 |
5 | public class Constants {
6 |
7 | public static final char LEFTMOUSEDOWN = 'a';
8 | public static final char LEFTMOUSEUP = 'b';
9 |
10 | public static final char RIGHTMOUSEDOWN = 'c';
11 | public static final char RIGHTMOUSEUP = 'd';
12 |
13 | public static final char LEFTCLICK = 'e';
14 |
15 | public static final char SCROLLUP = 'h';
16 | public static final char SCROLLDOWN = 'i';
17 |
18 | public static final char KEYBOARD = 'k';
19 | public static final char KEYCODE = 'l';
20 |
21 | public static final char DELIMITER = '/';
22 |
23 | public static final char MOVEMOUSE = 'p';
24 |
25 | public static final char REQUESTIMAGE = 'I';
26 |
27 | /*
28 | * Returns a string in the format that can be laster parsed
29 | * format: MOVEMOUSEintxDELIMITERinty
30 | * ex: p5/6
31 | */
32 | public static String createMoveMouseMessage(float x, float y){
33 | int intx = Math.round(x);
34 | int inty = Math.round(y);
35 | return ""+MOVEMOUSE + intx + DELIMITER + inty;
36 | }
37 |
38 | public static Point parseMoveMouseMessage(String message){
39 | String[] tokens = message.substring(1).split(""+Constants.DELIMITER );
40 | return new Point(Integer.parseInt(tokens[0]), Integer.parseInt(tokens[1]));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------