server: add a HELLO handshake
[fanfix.git] / src / be / nikiroo / utils / serial / server / ConnectActionServer.java
1 package be.nikiroo.utils.serial.server;
2
3 import java.io.IOException;
4 import java.net.Socket;
5
6 import javax.net.ssl.SSLException;
7
8 /**
9 * Base class used for the server basic handling.
10 * <p>
11 * It represents a single action: a server is expected to execute one action for
12 * each client action.
13 *
14 * @author niki
15 */
16 abstract class ConnectActionServer {
17 private boolean closing;
18
19 /**
20 * The underlying {@link ConnectAction}.
21 * <p>
22 * Cannot be NULL.
23 */
24 protected ConnectAction action;
25
26 /**
27 * Create a new {@link ConnectActionServer}.
28 *
29 * @param s
30 * the socket to bind to
31 * @param key
32 * an optional key to encrypt all the communications (if NULL,
33 * everything will be sent in clear text)
34 */
35 public ConnectActionServer(Socket s, String key) {
36 action = new ConnectAction(s, true, key) {
37 @Override
38 protected void action() throws Exception {
39 ConnectActionServer.this.serverHello();
40 ConnectActionServer.this.action();
41 }
42
43 @Override
44 protected void onError(Exception e) {
45 ConnectActionServer.this.onError(e);
46 }
47 };
48 }
49
50 /**
51 * Send the HELLO message (check that the client sends a String "HELLO" and
52 * send it back, to check I/O and encryption modes).
53 *
54 * @throws IOException
55 * in case of I/O error
56 * @throws SSLException
57 * in case of encryption error
58 */
59 protected void serverHello() throws IOException, SSLException {
60 String HELLO = action.recString();
61 if (!"HELLO".equals(HELLO)) {
62 throw new SSLException("Server did not accept the encryption key");
63 }
64 action.sendString(HELLO);
65 }
66
67 /**
68 * Actually start the process and call the action (synchronous).
69 */
70 public void connect() {
71 action.connect();
72 }
73
74 /**
75 * Actually start the process and call the action (asynchronous).
76 */
77 public void connectAsync() {
78 new Thread(new Runnable() {
79 @Override
80 public void run() {
81 connect();
82 }
83 }).start();
84 }
85
86 /**
87 * Stop the client/server connection on behalf of the server (usually, the
88 * client connects then is allowed to send as many requests as it wants; in
89 * some cases, though, the server may wish to forcefully close the
90 * connection and can do via this value, when it is set to TRUE).
91 * <p>
92 * Example of usage: the client failed an authentication check, cut the
93 * connection here and now.
94 *
95 * @return TRUE when it is
96 */
97 public boolean isClosing() {
98 return closing;
99 }
100
101 /**
102 * Can be called to stop the client/server connection on behalf of the
103 * server (usually, the client connects then is allowed to send as many
104 * requests as it wants; in some cases, though, the server may wish to
105 * forcefully close the connection and can do so by calling this method).
106 * <p>
107 * Example of usage: the client failed an authentication check, cut the
108 * connection here and now.
109 */
110 public void close() {
111 closing = true;
112 }
113
114 /**
115 * The total amount of bytes received.
116 *
117 * @return the amount of bytes received
118 */
119 public long getBytesReceived() {
120 return action.getBytesReceived();
121 }
122
123 /**
124 * The total amount of bytes sent.
125 *
126 * @return the amount of bytes sent
127 */
128 public long getBytesSent() {
129 return action.getBytesWritten();
130 }
131
132 /**
133 * Method that will be called when an action is performed on the server.
134 *
135 * @throws Exception
136 * in case of I/O error
137 */
138 @SuppressWarnings("unused")
139 public void action() throws Exception {
140 }
141
142 /**
143 * Handler called when an unexpected error occurs in the code.
144 * <p>
145 * Will just ignore the error by default.
146 *
147 * @param e
148 * the exception that occurred
149 */
150 protected void onError(@SuppressWarnings("unused") Exception e) {
151 }
152 }