Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/issue 388 #408

Merged
merged 9 commits into from Mar 10, 2017
@@ -1,8 +1,12 @@
package com.smartdevicelink.protocol;

import android.util.Log;

import com.smartdevicelink.util.BitConverter;

public class BinaryFrameHeader {
private static final String TAG = "BinaryFrameHeader";

private byte _rpcType;
private int _functionID;
private int _correlationID;
Expand All @@ -27,19 +31,24 @@ public static BinaryFrameHeader parseBinaryHeader(byte[] binHeader) {

int _jsonSize = BitConverter.intFromByteArray(binHeader, 8);
msg.setJsonSize(_jsonSize);

if (_jsonSize > 0) {
byte[] _jsonData = new byte[_jsonSize];
System.arraycopy(binHeader, 12, _jsonData, 0, _jsonSize);
msg.setJsonData(_jsonData);

try {
if (_jsonSize > 0) {
byte[] _jsonData = new byte[_jsonSize];
System.arraycopy(binHeader, 12, _jsonData, 0, _jsonSize);
msg.setJsonData(_jsonData);
}

if (binHeader.length - _jsonSize - 12 > 0) {
byte[] _bulkData = new byte[binHeader.length - _jsonSize - 12];
System.arraycopy(binHeader, 12 + _jsonSize, _bulkData, 0, _bulkData.length);
msg.setBulkData(_bulkData);
}
} catch (OutOfMemoryError e){
Log.e(TAG, "Unable to process data to form header");
return null;
}

if (binHeader.length - _jsonSize - 12 > 0) {
byte[] _bulkData = new byte[binHeader.length - _jsonSize - 12];
System.arraycopy(binHeader, 12 + _jsonSize, _bulkData, 0, _bulkData.length);
msg.setBulkData(_bulkData);
}

return msg;
}

Expand Down
@@ -0,0 +1,239 @@
package com.smartdevicelink.protocol;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import junit.framework.Assert;

import com.smartdevicelink.protocol.IProtocolListener;
import com.smartdevicelink.protocol.ProtocolMessage;
import com.smartdevicelink.protocol.SdlPacket;
import com.smartdevicelink.protocol.WiProProtocol;
import com.smartdevicelink.protocol.WiProProtocol.MessageFrameAssembler;
import com.smartdevicelink.protocol.enums.MessageType;
import com.smartdevicelink.protocol.enums.SessionType;
import com.smartdevicelink.test.SampleRpc;
import com.smartdevicelink.util.DebugTool;

import android.test.AndroidTestCase;
import android.util.Log;

public class WiProProtocolTests extends AndroidTestCase {

IProtocolListener defaultListener = new IProtocolListener(){
@Override
public void onProtocolMessageBytesToSend(SdlPacket packet) {}
@Override
public void onProtocolMessageReceived(ProtocolMessage msg) {}
@Override
public void onProtocolSessionStarted(SessionType sessionType,byte sessionID, byte version, String correlationID, int hashID,boolean isEncrypted){}
@Override
public void onProtocolSessionNACKed(SessionType sessionType,byte sessionID, byte version, String correlationID) {}
@Override
public void onProtocolSessionEnded(SessionType sessionType,byte sessionID, String correlationID) {}
@Override
public void onProtocolSessionEndedNACKed(SessionType sessionType,byte sessionID, String correlationID) {}
@Override
public void onProtocolHeartbeat(SessionType sessionType, byte sessionID) {}
@Override
public void onProtocolHeartbeatACK(SessionType sessionType,byte sessionID) {}
@Override
public void onProtocolServiceDataACK(SessionType sessionType,int dataSize, byte sessionID) {}
@Override
public void onResetOutgoingHeartbeat(SessionType sessionType,byte sessionID) {}
@Override
public void onResetIncomingHeartbeat(SessionType sessionType,byte sessionID) {}
@Override
public void onProtocolError(String info, Exception e) {}
};
public static class DidReceiveListener implements IProtocolListener{
boolean didReceive = false;

public void reset(){
didReceive = false;
}
public boolean didReceive(){
return didReceive;
}
@Override
public void onProtocolMessageBytesToSend(SdlPacket packet) {}
@Override
public void onProtocolMessageReceived(ProtocolMessage msg) {
didReceive = true;
Log.d("DidReceiveListener", "RPC Type: " + msg.getRPCType());
Log.d("DidReceiveListener", "Function Id: " + msg.getFunctionID());
Log.d("DidReceiveListener", "JSON Size: " + msg.getJsonSize());
}
@Override
public void onProtocolSessionStarted(SessionType sessionType,byte sessionID, byte version, String correlationID, int hashID,boolean isEncrypted){}
@Override
public void onProtocolSessionNACKed(SessionType sessionType,byte sessionID, byte version, String correlationID) {}
@Override
public void onProtocolSessionEnded(SessionType sessionType,byte sessionID, String correlationID) {}
@Override
public void onProtocolSessionEndedNACKed(SessionType sessionType,byte sessionID, String correlationID) {}
@Override
public void onProtocolHeartbeat(SessionType sessionType, byte sessionID) {}
@Override
public void onProtocolHeartbeatACK(SessionType sessionType,byte sessionID) {}
@Override
public void onProtocolServiceDataACK(SessionType sessionType,int dataSize, byte sessionID) {}
@Override
public void onResetOutgoingHeartbeat(SessionType sessionType,byte sessionID) {}
@Override
public void onResetIncomingHeartbeat(SessionType sessionType,byte sessionID) {}
@Override
public void onProtocolError(String info, Exception e) {}
};
DidReceiveListener onProtocolMessageReceivedListener = new DidReceiveListener();

public void testBase(){
WiProProtocol wiProProtocol = new WiProProtocol(defaultListener);

}

public void testVersion(){
WiProProtocol wiProProtocol = new WiProProtocol(defaultListener);

wiProProtocol.setVersion((byte)0x01);
assertEquals((byte)0x01,wiProProtocol.getVersion());

wiProProtocol = new WiProProtocol(defaultListener);
wiProProtocol.setVersion((byte)0x02);
assertEquals((byte)0x02,wiProProtocol.getVersion());

wiProProtocol = new WiProProtocol(defaultListener);
wiProProtocol.setVersion((byte)0x03);
assertEquals((byte)0x03,wiProProtocol.getVersion());

wiProProtocol = new WiProProtocol(defaultListener);
wiProProtocol.setVersion((byte)0x04);
assertEquals((byte)0x04,wiProProtocol.getVersion());

//If we get newer than 4, it should fall back to 4
wiProProtocol = new WiProProtocol(defaultListener);
wiProProtocol.setVersion((byte)0x05);
assertEquals((byte)0x04,wiProProtocol.getVersion());

//Is this right?
wiProProtocol = new WiProProtocol(defaultListener);
wiProProtocol.setVersion((byte)0x00);
assertEquals((byte)0x01,wiProProtocol.getVersion());
}

public void testMtu(){
WiProProtocol wiProProtocol = new WiProProtocol(defaultListener);

wiProProtocol.setVersion((byte)0x01);

try{
Field field = wiProProtocol.getClass().getDeclaredField("MAX_DATA_SIZE");
field.setAccessible(true);
int mtu = (Integer) field.get(wiProProtocol);
assertEquals(mtu, 1500-8);
//Ok our reflection works we can test the rest of the cases

//Version 2
wiProProtocol.setVersion((byte)0x02);
mtu = (Integer) field.get(wiProProtocol);
assertEquals(mtu, 1500-12);

//Version 3
wiProProtocol.setVersion((byte)0x03);
mtu = (Integer) field.get(wiProProtocol);
assertEquals(mtu, 131072);

//Version 4
wiProProtocol.setVersion((byte)0x04);
mtu = (Integer) field.get(wiProProtocol);
assertEquals(mtu, 131072);

//Version 4+
wiProProtocol.setVersion((byte)0x05);
mtu = (Integer) field.get(wiProProtocol);
assertEquals(mtu, 1500-12);

}catch(Exception e){
Assert.fail("Exceptin during reflection");
}

}

public void testHandleFrame(){
SampleRpc sampleRpc = new SampleRpc(4);
WiProProtocol wiProProtocol = new WiProProtocol(defaultListener);
MessageFrameAssembler assembler = wiProProtocol.new MessageFrameAssembler();
try{
assembler.handleFrame(sampleRpc.toSdlPacket());
}catch(Exception e){
Assert.fail("Exceptin during handleFrame - " + e.toString());
}
}
public void testHandleFrameCorrupt(){
SampleRpc sampleRpc = new SampleRpc(4);
BinaryFrameHeader header = sampleRpc.getBinaryFrameHeader(true);
header.setJsonSize(Integer.MAX_VALUE);
sampleRpc.setBinaryFrameHeader(header);
WiProProtocol wiProProtocol = new WiProProtocol(defaultListener);
MessageFrameAssembler assembler = wiProProtocol.new MessageFrameAssembler();
try{
assembler.handleFrame(sampleRpc.toSdlPacket());
}catch(Exception e){
Assert.fail("Exceptin during handleFrame - " + e.toString());
}
}

public void testHandleSingleFrameMessageFrame(){
SampleRpc sampleRpc = new SampleRpc(4);
WiProProtocol wiProProtocol = new WiProProtocol(defaultListener);
MessageFrameAssembler assembler = wiProProtocol.new MessageFrameAssembler();


try{
Method method = assembler.getClass().getDeclaredMethod ("handleSingleFrameMessageFrame", SdlPacket.class);
method.setAccessible(true);
method.invoke (assembler, sampleRpc.toSdlPacket());
}catch(Exception e){
Assert.fail("Exceptin during handleSingleFrameMessageFrame - " + e.toString());
}
}

public void testHandleSingleFrameMessageFrameCorruptBfh(){
SampleRpc sampleRpc = new SampleRpc(4);

//Create a corrupted header
BinaryFrameHeader header = sampleRpc.getBinaryFrameHeader(true);
header.setJsonSize(5);
header.setJsonData(new byte[5]);
header.setJsonSize(Integer.MAX_VALUE);
sampleRpc.setBinaryFrameHeader(header);

SdlPacket packet = sampleRpc.toSdlPacket();

BinaryFrameHeader binFrameHeader = BinaryFrameHeader.parseBinaryHeader(packet.payload);
assertNull(binFrameHeader);

WiProProtocol wiProProtocol = new WiProProtocol(onProtocolMessageReceivedListener);


wiProProtocol.handlePacketReceived(packet);
assertFalse(onProtocolMessageReceivedListener.didReceive());

onProtocolMessageReceivedListener.reset();
MessageFrameAssembler assembler =wiProProtocol.getFrameAssemblerForFrame(packet);// wiProProtocol.new MessageFrameAssembler();
assertNotNull(assembler);
assembler.handleFrame(packet);
assertFalse(onProtocolMessageReceivedListener.didReceive());

try{
Method method = assembler.getClass().getDeclaredMethod("handleSingleFrameMessageFrame", SdlPacket.class);
method.setAccessible(true);
method.invoke (assembler, sampleRpc.toSdlPacket());
}catch(Exception e){
Assert.fail("Exceptin during handleSingleFrameMessageFrame - " + e.toString());
}
}



}
90 changes: 90 additions & 0 deletions sdl_android_tests/src/com/smartdevicelink/test/SampleRpc.java
@@ -0,0 +1,90 @@
package com.smartdevicelink.test;

import com.smartdevicelink.marshal.JsonRPCMarshaller;
import com.smartdevicelink.protocol.BinaryFrameHeader;
import com.smartdevicelink.protocol.ProtocolMessage;
import com.smartdevicelink.protocol.SdlPacket;
import com.smartdevicelink.protocol.SdlPacketFactory;
import com.smartdevicelink.protocol.enums.FunctionID;
import com.smartdevicelink.protocol.enums.MessageType;
import com.smartdevicelink.protocol.enums.SessionType;
import com.smartdevicelink.proxy.rpc.GetVehicleData;

public class SampleRpc {


private final int SAMPLE_RPC_CORRELATION_ID = 630;

int version = 1;
int sessionId =1;
ProtocolMessage pm = null;
BinaryFrameHeader binFrameHeader = null;

/**
* Currently builds a GetVehicleData Request
*/
public SampleRpc(int version){
this.version = version;
createBase();

}
public void createBase(){
GetVehicleData request = new GetVehicleData();
request.setAirbagStatus(true);
request.setBeltStatus(true);
request.setBeltStatus(true);
request.setCorrelationID(SAMPLE_RPC_CORRELATION_ID);

byte[] msgBytes = JsonRPCMarshaller.marshall(request, (byte)version);
pm = new ProtocolMessage();
pm.setData(msgBytes);
pm.setSessionID((byte)sessionId);
pm.setMessageType(MessageType.RPC);
pm.setSessionType(SessionType.RPC);
pm.setFunctionID(FunctionID.getFunctionId(request.getFunctionName()));
pm.setCorrID(request.getCorrelationID());

if (request.getBulkData() != null) {
pm.setBulkData(request.getBulkData());
}

}
public ProtocolMessage getProtocolMessage(){
return pm;
}
public BinaryFrameHeader getBinaryFrameHeader(boolean refresh){
if(version>1 && (refresh || binFrameHeader == null)){
binFrameHeader = SdlPacketFactory.createBinaryFrameHeader(pm.getRPCType(), pm.getFunctionID(), pm.getCorrID(), pm.getJsonSize());
}
return binFrameHeader;
}

/**
* To manually set the bfh. Useful for trying to corrupt data
*/
public void setBinaryFrameHeader(BinaryFrameHeader binFrameHeader){
this.binFrameHeader = binFrameHeader;
}


public SdlPacket toSdlPacket(){
byte[] data = null;
if(version > 1) { //If greater than v1 we need to include a binary frame header in the data before all the JSON starts
data = new byte[12 + pm.getJsonSize()];
if(binFrameHeader == null){
getBinaryFrameHeader(false);
}
System.arraycopy(binFrameHeader.assembleHeaderBytes(), 0, data, 0, 12);
System.arraycopy(pm.getData(), 0, data, 12, pm.getJsonSize());
}else{
data = pm.getData();
}

return new SdlPacket(version,false,SdlPacket.FRAME_TYPE_SINGLE,SdlPacket.SERVICE_TYPE_RPC,0,sessionId,data.length,123,data);

}

public byte[] toByteArray(){
return toSdlPacket().constructPacket();
}
}