001/**
002 * Copyright 2017-2020, Digi International Inc.
003 *
004 * This Source Code Form is subject to the terms of the Mozilla Public
005 * License, v. 2.0. If a copy of the MPL was not distributed with this
006 * file, you can obtain one at http://mozilla.org/MPL/2.0/.
007 *
008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 
009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 
011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
015 */
016package com.digi.xbee.api.models;
017
018import java.net.Inet4Address;
019import java.net.Inet6Address;
020import java.util.LinkedList;
021
022import com.digi.xbee.api.RemoteXBeeDevice;
023import com.digi.xbee.api.packet.APIFrameType;
024import com.digi.xbee.api.packet.XBeeAPIPacket;
025import com.digi.xbee.api.packet.XBeePacket;
026import com.digi.xbee.api.packet.common.ExplicitRxIndicatorPacket;
027import com.digi.xbee.api.packet.common.ReceivePacket;
028import com.digi.xbee.api.packet.common.RemoteATCommandResponsePacket;
029import com.digi.xbee.api.packet.ip.RXIPv4Packet;
030import com.digi.xbee.api.packet.raw.RX16IOPacket;
031import com.digi.xbee.api.packet.raw.RX16Packet;
032import com.digi.xbee.api.packet.raw.RX64IOPacket;
033import com.digi.xbee.api.packet.raw.RX64Packet;
034import com.digi.xbee.api.packet.thread.RXIPv6Packet;
035
036/**
037 * This class represents a queue of XBee packets used for sequential packets 
038 * reading within the XBee Java API. 
039 * 
040 * <p>The class provides some methods to get specific packet types from 
041 * different source nodes.</p>
042 * 
043 * @see com.digi.xbee.api.packet.XBeePacket
044 */
045public class XBeePacketsQueue {
046
047        // Constants.
048        /**
049         * Default maximum number of packets to store in the queue 
050         * (value: {@value}).
051         */
052        public static final int DEFAULT_MAX_LENGTH = 50;
053        
054        // Variables.
055        private int maxLength = DEFAULT_MAX_LENGTH;
056        
057        private LinkedList<XBeePacket> packetsList;
058        
059        private Object lock = new Object();
060        
061        /**
062         * Class constructor. Instantiates a new object of type 
063         * {@code XBeePacketsQueue}.
064         */
065        public XBeePacketsQueue() {
066                this(DEFAULT_MAX_LENGTH);
067        }
068        
069        /**
070         * Class constructor. Instantiates a new object of type 
071         * {@code XBeePacketsQueue} with the given maximum length.
072         * 
073         * @param maxLength Maximum length of the queue.
074         * 
075         * @throws IllegalArgumentException if {@code maxLength < 1}.
076         */
077        public XBeePacketsQueue(int maxLength) {
078                if (maxLength < 1)
079                        throw new IllegalArgumentException("Queue length must be greater than 0.");
080                
081                this.maxLength = maxLength;
082                packetsList = new LinkedList<XBeePacket>();
083        }
084        
085        /**
086         * Adds the provided packet to the list of packets. If the queue is full 
087         * the first packet will be discarded to add the given one.
088         * 
089         * @param xbeePacket The XBee packet to be added to the list.
090         * 
091         * @see com.digi.xbee.api.packet.XBeePacket
092         */
093        public void addPacket(XBeePacket xbeePacket) {
094                synchronized (lock) {
095                        if (packetsList.size() == maxLength)
096                                packetsList.removeFirst();
097                        packetsList.add(xbeePacket);
098                }
099        }
100        
101        /**
102         * Clears the list of packets.
103         */
104        public void clearQueue() {
105                synchronized (lock) {
106                        packetsList.clear();
107                }
108        }
109        
110        /**
111         * Returns the first packet from the queue waiting up to the specified 
112         * timeout if  necessary for an XBee packet to become available. 
113         * {@code null }if the queue is empty.
114         * 
115         * @param timeout The time in milliseconds to wait for an XBee packet to 
116         *                become available. 0 to return immediately.
117         * @return The first packet from the queue, {@code null} if it is empty.
118         * 
119         * @see com.digi.xbee.api.packet.XBeePacket
120         */
121        public XBeePacket getFirstPacket(int timeout) {
122                if (timeout > 0) {
123                        XBeePacket xbeePacket = getFirstPacket(0);
124                        // Wait for a timeout or until an XBee packet is read.
125                        Long deadLine = System.currentTimeMillis() + timeout;
126                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
127                                sleep(100);
128                                xbeePacket = getFirstPacket(0);
129                        }
130                        return xbeePacket;
131                } 
132                synchronized (lock) {
133                        if (!packetsList.isEmpty())
134                                return packetsList.pop();
135                }
136                return null;
137        }
138        
139        /**
140         * Returns the first packet from the queue whose 64-bit source address 
141         * matches the address of the provided remote XBee device.
142         * 
143         * <p>The methods waits up to the specified timeout if necessary for an 
144         * XBee packet to become available. Null if the queue is empty or there is 
145         * not any XBee packet sent by the provided remote XBee device.</p>
146         * 
147         * @param remoteXBeeDevice The remote XBee device containing the 64-bit 
148         *                         address to look for in the list of packets.
149         * @param timeout The time in milliseconds to wait for an XBee packet from 
150         *                the specified remote XBee device to become available. 
151         *                0 to return immediately.
152         * 
153         * @return The first XBee packet whose 64-bit address matches the address 
154         *         of the provided remote XBee device. {@code null} if no packets 
155         *         from the specified XBee device are found in the queue.
156         * 
157         * @see com.digi.xbee.api.RemoteXBeeDevice
158         * @see com.digi.xbee.api.packet.XBeePacket
159         */
160        public XBeePacket getFirstPacketFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) {
161                if (timeout > 0) {
162                        XBeePacket xbeePacket = getFirstPacketFrom(remoteXBeeDevice, 0);
163                        // Wait for a timeout or until an XBee packet from remoteXBeeDevice is read.
164                        Long deadLine = System.currentTimeMillis() + timeout;
165                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
166                                sleep(100);
167                                xbeePacket = getFirstPacketFrom(remoteXBeeDevice, 0);
168                        }
169                        return xbeePacket;
170                } else {
171                        synchronized (lock) {
172                                for (int i = 0; i < packetsList.size(); i++) {
173                                        XBeePacket xbeePacket = packetsList.get(i);
174                                        if (addressesMatch(xbeePacket, remoteXBeeDevice))
175                                                return packetsList.remove(i);
176                                }
177                        }
178                }
179                return null;
180        }
181        
182        /**
183         * Returns the first data packet from the queue waiting up to the 
184         * specified timeout if necessary for an XBee data packet to become 
185         * available. {@code null} if the queue is empty or there is not any data 
186         * packet inside.
187         * 
188         * @param timeout The time in milliseconds to wait for an XBee data packet 
189         *                to become available. 0 to return immediately.
190         * 
191         * @return The first data packet from the queue, {@code null} if it is 
192         *         empty or no data packets are contained in the queue.
193         * 
194         * @see com.digi.xbee.api.packet.XBeePacket
195         */
196        public XBeePacket getFirstDataPacket(int timeout) {
197                if (timeout > 0) {
198                        XBeePacket xbeePacket = getFirstDataPacket(0);
199                        // Wait for a timeout or until a data XBee packet is read.
200                        Long deadLine = System.currentTimeMillis() + timeout;
201                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
202                                sleep(100);
203                                xbeePacket = getFirstDataPacket(0);
204                        }
205                        return xbeePacket;
206                } else {
207                        synchronized (lock) {
208                                for (int i = 0; i < packetsList.size(); i++) {
209                                        XBeePacket xbeePacket = packetsList.get(i);
210                                        if (isDataPacket(xbeePacket))
211                                                return packetsList.remove(i);
212                                }
213                        }
214                }
215                return null;
216        }
217        
218        /**
219         * Returns the first data packet from the queue whose 64-bit source 
220         * address matches the address of the provided remote XBee device.
221         * 
222         * <p>The methods waits up to the specified timeout if necessary for an 
223         * XBee data packet to become available. {@code null} if the queue is 
224         * empty or there is not any XBee data packet sent by the provided remote 
225         * XBee device.</p>
226         * 
227         * @param remoteXBeeDevice The XBee device containing the 64-bit address 
228         *                         to look for in the list of packets.
229         * @param timeout The time in milliseconds to wait for an XBee data packet 
230         *                from the specified remote XBee device to become 
231         *                available. 0 to return immediately.
232         * 
233         * @return The first XBee data packet whose its 64-bit address matches the 
234         *         address of the provided remote XBee device. {@code null} if no 
235         *         data packets from the specified XBee device are found in the 
236         *         queue.
237         * 
238         * @see com.digi.xbee.api.RemoteXBeeDevice
239         * @see com.digi.xbee.api.packet.XBeePacket
240         */
241        public XBeePacket getFirstDataPacketFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) {
242                if (timeout > 0) {
243                        XBeePacket xbeePacket = getFirstDataPacketFrom(remoteXBeeDevice, 0);
244                        // Wait for a timeout or until an XBee packet from remoteXBeeDevice is read.
245                        Long deadLine = System.currentTimeMillis() + timeout;
246                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
247                                sleep(100);
248                                xbeePacket = getFirstDataPacketFrom(remoteXBeeDevice, 0);
249                        }
250                        return xbeePacket;
251                } else {
252                        synchronized (lock) {
253                                for (int i = 0; i < packetsList.size(); i++) {
254                                        XBeePacket xbeePacket = packetsList.get(i);
255                                        if (isDataPacket(xbeePacket) && addressesMatch(xbeePacket, remoteXBeeDevice))
256                                                return packetsList.remove(i);
257                                }
258                        }
259                }
260                return null;
261        }
262        
263        /**
264         * Returns the first explicit data packet from the queue waiting up to the 
265         * specified timeout if necessary for an XBee explicit data packet to 
266         * become available. {@code null} if the queue is empty or there is not 
267         * any explicit data packet inside.
268         * 
269         * @param timeout The time in milliseconds to wait for an XBee explicit 
270         *                data packet to become available. 0 to return immediately.
271         * 
272         * @return The first explicit data packet from the queue, {@code null} if 
273         *         it is empty or no data packets are contained in the queue.
274         * 
275         * @see com.digi.xbee.api.packet.XBeePacket
276         * @see com.digi.xbee.api.packet.common.ExplicitRxIndicatorPacket
277         */
278        public XBeePacket getFirstExplicitDataPacket(int timeout) {
279                if (timeout > 0) {
280                        XBeePacket xbeePacket = getFirstExplicitDataPacket(0);
281                        // Wait for a timeout or until an explicit data XBee packet is read.
282                        Long deadLine = System.currentTimeMillis() + timeout;
283                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
284                                sleep(100);
285                                xbeePacket = getFirstExplicitDataPacket(0);
286                        }
287                        return xbeePacket;
288                } else {
289                        synchronized (lock) {
290                                for (int i = 0; i < packetsList.size(); i++) {
291                                        XBeePacket xbeePacket = packetsList.get(i);
292                                        if (isExplicitDataPacket(xbeePacket))
293                                                return packetsList.remove(i);
294                                }
295                        }
296                }
297                return null;
298        }
299        
300        /**
301         * Returns the first explicit data packet from the queue whose 64-bit 
302         * source address matches the address of the provided remote XBee device.
303         * 
304         * <p>The methods waits up to the specified timeout if necessary for an 
305         * XBee explicit data packet to become available. {@code null} if the 
306         * queue is empty or there is not any XBee explicit data packet sent by 
307         * the provided remote XBee device.</p>
308         * 
309         * @param remoteXBeeDevice The XBee device containing the 64-bit address 
310         *                         to look for in the list of packets.
311         * @param timeout The time in milliseconds to wait for an XBee explicit 
312         *                data packet from the specified remote XBee device to 
313         *                become available. 0 to return immediately.
314         * 
315         * @return The first XBee explicit data packet whose its 64-bit address 
316         *         matches the address of the provided remote XBee device. 
317         *         {@code null} if no explicit data packets from the specified 
318         *         XBee device are found in the queue.
319         * 
320         * @see com.digi.xbee.api.RemoteXBeeDevice
321         * @see com.digi.xbee.api.packet.XBeePacket
322         * @see com.digi.xbee.api.packet.common.ExplicitRxIndicatorPacket
323         */
324        public XBeePacket getFirstExplicitDataPacketFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) {
325                if (timeout > 0) {
326                        XBeePacket xbeePacket = getFirstExplicitDataPacketFrom(remoteXBeeDevice, 0);
327                        // Wait for a timeout or until an XBee explicit data packet from remoteXBeeDevice is read.
328                        Long deadLine = System.currentTimeMillis() + timeout;
329                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
330                                sleep(100);
331                                xbeePacket = getFirstExplicitDataPacketFrom(remoteXBeeDevice, 0);
332                        }
333                        return xbeePacket;
334                } else {
335                        synchronized (lock) {
336                                for (int i = 0; i < packetsList.size(); i++) {
337                                        XBeePacket xbeePacket = packetsList.get(i);
338                                        if (isExplicitDataPacket(xbeePacket) && addressesMatch(xbeePacket, remoteXBeeDevice))
339                                                return packetsList.remove(i);
340                                }
341                        }
342                }
343                return null;
344        }
345        
346        /**
347         * Returns the first IP data packet from the queue waiting up to the 
348         * specified timeout if necessary for a IP data packet to 
349         * become available. {@code null} if the queue is empty or there is not 
350         * any IP data packet inside.
351         * 
352         * @param timeout The time in milliseconds to wait for a IP data 
353         *                packet to become available. 0 to return immediately.
354         * 
355         * @return The first IP data packet from the queue, {@code null} if 
356         *         it is empty or no IP packets are contained in the queue.
357         * 
358         * @see com.digi.xbee.api.packet.XBeePacket
359         * @see com.digi.xbee.api.packet.ip.RXIPv4Packet
360         * 
361         * @since 1.2.0
362         */
363        public XBeePacket getFirstIPDataPacket(int timeout) {
364                if (timeout > 0) {
365                        XBeePacket xbeePacket = getFirstIPDataPacket(0);
366                        // Wait for a timeout or until a IP data packet is read.
367                        Long deadLine = System.currentTimeMillis() + timeout;
368                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
369                                sleep(100);
370                                xbeePacket = getFirstIPDataPacket(0);
371                        }
372                        return xbeePacket;
373                } else {
374                        synchronized (lock) {
375                                for (int i = 0; i < packetsList.size(); i++) {
376                                        XBeePacket xbeePacket = packetsList.get(i);
377                                        if (isIPDataPacket(xbeePacket))
378                                                return packetsList.remove(i);
379                                }
380                        }
381                }
382                return null;
383        }
384        
385        /**
386         * Returns the first IPv6 data packet from the queue waiting up to the 
387         * specified timeout if necessary for a IPv6 data packet to 
388         * become available. {@code null} if the queue is empty or there is not 
389         * any IPv6 data packet inside.
390         * 
391         * @param timeout The time in milliseconds to wait for a IPv6 data 
392         *                packet to become available. 0 to return immediately.
393         * 
394         * @return The first IPv6 data packet from the queue, {@code null} if 
395         *         it is empty or no IPv6 packets are contained in the queue.
396         * 
397         * @see com.digi.xbee.api.packet.XBeePacket
398         * @see com.digi.xbee.api.packet.thread.RXIPv6Packet
399         * 
400         * @since 1.2.1
401         */
402        public XBeePacket getFirstIPv6DataPacket(int timeout) {
403                if (timeout > 0) {
404                        XBeePacket xbeePacket = getFirstIPv6DataPacket(0);
405                        // Wait for a timeout or until a IPv6 data packet is read.
406                        Long deadLine = System.currentTimeMillis() + timeout;
407                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
408                                sleep(100);
409                                xbeePacket = getFirstIPv6DataPacket(0);
410                        }
411                        return xbeePacket;
412                } else {
413                        synchronized (lock) {
414                                for (int i = 0; i < packetsList.size(); i++) {
415                                        XBeePacket xbeePacket = packetsList.get(i);
416                                        if (isIPv6DataPacket(xbeePacket))
417                                                return packetsList.remove(i);
418                                }
419                        }
420                }
421                return null;
422        }
423        
424        /**
425         * Returns the first IP data packet from the queue whose IP address 
426         * matches the provided address.
427         * 
428         * <p>The methods waits up to the specified timeout if necessary for a 
429         * IP data packet to become available. {@code null} if the 
430         * queue is empty or there is not any IP data packet sent by 
431         * the provided IP address.</p>
432         * 
433         * @param ipAddress The IP address to look for in the list of packets.
434         * @param timeout The time in milliseconds to wait for a IP data 
435         *                packet from the specified IP address to become available.
436         *                0 to return immediately.
437         * 
438         * @return The first IP packet whose IP address matches the provided 
439         *         IP address. {@code null} if no IP data packets from the 
440         *         specified IP address are found in the queue.
441         * 
442         * @see com.digi.xbee.api.packet.XBeePacket
443         * @see com.digi.xbee.api.packet.ip.RXIPv4Packet
444         * @see java.net.Inet4Address
445         * 
446         * @since 1.2.0
447         */
448        public XBeePacket getFirstIPDataPacketFrom(Inet4Address ipAddress, int timeout) {
449                if (timeout > 0) {
450                        XBeePacket xbeePacket = getFirstIPDataPacketFrom(ipAddress, 0);
451                        // Wait for a timeout or until a IP data packet with the provided IP address is read.
452                        Long deadLine = System.currentTimeMillis() + timeout;
453                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
454                                sleep(100);
455                                xbeePacket = getFirstIPDataPacketFrom(ipAddress, 0);
456                        }
457                        return xbeePacket;
458                } else {
459                        synchronized (lock) {
460                                for (int i = 0; i < packetsList.size(); i++) {
461                                        XBeePacket xbeePacket = packetsList.get(i);
462                                        if (isIPDataPacket(xbeePacket) && ipAddressesMatch(xbeePacket, ipAddress))
463                                                return packetsList.remove(i);
464                                }
465                        }
466                }
467                return null;
468        }
469        
470        /**
471         * Returns the first IPv6 data packet from the queue whose IPv6 address 
472         * matches the provided address.
473         * 
474         * <p>The methods waits up to the specified timeout if necessary for a 
475         * IPv6 data packet to become available. {@code null} if the 
476         * queue is empty or there is not any IPv6 data packet sent by 
477         * the provided IPv6 address.</p>
478         * 
479         * @param ipv6Address The IPv6 address to look for in the list of packets.
480         * @param timeout The time in milliseconds to wait for a IPv6 data 
481         *                packet from the specified IPv6 address to become available.
482         *                0 to return immediately.
483         * 
484         * @return The first IPv6 packet whose IPv6 address matches the provided 
485         *         IPv6 address. {@code null} if no IPv6 data packets from the 
486         *         specified IPv6 address are found in the queue.
487         * 
488         * @see com.digi.xbee.api.packet.XBeePacket
489         * @see com.digi.xbee.api.packet.thread.RXIPv6Packet
490         * @see java.net.Inet6Address
491         * 
492         * @since 1.2.1
493         */
494        public XBeePacket getFirstIPv6DataPacketFrom(Inet6Address ipv6Address, int timeout) {
495                if (timeout > 0) {
496                        XBeePacket xbeePacket = getFirstIPv6DataPacketFrom(ipv6Address, 0);
497                        // Wait for a timeout or until a IPv6 data packet with the provided IPv6 address is read.
498                        Long deadLine = System.currentTimeMillis() + timeout;
499                        while (xbeePacket == null && deadLine > System.currentTimeMillis()) {
500                                sleep(100);
501                                xbeePacket = getFirstIPv6DataPacketFrom(ipv6Address, 0);
502                        }
503                        return xbeePacket;
504                } else {
505                        synchronized (lock) {
506                                for (int i = 0; i < packetsList.size(); i++) {
507                                        XBeePacket xbeePacket = packetsList.get(i);
508                                        if (isIPv6DataPacket(xbeePacket) && ipv6AddressesMatch(xbeePacket, ipv6Address))
509                                                return packetsList.remove(i);
510                                }
511                        }
512                }
513                return null;
514        }
515        
516        /**
517         * Returns whether or not the source address of the provided XBee packet 
518         * matches the address of the given remote XBee device.
519         * 
520         * @param xbeePacket The XBee packet to compare its address with the 
521         *                   remote XBee device.
522         * @param remoteXBeeDevice The remote XBee device to compare its address 
523         *                         with the XBee packet.
524         * 
525         * @return {@code true} if the source address of the provided packet (if 
526         *         it has) matches the address of the remote XBee device.
527         * 
528         * @see com.digi.xbee.api.RemoteXBeeDevice
529         * @see com.digi.xbee.api.packet.XBeePacket
530         */
531        private boolean addressesMatch(XBeePacket xbeePacket, RemoteXBeeDevice remoteXBeeDevice) {
532                if (!(xbeePacket instanceof XBeeAPIPacket))
533                        return false;
534                APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType();
535                switch (packetType) {
536                case RECEIVE_PACKET:
537                        if (remoteXBeeDevice.get64BitAddress() != null
538                                        && ((ReceivePacket)xbeePacket).get64bitSourceAddress().equals(remoteXBeeDevice.get64BitAddress()))
539                                return true;
540                        if (remoteXBeeDevice.get16BitAddress() != null
541                                        && !remoteXBeeDevice.get16BitAddress().equals(XBee16BitAddress.UNKNOWN_ADDRESS)
542                                        && ((ReceivePacket)xbeePacket).get16bitSourceAddress().equals(remoteXBeeDevice.get16BitAddress()))
543                                return true;
544                        break;
545                case REMOTE_AT_COMMAND_RESPONSE:
546                        if (remoteXBeeDevice.get64BitAddress() != null
547                                        && ((RemoteATCommandResponsePacket)xbeePacket).get64bitSourceAddress().equals(remoteXBeeDevice.get64BitAddress()))
548                                return true;
549                        if (remoteXBeeDevice.get16BitAddress() != null
550                                        && !remoteXBeeDevice.get16BitAddress().equals(XBee16BitAddress.UNKNOWN_ADDRESS)
551                                        && ((RemoteATCommandResponsePacket)xbeePacket).get16bitSourceAddress().equals(remoteXBeeDevice.get16BitAddress()))
552                                return true;
553                        break;
554                case RX_16:
555                        if (((RX16Packet)xbeePacket).get16bitSourceAddress().equals(remoteXBeeDevice.get16BitAddress()))
556                                return true;
557                        break;
558                case RX_64:
559                        if (((RX64Packet)xbeePacket).get64bitSourceAddress().equals(remoteXBeeDevice.get64BitAddress()))
560                                return true;
561                        break;
562                case RX_IO_16:
563                        if (((RX16IOPacket)xbeePacket).get16bitSourceAddress().equals(remoteXBeeDevice.get16BitAddress()))
564                                return true;
565                        break;
566                case RX_IO_64:
567                        if (((RX64IOPacket)xbeePacket).get64bitSourceAddress().equals(remoteXBeeDevice.get64BitAddress()))
568                                return true;
569                        break;
570                case EXPLICIT_RX_INDICATOR:
571                        if (((ExplicitRxIndicatorPacket)xbeePacket).get64BitSourceAddress().equals(remoteXBeeDevice.get64BitAddress()))
572                                return true;
573                        break;
574                default:
575                        return false;
576                }
577                return false;
578        }
579        
580        /**
581         * Returns whether or not the IP address of the XBee packet matches the 
582         * provided one. 
583         * 
584         * @param xbeePacket The XBee packet to compare its IP address with the 
585         *                   provided one.
586         * @param ipAddress The IP address to be compared with the XBee packet's one.
587         * 
588         * @return {@code true} if the IP address of the XBee packet (if it has) 
589         *         matches the provided one. {@code false} otherwise.
590         * 
591         * @see com.digi.xbee.api.packet.XBeePacket
592         * @see java.net.Inet4Address
593         * 
594         * @since 1.2.0
595         */
596        private boolean ipAddressesMatch(XBeePacket xbeePacket, Inet4Address ipAddress) {
597                if (xbeePacket == null || ipAddress == null 
598                                || !(xbeePacket instanceof XBeeAPIPacket))
599                        return false;
600                APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType();
601                switch (packetType) {
602                case RX_IPV4:
603                        if (((RXIPv4Packet)xbeePacket).getSourceAddress().equals(ipAddress))
604                                return true;
605                        break;
606                default:
607                        return false;
608                }
609                return false;
610        }
611        
612        /**
613         * Returns whether the IPv6 address of the XBee packet matches the 
614         * provided one or not. 
615         * 
616         * @param xbeePacket The XBee packet to compare its IPv6 address with the 
617         *                   provided one.
618         * @param ipv6Address The IPv6 address to be compared with the XBee 
619         *                    packet's one.
620         * 
621         * @return {@code true} if the Iv6P address of the XBee packet (if it has) 
622         *         matches the provided one. {@code false} otherwise.
623         * 
624         * @see com.digi.xbee.api.packet.XBeePacket
625         * @see java.net.Inet6Address
626         * 
627         * @since 1.2.1
628         */
629        private boolean ipv6AddressesMatch(XBeePacket xbeePacket, Inet6Address ipv6Address) {
630                if (xbeePacket == null || ipv6Address == null 
631                                || !(xbeePacket instanceof XBeeAPIPacket))
632                        return false;
633                APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType();
634                switch (packetType) {
635                case RX_IPV6:
636                        if (((RXIPv6Packet)xbeePacket).getSourceAddress().equals(ipv6Address))
637                                return true;
638                        break;
639                default:
640                        return false;
641                }
642                return false;
643        }
644        
645        /**
646         * Returns whether or not the given XBee packet is a data packet.
647         * 
648         * @param xbeePacket The XBee packet to check if is data packet.
649         * 
650         * @return {@code true} if the XBee packet is a data packet, {@code false} 
651         *         otherwise.
652         * 
653         * @see com.digi.xbee.api.packet.XBeePacket
654         */
655        private boolean isDataPacket(XBeePacket xbeePacket) {
656                if (!(xbeePacket instanceof XBeeAPIPacket))
657                        return false;
658                APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType();
659                switch (packetType) {
660                        case RECEIVE_PACKET:
661                        case RX_16:
662                        case RX_64:
663                                return true;
664                        default:
665                                return false;
666                }
667        }
668        
669        /**
670         * Returns whether or not the given XBee packet is an explicit data packet.
671         * 
672         * @param xbeePacket The XBee packet to check if is an explicit data packet.
673         * 
674         * @return {@code true} if the XBee packet is an explicit data packet, 
675         *         {@code false} otherwise.
676         * 
677         * @see com.digi.xbee.api.packet.XBeePacket
678         * @see com.digi.xbee.api.packet.common.ExplicitRxIndicatorPacket
679         */
680        private boolean isExplicitDataPacket(XBeePacket xbeePacket) {
681                if (!(xbeePacket instanceof XBeeAPIPacket))
682                        return false;
683                APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType();
684                return packetType == APIFrameType.EXPLICIT_RX_INDICATOR;
685        }
686        
687        /**
688         * Returns whether or not the given XBee packet is a IP data packet.
689         * 
690         * @param xbeePacket The XBee packet to check if is a IP data packet.
691         * 
692         * @return {@code true} if the XBee packet is a IP data packet, 
693         *         {@code false} otherwise.
694         * 
695         * @see com.digi.xbee.api.packet.XBeePacket
696         * @see com.digi.xbee.api.packet.ip.RXIPv4Packet
697         * 
698         * @since 1.2.0
699         */
700        private boolean isIPDataPacket(XBeePacket xbeePacket) {
701                if (!(xbeePacket instanceof XBeeAPIPacket))
702                        return false;
703                APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType();
704                return packetType == APIFrameType.RX_IPV4;
705        }
706        
707        /**
708         * Returns whether the given XBee packet is an IPv6 data packet or not.
709         * 
710         * @param xbeePacket The XBee packet to check if is an IPv6 data packet.
711         * 
712         * @return {@code true} if the XBee packet is an IPv6 data packet, 
713         *         {@code false} otherwise.
714         * 
715         * @see com.digi.xbee.api.packet.XBeePacket
716         * @see com.digi.xbee.api.packet.thread.RXIPv6Packet
717         * 
718         * @since 1.2.1
719         */
720        private boolean isIPv6DataPacket(XBeePacket xbeePacket) {
721                if (!(xbeePacket instanceof XBeeAPIPacket))
722                        return false;
723                APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType();
724                return packetType == APIFrameType.RX_IPV6;
725        }
726        
727        /**
728         * Sleeps the thread for the given number of milliseconds.
729         * 
730         * @param milliseconds The number of milliseconds that the thread should 
731         *        be sleeping.
732         */
733        private void sleep(int milliseconds) {
734                try {
735                        Thread.sleep(milliseconds);
736                } catch (InterruptedException e) { }
737        }
738        
739        /**
740         * Returns the maximum size of the XBee packets queue.
741         * 
742         * @return The maximum size of the XBee packets queue.
743         */
744        public int getMaxSize() {
745                return maxLength;
746        }
747        
748        /**
749         * Returns the current size of the XBee packets queue.
750         * 
751         * @return The current size of the XBee packets queue.
752         */
753        public int getCurrentSize() {
754                synchronized (lock) {
755                        return packetsList.size();
756                }
757        }
758}