Commit | Line | Data |
---|---|---|
1b37400b FT |
1 | package dolda.dolcon; |
2 | ||
3 | import java.io.*; | |
4 | import java.net.Socket; | |
5 | import java.util.*; | |
6 | ||
7 | public class Connection { | |
8 | Socket s; | |
9 | Reader reader; | |
10 | LinkedList<Response> resps = new LinkedList<Response>(); | |
11 | ||
12 | public Connection(String aspec) throws ConnectException { | |
13 | try { | |
14 | s = new Socket(aspec, 1500); | |
15 | } catch(java.net.UnknownHostException e) { | |
16 | throw(new ConnectException("Could not resolve host " + aspec, e)); | |
17 | } catch(IOException e) { | |
18 | throw(new ConnectException("Could not connect to host " + aspec, e)); | |
19 | } | |
20 | reader = new Reader(s, resps); | |
21 | reader.start(); | |
22 | } | |
23 | ||
24 | static private class Reader extends Thread { | |
25 | Exception error = null; | |
26 | Socket s; | |
27 | Collection<Response> resps; | |
28 | ||
29 | public Reader(Socket s, Collection<Response> resps) { | |
30 | this.s = s; | |
31 | this.resps = resps; | |
32 | setDaemon(true); | |
33 | } | |
34 | ||
35 | public void run() { | |
36 | java.io.Reader r; | |
37 | try { | |
38 | r = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); | |
39 | } catch(IOException e) { | |
40 | synchronized(resps) { | |
41 | resps.notifyAll(); | |
42 | error = e; | |
43 | } | |
44 | return; | |
45 | } | |
46 | String state = "start"; | |
47 | StringBuilder ct = new StringBuilder(); | |
48 | int code = -1; | |
49 | boolean last = true; | |
50 | List<List<String>>lines = new LinkedList<List<String>>(); | |
51 | List<String>tokens = new LinkedList<String>(); | |
52 | while(true) { | |
53 | char c; | |
54 | { | |
55 | int i; | |
56 | try { | |
57 | if((i = r.read()) < 0) { | |
58 | throw(new IOException("The server closed the connection")); | |
59 | } | |
60 | } catch(IOException e) { | |
61 | synchronized(resps) { | |
62 | resps.notifyAll(); | |
63 | error = e; | |
64 | } | |
65 | return; | |
66 | } | |
67 | c = (char)i; | |
68 | } | |
69 | eat: do { | |
70 | if(state == "start") { | |
71 | if(c == '\r') { | |
72 | state = "nl"; | |
73 | } else if(Character.isWhitespace(c)) { | |
74 | } else { | |
75 | if(code == -1) | |
76 | state = "code"; | |
77 | else | |
78 | state = "token"; | |
79 | continue eat; | |
80 | } | |
81 | } else if(state == "nl") { | |
82 | if(c == '\n') { | |
83 | if(code == -1) { | |
84 | synchronized(resps) { | |
85 | resps.notifyAll(); | |
86 | try { | |
87 | throw(new IOException("Illegal response code " + code + " from the server")); | |
88 | } catch(IOException e) { | |
89 | error = e; | |
90 | } | |
91 | } | |
92 | return; | |
93 | } | |
94 | lines.add(tokens); | |
95 | tokens = new LinkedList<String>(); | |
96 | if(last) { | |
97 | synchronized(resps) { | |
98 | resps.add(new Response(code, lines)); | |
99 | resps.notifyAll(); | |
100 | } | |
101 | lines = new LinkedList<List<String>>(); | |
102 | } | |
103 | state = "start"; | |
104 | } else { | |
105 | state = "start"; | |
106 | continue eat; | |
107 | } | |
108 | } else if(state == "code") { | |
109 | if((c == '-') || Character.isWhitespace(c)) { | |
110 | last = c != '-'; | |
111 | code = Integer.parseInt(ct.toString()); | |
112 | ct.setLength(0); | |
113 | state = "start"; | |
114 | continue eat; | |
115 | } else { | |
116 | ct.append(c); | |
117 | } | |
118 | } else if(state == "token") { | |
119 | if(Character.isWhitespace(c)) { | |
120 | tokens.add(ct.toString()); | |
121 | ct.setLength(0); | |
122 | state = "start"; | |
123 | code = -1; | |
124 | continue eat; | |
125 | } else if(c == '\\') { | |
126 | state = "bs"; | |
127 | } else if(c == '"') { | |
128 | state = "cited"; | |
129 | } else { | |
130 | ct.append(c); | |
131 | } | |
132 | } else if(state == "bs") { | |
133 | ct.append(c); | |
134 | state = "token"; | |
135 | } else if(state == "cited") { | |
136 | if(c == '\\') | |
137 | state = "cbs"; | |
138 | else if(c == '"') | |
139 | state = "token"; | |
140 | else | |
141 | ct.append(c); | |
142 | } else if(state == "cbs") { | |
143 | ct.append(c); | |
144 | state = "cited"; | |
145 | } else { | |
146 | throw(new Error("invalid state " + state)); | |
147 | } | |
148 | break; | |
149 | } while(true); | |
150 | } | |
151 | } | |
152 | } | |
153 | ||
154 | protected void finalize() { | |
155 | try { | |
156 | s.close(); | |
157 | } catch(IOException e) { | |
158 | } | |
159 | reader.interrupt(); | |
160 | } | |
161 | ||
162 | public static void main(String[] args) throws Exception { | |
163 | Connection c = new Connection("pc18"); | |
164 | while(true) { | |
165 | while(c.resps.size() > 0) { | |
166 | System.out.println(c.resps.remove(0)); | |
167 | } | |
168 | synchronized(c.resps) { | |
169 | c.resps.wait(); | |
170 | } | |
171 | } | |
172 | } | |
173 | } |