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