/*
* Copyright (c) 2015 Huawei, Inc and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.usc.crypto.dtls;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.socket.DatagramPacket;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import org.bouncycastle.crypto.tls.DTLSTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DtlsEngine {
private static final Logger log = LoggerFactory.getLogger(DtlsEngine.class);
private DTLSTransport encTransport = null;
private final DtlsHandlerTransport rawTransport;
private final LinkedBlockingQueue<DatagramPacket> writeQueue = new LinkedBlockingQueue<>();
public DtlsEngine(DtlsHandlerTransport rawTransport) {
this.rawTransport = rawTransport;
}
public ArrayList<DatagramPacket> read(DatagramPacket msg) throws InterruptedException, ExecutionException,
IOException {
log.trace("DtlsEngine read " + msg);
// add to queue irrespective of whether initialized or not;
// this way the protocol handshake can retrieve them
rawTransport.enqueue(msg);
ArrayList<DatagramPacket> packets = new ArrayList<>();
if (encTransport != null) {
byte buf[] = new byte[encTransport.getReceiveLimit()];
while (rawTransport.hasPackets()) {
int bytesRead = encTransport.receive(buf, 0, buf.length, 100);
if (bytesRead > 0) {
packets.add(new DatagramPacket(Unpooled.copiedBuffer(buf, 0, bytesRead), rawTransport
.getRemoteAddress()));
}
}
}
return packets;
}
private static void write(DTLSTransport encTransport, DatagramPacket packet) throws IOException {
ByteBuf byteBuf = packet.content();
int readableBytes = byteBuf.readableBytes();
log.trace("DtlsEngine write " + packet);
byte buf[] = new byte[encTransport.getSendLimit()];
byteBuf.readBytes(buf, 0, readableBytes);
byteBuf.release();
encTransport.send(buf, 0, readableBytes);
}
public void write(DatagramPacket packet) throws IOException, InterruptedException, ExecutionException {
if (encTransport != null) {
write(encTransport, packet);
} else {
writeQueue.add(packet);
}
}
public void initialize(DTLSTransport encTransport) throws InterruptedException, ExecutionException, IOException {
// first send all queued up messages
ArrayList<DatagramPacket> packets = new ArrayList<>();
writeQueue.drainTo(packets);
for (DatagramPacket packet : packets) {
write(encTransport, packet);
}
// expose this to the outside world last to avoid race conditions
this.encTransport = encTransport;
}
public boolean isInitialized() {
return encTransport != null;
}
}