4 * This module handles the tasks involving establishing a connection to a
5 * Citadel/UX server and moving data across the connection. It also handles
6 * server "keepalives", the dispatching of "express messages", the
7 * registration & termination of multiple threads, and a semaphore mechanism
8 * to prevent multiple threads from executing server commands at the same
17 * We send 'keepalive' commands (actually just a NOOP) to the server every
18 * fifteen seconds, as a separate thread. This prevents the server session
19 * from timing out, and also allows the client to be notified of any incoming
20 * express messages if the user isn't doing anything.
22 class wcKeepAlive extends Thread {
24 wcCitServer serv; /* Pointer to server connection class */
25 boolean FullKeepAlives; /* TRUE for full keepalives, FALSE for half keepalives */
30 public void PointToServer(wcCitServer which_serv, boolean WhatKindOfKeepAlives) {
32 serv.AddClientThread(this);
33 FullKeepAlives = WhatKindOfKeepAlives;
40 /* Sleep for sixty seconds between keepalives. */
44 catch (InterruptedException e) {
46 /* Full keepalives - send a NOOP, wait for a reply, then retrieve
47 * express messages if the server said there are any.
50 buf = serv.ServTrans("NOOP") + " ";
53 /* Half keepalives - blindly send a NOOP and we're done. */
55 serv.ServPuts("NOOP");
66 * the wcCitServer class handles communication with the server.
68 public class wcCitServer {
75 boolean in_trans = false;
76 Vector ClientThreads = new Vector();
77 Vector ServerInfo = new Vector();
78 String PrimaryServerHost;
79 int PrimaryServerPort;
80 String PrimaryServerUser;
81 String PrimaryServerPassword;
83 public void SetTransBuf(String bufstring) {
87 public String GetTransBuf() {
91 /* attach to the server */
92 private void BuildConnection(String ServerHost, int ServerPort, boolean WhichKA) {
97 sock = new Socket(ServerHost, ServerPort);
99 DataOutputStream(sock.getOutputStream());
101 DataInputStream(sock.getInputStream());
103 catch(UnknownHostException e) {
104 System.out.println(e);
106 catch(IOException e) {
107 System.out.println(e);
110 /* Connection established. At this point, this function
111 * has the server connection all to itself, so we can do
112 * whatever we want with it. */
114 /* Get the 'server ready' message */
117 /* Identify the client software to the server */
118 ServTrans("IDEN 0|5|001|Cit/UX Java Client|");
120 /* Download various information about the server */
122 buf = ServTrans("INFO");
123 StringTokenizer InfoST = new StringTokenizer(TransBuf,"\n");
124 while (InfoST.hasMoreTokens()) {
125 ServerInfo.addElement(InfoST.nextToken());
129 /* At this point, all server accesses must cooperate with
130 * server accesses from other threads by using the BeginTrans
131 * and EndTrans semaphore mechanism.
133 ka = new wcKeepAlive();
134 ka.PointToServer(this, WhichKA);
141 * Attach to server command for the primary socket
143 public void AttachToServer(String ServerHost, int ServerPort) {
145 /* Connect to the server */
146 /* NOTE ... we've changed the primary connection keepalives to HALF because we're using the
147 * primary connection to jump right into a chat window.
149 BuildConnection(ServerHost, ServerPort, false);
151 /* And remember where we connected to, in case we have to
152 * build any piggyback connections later on.
154 PrimaryServerHost = ServerHost;
155 PrimaryServerPort = ServerPort;
160 * Learn info about the primary connection for setting up piggybacks
162 public String GetServerHost() {
163 return PrimaryServerHost;
166 public int GetServerPort() {
167 return PrimaryServerPort;
172 * Set up a piggyback connection
174 public void Piggyback(wcCitServer PrimaryServ, boolean KeepAliveType) {
175 PrimaryServerHost = PrimaryServ.GetServerHost();
176 PrimaryServerPort = PrimaryServ.GetServerPort();
177 PrimaryServerUser = PrimaryServ.GetUserName();
178 PrimaryServerPassword = PrimaryServ.GetPassword();
179 BuildConnection(PrimaryServerHost, PrimaryServerPort,
186 /* return info about the site we're currently connected to */
187 public String ServInfo(int index) {
189 if (index >= ServerInfo.size()) {
193 retbuf = ServerInfo.elementAt(index).toString();
199 /* read a line from the server */
200 public String ServGets() {
205 buf = ifp.readLine();
207 catch(IOException e) {
208 System.out.println(e);
214 /* write a line to the server */
215 public void ServPuts(String buf) {
218 ofp.writeBytes(buf + "\n");
220 catch(IOException e) {
221 System.out.println(e);
226 /* lock the server connection so other threads don't screw us up */
227 public synchronized void BeginTrans() {
230 System.out.println("-sleeping-"); /* trace */
233 catch (InterruptedException e) {
240 /* release the lock */
241 public void EndTrans() {
246 /* perform an autonomous server transaction */
247 public String ServTrans(String ServCmd) {
250 buf = DataTrans(ServCmd);
255 /* perform a non-autonomous server transaction */
256 public String DataTrans(String ServCmd) {
261 /* perform the transaction */
263 System.out.println(">"+ServCmd); /* trace */
266 System.out.println("<"+buf); /* trace */
269 if (buf.startsWith("4")) {
270 ofp.writeBytes(TransBuf);
271 if (!TransBuf.endsWith("\n")) {
272 ofp.writeBytes("\n");
274 ofp.writeBytes("000");
278 if (buf.startsWith("1")) {
283 if (!TransBuf.equals("")) {
284 TransBuf = TransBuf + "\n";
286 if (!inbuf.equals("000")) {
287 TransBuf = TransBuf + inbuf;
289 } while (!inbuf.equals("000"));
292 catch(IOException e) {
293 System.out.println(e);
299 public void AddClientThread(Thread ct) {
300 ClientThreads.addElement(ct);
301 System.out.println("--new thread registered--");
304 public void RemoveClientThread(Thread ct) {
305 ClientThreads.removeElement(ct);
306 System.out.println("--thread removed--");
311 /* The following four functions take care of keeping track of the
312 * user name and password being used on the primary server connection
313 * in case we want to use them for a piggyback connection.
315 public void SetUserName(String U) {
316 PrimaryServerUser = U;
319 public void SetPassword(String P) {
320 PrimaryServerPassword = P;
323 public String GetUserName() {
324 return PrimaryServerUser;
327 public String GetPassword() {
328 return PrimaryServerPassword;