1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sf.dexterim.msn;
20
21 import net.sf.dexterim.core.AbstractConversation;
22 import net.sf.dexterim.core.Account;
23 import net.sf.dexterim.core.Contact;
24 import net.sf.dexterim.core.event.ConversationEvent;
25 import net.sf.dexterim.msn.entity.SwitchBoardServer;
26 import net.sf.dexterim.msn.event.MessageEvent;
27 import net.sf.dexterim.msn.event.MessageListener;
28 import net.sf.dexterim.msn.io.BufferedMsnMessageReader;
29 import net.sf.dexterim.msn.message.AnswerMessage;
30 import net.sf.dexterim.msn.message.JoinMessage;
31 import net.sf.dexterim.msn.message.JoiningMessage;
32 import net.sf.dexterim.msn.message.LoginReplyMessage;
33 import net.sf.dexterim.msn.message.MsnMessage;
34 import net.sf.dexterim.msn.message.UserMessage;
35 import net.sf.dexterim.msn.util.ContactQueque;
36 import net.sf.dexterim.msn.util.MessageQueque;
37 import net.sf.dexterim.msn.util.SpecialCharacters;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 /***
43 * @author Christoph Walcher
44 */
45 public class MsnConversation
46 extends AbstractConversation
47 implements MessageListener {
48 private final static String HEADER =
49 "MIME-Version: 1.0\r\nContent-Type: text/plain; "
50 + "charset=UTF-8\r\nX-MMS-IM-Format: FN=Microsoft%20Sans%20Serif;"
51 + " EF=; CO=000000; CS=0; PF=22\r\n";
52
53
54
55
56 private MsnConnection connection;
57 private ContactQueque contactQueque;
58 private MessageQueque messageQueque;
59 private BufferedMsnMessageReader messageReader;
60 private java.io.PrintStream out;
61 private java.net.Socket soc;
62 private boolean connected;
63 private Log log;
64 private int transmissionID;
65
66 /*** Creates a new instance of MsnConversation */
67 public MsnConversation(MsnConnection connection) {
68 this.connection = connection;
69
70 messageQueque = new MessageQueque();
71 contactQueque = new ContactQueque();
72
73 connected = false;
74
75 log = LogFactory.getLog(getClass());
76
77 transmissionID = 1;
78 }
79
80 public void close() {
81 out.println("OUT");
82 this.connected = false;
83
84 try {
85 stopIO();
86 } catch (java.io.IOException ioex) {
87 if (log.isDebugEnabled()) {
88 log.info("Failed to free Conversation resources", ioex);
89 }
90 }
91 }
92
93 public void join(Contact contact) {
94 if (!connected) {
95 contactQueque.addContact(contact);
96 } else {
97 inviteContact(contact);
98 }
99 }
100
101 public void open() {
102 connection.sendSwitchboardRequest(this);
103 }
104
105 public void sendMessage(String message) {
106 if (!connected) {
107 messageQueque.addMessage(message);
108 } else {
109 sendTextMessage(message);
110 }
111 }
112
113 protected void connectionEstablished() {
114 messageQueque.sendQuequed(this);
115 messageQueque.clear();
116 }
117
118 public synchronized void sendTextMessage(String message) {
119 try {
120 String encodedMessage = SpecialCharacters.getInstance().encode(message);
121
122 int length = 0;
123
124 length =
125 computeMessageLength(encodedMessage)
126 + computeMessageLength(HEADER)
127 + computeMessageLength("\r\n");
128
129 out.print(
130 "MSG "
131 + transmissionID
132 + " N "
133 + length
134 + "\r\n"
135 + HEADER
136 + "\r\n"
137 + encodedMessage);
138
139 if (log.isDebugEnabled()) {
140 log.debug(
141 "MSG "
142 + transmissionID
143 + " N "
144 + length
145 + "\r\n"
146 + HEADER
147 + "\r\n"
148 + encodedMessage);
149 }
150
151 transmissionID++;
152 } catch (Exception ex) {
153 ex.printStackTrace();
154 }
155 }
156
157 /***
158 * Description of the Method
159 *
160 * @param message
161 * Description of the Parameter
162 * @return Description of the Return Value
163 */
164 protected int computeMessageLength(String message) {
165 if (message != null) {
166 return message.getBytes().length;
167 } else {
168 return 0;
169 }
170 }
171
172 /***
173 * Binds Conversation to a specified SwitchboardServer. This method physicaly
174 * connects this conversation instance to the server and opens the
175 * Conversation for message transmission.
176 */
177 public void bind(SwitchBoardServer server) {
178 try {
179 initIO(server);
180 signIn(server);
181 } catch (java.io.IOException ioex) {
182 if (log.isErrorEnabled()) {
183 log.error("Could not setup Socket Connection", ioex);
184 }
185 }
186 }
187
188 public synchronized void answer(
189 SwitchBoardServer server,
190 String conversationID) {
191 try {
192 initIO(server);
193
194 log.debug(
195 "ANS "
196 + transmissionID
197 + " "
198 + connection.connectedAs().getIdentity()
199 + " "
200 + server.getCKI()
201 + " "
202 + conversationID);
203
204 out.println(
205 "ANS "
206 + transmissionID
207 + " "
208 + connection.connectedAs().getIdentity()
209 + " "
210 + server.getCKI()
211 + " "
212 + conversationID);
213 transmissionID++;
214 } catch (java.io.IOException ioex) {
215 if (log.isErrorEnabled()) {
216 log.error("Could not setup Socket Connection", ioex);
217 }
218 }
219 }
220
221 protected void signInReceived() {
222 this.connected = true;
223
224 contactQueque.joinQuequed(this);
225 contactQueque.clear();
226 }
227
228 /***
229 * Sends a Message of the form <CODE>USR 1 example@passport.com
230 * 16925950.1016955577.17693</CODE> to sign in as creater to the new
231 * SwitchBoard
232 */
233 public synchronized void signIn(SwitchBoardServer server) {
234 if (log.isDebugEnabled()) {
235 log.debug("Signing in to Switchboard Server ");
236 }
237
238 Account account = connection.connectedAs();
239
240 log.debug(
241 "USR "
242 + transmissionID
243 + " "
244 + account.getIdentity()
245 + " "
246 + server.getCKI());
247
248 out.println(
249 "USR "
250 + transmissionID
251 + " "
252 + account.getIdentity()
253 + " "
254 + server.getCKI());
255 transmissionID++;
256 }
257
258 /***
259 * Sends a Message of the form <CODE>CAL 2 name_123@hotmail.com</CODE> to
260 * invite User name_123@hotmail.com to a chat session
261 */
262 public synchronized void inviteContact(Contact contact) {
263 if (log.isDebugEnabled()) {
264 log.debug(
265 "Inviting Contact to Conversation "
266 + contact.getIdentity()
267 + " "
268 + contact.getFriendlyName());
269 }
270
271 out.println("CAL " + transmissionID + " " + contact.getIdentity().toString());
272 transmissionID++;
273 }
274
275 protected void initIO(SwitchBoardServer server) throws java.io.IOException {
276 soc = new java.net.Socket(server.getIP(), server.getPort());
277 soc.setSoTimeout(10000);
278
279 out = new java.io.PrintStream(soc.getOutputStream());
280 messageReader =
281 new net.sf.dexterim.msn.io.BufferedMsnMessageReader(
282 new java.io.InputStreamReader(soc.getInputStream()));
283
284 ReceiverThread receiver =
285 new ReceiverThread(connection.connectedAs().toString(), messageReader);
286
287 receiver.addMessageListener(this);
288
289 receiver.start();
290 }
291
292 protected void stopIO() throws java.io.IOException {
293 if (messageReader != null) {
294 messageReader.close();
295 }
296
297 if (out != null) {
298 out.close();
299 }
300
301 if (soc != null) {
302 soc.close();
303 }
304 }
305
306 public void messageReceived(MessageEvent event) {
307
308 MsnMessage message = (MsnMessage)event.getMessage();
309
310 if (message instanceof LoginReplyMessage) {
311 signInReceived();
312 } else if (message instanceof JoinMessage) {
313 String account = ((JoinMessage)message).getAccount();
314 String nick = ((JoinMessage)message).getNick();
315
316 log.debug(
317 message + " " + connection.connectedAs() + " " + account + " " + nick);
318
319 connectionEstablished();
320 } else if (message instanceof JoiningMessage) {
321 String account = ((JoiningMessage)message).getAccount();
322 String nick = ((JoiningMessage)message).getNick();
323
324 log.debug(
325 message + " " + connection.connectedAs() + " " + account + " " + nick);
326 } else if (message instanceof UserMessage) {
327 UserMessage userMessage = ((UserMessage)message);
328
329 log.debug(
330 "Received Text "
331 + userMessage.getAccount()
332 + " "
333 + userMessage.getNick()
334 + " Message: "
335 + userMessage.getMessage());
336
337 fireMessageReceived(
338 new ConversationEvent(this, userMessage.getMessage()));
339 } else if (message instanceof AnswerMessage) {
340 if (((AnswerMessage)message).isOk()) {
341 connectionEstablished();
342 }
343 }
344 }
345 }