Newer
Older
package org.etsi.its.adapter.layers;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.TimeoutException;
import org.etsi.adapter.TERFactory;
import org.etsi.common.ByteHelper;
import org.etsi.its.adapter.IManagementLayers;
import org.etsi.its.adapter.PcapMultiplexer;
import com.commsignia.v2x.client.ITSApplication;
import com.commsignia.v2x.client.MessageSet;
import com.commsignia.v2x.client.exception.ClientException;
import com.commsignia.v2x.client.model.BTPType;
import com.commsignia.v2x.client.model.InjectData;
import com.commsignia.v2x.client.model.InjectData.Builder;
import com.commsignia.v2x.client.model.InjectData.Type;
import com.commsignia.v2x.client.model.dev.DeviceInfoResponse;
import com.commsignia.v2x.client.model.dev.FacilityModule;
public class CommsigniaLayer extends Layer implements IEthernetSpecific {
private static final byte[] DeviceMacAddress = new byte[] { (byte)0x70, (byte)0xb3, (byte)0xd5, (byte)0xf2, (byte)0xa1, (byte)0xe3 };
private static final String TargetHost = "172.17.15.38";
private static final int TargetPort = 7942;
private static final int SourcePort = 7943;
private static final int ItsAid = 5;
private static final int TxPowerDbm = -10; // Max value: -33dBm, RSU: -30dBm, Lab: -10dBm
private static String pcapFilter = null;
/**
* Well-known Ethernet broadcast address
*/
public static byte[] MAC_BROADCAST = new byte[]{(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
/**
* Parameter name for Link-Layer destination
*/
public static final String LINK_LAYER_DESTINATION = "LinkLayerDestination";
private Map<String, byte[]> ClientsToMacs = new HashMap<String, byte[]>();
private Map<String, Short> ClientsToFrameTypes = new HashMap<String, Short>();
private HashMap<String, Layer> ClientsToLayers = new HashMap<String, Layer>();
/**
* Constructor
* @param management Layer management instance
* @param lowerStack Lower protocol stack
*/
public CommsigniaLayer(IManagementLayers management, Stack<String> lowerStack) {
super(management, lowerStack);
MessageSet defaultMessageSet = MessageSet.C;
itsApplication = new ITSApplication(ItsAid, TargetHost, TargetPort, defaultMessageSet);
try {
itsApplication.connect(1000);
itsApplication.registerBlocking();
DeviceInfoResponse deviceInfoResponse = itsApplication.requestDeviceInfoBlocking();
System.out.println(deviceInfoResponse);
itsApplication.setFacilityModuleStatus(FacilityModule.BSM, false);
itsApplication.setFacilityModuleStatus(FacilityModule.CAM, false);
// itsApplication.addEventListener(new ITSEventAdapter() {
// @Override
// public void onGnNotification(GNNotification notification) {
// ByteBuffer buffer = ByteBuffer.wrap(notification.getData());
//
// System.out.printf("GN GBC receive. GN address: %s Sequence number: %d RSSI: %d dBm\n",
// notification.getGNAddress(),
// buffer.getInt(),
// notification.getRssi()
// );
// }
// });
itsApplication. gnBindBlocking(BTPType.NONE, 65535);
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see org.etsi.its.adapter.layers.Layer#register(org.etsi.its.adapter.layers.Layer)
*/
@Override
public void register(Layer upperLayer) {
TERFactory.getInstance().logDebug(">>> CommsigniaLayer.register: " + upperLayer);
if(registeredUpperLayer == null) {
super.register(upperLayer);
try {
Method getEthernetType = registeredUpperLayer.getClass().getMethod("getEthernetType", (Class<?>[])null);
if (getEthernetType != null) {
upperLayerFrameType = (Short) getEthernetType.invoke(registeredUpperLayer, (Object[]) null);
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
localMacAddress = management.getLinkLayerAddress();
PcapMultiplexer.getInstance().register(this, DeviceMacAddress, this.getEthernetType());
}
if(ClientsToMacs.isEmpty()) {
pcapFilter = "udp dst port " + SourcePort + " and ";
} else {
TERFactory.getInstance().logDebug("CommsigniaLayer.register: Another Client !");
pcapFilter = pcapFilter + " and ";
}
// Update Filter
String strMacAddress = String.format("%02x", localMacAddress[0]);
for(int i=1; i < localMacAddress.length; i++) {
strMacAddress += String.format(":%02x", localMacAddress[i]);
}
//udp dst port 74 && wlan src 8b:ad:f0:0d:01:02
pcapFilter = pcapFilter + "not wlan src " + strMacAddress;
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Reset filter
PcapMultiplexer.getInstance().resetFilter(pcapFilter);
// Register client
ClientsToMacs.put(this.toString(), localMacAddress);
ClientsToLayers.put(this.toString(), upperLayer);
ClientsToFrameTypes.put(this.toString(), upperLayerFrameType);
}
/* (non-Javadoc)
* @see org.etsi.its.adapter.layers.Layer#receive(byte[])
*/
@Override
public void receive(byte[] message, Map<String, Object> lowerInfo) {
TERFactory.getInstance().logDebug(">>> CommsigniaLayer.receive: " + ByteHelper.byteArrayToString(message));
ByteBuffer byteBuffer = ByteBuffer.wrap(message);
// Skip C2P protocol
byteBuffer.position(
20 + // IP Layer: 45 00 01 1f 13 8c 00 00 80 11 6b 0b ac 11 0f 26 ff ff ff ff
8 + // UDP Layer: 75 30 1f 07 01 0b a6 cd
29 + // C2P Layer: 12 00 00 33 41 00 00 03 5c ac 00 02 0c 02 35 a4 e9 01 6b 49 d2 01 3f ff 00 00 7f ff 16
4 // IEEE 802.11L Layer: 88 00 00 00 00
);
// Extract Dst
byte[] dst = new byte[6];
byteBuffer.get(dst, 0, dst.length);
lowerInfo.put(EthernetLayer.LINK_LAYER_DESTINATION, dst);
// Skip Src
byteBuffer.position(byteBuffer.position() + 6);
// Skip IEEE 802.11L Layer
byteBuffer.position(byteBuffer.position() + 10);
// Skip LLC header
byteBuffer.position(byteBuffer.position() + 6);
// Extract FrameType info
byte[] rawFrameType = new byte[2];
byteBuffer.get(rawFrameType, 0, rawFrameType.length);
short frameType = ByteHelper.byteArrayToInt(rawFrameType).shortValue();
// Extract Data
byte[] data = new byte[byteBuffer.remaining()];
byteBuffer.get(data, 0, byteBuffer.remaining());
// Dispatch
for (String mapKey : ClientsToMacs.keySet()) {
if(frameType == ClientsToFrameTypes.get(mapKey)) {
if(Arrays.equals(dst, MAC_BROADCAST) || Arrays.equals(dst, ClientsToMacs.get(mapKey))) {
ClientsToLayers.get(mapKey).receive(data, lowerInfo);
}
}
}
}
/* (non-Javadoc)
* @see org.etsi.its.adapter.layers.Layer#send(byte[], java.util.Map)
*/
@Override
public boolean send(byte[] message, Map<String, Object> params) {
//TERFactory.getInstance().logDebug(">>> CommsigniaLayer.send: " + ByteHelper.byteArrayToString(message));
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
byte[] dst = (byte[])params.get(LINK_LAYER_DESTINATION);
if(dst == null) {
dst = MAC_BROADCAST;
}
byte[] packet = ByteHelper.concat(
dst,
localMacAddress,
ByteHelper.intToByteArray(upperLayerFrameType, 2),
message
);
try {
String dstAddress = String.format(
"%02x:%02x:%02x:%02x:%02x:%02x",
dst[0],
dst[1],
dst[2],
dst[3],
dst[4],
dst[5]);
String srcAddress = String.format(
"%02x:%02x:%02x:%02x:%02x:%02x",
localMacAddress[0],
localMacAddress[1],
localMacAddress[2],
localMacAddress[3],
localMacAddress[4],
localMacAddress[5]);
Builder build = new InjectData.Builder();
build
.withDstAddress(dstAddress)
.withSrcAddress(srcAddress)
.withType(Type.GNP)
.withInterfaceID(2)
.withData(message);
InjectData injectData = build.build();
//TERFactory.getInstance().logDebug("CommsigniaLayer.send: " + ByteHelper.byteArrayToString(injectData.getData()));
itsApplication.sendOnRadioBlocking(injectData);
//TERFactory.getInstance().logDebug("<<< CommsigniaLayer.send: " + ByteHelper.byteArrayToString(packet));
return true;//super.send(packet, params);
} catch (ClientException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
/* (non-Javadoc)
* @see org.etsi.its.adapter.layers.Layer#unregister(org.etsi.its.adapter.layers.Layer)
*/
@Override
public void unregister(Layer upperLayer) {
PcapMultiplexer.getInstance().unregister(this);
if(ClientsToMacs.containsKey(this.toString())) {
ClientsToMacs.remove(this.toString());
ClientsToFrameTypes.remove(this.toString());
ClientsToLayers.remove(this.toString());
if(ClientsToMacs.isEmpty()) {
if (itsApplication != null) {
try {
itsApplication.gnCloseBlocking(BTPType.NONE, 65535);
itsApplication.deregisterBlocking();
} catch (ClientException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
itsApplication.shutdown();
itsApplication = null;
}
/* (non-Javadoc)
* @see org.etsi.its.adapter.ports.IEthernetSpecific#getEthernetType()
*/
@Override
public short getEthernetType() {
return (short)0x0800;
}