Skip to content

Commit ecd385b

Browse files
authored
GUACAMOLE-221: Expose underlying protocol at tunnel level.
2 parents 920d83f + d1de61d commit ecd385b

12 files changed

Lines changed: 297 additions & 165 deletions

File tree

extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java

Lines changed: 32 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -201,87 +201,52 @@ protected abstract void release(RemoteAuthenticatedUser user,
201201
ModeledConnectionGroup connectionGroup);
202202

203203
/**
204-
* Returns a guacamole configuration containing the protocol and parameters
205-
* from the given connection. If the ID of an active connection is
206-
* provided, that connection will be joined instead of starting a new
207-
* primary connection. If tokens are used in the connection parameter
208-
* values, credentials from the given user will be substituted
209-
* appropriately.
210-
*
211-
* @param user
212-
* The user whose credentials should be used if necessary.
204+
* Returns a GuacamoleConfiguration which connects to the given connection.
205+
* If the ID of an active connection is provided, that active connection
206+
* will be joined rather than establishing an entirely new connection. If
207+
* a sharing profile is provided, the parameters associated with that
208+
* sharing profile will be used to define the access provided to the user
209+
* accessing the shared connection.
213210
*
214211
* @param connection
215-
* The connection whose protocol and parameters should be added to the
216-
* returned configuration.
212+
* The connection that the user is connecting to.
217213
*
218214
* @param connectionID
219-
* The ID of the active connection to be joined, as returned by guacd,
220-
* or null if a new primary connection should be established.
221-
*
222-
* @return
223-
* A GuacamoleConfiguration containing the protocol and parameters from
224-
* the given connection.
225-
*/
226-
private GuacamoleConfiguration getGuacamoleConfiguration(RemoteAuthenticatedUser user,
227-
ModeledConnection connection, String connectionID) {
228-
229-
// Generate configuration from available data
230-
GuacamoleConfiguration config = new GuacamoleConfiguration();
231-
232-
// Join existing active connection, if any
233-
if (connectionID != null)
234-
config.setConnectionID(connectionID);
235-
236-
// Set protocol from connection if not joining an active connection
237-
else {
238-
ConnectionModel model = connection.getModel();
239-
config.setProtocol(model.getProtocol());
240-
}
241-
242-
// Set parameters from associated data
243-
Collection<ConnectionParameterModel> parameters = connectionParameterMapper.select(connection.getIdentifier());
244-
for (ConnectionParameterModel parameter : parameters)
245-
config.setParameter(parameter.getName(), parameter.getValue());
246-
247-
return config;
248-
249-
}
250-
251-
/**
252-
* Returns a guacamole configuration which joins the active connection
253-
* having the given ID, using the provided sharing profile to restrict the
254-
* access provided to the user accessing the shared connection. If tokens
255-
* are used in the connection parameter values of the sharing profile,
256-
* credentials from the given user will be substituted appropriately.
257-
*
258-
* @param user
259-
* The user whose credentials should be used if necessary.
215+
* The ID of the active connection being joined, as provided by guacd
216+
* when the original connection was established, or null if a new
217+
* connection should be established instead.
260218
*
261219
* @param sharingProfile
262220
* The sharing profile whose associated parameters dictate the level
263-
* of access granted to the user joining the connection.
264-
*
265-
* @param connectionID
266-
* The ID of the connection being joined, as provided by guacd when the
267-
* original connection was established, or null if a new connection
268-
* should be created instead.
221+
* of access granted to the user joining the connection, or null if the
222+
* parameters associated with the connection should be used.
269223
*
270224
* @return
271-
* A GuacamoleConfiguration containing the protocol and parameters from
272-
* the given connection.
225+
* A GuacamoleConfiguration defining the requested, possibly shared
226+
* connection.
273227
*/
274-
private GuacamoleConfiguration getGuacamoleConfiguration(RemoteAuthenticatedUser user,
275-
ModeledSharingProfile sharingProfile, String connectionID) {
228+
private GuacamoleConfiguration getGuacamoleConfiguration(
229+
ModeledConnection connection, String connectionID,
230+
ModeledSharingProfile sharingProfile) {
231+
232+
ConnectionModel model = connection.getModel();
276233

277234
// Generate configuration from available data
278235
GuacamoleConfiguration config = new GuacamoleConfiguration();
236+
config.setProtocol(model.getProtocol());
279237
config.setConnectionID(connectionID);
280238

281239
// Set parameters from associated data
282-
Collection<SharingProfileParameterModel> parameters = sharingProfileParameterMapper.select(sharingProfile.getIdentifier());
283-
for (SharingProfileParameterModel parameter : parameters)
284-
config.setParameter(parameter.getName(), parameter.getValue());
240+
if (sharingProfile != null) {
241+
Collection<SharingProfileParameterModel> parameters = sharingProfileParameterMapper.select(sharingProfile.getIdentifier());
242+
for (SharingProfileParameterModel parameter : parameters)
243+
config.setParameter(parameter.getName(), parameter.getValue());
244+
}
245+
else {
246+
Collection<ConnectionParameterModel> parameters = connectionParameterMapper.select(connection.getIdentifier());
247+
for (ConnectionParameterModel parameter : parameters)
248+
config.setParameter(parameter.getName(), parameter.getValue());
249+
}
285250

286251
return config;
287252

@@ -488,7 +453,7 @@ private GuacamoleTunnel assignGuacamoleTunnel(ActiveConnectionRecord activeConne
488453
if (activeConnection.isPrimaryConnection()) {
489454
activeConnections.put(connection.getIdentifier(), activeConnection);
490455
activeConnectionGroups.put(connection.getParentIdentifier(), activeConnection);
491-
config = getGuacamoleConfiguration(activeConnection.getUser(), connection, activeConnection.getConnectionID());
456+
config = getGuacamoleConfiguration(connection, activeConnection.getConnectionID(), null);
492457
}
493458

494459
// If we ARE joining an active connection under the restrictions of
@@ -502,8 +467,7 @@ private GuacamoleTunnel assignGuacamoleTunnel(ActiveConnectionRecord activeConne
502467

503468
// Build configuration from the sharing profile and the ID of
504469
// the connection being joined
505-
config = getGuacamoleConfiguration(activeConnection.getUser(),
506-
activeConnection.getSharingProfile(), connectionID);
470+
config = getGuacamoleConfiguration(connection, connectionID, activeConnection.getSharingProfile());
507471

508472
}
509473

guacamole-common-js/src/main/webapp/modules/Tunnel.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,20 @@ Guacamole.Tunnel = function() {
7373

7474
};
7575

76+
/**
77+
* Changes the stored UUID that uniquely identifies this tunnel, firing the
78+
* onuuid event if a handler has been defined.
79+
*
80+
* @private
81+
* @param {String} uuid
82+
* The new state of this tunnel.
83+
*/
84+
this.setUUID = function setUUID(uuid) {
85+
this.uuid = uuid;
86+
if (this.onuuid)
87+
this.onuuid(uuid);
88+
};
89+
7690
/**
7791
* Returns whether this tunnel is currently connected.
7892
*
@@ -119,6 +133,15 @@ Guacamole.Tunnel = function() {
119133
*/
120134
this.uuid = null;
121135

136+
/**
137+
* Fired when the UUID that uniquely identifies this tunnel is known.
138+
*
139+
* @event
140+
* @param {String}
141+
* The UUID uniquely identifying this tunnel.
142+
*/
143+
this.onuuid = null;
144+
122145
/**
123146
* Fired whenever an error is encountered by the tunnel.
124147
*
@@ -706,7 +729,7 @@ Guacamole.HTTPTunnel = function(tunnelURL, crossDomain, extraTunnelHeaders) {
706729
reset_timeout();
707730

708731
// Get UUID from response
709-
tunnel.uuid = connect_xmlhttprequest.responseText;
732+
tunnel.setUUID(connect_xmlhttprequest.responseText);
710733

711734
// Mark as open
712735
tunnel.setState(Guacamole.Tunnel.State.OPEN);
@@ -1019,7 +1042,7 @@ Guacamole.WebSocketTunnel = function(tunnelURL) {
10191042

10201043
// Associate tunnel UUID if received
10211044
if (opcode === Guacamole.Tunnel.INTERNAL_DATA_OPCODE)
1022-
tunnel.uuid = elements[0];
1045+
tunnel.setUUID(elements[0]);
10231046

10241047
// Tunnel is now open and UUID is available
10251048
tunnel.setState(Guacamole.Tunnel.State.OPEN);
@@ -1155,11 +1178,18 @@ Guacamole.ChainedTunnel = function(tunnelChain) {
11551178
* @private
11561179
*/
11571180
function commit_tunnel() {
1181+
11581182
tunnel.onstatechange = chained_tunnel.onstatechange;
11591183
tunnel.oninstruction = chained_tunnel.oninstruction;
11601184
tunnel.onerror = chained_tunnel.onerror;
1161-
chained_tunnel.uuid = tunnel.uuid;
1185+
tunnel.onuuid = chained_tunnel.onuuid;
1186+
1187+
// Assign UUID if already known
1188+
if (tunnel.uuid)
1189+
chained_tunnel.setUUID(tunnel.uuid);
1190+
11621191
committedTunnel = tunnel;
1192+
11631193
}
11641194

11651195
// Wrap own onstatechange within current tunnel

guacamole-common/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@
5757
<build>
5858
<plugins>
5959

60-
<!-- Written for 1.6 -->
60+
<!-- Written for 1.8 -->
6161
<plugin>
6262
<groupId>org.apache.maven.plugins</groupId>
6363
<artifactId>maven-compiler-plugin</artifactId>
6464
<version>3.3</version>
6565
<configuration>
66-
<source>1.6</source>
67-
<target>1.6</target>
66+
<source>1.8</source>
67+
<target>1.8</target>
6868
<compilerArgs>
6969
<arg>-Xlint:all</arg>
7070
<arg>-Werror</arg>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.guacamole.net;
21+
22+
import org.apache.guacamole.GuacamoleException;
23+
import org.apache.guacamole.io.GuacamoleReader;
24+
import org.apache.guacamole.io.GuacamoleWriter;
25+
26+
/**
27+
* GuacamoleSocket implementation which simply delegates all function calls to
28+
* an underlying GuacamoleSocket.
29+
*/
30+
public class DelegatingGuacamoleSocket implements GuacamoleSocket {
31+
32+
/**
33+
* The wrapped socket.
34+
*/
35+
private final GuacamoleSocket socket;
36+
37+
/**
38+
* Wraps the given GuacamoleSocket such that all function calls against
39+
* this DelegatingGuacamoleSocket will be delegated to it.
40+
*
41+
* @param socket
42+
* The GuacamoleSocket to wrap.
43+
*/
44+
public DelegatingGuacamoleSocket(GuacamoleSocket socket) {
45+
this.socket = socket;
46+
}
47+
48+
/**
49+
* Returns the underlying GuacamoleSocket wrapped by this
50+
* DelegatingGuacamoleSocket.
51+
*
52+
* @return
53+
* The GuacamoleSocket wrapped by this DelegatingGuacamoleSocket.
54+
*/
55+
protected GuacamoleSocket getDelegateSocket() {
56+
return socket;
57+
}
58+
59+
@Override
60+
public String getProtocol() {
61+
return socket.getProtocol();
62+
}
63+
64+
@Override
65+
public GuacamoleReader getReader() {
66+
return socket.getReader();
67+
}
68+
69+
@Override
70+
public GuacamoleWriter getWriter() {
71+
return socket.getWriter();
72+
}
73+
74+
@Override
75+
public void close() throws GuacamoleException {
76+
socket.close();
77+
}
78+
79+
@Override
80+
public boolean isOpen() {
81+
return socket.isOpen();
82+
}
83+
84+
}

guacamole-common/src/main/java/org/apache/guacamole/net/GuacamoleSocket.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@
2929
*/
3030
public interface GuacamoleSocket {
3131

32+
/**
33+
* Returns the name of the protocol to be used. If the protocol is not
34+
* known or the implementation refuses to reveal the underlying protocol,
35+
* null is returned.
36+
*
37+
* <p>Implementations <strong>should</strong> aim to expose the name of the
38+
* underlying protocol, such that protocol-specific responses like the
39+
* "required" and "argv" instructions can be handled correctly by code
40+
* consuming the GuacamoleSocket.
41+
*
42+
* @return
43+
* The name of the protocol to be used, or null if this information is
44+
* not available.
45+
*/
46+
public default String getProtocol() {
47+
return null;
48+
}
49+
3250
/**
3351
* Returns a GuacamoleReader which can be used to read from the
3452
* Guacamole instruction stream associated with the connection

guacamole-common/src/main/java/org/apache/guacamole/protocol/ConfiguredGuacamoleSocket.java

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.guacamole.GuacamoleServerException;
2525
import org.apache.guacamole.io.GuacamoleReader;
2626
import org.apache.guacamole.io.GuacamoleWriter;
27+
import org.apache.guacamole.net.DelegatingGuacamoleSocket;
2728
import org.apache.guacamole.net.GuacamoleSocket;
2829

2930
/**
@@ -36,12 +37,7 @@
3637
* this GuacamoleSocket from manually controlling the initial protocol
3738
* handshake.
3839
*/
39-
public class ConfiguredGuacamoleSocket implements GuacamoleSocket {
40-
41-
/**
42-
* The wrapped socket.
43-
*/
44-
private GuacamoleSocket socket;
40+
public class ConfiguredGuacamoleSocket extends DelegatingGuacamoleSocket {
4541

4642
/**
4743
* The configuration to use when performing the Guacamole protocol
@@ -125,7 +121,7 @@ public ConfiguredGuacamoleSocket(GuacamoleSocket socket,
125121
GuacamoleConfiguration config,
126122
GuacamoleClientInformation info) throws GuacamoleException {
127123

128-
this.socket = socket;
124+
super(socket);
129125
this.config = config;
130126

131127
// Get reader and writer
@@ -268,23 +264,8 @@ public GuacamoleProtocolVersion getProtocolVersion() {
268264
}
269265

270266
@Override
271-
public GuacamoleWriter getWriter() {
272-
return socket.getWriter();
273-
}
274-
275-
@Override
276-
public GuacamoleReader getReader() {
277-
return socket.getReader();
278-
}
279-
280-
@Override
281-
public void close() throws GuacamoleException {
282-
socket.close();
283-
}
284-
285-
@Override
286-
public boolean isOpen() {
287-
return socket.isOpen();
267+
public String getProtocol() {
268+
return getConfiguration().getProtocol();
288269
}
289270

290271
}

0 commit comments

Comments
 (0)