All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.luminis.quic.core.TransportParameters Maven / Gradle / Ivy

There is a newer version: 0.9.1
Show newest version
/*
 * Copyright © 2019, 2020, 2021, 2022, 2023 Peter Doornbosch
 *
 * This file is part of Kwik, an implementation of the QUIC protocol in Java.
 *
 * Kwik is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Kwik is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see .
 */
package net.luminis.quic.core;

import net.luminis.quic.receive.Receiver;
import net.luminis.tls.util.ByteUtils;

import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.List;

public class TransportParameters {

    private byte[] originalDestinationConnectionId;
    private long maxIdleTimeout;
    private long initialMaxData;
    private long initialMaxStreamDataBidiLocal;
    private long initialMaxStreamDataBidiRemote;
    private long initialMaxStreamDataUni;
    private long initialMaxStreamsBidi;
    private long initialMaxStreamsUni;
    private int ackDelayExponent;
    private boolean disableMigration;
    private PreferredAddress preferredAddress;
    private int maxAckDelay;
    private int activeConnectionIdLimit;
    private byte[] initialSourceConnectionId;
    private byte[] retrySourceConnectionId;
    private int maxUdpPayloadSize;
    private byte[] statelessResetToken;
    private VersionInformation versionInformation;

    public TransportParameters() {
        setDefaults();
        maxUdpPayloadSize = Receiver.MAX_DATAGRAM_SIZE;
    }

    public TransportParameters(int maxIdleTimeoutInSeconds, int initialMaxStreamData, int initialMaxStreamsBidirectional, int initialMaxStreamsUnidirectional) {
        setDefaults();
        this.maxIdleTimeout = maxIdleTimeoutInSeconds * 1000L;
        setInitialMaxStreamData(initialMaxStreamData);
        initialMaxData = 10L * initialMaxStreamData;
        initialMaxStreamsBidi = initialMaxStreamsBidirectional;
        initialMaxStreamsUni = initialMaxStreamsUnidirectional;
        maxUdpPayloadSize = Receiver.MAX_DATAGRAM_SIZE;
    }

    private void setDefaults() {
        // https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-18.2
        // "The default for this parameter is the maximum permitted UDP payload of 65527"
        maxUdpPayloadSize = 65527;
        // "If this value is absent, a default value of 3 is assumed (indicating a multiplier of 8)."
        ackDelayExponent = 3;
        // "If this value is absent, a default of 25 milliseconds is assumed."
        maxAckDelay = 25;
        // "If this transport parameter is absent, a default of 2 is assumed."
        activeConnectionIdLimit = 2;
    }

    public byte[] getOriginalDestinationConnectionId() {
        return originalDestinationConnectionId;
    }

    public void setOriginalDestinationConnectionId(byte[] initialSourceConnectionId) {
        this.originalDestinationConnectionId = initialSourceConnectionId;
    }

    public void setAckDelayExponent(int ackDelayExponent) {
        this.ackDelayExponent = ackDelayExponent;
    }

    public int getAckDelayExponent() {
        return ackDelayExponent;
    }

    public PreferredAddress getPreferredAddress() {
        return preferredAddress;
    }

    public void setPreferredAddress(PreferredAddress preferredAddress) {
        this.preferredAddress = preferredAddress;
    }

    public long getMaxIdleTimeout() {
        return maxIdleTimeout;
    }

    public void setMaxIdleTimeout(long idleTimeout) {
        maxIdleTimeout = idleTimeout;
    }

    public long getInitialMaxData() {
        return initialMaxData;
    }

    public void setInitialMaxData(long initialMaxData) {
        this.initialMaxData = initialMaxData;
    }

    public long getInitialMaxStreamDataBidiLocal() {
        return initialMaxStreamDataBidiLocal;
    }

    public void setInitialMaxStreamDataBidiLocal(long initialMaxStreamDataBidiLocal) {
        this.initialMaxStreamDataBidiLocal = initialMaxStreamDataBidiLocal;
    }

    public long getInitialMaxStreamDataBidiRemote() {
        return initialMaxStreamDataBidiRemote;
    }

    public void setInitialMaxStreamDataBidiRemote(long initialMaxStreamDataBidiRemote) {
        this.initialMaxStreamDataBidiRemote = initialMaxStreamDataBidiRemote;
    }

    public long getInitialMaxStreamDataUni() {
        return initialMaxStreamDataUni;
    }

    public void setInitialMaxStreamDataUni(long initialMaxStreamDataUni) {
        this.initialMaxStreamDataUni = initialMaxStreamDataUni;
    }

    public long getInitialMaxStreamData() {
        // All max stream data values are equal in this implementation.
        return initialMaxStreamDataBidiLocal;
    }

    public void setInitialMaxStreamData(long maxStreamData) {
        // All max stream data values are equal in this implementation. When changing this, also change the getter in QuicConnection, used by the streams.
        initialMaxStreamDataBidiLocal = maxStreamData;
        initialMaxStreamDataBidiRemote = maxStreamData;
        initialMaxStreamDataUni = maxStreamData;
    }

    public long getInitialMaxStreamsBidi() {
        return initialMaxStreamsBidi;
    }

    public void setInitialMaxStreamsBidi(long initialMaxStreamsBidi) {
        this.initialMaxStreamsBidi = initialMaxStreamsBidi;
    }

    public long getInitialMaxStreamsUni() {
        return initialMaxStreamsUni;
    }

    public void setInitialMaxStreamsUni(long initialMaxStreamsUni) {
        this.initialMaxStreamsUni = initialMaxStreamsUni;
    }

    public void setMaxAckDelay(int maxAckDelay) {
        this.maxAckDelay = maxAckDelay;
    }

    /**
     * Retrieve the max ack delay in milliseconds
     * @return
     */
    public int getMaxAckDelay() {
        return maxAckDelay;
    }

    public int getActiveConnectionIdLimit() {
        return activeConnectionIdLimit;
    }

    public void setActiveConnectionIdLimit(int activeConnectionIdLimit) {
        this.activeConnectionIdLimit = activeConnectionIdLimit;
    }

    public void setDisableMigration(boolean disableMigration) {
        this.disableMigration = disableMigration;
    }

    public boolean getDisableMigration() {
        return disableMigration;
    }

    public byte[] getInitialSourceConnectionId() {
        return initialSourceConnectionId;
    }

    public void setInitialSourceConnectionId(byte[] initialSourceConnectionId) {
        this.initialSourceConnectionId = initialSourceConnectionId;
    }

    public byte[] getRetrySourceConnectionId() {
        return retrySourceConnectionId;
    }

    public void setRetrySourceConnectionId(byte[] retrySourceConnectionId) {
        this.retrySourceConnectionId = retrySourceConnectionId;
    }

    public int getMaxUdpPayloadSize() {
        return maxUdpPayloadSize;
    }

    public void setMaxUdpPayloadSize(int maxUdpPayloadSize) {
        this.maxUdpPayloadSize = maxUdpPayloadSize;
    }

    public byte[] getStatelessResetToken() {
        return statelessResetToken;
    }

    public void setStatelessResetToken(byte[] statelessResetToken) {
        this.statelessResetToken = statelessResetToken;
    }

    @Override
    public String toString() {
        return "\n- original destination connection id\t" + formatCid(originalDestinationConnectionId) +
                "\n- max idle timeout\t" + (maxIdleTimeout / 1000) +
                "\n- max udp payload size\t" + maxUdpPayloadSize +
                "\n- initial max data\t\t\t" + initialMaxData +
                "\n- initial max stream data bidi local\t" + initialMaxStreamDataBidiLocal +
                "\n- initial max stream data bidi remote\t" + initialMaxStreamDataBidiRemote +
                "\n- initial max stream data unit\t\t" + initialMaxStreamDataUni +
                "\n- initial max streams bidi\t\t" + initialMaxStreamsBidi +
                "\n- initial max streams uni\t\t" + initialMaxStreamsUni +
                "\n- ack delay exponent\t\t\t" + ackDelayExponent +
                "\n- max ack delay\t\t\t\t" + maxAckDelay +
                "\n- disable migration\t\t\t" + disableMigration +
                "\n- active connection id limit\t\t" + activeConnectionIdLimit +
                "\n- initial source connection id\t\t" + formatCid(initialSourceConnectionId) +
                "\n- retry source connection id\t\t" + formatCid(retrySourceConnectionId);
    }

    private String formatCid(byte[] data) {
        if (data != null) {
            return ByteUtils.bytesToHex(data);
        }
        else {
            return "null";
        }
    }

    public VersionInformation getVersionInformation() {
        return versionInformation;
    }

    public void setVersionInformation(VersionInformation versionInfo) {
        versionInformation = versionInfo;
    }

    public static class PreferredAddress {
        InetAddress ip4;
        int ip4Port;
        InetAddress ip6;
        int ip6Port;
        byte[] connectionId;
        byte[] statelessResetToken;

        public InetAddress getIp4() {
            return ip4;
        }

        public void setIp4(InetAddress ip4) {
            this.ip4 = ip4;
        }

        public int getIp4Port() {
            return ip4Port;
        }

        public void setIp4Port(int ip4Port) {
            this.ip4Port = ip4Port;
        }

        public InetAddress getIp6() {
            return ip6;
        }

        public void setIp6(InetAddress ip6) {
            this.ip6 = ip6;
        }

        public int getIp6Port() {
            return ip6Port;
        }

        public void setIp6Port(int ip6Port) {
            this.ip6Port = ip6Port;
        }

        public byte[] getConnectionId() {
            return connectionId;
        }

        public byte[] getStatelessResetToken() {
            return statelessResetToken;
        }

        public void setConnectionId(ByteBuffer buffer, int connectionIdSize) {
             connectionId = new byte[connectionIdSize];
             buffer.get(connectionId);
        }

        public void setStatelessResetToken(ByteBuffer buffer, int size) {
            statelessResetToken = new byte[size];
            buffer.get(statelessResetToken);
        }
    }

    public static class VersionInformation {

        private final Version chosenVersion;
        private final List otherVersions;

        public VersionInformation(Version chosenVersion, List otherVersions) {
            this.chosenVersion = chosenVersion;
            this.otherVersions = otherVersions;
        }

        public Version getChosenVersion() {
            return chosenVersion;
        }

        public List getOtherVersions() {
            return otherVersions;
        }

        @Override
        public String toString() {
            return String.format("%s|%s", chosenVersion, otherVersions);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy