Skip to content

Commit 9eace74

Browse files
Fix backward compatibility (#150)
* add cli option for compatibility mode with various destination clients
1 parent 0a72168 commit 9eace74

File tree

3 files changed

+45
-14
lines changed

3 files changed

+45
-14
lines changed

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,20 @@ V1 local proxy: local proxy uses Sec-WebSocket-Protocol _aws.iot.securetunneling
233233

234234
V2 local proxy: local proxy uses Sec-WebSocket-Protocol _aws.iot.securetunneling-2.0_ when communicates with AWS IoT Tunneling Service.
235235

236+
V3 local proxy: local proxy uses Sec-WebSocket-Protocol _aws.iot.securetunneling-3.0_ when communicates with AWS IoT Tunneling Service.
237+
236238
Source local proxy: local proxy that runs in source mode.
237239

238240
Destination local proxy: local proxy that runs in destination mode.
239241

240-
241242
### Multi-port tunneling feature support
242243
Multi-port tunneling feature allows more than one stream multiplexed on same tunnel.
243244
This feature is only supported with V2 local proxy. If you have some devices that on V1 local proxy, some on V2 local proxy, simply upgrade the local proxy on the source device to V2 local proxy. When V2 local proxy talks to V1 local proxy, the backward compatibility is maintained. For more details, please refer to section [backward compatibility](#backward-compatibility)
244245

246+
### Simultaneous TCP connections feature support
247+
Simultaneous TCP is a feature that allows application layer (e.g. HTTP) protocols to open multiple TCP connections over a single stream.
248+
This feature is only supported with V3 local proxy. If you have some devices that on V1/V2 local proxy, some on V3 local proxy, simply upgrade the local proxy on the source device to V3 local proxy. When V3 local proxy talks to V1/V2 local proxy, the backward compatibility is maintained as long as users specify `V1` or `V2` as the value for `destination-client-type`. For more details, please refer to section [backward compatibility](#backward-compatibility)
249+
245250
### Service identifier (Service ID)
246251
If you need to use multi-port tunneling feature, service ID is needed to start local proxy. A service identifier will be used as the new format to specify the source listening port or destination service when start local proxy. The identifier is like an alias for the source listening port or destination service. For the format requirement of service ID, please refer to AWS public doc [services in DestinationConfig ](https://docs.aws.amazon.com/iot/latest/apireference/API_iot-secure-tunneling_DestinationConfig.html). There is no restriction on how this service ID should be named, as long as it can help uniquely identifying a connection or stream.
247252

@@ -327,6 +332,16 @@ Example 3:
327332

328333
In this example, no service ID is used. Backward compatibility is supported.
329334

335+
V3 local proxy is able to communicate with V1 and V2 local proxy if only one connection/stream needs to be established over the tunnel. When connecting to older versions, you will need to pass the `destination-client-type` CLI arg if and only if starting the localproxy in source mode. The same rules listed above still apply when connecting over V1.
336+
337+
Example when targeting a V1 destination, like Device Client of the Greengrass Secure Tunneling Component:
338+
339+
./localproxy -s 3333 --destination-client-type V1 -v 6 -r us-east-1
340+
341+
Example when targeting a V2 destination:
342+
343+
./localproxy -s 3333 --destination-client-type V2 -v 6 -r us-east-1
344+
330345
### HTTP proxy Support
331346

332347
The local proxy relies on the HTTP tunneling mechanism described by the [HTTP/1.1 specification](https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.6). To comply with the specifications, your web proxy must allow devices to use the CONNECT method. For more details on how that works and how configure it properly, Please refer to "[Configure local proxy for devices that use web proxy](https://docs.aws.amazon.com/iot/latest/developerguide/configure-local-proxy-web-proxy.html)"
@@ -450,6 +465,9 @@ Specifies the verbosity of the output. Value must be between 0-255, however mean
450465
**-m/--mode [argvalue]**
451466
Specifies the mode local proxy will run. Accepted values are: src, source, dst, destination.
452467

468+
**-y/--destination-client-type [argvalue]**
469+
Specifies the backward compatibility mode the local proxy will run when opening a source connection to an older destination client. Currently supported values are: V1, V2. The localproxy will assume the destination to be V3 if no/invalid value is passed.
470+
453471
**--config-dir [argvalue]**
454472
Specifies the configuration directory where service identifier mappings are configured. If this parameter is not specified, local proxy will read configuration files from default directory _./config_, under the file path where `localproxy` binary are located.
455473

src/TcpAdapterProxy.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ namespace aws { namespace iot { namespace securedtunneling {
11091109
std::int32_t stream_id = static_cast<std::int32_t>(message.streamid());
11101110
uint32_t connection_id = static_cast<uint32_t>(message.connectionid());
11111111

1112-
// backward compatibility: set connection id to 1 if first received a message with no connection id (id value will be 0)
1112+
// backward compatibility: set is_v2_message_format to true if receives no connection id
11131113
if (!connection_id)
11141114
{
11151115
BOOST_LOG_SEV(log, info) << "reverting to v2 message format";
@@ -1257,14 +1257,6 @@ namespace aws { namespace iot { namespace securedtunneling {
12571257
throw std::runtime_error("Wrong configurations detected in local proxy. Please starts local proxy with right sets of service ids.");
12581258
}
12591259

1260-
/**
1261-
* Set flag to mark local proxy will communicate using local proxy v1 message format.
1262-
* local proxy v1 message format: 1 service id. It can be a empty string when open tunnel with no service in destination config.
1263-
*/
1264-
if (service_id_list.size() == 1)
1265-
{
1266-
tac.adapter_config.is_v1_message_format = true;
1267-
}
12681260
/**
12691261
* Build serviceId <-> endpoint mapping if not done yet.
12701262
* Case1: Configuration is provided through configuration files. Upon receiving service ids, search through
@@ -1365,7 +1357,7 @@ namespace aws { namespace iot { namespace securedtunneling {
13651357
std::int32_t stream_id = static_cast<std::int32_t>(message.streamid());
13661358
uint32_t connection_id = static_cast<uint32_t>(message.connectionid());
13671359

1368-
// backward compatibility: set connection id to 1 if first received a message with no connection id (id value will be 0)
1360+
// backward compatibility: set is_v2_message_format to true if receives no connection id
13691361
if (!connection_id)
13701362
{
13711363
BOOST_LOG_SEV(log, info) << "reverting to v2 message format";
@@ -1468,7 +1460,7 @@ namespace aws { namespace iot { namespace securedtunneling {
14681460

14691461
BOOST_LOG_SEV(log, trace) << "Forwarding message to tcp socket with connection id: " << connection_id;
14701462

1471-
// backward compatibility: set connection id to 1 if first received a message with no connection id (id value will be 0)
1463+
// backward compatibility: set is_v2_message_format to true if receives no connection id
14721464
if (!connection_id)
14731465
{
14741466
BOOST_LOG_SEV(log, info) << "reverting to v2 message format";
@@ -1599,7 +1591,7 @@ namespace aws { namespace iot { namespace securedtunneling {
15991591
{
16001592
BOOST_LOG_SEV(log, trace) << "Processing data message";
16011593

1602-
// backward compatibility: set connection id to 1 if first received a message with no connection id (id value will be 0)
1594+
// backward compatibility: set is_v2_message_format to true if receives no connection id
16031595
if (!connection_id)
16041596
{
16051597
BOOST_LOG_SEV(log, info) << "reverting to v2 message format";
@@ -2036,12 +2028,13 @@ namespace aws { namespace iot { namespace securedtunneling {
20362028

20372029
uint32_t new_connection_id = ++server->highest_connection_id;
20382030

2039-
// backward compatibility: set connection id to 1 if simultaneous connections is not enabled
2031+
// backward compatibility: set connection id to 0 if simultaneous connections is not enabled
20402032
if (tac.adapter_config.is_v2_message_format || tac.adapter_config.is_v1_message_format)
20412033
{
20422034
BOOST_LOG_SEV(log, info) << "Falling back to older protocol, setting new connection id to 0";
20432035
new_connection_id = 0;
20442036
}
2037+
20452038
BOOST_LOG_SEV(log, info) << "creating tcp connection id " << new_connection_id;
20462039

20472040
if (server->connectionId_to_tcp_connection_map.find(new_connection_id) == server->connectionId_to_tcp_connection_map.end() &&

src/main.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ bool process_cli(int argc, char ** argv, LocalproxyConfig &cfg, ptree &settings,
172172
("config", value<string>(), "Use the supplied configuration file to apply CLI args. Actual CLI args override the contents of this file")
173173
("verbose,v", value<std::uint16_t>()->default_value(4), "Logging level to standard out. [0, 255] (0=off, 1=fatal, 2=error, 3=warning, 4=info, 5=debug, >=6=trace)")
174174
("mode,m", value<string>(), "The mode local proxy will run: src(source) or dst(destination)")
175+
("destination-client-type,y", value<string>(), "Specify the value V1 or V2 to run the localproxy in compatibility mode with older clients. This should only be used when running localproxy in source mode.")
175176
("config-dir", value<string>(), "Set the configuration directory where service identifier mappings are stored. If not specified, will read mappings from default directory ./config (same directory where local proxy binary is running)")
176177
;
177178
store(parse_command_line(argc, argv, cliargs_desc), vm);
@@ -305,6 +306,25 @@ bool process_cli(int argc, char ** argv, LocalproxyConfig &cfg, ptree &settings,
305306
}
306307
}
307308

309+
if (vm.count("destination-client-type"))
310+
{
311+
string type = vm["destination-client-type"].as<string>();
312+
if (type == "V1")
313+
{
314+
BOOST_LOG_TRIVIAL(info) << "setting source protocol to V1";
315+
cfg.is_v1_message_format = true;
316+
}
317+
else if (type == "V2")
318+
{
319+
BOOST_LOG_TRIVIAL(info) << "setting source protocol to V2";
320+
cfg.is_v2_message_format = true;
321+
}
322+
else
323+
{
324+
BOOST_LOG_TRIVIAL(warning) << "unknown value for destination-client-type, assuming default protocol V3.";
325+
}
326+
}
327+
308328
/** Invalid input combination for: -s, -d and --mode
309329
* 1. -s and -d should NOT used together
310330
* 2. -s and mode value is dst/destination should NOT used together

0 commit comments

Comments
 (0)