这段代码中和0x0ff与运算是什么意思? 获取length的原理是什么?
其中对象in如下
// read and check header
int type = in.read() & 0x0ff;
int identifier = in.read() & 0x0ff;
int length = (in.read() & 0x0ff) << 8 | (in.read() & 0x0ff);
所有的代码
/**
Reads a Radius packet from the given input stream and
creates an appropiate RadiusPacket descendant object.
Reads in all attributes and returns the object.
Decodes the encrypted fields and attributes of the packet.
@param dictionary dictionary to use for attributes
@param sharedSecret shared secret to be used to decode this packet
@param request Radius request packet if this is a response packet to be
decoded, null if this is a request packet to be decoded
@return new RadiusPacket object
@exception IOException if an IO error occurred
@exception RadiusException if the Radius packet is malformed
*/
static RadiusPacket decodePacket(Dictionary dictionary, InputStream in, String sharedSecret, RadiusPacket request)
-
IOException, RadiusException {
// check shared secret if (sharedSecret == null || sharedSecret.length() == 0) throw new RuntimeException("no shared secret has been set"); // check request authenticator if (request != null && request.getAuthenticator() == null) throw new RuntimeException("request authenticator not set"); // read and check header int type = in.read() & 0x0ff; int identifier = in.read() & 0x0ff; int length = (in.read() & 0x0ff) << 8 | (in.read() & 0x0ff); if (request != null && request.getPacketIdentifier() != identifier) throw new RadiusException("bad packet: invalid packet identifier (request: " + request.getPacketIdentifier() + ", response: " + identifier); if (length < RADIUS_HEADER_LENGTH) throw new RadiusException("bad packet: packet too short (" + length + " bytes)"); if (length > MAX_PACKET_LENGTH) throw new RadiusException("bad packet: packet too long (" + length + " bytes)"); // read rest of packet byte[] authenticator = new byte[16]; byte[] attributeData = new byte[length - RADIUS_HEADER_LENGTH]; in.read(authenticator); in.read(attributeData); // check and count attributes int pos = 0; int attributeCount = 0; while (pos < attributeData.length) { if (pos + 1 >= attributeData.length) throw new RadiusException("bad packet: attribute length mismatch"); int attributeLength = attributeData[pos + 1] & 0x0ff; if (attributeLength < 2) throw new RadiusException("bad packet: invalid attribute length"); pos += attributeLength; attributeCount++; } if (pos != attributeData.length) throw new RadiusException("bad packet: attribute length mismatch"); // create RadiusPacket object; set properties RadiusPacket rp = createRadiusPacket(type); rp.setPacketType(type); rp.setPacketIdentifier(identifier); rp.authenticator = authenticator; // load attributes pos = 0; while (pos < attributeData.length) { int attributeType = attributeData[pos] & 0x0ff; int attributeLength = attributeData[pos + 1] & 0x0ff; RadiusAttribute a = RadiusAttribute.createRadiusAttribute(dictionary, -1, attributeType); a.readAttribute(attributeData, pos, attributeLength); rp.addAttribute(a); pos += attributeLength; } // request packet? if (request == null) { // decode attributes rp.decodeRequestAttributes(sharedSecret); rp.checkRequestAuthenticator(sharedSecret, length, attributeData); } else { // response packet: check authenticator rp.checkResponseAuthenticator(sharedSecret, length, attributeData, request.getAuthenticator()); } return rp;
}
0x0ff 就是
一个数字和 0x0ff 进行与运算,则会把高8位置0,低8位保留。
回到你的程序中,通过这个函数猜测应该是解析的 RFC2866 报文:
报文格式:
根据格式, 0-7位是 CODE 信息,在你的函数中用 type 存储。(注意 type 的类型,是 int)
@brayden 提到了,
InputStream.read()
一个读一个 byte,正好是 8 位,所以,如果写byte type = in.read()
就正好了。但是 type 的类型是 int,因此我们需要处理一下。如果我们读入的是 5,那么当我们把他转换成 int 时,也应该是 5。那么需要在前面添加 0。
同理,读报文的 8-15位。
length
的值比较难读取,因为它一共16位,而in.read()
每次只能读8个字节,那么就需要读取两次,然后拼凑。方法是,先读8位,然后左移,再读8位。