001/*
002 *   Copyright 2024 Vonage
003 *
004 *   Licensed under the Apache License, Version 2.0 (the "License");
005 *   you may not use this file except in compliance with the License.
006 *   You may obtain a copy of the License at
007 *
008 *        http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *   Unless required by applicable law or agreed to in writing, software
011 *   distributed under the License is distributed on an "AS IS" BASIS,
012 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *   See the License for the specific language governing permissions and
014 *   limitations under the License.
015 */
016package com.vonage.client.video;
017
018import com.vonage.client.QueryParamsRequest;
019import java.net.InetAddress;
020import java.net.UnknownHostException;
021import java.util.LinkedHashMap;
022import java.util.Map;
023
024/**
025 * Defines the properties used to create a new video session.
026 */
027public class CreateSessionRequest implements QueryParamsRequest {
028        private final InetAddress location;
029        private final MediaMode mediaMode;
030        private final ArchiveMode archiveMode;
031        private final Boolean e2ee;
032
033        private CreateSessionRequest(Builder builder) {
034                location = builder.location;
035                archiveMode = builder.archiveMode;
036                mediaMode = builder.mediaMode;
037                e2ee = builder.e2ee;
038                if (archiveMode == ArchiveMode.ALWAYS && mediaMode != MediaMode.ROUTED) {
039                    throw new IllegalStateException("A session with automatic archiving must also have the ROUTED media mode.");
040                }
041        }
042
043        @Override
044        public Map<String, String> makeParams() {
045                Map<String, String> params = new LinkedHashMap<>(4, 1f);
046                if (location != null) {
047                        params.put("location", location.getHostAddress());
048                }
049                if (mediaMode != null) {
050                        params.put("p2p.preference", mediaMode.toString());
051                }
052                if (archiveMode != null) {
053                        params.put("archiveMode", getArchiveMode().toString());
054                }
055                if (e2ee != null) {
056                        params.put("e2ee", e2ee.toString());
057                }
058                return params;
059        }
060
061        /**
062         * The location hint IP address.
063         *
064         * @return The IP address, or {@code null} if unspecified.
065         */
066        public InetAddress getLocation() {
067                return location;
068        }
069
070        /**
071         * Defines whether the session will transmit streams using the Vonage Media Server or attempt
072         * to transmit streams directly between clients.
073         *
074         * @return The MediaMode as an enum, or {@code null} if unspecified.
075         */
076        public MediaMode getMediaMode() {
077                return mediaMode;
078        }
079
080        /**
081         * Defines whether the session will be automatically archived ({@code ArchiveMode.ALWAYS})
082         * or not ({@code ArchiveMode.MANUAL}).
083         *
084         * @return The ArchiveMode as an enum, or {@code null} if unspecified.
085         */
086        public ArchiveMode getArchiveMode() {
087                return archiveMode;
088        }
089
090        /**
091         * Defines whether the session will be end-to-end encrypted.
092         *
093         * @return {@code true} if end-to-end encryption is enabled, {@code null} if unspecified.
094         * @since 8.12.0
095         */
096        public Boolean getE2ee() {
097                return e2ee;
098        }
099
100        /**
101         * Instantiates a Builder, used to construct this object.
102         *
103         * @return A new {@linkplain Builder}.
104         */
105        public static Builder builder() {
106                return new Builder();
107        }
108
109        /**
110         * Builder for constructing {@linkplain CreateSessionRequest}.
111         */
112        public static final class Builder {
113                private InetAddress location;
114                private MediaMode mediaMode;
115                private ArchiveMode archiveMode;
116                private Boolean e2ee;
117
118                Builder() {}
119
120                /**
121                 * Call this method to set an IP address that the Vonage servers will use to
122                 * situate the session in its global network. If you do not set a location hint,
123                 * the Vonage servers will be based on the first client connecting to the session.
124                 *
125                 * @param location The IP address to serve as the location hint.
126                 *
127                 * @return This builder.
128                 */
129                public Builder location(InetAddress location) {
130                        this.location = location;
131                        return this;
132                }
133
134                /**
135                 * Call this method to set an IP address that the Vonage servers will use to
136                 * situate the session in its global network. If you do not set a location hint,
137                 * the Vonage servers will be based on the first client connecting to the session.
138                 *
139                 * @param location The IP address to serve as the location hint.
140                 *
141                 * @return This builder.
142                 */
143                public Builder location(String location) {
144                        try {
145                                return location(InetAddress.getByName(location));
146                        }
147                        catch (UnknownHostException ex) {
148                                throw new IllegalArgumentException(ex);
149                        }
150                }
151
152                /**
153                 * Call this method to determine whether the session will transmit streams using the
154                 * Vonage Media Router ({@code MediaMode.ROUTED}) or not
155                 * ({@code MediaMode.RELAYED}). By default, the {@code mediaMode} property
156                 * is set to {@code MediaMode.RELAYED}.
157                 *
158                 * <p>
159                 * With the {@code mediaMode} property set to {@code MediaMode.RELAYED}, the session
160                 * will attempt to transmit streams directly between clients. If clients cannot connect due to
161                 * firewall restrictions, the session uses the TURN server to relay audio-video streams.
162                 *
163                 * <p>
164                 * The
165                 * <a href="https://tokbox.com/developer/guides/create-session/#media-mode" target="_top">
166                 * Media Router</a> provides the following benefits:
167                 *
168                 * <ul>
169                 *   <li>The Media Router can decrease bandwidth usage in multiparty sessions.
170                 *       (When the {@code mediaMode} property is set to {@code MediaMode.RELAYED},
171                 *       each client must send a separate audio-video stream to each client subscribing to
172                 *       it.)</li>
173                 *   <li>The Media Router can improve the quality of the user experience through
174                 *     <a href="https://tokbox.com/platform/fallback" target="_top">audio fallback and video
175                 *     recovery</a>. With these features, if a client's connectivity degrades to a degree that
176                 *     it does not support video for a stream it's subscribing to, the video is dropped on
177                 *     that client (without affecting other clients), and the client receives audio only.
178                 *     If the client's connectivity improves, the video returns.</li>
179                 *   <li>The Media Router supports the
180                 *     <a href="http://tokbox.com/developer/guides/archiving" target="_top">archiving</a>
181                 *     feature, which lets you record, save, and retrieve video sessions.</li>
182                 * </ul>
183                 *
184                 * @param mediaMode Set to a value defined in the {@link MediaMode} enum.
185                 *
186                 * @return This builder.
187                 */
188                public Builder mediaMode(MediaMode mediaMode) {
189                        this.mediaMode = mediaMode;
190                        return this;
191                }
192
193                /**
194                 * Call this method to determine whether the session will be automatically archived ({@code ArchiveMode.ALWAYS})
195                 * or not ({@code ArchiveMode.MANUAL}).
196                 * Using an always archived session also requires the routed media mode ({@code MediaMode.ROUTED}).
197                 *
198                 * @param archiveMode The Archive mode.
199                 *
200                 * @return This builder.
201                 */
202                public Builder archiveMode(ArchiveMode archiveMode) {
203                        this.archiveMode = archiveMode;
204                        return this;
205                }
206
207                /**
208                 * Call this method to enable end-to-end encryption for the session.
209                 *
210                 * @param e2ee Set to {@code true} to enable end-to-end encryption.
211                 *
212                 * @return This builder.
213                 * @since 8.12.0
214                 */
215                public Builder e2ee(boolean e2ee) {
216                        this.e2ee = e2ee;
217                        return this;
218                }
219
220                /**
221                 * Builds the CreateSessionRequest object.
222                 *
223                 * @return A new {@linkplain CreateSessionRequest} with this builder's properties.
224                 */
225                public CreateSessionRequest build() {
226                        return new CreateSessionRequest(this);
227                }
228        }
229}