Source code: com/ciphermod/cipherchat/ChatChild.java
1 /* $Id: ChatChild.java,v 1.1 2001/03/26 10:48:43 cvsbob Exp $ */
2
3 /*
4 * ChatChild.java, handles server side of the CipherChat protocol.
5 * Copyright (C) 2001 Robert Bushman.
6 *
7 * I reserve the right to release this program under seperate license.
8 * If you require a special license grant contact Robert Bushman.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 * 02111-1307, USA.
24 */
25
26 package com.ciphermod.cipherchat;
27
28 import java.io.DataInputStream;
29 import java.io.DataOutputStream;
30 import java.io.EOFException;
31 import java.io.IOException;
32
33 import java.util.Vector;
34
35 import com.ciphercore.Child;
36 import com.ciphercore.InterProcessObject;
37
38 public class ChatChild extends Child {
39
40 // --------------------------------------------
41 // PUBLIC API
42 // --------------------------------------------
43
44 public void handleClient() {
45 int messageLength;
46 int nameLength;
47 byte[] nameBytes;
48 byte[] messageBytes;
49 String message;
50 DataInputStream in;
51 DataOutputStream out;
52 ChatChildTransmitter transmitter = null;
53
54 try {
55 in = new DataInputStream( getBaseInputStream() );
56 out = new DataOutputStream(getBaseOutputStream());
57 transmitter = new ChatChildTransmitter( out, getGroup() );
58 transmitter.start();
59 setIn( in );
60 nameLength = getIn().readInt();
61 nameBytes = new byte[ nameLength ];
62 getIn().readFully( nameBytes );
63 setUserName( new String( nameBytes ) );
64 getGroup().addUser( getUserName() );
65 while( ( messageLength = getIn().readInt() ) != -1 ) {
66 messageBytes = new byte[ messageLength ];
67 getIn().readFully( messageBytes );
68 message = new String( messageBytes );
69 getGroup().addMessage( getUserName() + ": " + message );
70 }
71 } catch( EOFException e ) {
72 // This is the normal exit condition for a crashed client.
73 } catch( IOException e ) {
74 e.printStackTrace();
75 } finally {
76 if( transmitter != null ) {
77 try {
78 getGroup().removeUser( getUserName() );
79 transmitter.pleaseStop();
80 transmitter.join();
81 System.out.println( "Transmitter joined, exiting." );
82 } catch( InterruptedException e ) {
83 e.printStackTrace();
84 }
85 }
86 }
87 }
88
89 private static Object _ipoLock = new Object();
90
91 public void initializeInterProcessObject( InterProcessObject ipo ) {
92 synchronized( _ipoLock ) {
93 if( ipo == null ) {
94 ChatGroup chat = new ChatGroup();
95 chat.start();
96 ipo = chat;
97 }
98 }
99 setInterProcessObject( ipo );
100 }
101
102 // --------------------------------------------
103 // INTERNAL METHODS
104 // --------------------------------------------
105
106 // -------------------------------------------
107 // INSTANCE PARAMETERS AND ACCESSORS
108 // --------------------------------------------
109
110 // PARAMETERS
111 private DataInputStream _in;
112 private String _userName;
113
114 // SETTERS
115 protected void setIn( DataInputStream in ) { _in = in; }
116 protected void setUserName( String userName ) { _userName = userName; }
117
118 // GETTERS
119 protected DataInputStream getIn() { return( _in ); }
120 protected String getUserName() { return( _userName ); }
121 protected ChatGroup getGroup() {
122 return( (ChatGroup)getInterProcessObject() );
123 }
124 }
125
126 class ChatChildTransmitter extends Thread {
127
128 // ---------------------------------------------------------
129 // CONSTRUCTOR
130 // ---------------------------------------------------------
131
132 public ChatChildTransmitter( DataOutputStream out, ChatGroup group ) {
133 setOut( out );
134 setGroup( group );
135 }
136
137 // -------------------------------------------------------
138 // THREAD IMPLEMENTATION
139 // -------------------------------------------------------
140
141 private boolean _stopRequested = false;
142
143 public void run() {
144 Object waiter;
145 Vector newMessages;
146 String lastMessageId;
147 String message;
148
149 try {
150 waiter = new Object();
151 while( ! _stopRequested ) {
152 try{ synchronized(waiter){waiter.wait(1000);} }
153 catch( Exception e ){}
154
155 newMessages = getGroup().getMessages( getLastMessageId() );
156 if( newMessages.size() > 0 && newMessages.get( 0 ) != null ) {
157 lastMessageId = (String)newMessages.get( 0 );
158 setLastMessageId( lastMessageId );
159 for( int i = 1; i < newMessages.size(); i++ ) {
160 message = (String)newMessages.get( i );
161 getOut().writeInt( message.getBytes().length );
162 getOut().write( message.getBytes() );
163 }
164 }
165 }
166 } catch( IOException e ) {
167 e.printStackTrace();
168 }
169 }
170
171 public void pleaseStop() {
172 _stopRequested = true;
173 }
174
175 // --------------------------------------------------------
176 // INSTANCE PARAMETERS AND ACCESSORS
177 // --------------------------------------------------------
178
179 // PARAMETERS
180 private DataOutputStream _out;
181 private ChatGroup _group;
182 private String _lastMessageId;
183
184 // SETTERS
185 protected void setOut( DataOutputStream out ) { _out = out; }
186 protected void setGroup( ChatGroup group ) { _group = group; }
187 protected void setLastMessageId( String lastMessageId ) {
188 _lastMessageId = lastMessageId;
189 }
190
191 // GETTERS
192 protected DataOutputStream getOut() { return( _out ); }
193 protected ChatGroup getGroup() { return( _group ); }
194 protected String getLastMessageId() { return( _lastMessageId ); }
195 }
196