Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/synchrona/jred/irlap/IrLAPContext.java


1   /*
2   **************************************************************************
3   ** $Header: /cvsroot/jred/jred/src/com/synchrona/jred/irlap/IrLAPContext.java,v 1.1.1.1 2000/07/05 04:41:52 mpatters Exp $
4   **
5   ** Copyright (C) 2000 Synchrona, Inc. All rights reserved.
6   **
7   ** This file is part of JRed, a 100% Java implementation of the IrDA
8   ** infrared communications protocols.
9   **
10  ** This file may be distributed under the terms of the Synchrona Public
11  ** License as defined by Synchrona, Inc. and appearing in the file
12  ** LICENSE included in the packaging of this file. The Synchrona Public
13  ** License is based on the Q Public License as defined by Troll Tech AS
14  ** of Norway; it differs only in its use of the courts of Florida, USA
15  ** rather than those of Oslo, Norway.
16  **************************************************************************
17  */
18  package com.synchrona.jred.irlap;
19  
20  import com.synchrona.util.Log;
21  import com.synchrona.util.Utilities;
22  import java.awt.event.ActionEvent;
23  import java.awt.event.ActionListener;
24  import java.io.PrintWriter;
25  import java.util.Random;
26  import javax.swing.Timer;
27  
28  /**
29   * IrLAPContext offers services for the IrLAP states.
30   * Log messages mimic directives in the IrLAP specification, which
31   * helps in debuggering.
32   */
33  public class IrLAPContext implements iIrLAPFramerListener {
34    public static final int DEFAULT_F_TIMEOUT_MSEC        = 500;
35    public static final int DEFAULT_MIN_TURNAROUND_MSEC   = 5; // was 10
36    public static final int DEFAULT_QUERY_TIMEOUT_MSEC    = 500;
37    public static final int DEFAULT_WATCHDOG_TIMEOUT_MSEC = 5000;
38    public static final int DEFAULT_WINDOW_SIZE           = 1;
39  
40    // TBD: This should really be provided by the service user (IrOBEX) via
41    //      IrLMP.
42    private static final byte [] DISCOVERY_INFO = {
43      (byte) 0x82, // means "I am a PDA, and this byte is followed by another"
44      (byte) 0x20, // means "I am a file server and this is the last service hint"
45      (byte) 0x00, // means "ASCII data follows"
46      (byte) 'J',  // what follows is a device hint that identifies this station
47      (byte) 'R',
48      (byte) 'e',
49      (byte) 'd',
50      (byte) '0',
51      (byte) '.',
52      (byte) '1'
53    };
54  
55    private byte []        m_ayCommParameters     = null;
56    private boolean        m_bAckRequired         = false;
57    private boolean        m_bConnectionConfirmed = false;
58    private boolean        m_bFrameSent           = false;
59    private boolean        m_bMediaBusy           = false;
60    private boolean        m_bRemoteBusy          = false;
61    private ConnectionLog  m_connectionLog        = null;
62    private DiscoveryLog   m_discoveryLog         = null;
63    private IrLAPFramer    m_framer               = null;
64    private Timer          m_fTimer               = null;
65    private iIrLAPListener m_listener             = null;
66    private Log            m_log                  = null;
67    private int            m_nFTimeout            = DEFAULT_F_TIMEOUT_MSEC;
68    private int            m_nMyAddress           = 12345678;
69    private int            m_nQueryTimeout        = DEFAULT_QUERY_TIMEOUT_MSEC;
70    private int            m_nRemoteAddress       = 0;
71    private int            m_nRetryCount          = 0;
72    private int            m_nWatchdogTimeout     = DEFAULT_WATCHDOG_TIMEOUT_MSEC;
73    private int            m_nVr                  = 0;
74    private int            m_nVs                  = 0;
75    private int            m_nWindowSize          = 1;
76    private Timer          m_queryTimer           = null; 
77    private Random         m_random               = new Random();
78    private IrLAPSendQueue m_sendQueue            = new IrLAPSendQueue();
79    private IrLAPState     m_state                = IrLAPStateNDM.getInstance();
80    private IrLAPContext   m_this                 = null;
81    private Timer          m_watchdogTimer        = null;
82    private byte           m_yConnection          = 0;
83    private byte           m_yResponseSlot        = 2;
84  
85    private IrLAPContext() {
86      // No-arg constructor is private so we don't get a null
87      // log device; that would cause NullPointerExceptions
88      // all over the place.
89    }
90  
91    public IrLAPContext(Log log) {
92      m_log           = log;
93      m_this          = this;
94      m_yResponseSlot = (byte) 2;
95      m_connectionLog = new ConnectionLog(m_log);
96      m_discoveryLog  = new DiscoveryLog(m_log);
97  
98      generateAddress();
99  
100     m_fTimer = new Timer(m_nFTimeout, new ActionListener() {
101       public void actionPerformed(ActionEvent action) {
102         try {
103           m_log.debug("IrLAPContext", "F-timer-expired");
104           m_state.handleFTimerExpired(m_this);
105         } catch ( Exception e ) {
106           System.err.println(e);
107         }
108       }
109     });
110 
111     m_queryTimer = new Timer(m_nQueryTimeout, new ActionListener() {
112       public void actionPerformed(ActionEvent action) {
113         try {
114           m_log.debug("IrLAPContext", "query-timer-expired");
115           m_state.handleQueryTimerExpired(m_this);
116         } catch ( Exception e ) {
117           System.err.println(e);
118         }
119       }
120     });
121 
122     m_watchdogTimer = new Timer(m_nWatchdogTimeout, new ActionListener() {
123       public void actionPerformed(ActionEvent action) {
124         try {
125           m_log.debug("IrLAPContext", "WD-timer-expired");
126           m_state.handleWatchdogTimerExpired(m_this);
127         } catch ( Exception e ) {
128           System.err.println(e);
129         }
130       }
131     });
132   }
133 
134   //------------------------------------------------------------------
135   // Users of IrLAPContext instances use these
136   //------------------------------------------------------------------
137 
138   public void addIrLAPListener(iIrLAPListener listener) throws Exception {  
139     if ( null != m_listener ) {
140       throw new Exception("This IrLAPContext already has a listener.");
141     } else {
142       m_listener = listener;
143     }
144   }
145 
146   /**
147    * @deprecated
148    */
149   public void setLog(PrintWriter log) {
150   }
151 
152   /**
153    * @deprecated
154    */
155   public void setLogging(boolean bDoLogging) {
156   }
157 
158   //------------------------------------------------------------------
159   // Implement iIrLAPFramerListener
160   //------------------------------------------------------------------
161 
162   public void handleData(byte yConnection, boolean bCommand, int nNs, int nNr, boolean bPoll, byte [] ayData) throws Exception {
163     m_log.debug("IrLAPContext", "Recv i:" + ( bCommand ? "cmd" : "rsp" ) + ":" + (0x00000007 & nNs) + ":" + (0x00000007 & nNr) + ":" + ( bPoll ? "P" : "~P"));
164     m_state.handleData(this, yConnection, nNr, bCommand, bPoll, ayData);
165   }
166 
167   public void handleDisconnect(byte yConnection, boolean bCommand, boolean bPoll) throws Exception {
168     m_log.debug("IrLAPContext", "u:disc:" + (bCommand ? "cmd" : "rsp") + ":" + (bPoll ? "P" : "~P"));
169     m_state.handleDisconnect(this, m_nRemoteAddress, yConnection);
170   }
171 
172   public void handleRR(byte yConnection, int nNr, boolean bCommand, boolean bPoll) throws Exception {
173     m_log.debug("IrLAPContext", "Recv s:rr:" + ( bCommand ? "cmd" : "rsp" ) + ":" + (0x00000007 & nNr) + ":" + ( bPoll ? "P" : "~P"));
174     m_state.handleRR(this, yConnection, nNr, bCommand, bPoll);
175   }
176 
177   public void handleSNRM(int nSource, int nDestination, byte yConnection, byte [] ayParameters) throws Exception {
178     m_log.debug("IrLAPContext", "Recv u:snrm:cmd:P:" + Utilities.byteToString(yConnection) + ":" + nSource);
179     m_yConnection = yConnection;
180     m_state.handleSNRM(this, nSource, nDestination, yConnection, ayParameters);
181   } 
182 
183   public void handleXID(int nSource, int nDestination, byte yNumSlots, byte ySlot, boolean bCommand, byte [] ayHints) throws Exception {
184     if ( (byte) 0xFF == ySlot ) {
185       m_log.debug("IrLAPContext", "Recv End-Discovery-XID-Cmd");
186     } else {
187       m_log.debug("IrLAPContext", "Recv Discovery-XID-Cmd:" + yNumSlots + "," + ySlot);
188     }
189     m_state.handleXID(this, nSource, nDestination, ySlot, bCommand, ayHints);
190   }
191 
192   //------------------------------------------------------------------
193   // End implementation of iIrLAPFramerListener, start methods to
194   // support IrLAPState
195   //------------------------------------------------------------------
196 
197   public void applyConnectionParameters() throws Exception {
198     m_log.debug("IrLAPContext", "\tApply-Connection-Parameters");
199   }
200 /*
201   public void connectionConfirm() {
202     m_log.debug("connection-confirm");
203   }
204 
205   public void connectRequest(int nDestination) throws Exception {
206     m_log.debug("Connect-Request(" + nDestination + ")");
207     m_state.connectionRequest(this, nDestination);
208   }
209 */
210   public void connectIndication(int nRemote, byte yConnection, byte [] ayParameters) throws Exception {
211     m_log.debug("IrLAPContext", "\tConnect-Indication");
212 
213     ConnectionInformation conn = new ConnectionInformation(yConnection, ayParameters, m_discoveryLog.get(nRemote));
214     m_connectionLog.add(conn);
215 
216     if ( null != m_listener ) {
217       m_nRemoteAddress = nRemote;
218       //m_listener.connectIndication(this, nRemote, yConnection, ayParameters);
219       m_listener.connectIndication(this, conn);
220     }
221   }
222 
223   public void connectResponse(int nDestination, byte yConnection, byte [] ayParams) throws Exception {
224     m_state.connectResponse(this, nDestination, yConnection, ayParams);
225   }
226 
227 
228   public void dataIndication(byte yConnection, byte [] ayData) throws Exception {
229     m_log.debug("IrLAPContext", "\tData-Indication");
230     if ( null != m_listener ) {
231       ConnectionInformation connInfo = m_connectionLog.get(yConnection);
232       m_listener.dataIndication(this, connInfo, ayData);
233     }
234   }
235 
236   public void discoveryIndication(DiscoveryInformation discoveryInfo) throws Exception {
237     m_log.debug("IrLAPContext", "\tDiscovery-Indication(" + discoveryInfo + ")");
238     m_discoveryLog.add(discoveryInfo);
239     if ( null != m_listener ) {
240       m_listener.discoveryIndication(this, discoveryInfo);
241     }
242   }
243 
244   public void flushQueue(byte yConnection) throws Exception {
245     if ( m_sendQueue.pendingDataRequests() ) {
246       for ( int i = 0; i < m_sendQueue.size(); i++ ) {
247         IrLAPFrame nextFrame  = m_sendQueue.get(i);
248         byte []    ayNextData = nextFrame.getData();
249         m_log.debug("IrLAPContext", "Data-Request(" + Utilities.bytesToString(ayNextData, 0, ayNextData.length) + ")");
250         m_framer.sendI(yConnection, m_nVr, nextFrame.getSequenceNumber(), true, ayNextData, 0, ayNextData.length);
251       }
252     }
253   }
254 
255   public void generateAddress() {
256     m_nMyAddress = m_random.nextInt();
257     m_log.debug("IrLAPContext", "\tGenerate-Random-Address => " + m_nMyAddress);
258   }
259 
260   public byte generateConnectionAddress() throws Exception {
261     byte yConnection = (byte) 0x35;
262     m_log.debug("IrLAPContext", "\tGenerate-Random-ConnectionAdr(" + yConnection + ")");
263     return yConnection;
264   }
265 
266   public byte generateResponseSlot(byte yNumSlots, byte ySlot) throws Exception {
267     m_yResponseSlot = (byte) (m_random.nextInt() % (yNumSlots - ySlot) + ySlot);
268     if ( m_yResponseSlot < 0 ) {
269       m_yResponseSlot *= -1;
270     }
271     m_log.debug("IrLAPContext", "\tslot := Generate-Random-Time-Slot(" + yNumSlots + "," + ySlot + ") => " + m_yResponseSlot);
272     return m_yResponseSlot;
273   }
274 
275   public byte getConnection() {
276     return m_yConnection;
277   }
278 
279   public byte getResponseSlot() {
280     return m_yResponseSlot;
281   }
282 
283   public int getVr() {
284     return m_nVr;
285   }
286 
287   public int getVs() {
288     return m_nVs;
289   }
290 
291   public void incrementVr() throws Exception {
292     m_log.debug("IrLAPContext", "\tVr := (Vr + 1) % 8");
293     m_nVr = (m_nVr + 1) % 8;
294   }
295 
296   public void initializeConnectionState() throws Exception {
297     m_log.debug("IrLAPContext", "\tInitialize-Connection-State");
298 
299     m_bFrameSent  = false;
300     m_bRemoteBusy = false;
301     m_nRetryCount = 0;
302     m_nVr         = 0;
303     m_nVs         = 0;
304     m_nWindowSize = DEFAULT_WINDOW_SIZE;
305 
306     //m_framer.initialize();
307   }
308 
309   public boolean isConnectionConfirmed() {
310     return m_bConnectionConfirmed;
311   }
312 
313   public boolean isFrameSent() {
314     return m_bFrameSent;
315   }
316 
317   public boolean isMediaBusy() throws Exception {
318     m_log.debug("IrLAPContext", "\tmediaBusy = " + m_bMediaBusy);
319     return m_bMediaBusy;
320   }
321 
322   public boolean isRemoteBusy() throws Exception {
323     m_log.debug("IrLAPContext", "\tremoteBusy = " + m_bRemoteBusy);
324     return m_bRemoteBusy;
325   }
326 
327 
328   /**
329    * Does nothing right now. We stick to 9600bps, 8 data bits, 1 stop bit,
330    * no parity. We gotta fix that -- 9600 is painfully slow.
331    */
332   public void negotiateConnectionParameters(byte [] ayParameters) throws Exception {
333     m_log.debug("IrLAPContext", "\tNegotiate-Connection-Parameters: " + Utilities.bytesToString(ayParameters, 0, ayParameters.length));
334     m_ayCommParameters = ayParameters;
335     m_framer.setConnectionParameters(m_ayCommParameters);
336   }
337 
338   public void nextState(IrLAPState nextState) throws Exception {
339     m_log.debug("IrLAPContext", "[transition from " + m_state.getClass().getName() + " to " + nextState.getClass().getName() + "]");
340     m_state = nextState;
341   }
342 
343   public boolean pendingDataRequests() throws Exception {
344     boolean bPending = m_sendQueue.pendingDataRequests();
345     m_log.debug("IrLAPContext", bPending ? "\tPending-Data-Requests" : "\tNo-Pending-Data-Requests");
346     return bPending;
347   }
348 
349   public void sendData(byte yConnection, byte [] ayData, int nOffset, int nLength) throws Exception {
350     m_log.debug("IrLAPContext", "sendData");
351     m_sendQueue.addFrame(new IrLAPFrame(m_nVs, ayData, nOffset, nLength));
352     m_nVs = (m_nVs + 1) % 8;
353   }
354 
355   public void sendDiscoveryResponse(int nDestination) throws Exception {
356     m_log.debug("IrLAPContext", "\tSend-Discovery-XID-Rsp:" + m_nMyAddress + ",discovery-info");
357     m_framer.sendXID(m_nMyAddress, nDestination, false, (byte) 0xFF, DISCOVERY_INFO);
358   }
359 
360   public void sendNext(byte yConnection) throws Exception {
361     if ( !m_sendQueue.pendingDataRequests() ) {
362       throw new Exception("No pending requests");
363     }
364     IrLAPFrame nextFrame  = m_sendQueue.getNext();
365     byte []    ayNextData = nextFrame.getData();
366     m_log.debug("IrLAPContext", "Data-Request(" + Utilities.bytesToString(ayNextData, 0, ayNextData.length) + ")");
367     m_framer.sendI(yConnection, m_nVr, nextFrame.getSequenceNumber(), true, ayNextData, 0, ayNextData.length);
368   }
369 
370   public void sendRR(byte yConnection, boolean bCommand, boolean bFinal) throws Exception {
371     m_log.debug("IrLAPContext", "\tSend s:rr:" + (bCommand ? "cmd" : "rsp") + ":" + m_nVr + ":" + (bFinal ? "F" : "~F"));
372     m_framer.sendRR(yConnection, m_nVr, bCommand, bFinal);
373   }
374 
375   public void sendSNRM(int nDestination, byte yConnection) throws Exception {
376     m_log.debug("IrLAPContext", "\tsend u:snrm:cmd:P:" + yConnection + ":" + nDestination);
377     m_framer.sendSNRM(m_nMyAddress, nDestination, yConnection);
378   }
379 
380   public void sendUA(int nDestination, byte yConnection, boolean bSendParameters) throws Exception {
381     if ( bSendParameters ) {  
382       m_log.debug("IrLAPContext", "\tsend u:ua:cmd:F (+ parameters) (" + Utilities.byteToString(yConnection) + ")");
383     } else {
384       m_log.debug("IrLAPContext", "\tsend u:ua:cmd:F (" + Utilities.byteToString(yConnection) + ")");
385     }
386     m_framer.sendUA(m_nMyAddress, nDestination, yConnection, bSendParameters);
387   }
388 
389 /*
390   public void setAckRequired(boolean bAckRequired) {
391     m_log.debug("ackRequired := " + bAckRequired);
392     m_bAckRequired = bAckRequired;
393   }
394 
395   public void setConnectionConfirmed(boolean bConnectionConfirmed) {
396     m_log.debug("connection-confirm(" + bConnectionConfirmed + ")");
397     m_bConnectionConfirmed = bConnectionConfirmed;
398   }
399 */
400 
401   public void setFramer(IrLAPFramer framer) throws Exception {
402     m_framer = framer;
403     m_framer.addIrLAPFramerListener(this);  
404   }
405 
406   public void setFrameSent(boolean bFrameSent) throws Exception {
407     m_log.debug("IrLAPContext", "\tframeSent := " + bFrameSent);
408     m_bFrameSent = bFrameSent;
409   }
410 
411   public void setRemoteBusy(boolean bRemoteBusy) throws Exception {
412     m_log.debug("IrLAPContext", "\tremoteBusy := " + bRemoteBusy);
413     m_bRemoteBusy = bRemoteBusy;
414   }
415 
416   public void startFTimer() throws Exception {
417     m_log.debug("IrLAPContext", "\tstart-F-timer");
418     m_fTimer.setRepeats(false);
419     m_fTimer.start();
420   }
421 
422   public void startQueryTimer() throws Exception {
423     m_log.debug("IrLAPContext", "\tstart-query-timer");
424     m_queryTimer.setRepeats(false);
425     m_queryTimer.start();
426   }
427 
428   public void startWatchdogTimer() throws Exception {
429     m_log.debug("IrLAPContext", "\tstart-WD-timer");
430     m_watchdogTimer.stop();
431     m_watchdogTimer.setRepeats(false);
432     m_watchdogTimer.start();
433   }
434 
435   public void stopQueryTimer() throws Exception {
436     m_log.debug("IrLAPContext", "\tstop-query-timer");
437     m_queryTimer.stop();
438   }
439 
440   public void stopWatchdogTimer() throws Exception {
441     m_log.debug("IrLAPContext", "\tstop-WD-timer");
442     m_watchdogTimer.stop();
443   }
444 
445   /**
446    * Acknowledge frames through Nr - 1 by removing them from
447    * the send queue.
448    */
449   public void updateNr(int nNr) throws Exception {
450     // Damned sign extension.
451     nNr &= 0x00000007;
452     m_log.debug("IrLAPContext", "\tUpdate Nr Received (Nr: " + nNr + ")");
453     m_log.debug("IrLAPContext", "\t\tsend queue size = " + m_sendQueue.size());
454 
455     int i = 0;
456     while ( i < m_sendQueue.size() ) {
457       IrLAPFrame frame          = m_sendQueue.get(i);
458       int        sequenceNumber = frame.getSequenceNumber();
459       m_log.debug("IrLAPContext", "\t\tframe sequence number = " + frame.getSequenceNumber());
460       if ( (sequenceNumber < nNr) || ((sequenceNumber == 7) && (0 == nNr)) ) {
461         m_log.debug("IrLAPContext", "\t\tpeer acknowledges receipt of frame " + frame.getSequenceNumber() + ", removing from send buffer");
462         m_sendQueue.remove(i);
463         i --;
464       } 
465       i++;
466     }
467   }
468 
469   public void waitMinimumTurnaroundTime() throws Exception {
470     //m_log.debug("IrLAPContext", "\tWait-Minimum-Turnaround-Time");
471     //Thread.sleep(DEFAULT_MIN_TURNAROUND_MSEC);
472   }
473 
474   public void zeroRetryCount() throws Exception {
475     m_log.debug("IrLAPContext", "\tretryCount := 0");
476     m_nRetryCount = 0;
477   }
478 }