1 package be
.nikiroo
.jvcard
.remote
;
3 import java
.io
.BufferedReader
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStreamReader
;
6 import java
.io
.PrintWriter
;
7 import java
.net
.InetAddress
;
8 import java
.net
.Socket
;
9 import java
.util
.Arrays
;
10 import java
.util
.LinkedList
;
11 import java
.util
.List
;
13 import be
.nikiroo
.jvcard
.remote
.Command
.Verb
;
16 * A client or server connection, that will allow you to connect to, send and
17 * receive data to/from a jVCard remote server.
23 public class SimpleSocket
{
25 * The current version of the network protocol.
27 static private final int CURRENT_VERSION
= 1;
30 * The end of block marker.
32 * An end of block marker needs to be on a line on itself to be valid, and
33 * will denote the end of a block of data.
35 static private String EOB
= ".";
38 private PrintWriter out
;
39 private BufferedReader in
;
40 private int version
; // version of the OTHER end, not this one (this one is
41 // CURRENT_VERSION obviously)
43 private String label
; // can be used for debugging
46 * Create a new {@link SimpleSocket} with the given {@link Socket}.
51 public SimpleSocket(Socket s
, String label
) {
57 * Return the label of this {@link SimpleSocket}. This is mainly used for
58 * debugging purposes or user display if any. It is optional.
62 public String
getLabel() {
69 * Open the {@link SimpleSocket} for reading/writing and negotiates the
72 * Note that you <b>MUST</b> call {@link SimpleSocket#close()} when you are
73 * done to release the acquired resources.
76 * TRUE for clients, FALSE for servers (server speaks first)
81 public void open(boolean client
) throws IOException
{
82 out
= new PrintWriter(s
.getOutputStream(), false);
83 in
= new BufferedReader(new InputStreamReader(s
.getInputStream()));
86 version
= new Command(receiveLine(), -1).getVersion();
87 sendLine(new Command(Command
.Verb
.VERSION
, CURRENT_VERSION
)
90 send(new Command(Command
.Verb
.VERSION
, CURRENT_VERSION
).toString());
92 send("[Some help info here]");
93 send("you need to reply with your VERSION + end of block");
94 send("please send HELP in a full block or help");
96 version
= new Command(receiveLine(), -1).getVersion();
101 * Close the connection and release acquired resources.
103 * @return TRUE if everything was closed properly, FALSE if the connection
104 * was broken (in all cases, resources are released)
106 public boolean close() {
107 boolean broken
= false;
111 broken
= out
.checkError();
112 } catch (IOException e
) {
118 } catch (IOException e
) {
123 } catch (IOException ee
) {
136 * Sends commands to the remote server. Do <b>NOT</b> sends the end-of-block
142 * @throws IOException
143 * in case of IO error
145 protected void send(String data
) throws IOException
{
152 if (out
.checkError())
153 throw new IOException();
157 * Sends an end-of-block marker to the remote server.
159 * @throws IOException
160 * in case of IO error
162 public void sendBlock() throws IOException
{
163 sendBlock((List
<String
>) null);
167 * Sends commands to the remote server, then sends an end-of-block marker.
172 * @throws IOException
173 * in case of IO error
175 public void sendLine(String data
) throws IOException
{
176 sendBlock(Arrays
.asList(new String
[] { data
}));
180 * Sends commands to the remote server, then sends an end-of-block marker.
185 * @throws IOException
186 * in case of IO error
188 public void sendBlock(List
<String
> data
) throws IOException
{
190 for (String dataLine
: data
) {
199 * Sends commands to the remote server, then sends an end-of-block marker.
202 * the {@link Verb} to send
204 * @throws IOException
205 * in case of IO error
207 public void sendCommand(Command
.Verb verb
) throws IOException
{
208 sendCommand(verb
, null);
212 * Sends commands to the remote server, then sends an end-of-block marker.
218 * the parameter for this command if any
220 * @throws IOException
221 * in case of IO error
223 public void sendCommand(Command
.Verb verb
, String param
) throws IOException
{
224 sendLine(new Command(verb
, param
, CURRENT_VERSION
).toString());
228 * Read a line from the remote server.
230 * Do <b>NOT</b> read until the end-of-block marker, and can return said
231 * block without conversion.
233 * @return the read line
235 * @throws IOException
236 * in case of IO error
238 protected String
receive() throws IOException
{
239 String line
= in
.readLine();
244 * Read lines from the remote server until the end-of-block ("\0\n") marker
247 * @return the read lines without the end marker, or NULL if nothing more to
250 * @throws IOException
251 * in case of IO error
253 public List
<String
> receiveBlock() throws IOException
{
254 List
<String
> result
= new LinkedList
<String
>();
256 String line
= receive();
257 for (; line
!= null && !line
.equals(EOB
); line
= receive()) {
268 * Read a line from the remote server then read until the next end-of-block
271 * @return the parsed line, or NULL if nothing more to read
273 * @throws IOException
274 * in case of IO error
276 public String
receiveLine() throws IOException
{
277 List
<String
> lines
= receiveBlock();
279 if (lines
.size() > 0)
286 * Read a line from the remote server and convert it to a {@link Command},
287 * then read until the next end-of-block marker.
289 * @return the parsed {@link Command}
291 * @throws IOException
292 * in case of IO error
294 public Command
receiveCommand() throws IOException
{
295 String line
= receive();
296 Command cmd
= new Command(line
, version
);
302 public String
toString() {
303 String source
= "[not connected]";
304 InetAddress iadr
= s
.getInetAddress();
306 source
= iadr
.getHostName();
308 return getLabel() + " (" + source
+ ")";