com.bitbreeds.webrtc.dtls.DtlsMuxStunTransport.java Source code

Java tutorial

Introduction

Here is the source code for com.bitbreeds.webrtc.dtls.DtlsMuxStunTransport.java

Source

package com.bitbreeds.webrtc.dtls;

import com.bitbreeds.webrtc.common.ByteRange;
import com.bitbreeds.webrtc.common.SignalUtil;
import com.bitbreeds.webrtc.signaling.BindingService;
import com.bitbreeds.webrtc.signaling.PeerConnection;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.crypto.tls.AlertDescription;
import org.bouncycastle.crypto.tls.DatagramTransport;
import org.bouncycastle.crypto.tls.TlsFatalAlert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.*;
import java.util.Arrays;

/**
 * Copyright (c) 28/02/2017, Jonas Waage
 * <p>
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * <p>
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * <p>
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 *
 * Handles DTLS over UDP.
 *
 * If we receive a STUN message, we reply and do not pass the message to the layer below
 */
public class DtlsMuxStunTransport implements DatagramTransport {

    private final static int IP_BYTES = 20;
    private final static int IP_MAX_BYTES = IP_BYTES + 64;
    private final static int UDP_BYTES = 8;

    private final DatagramSocket socket;
    private final int receiveLimit, sendLimit;

    private final PeerConnection parent;

    private final BindingService bindingService = new BindingService();

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public DtlsMuxStunTransport(PeerConnection parent, DatagramSocket socket, int mtu) throws IOException {
        this.parent = parent;
        this.socket = socket;
        this.receiveLimit = mtu - IP_BYTES - UDP_BYTES;
        this.sendLimit = mtu - IP_MAX_BYTES - UDP_BYTES;
        if (!socket.isBound() || !socket.isConnected()) {
            throw new IllegalArgumentException("Unbound socket");
        }
    }

    public int receive(byte[] buf, int off, int len, int waitMillis) throws IOException {
        socket.setSoTimeout(waitMillis);
        DatagramPacket packet = new DatagramPacket(buf, off, len);
        socket.receive(packet);
        logger.trace("Socket read msg: {}",
                Hex.encodeHexString(SignalUtil.copyRange(buf, new ByteRange(0, packet.getLength()))));
        if (buf.length >= 2 && buf[0] == 0 && buf[1] == 1) {
            SocketAddress currentSender = packet.getSocketAddress();

            byte[] data = Arrays.copyOf(packet.getData(), packet.getLength());

            byte[] out = bindingService.processBindingRequest(data, parent.getLocal().getUserName(),
                    parent.getLocal().getPassword(), (InetSocketAddress) currentSender);

            logger.trace("Stun packet received, responding with {}", Hex.encodeHexString(out));
            this.send(out, 0, out.length);
            return 0; //We do not want DTLS to process (not that it will anyway), so we return 0 here.
        }

        return packet.getLength();
    }

    public void send(byte[] buf, int off, int len) throws IOException {
        if (len > getSendLimit()) {
            throw new TlsFatalAlert(AlertDescription.record_overflow);
        }
        DatagramPacket packet = new DatagramPacket(buf, off, len);
        socket.send(packet);
    }

    public void close() throws IOException {
        socket.close();
    }

    public int getReceiveLimit() {
        return receiveLimit;
    }

    public int getSendLimit() {
        return sendLimit;
    }

}