⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packetizer.java

📁 无线通信的主要编程软件,是无线通信工作人员的必备工具,关天相关教程我会在后续传上.
💻 JAVA
字号:
// $Id: Packetizer.java,v 1.14 2004/11/18 19:02:18 idgay Exp $/*									tab:4 * "Copyright (c) 2000-2003 The Regents of the University  of California.   * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. *  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Copyright (c) 2002-2003 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE      * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,  * 94704.  Attention:  Intel License Inquiry. */package net.tinyos.packet;import net.tinyos.util.*;import net.tinyos.message.*;import java.io.*;import java.util.*;/** * The Packetizer class implements the new mote-PC protocol, using * a ByteSource for low-level I/O */public class Packetizer extends AbstractSource implements Runnable {    /* Protocol inspired by, but not identical to, RFC 1663.     * There is currently no protocol establishment phase, and a single     * byte ("packet type") to identify the kind/target/etc of each packet.     *     * The protocol is really, really not aiming for high performance.     *      * There is however a hook for future extensions: implementations are     * required to answer all unknown packet types with a P_UNKNOWN packet.     *     * To summarise the protocol:     * - the two sides (A & B) are connected by a (potentially unreliable)     *   byte stream     * - the two sides exchange packets framed by 0x7e (SYNC_BYTE) bytes     * - each packet has the form     *     <packet type> <data bytes 1..n> <16-bit crc>     *   where the crc (see net.tinyos.util.Crc) covers the packet type     *   and bytes 1..n     * - bytes can be escaped by preceding them with 0x7d and their     *   value xored with 0x20; 0x7d and 0x7e bytes must be escaped,      *   0x00 - 0x1f and 0x80-0x9f may be optionally escaped     * - There are currently 5 packet types:     *   P_PACKET_NO_ACK: A user-packet, with no ack required     *   P_PACKET_ACK: A user-packet with a prefix byte, ack required.      *     The receiver must send a P_ACK packet with the prefix byte     *     as its contents.     *   P_ACK: ack for a previous P_PACKET_ACK packet     *   P_UNKNOWN: unknown packet type received. On reception of an     *     unknown packet type, the receicer must send a P_UNKNOWN packet,     *     the first byte must be the unknown packet type.     * - Packets that are greater than a (private) MTU are silently dropped.     */    final static boolean DEBUG = false;    final static int SYNC_BYTE = 0x7e;    final static int ESCAPE_BYTE = 0x7d;    final static int MTU = 256;    final static int ACK_TIMEOUT = 1000; // in milliseconds    final static int P_ACK = 64;    final static int P_PACKET_ACK = 65;    final static int P_PACKET_NO_ACK = 66;    final static int P_UNKNOWN = 255;    private ByteSource io;    private boolean inSync;    private byte[] receiveBuffer = new byte[MTU];    private int seqNo;    // Packets are received by a separate thread and placed in a    // per-packet-type queue. If received[x] is null, then x is an    // unknown protocol (but P_UNKNOWN and P_PACKET_ACK are handled    // specially)    private Thread reader;    private LinkedList[] received;    /**     * Packetizers are built using the makeXXX methods in BuildSource     */    Packetizer(String name, ByteSource io, int plat) {	super(name);	this.io = io;	platform = plat;	inSync = false;	seqNo = 13;	reader = new Thread(this);	received = new LinkedList[256];	received[P_ACK] = new LinkedList();	received[P_PACKET_NO_ACK] = new LinkedList();    }    synchronized public void open(Messenger messages) throws IOException {	super.open(messages);	reader.start();    }    protected void openSource() throws IOException {	io.open();    }    protected void closeSource() {        io.close();    }    protected byte[] readProtocolPacket(int packetType, long deadline) throws IOException {	LinkedList inPackets = received[packetType];	// Wait for a packet on inPackets	synchronized (inPackets) {	    while (inPackets.isEmpty()) {		long now = System.currentTimeMillis();		if (deadline != 0 && now >= deadline) {		    return null;		}		try {		    inPackets.wait(deadline != 0 ? deadline - now : 0);		}		catch (InterruptedException e) {		    throw new IOException("interrupted");		}	    }	    return (byte [])inPackets.removeFirst();	}    }    // Place a packet in its packet queue, or reject unknown packet    // types (which don't have a queue)    protected void pushProtocolPacket(int packetType, byte[] packet) {	LinkedList inPackets = received[packetType];	if (inPackets != null) {	    synchronized (inPackets) {		inPackets.add(packet);		inPackets.notify();	    }	}	else if (packetType != P_UNKNOWN) {	    try {		writeFramedPacket(P_UNKNOWN, packetType, ackPacket, 0);	    }	    catch (IOException e) { }	    message(name + ": ignoring unknown packet type " +		    Integer.toHexString(packetType));	}    }    protected byte[] readSourcePacket() throws IOException {	// Packetizer packet format is identical to PacketSource's	return readProtocolPacket(P_PACKET_NO_ACK, 0);    }    // Write an ack-ed packet    protected boolean writeSourcePacket(byte[] packet) throws IOException {	seqNo++;	writeFramedPacket(P_PACKET_ACK, seqNo, packet, packet.length);	long deadline = System.currentTimeMillis() + ACK_TIMEOUT;	for (;;) {	    byte[] ack = readProtocolPacket(P_ACK, deadline);	    if (ack == null) {		if (DEBUG) {		    message(name + ": ACK timed out");		}		return false;	    }	    if (ack[0] == (byte)seqNo) {		if (DEBUG) {		    message(name + ": Rcvd ACK");		}		return true;	    }	}    }    static private byte ackPacket[] = new byte[0];    public void run() {	try {	    for (;;) {		byte[] packet = readFramedPacket();		int packetType = packet[0] & 0xff;		int pdataOffset = 1;		if (packetType == P_PACKET_ACK) {		    // send ack		    writeFramedPacket(P_ACK, packet[1], ackPacket, 0);		    // And merge with un-acked packets		    packetType = P_PACKET_NO_ACK;		    pdataOffset = 2;		}		int dataLength = packet.length - pdataOffset;		byte[] dataPacket = new byte[dataLength];		System.arraycopy(packet, pdataOffset, dataPacket, 0, dataLength);		pushProtocolPacket(packetType, dataPacket);	    }	}	catch (IOException e) { }    }    // Read system-level packet. If inSync is false, we currently don't    // have sync    private byte[] readFramedPacket() throws IOException {	int count = 0;	boolean escaped = false;	for (;;) {	    if (!inSync) {		message(name + ": resynchronising");		// re-synchronise		while (io.readByte() != SYNC_BYTE)		    ;		inSync = true;		count = 0;		escaped = false;	    }	    if (count >= MTU) {		// Packet too long, give up and try to resync		message(name + ": packet too long");		inSync = false;		continue;	    }	    byte b = io.readByte();	    if (escaped) {		if (b == SYNC_BYTE) {		    // sync byte following escape is an error, resync		    message(name + ": unexpected sync byte");		    inSync = false;		    continue;		}		b ^= 0x20;		escaped = false;	    }	    else if (b == ESCAPE_BYTE) {		escaped = true;		continue;	    }	    else if (b == SYNC_BYTE) {		if (count < 4) {		    // too-small frames are ignored		    count = 0;		    continue;		}		byte[] packet = new byte[count - 2];		System.arraycopy(receiveBuffer, 0, packet, 0, count - 2);		int readCrc = (receiveBuffer[count - 2]  & 0xff) |		  (receiveBuffer[count - 1] & 0xff) << 8;		int computedCrc = Crc.calc(packet, packet.length);		if (DEBUG) {		    System.err.println("received: ");		    Dump.printPacket(System.err, packet);		    System.err.println(" rcrc: " + Integer.toHexString(readCrc) +				       " ccrc: " + Integer.toHexString(computedCrc));		}		if (readCrc == computedCrc) {		    return packet;		}		else {		    message(name + ": bad packet");		    /* We don't lose sync here. If we did, garbage on the line		       at startup will cause loss of the first packet. */		    count = 0;		    continue;		}	    }	    receiveBuffer[count++] = b;	}    }    // Class to build a framed, escaped and crced packet byte stream    static class Escaper {	byte[] escaped;	int escapePtr;	int crc;	// We're building a length-byte packet	Escaper(int length) {	    escaped = new byte[2 * length];	    escapePtr = 0;	    crc = 0;	    escaped[escapePtr++] = SYNC_BYTE;	}	static private boolean needsEscape(int b) {	    return b == SYNC_BYTE || b == ESCAPE_BYTE;	}	void nextByte(int b) {	    b = b & 0xff;	    crc = Crc.calcByte(crc, b);	    if (needsEscape(b)) {		escaped[escapePtr++] = ESCAPE_BYTE;		escaped[escapePtr++] = (byte)(b ^ 0x20);	    }	    else {		escaped[escapePtr++] = (byte)b;	    }	}	void terminate() {	    escaped[escapePtr++] = SYNC_BYTE;	}    }    // Write a packet of type 'packetType', first byte 'firstByte'    // and bytes 2..'count'+1 in 'packet'    private synchronized void writeFramedPacket(int packetType, int firstByte,						byte[] packet, int count) throws IOException {	if (DEBUG) {	    System.err.println("sending: ");	    Dump.printByte(System.err, packetType);	    Dump.printByte(System.err, firstByte);	    Dump.printPacket(System.err, packet);	    System.err.println();	}	Escaper buffer = new Escaper(count + 6);		buffer.nextByte(packetType);	buffer.nextByte(firstByte);	for (int i = 0; i < count; i++) {	    buffer.nextByte(packet[i]);	}	int crc = buffer.crc;	buffer.nextByte(crc & 0xff);	buffer.nextByte(crc >> 8);	buffer.terminate();	byte[] realPacket = new byte[buffer.escapePtr];	System.arraycopy(buffer.escaped, 0, realPacket, 0, buffer.escapePtr);	if (DEBUG) {	    Dump.dump("encoded", realPacket);	}	io.writeBytes(realPacket);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -