-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from gkc/socket-authenticator-option
feat: Socket authenticators and data transformers
- Loading branch information
Showing
13 changed files
with
1,442 additions
and
417 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: unit_tests | ||
|
||
permissions: | ||
contents: read | ||
|
||
on: | ||
workflow_dispatch: | ||
push: | ||
branches: | ||
- trunk | ||
|
||
pull_request: | ||
branches: | ||
- trunk | ||
|
||
jobs: | ||
unit_tests: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 | ||
- uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # v1.6.1 | ||
- name: dart pub get | ||
run: dart pub get | ||
- name: dart analyze | ||
run: dart analyze | ||
- name: dart test | ||
run: dart test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,85 @@ | ||
<h1><a href="https://atsign.com#gh-light-mode-only"><img width=250px | ||
src="https://atsign.com/wp-content/uploads/2022/05/atsign-logo-horizontal-color2022.svg#gh-light-mode-only" | ||
alt="The Atsign Foundation"></a> | ||
<a href="https://atsign.com#gh-dark-mode-only"><img width=250px | ||
src="https://atsign.com/wp-content/uploads/2023/08/atsign-logo-horizontal-reverse2022-Color.svg#gh-dark-mode-only" | ||
alt="The Atsign Foundation"></a></h1> | ||
<h1> | ||
<a href="https://atsign.com#gh-light-mode-only"> | ||
<img width=250px | ||
src="https://atsign.com/wp-content/uploads/2022/05/atsign-logo-horizontal-color2022.svg#gh-light-mode-only" | ||
alt="The Atsign Foundation"> | ||
</a> | ||
<a href="https://atsign.com#gh-dark-mode-only"> | ||
<img width=250px | ||
src="https://atsign.com/wp-content/uploads/2023/08/atsign-logo-horizontal-reverse2022-Color.svg#gh-dark-mode-only" | ||
alt="The Atsign Foundation"> | ||
</a> | ||
</h1> | ||
|
||
# Socket Connector | ||
|
||
Connect two TCP sockets and optionally display the traffic. | ||
|
||
## Features | ||
|
||
TCP Sockets come in two flavours a server and a client, you have to be one or | ||
the other. If you want to join two clients or two servers this package | ||
includes all the tools you need. to connect servers to servers and clients to | ||
clients. Why would you need this type of service? To create a rendezvous | ||
service that two clients can connect to for example or to join two servers | ||
with a shared client. Also included is a client to server, this acts as a | ||
simple TCP proxy and as with all the services you can optionally set the | ||
verbose flag and the readable (ascii) characters that are being transmitted | ||
and received will be displayed. | ||
TCP Sockets come in two flavours - a server and a client; you have to be one or | ||
the other. If you want to join two clients or two servers this package includes | ||
all the tools you need to connect servers to servers and clients to clients. | ||
Why would you need this type of service? To create a rendezvous service that two | ||
clients can connect to for example or to join two servers with a shared client. | ||
Also included is a client to server, this acts as a simple TCP proxy and as with | ||
all the services you can optionally set the verbose flag in order to see | ||
more info about what is happening, and the logTraffic flag in order to see the | ||
readable (ascii) characters that are being transmitted and received. | ||
|
||
## Getting started | ||
|
||
dart pub add socket_connector | ||
|
||
## Usage | ||
|
||
The following code will open two server sockets and connect them and display | ||
any traffic that goes between the sockets. You can test this using ncat to | ||
connect to the two listening ports in two sessions. You will see what is typed | ||
in one window appear in the other plus see the data on at the dart program. | ||
The following code will open two server sockets and connect them and display any | ||
traffic that goes between the sockets. You can test this using ncat to connect | ||
to the two listening ports in two sessions. You will see what is typed in one | ||
window appear in the other plus see the data on at the dart program. | ||
|
||
[![asciicast](https://asciinema.org/a/cglnKVtH16DPwWfqGJXgPMCKn.svg)](https://asciinema.org/a/cglnKVtH16DPwWfqGJXgPMCKn) | ||
```dart | ||
// Once running use ncat to check the sockets | ||
SocketConnector socketConnector = await SocketConnector.serverToServer( | ||
addressA: InternetAddress.anyIPv4, | ||
addressB: InternetAddress.anyIPv4, | ||
portA: 9000, | ||
portB: 8000, | ||
verbose: true, | ||
logTraffic: true, | ||
); | ||
print('Sender Port: ${socketConnector.sideAPort}' | ||
' Receiver Port: ${socketConnector.sideBPort}'); | ||
``` | ||
|
||
`ncat localhost 8000` | ||
|
||
`ncat localhost 9000` | ||
|
||
```dart | ||
SocketConnector socketStream = await SocketConnector.serverToServer( | ||
serverAddressA: InternetAddress.anyIPv4, | ||
serverAddressB: InternetAddress.anyIPv4, | ||
serverPortA: 9000, | ||
serverPortB: 8000, | ||
verbose: true); | ||
print( | ||
'Sender Port: ${socketStream.senderPort().toString()} Receiver Port: ${socketStream.receiverPort().toString()}'); | ||
} | ||
``` | ||
[![asciicast](https://asciinema.org/a/cglnKVtH16DPwWfqGJXgPMCKn.svg)](https://asciinema.org/a/cglnKVtH16DPwWfqGJXgPMCKn) | ||
|
||
|
||
## Additional information | ||
|
||
TODO: All SocketConnectors only acceot a single session currently, so there | ||
is one type of connection that is currently missing which is server to socket | ||
which could allow separate sessions as clients connect. | ||
Excerpted from the SocketConnector class's documentation: | ||
``` | ||
/// Typical usage is via the [serverToServer], [serverToSocket], | ||
/// [socketToSocket] and [socketToServer] methods which are different flavours | ||
/// of the same functionality - to relay information from one socket to another. | ||
/// | ||
/// - Upon creation, a [Timer] will be created for [timeout] duration. The | ||
/// timer callback, when it executes, calls [close] if [connections] | ||
// is empty | ||
/// - When an established connection is closed, [close] will be called if | ||
/// [connections] is empty | ||
/// - New [Connection]s are added to [connections] when both | ||
/// [pendingA] and [pendingB] have at least one entry | ||
/// - When [verbose] is true, log messages will be logged to [logger] | ||
/// - When [logTraffic] is true, socket traffic will be logged to [logger] | ||
``` | ||
|
||
TODO: Currently only `SocketConnector.serverToServer` handles more than one | ||
pair of sockets in a given session; code needs to be added to `serverToSocket` | ||
and `socketToServer` so that when a new connection is received to the | ||
serverSocket, then a new connection is opened to the address and port on the | ||
other side. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import 'dart:async'; | ||
import 'dart:io'; | ||
import 'dart:typed_data'; | ||
|
||
import 'package:socket_connector/socket_connector.dart'; | ||
|
||
void main() async { | ||
Duration demoConnectorTimeout = Duration(seconds: 30); | ||
|
||
stdout.writeln("Select test scenario"); | ||
stdout.writeln("1.No side authenticated 0----0"); | ||
stdout.writeln("2.Both sides authenticated 0#----#0"); | ||
stdout.writeln("3.Only sender authenticated 0#----0"); | ||
stdout.writeln("4.Only receiver authenticated 0----#0"); | ||
stdout.write("> "); | ||
|
||
String? option = stdin.readLineSync(); | ||
switch (option) { | ||
case "1": | ||
SocketConnector connector = await SocketConnector.serverToServer( | ||
verbose: true, | ||
timeout: demoConnectorTimeout, | ||
); | ||
|
||
stdout.writeln('You may now telnet to' | ||
' Sender Port: ${connector.sideAPort}' | ||
' Receiver Port: ${connector.sideBPort}'); | ||
stdout.writeln('There is no authentication on either side'); | ||
|
||
await connector.done; | ||
break; | ||
|
||
case "2": | ||
SocketConnector connector = await SocketConnector.serverToServer( | ||
verbose: true, | ||
timeout: demoConnectorTimeout, | ||
socketAuthVerifierA: goAuthVerifier, | ||
socketAuthVerifierB: goAuthVerifier, | ||
); | ||
|
||
stdout.writeln('You may now telnet to' | ||
' Sender Port: ${connector.sideAPort}' | ||
' Receiver Port: ${connector.sideBPort}'); | ||
stdout.writeln('Both sides require authentication - to authenticate,' | ||
' type \'go\' '); | ||
await connector.done; | ||
break; | ||
|
||
case "3": | ||
SocketConnector connector = await SocketConnector.serverToServer( | ||
verbose: true, | ||
timeout: demoConnectorTimeout, | ||
socketAuthVerifierA: goAuthVerifier, | ||
); | ||
|
||
stdout.writeln('You may now telnet to' | ||
' Sender Port: ${connector.sideAPort}' | ||
' Receiver Port: ${connector.sideBPort}'); | ||
stdout.writeln( | ||
'${connector.sideAPort} requires authentication - to authenticate,' | ||
' type \'go\' '); | ||
|
||
await connector.done; | ||
break; | ||
|
||
case "4": | ||
SocketConnector connector = await SocketConnector.serverToServer( | ||
verbose: true, | ||
timeout: demoConnectorTimeout, | ||
socketAuthVerifierB: goAuthVerifier, | ||
); | ||
|
||
stdout.writeln('You may now telnet to' | ||
' Sender Port: ${connector.sideAPort}' | ||
' Receiver Port: ${connector.sideBPort}'); | ||
stdout.writeln( | ||
'${connector.sideBPort} requires authentication - to authenticate,' | ||
' type \'go\' '); | ||
await connector.done; | ||
break; | ||
|
||
default: | ||
stderr.writeln("Enter 1, 2, 3 or 4"); | ||
exit(1); | ||
} | ||
exit(0); | ||
} | ||
|
||
Future<(bool, Stream<Uint8List>?)> goAuthVerifier(Socket socket) async { | ||
Completer<(bool, Stream<Uint8List>?)> completer = Completer(); | ||
bool authenticated = false; | ||
StreamController<Uint8List> sc = StreamController(); | ||
socket.listen((Uint8List data) { | ||
if (authenticated) { | ||
sc.add(data); | ||
} else { | ||
final message = String.fromCharCodes(data); | ||
|
||
if (message.startsWith("go")) { | ||
authenticated = true; | ||
completer.complete((true, sc.stream)); | ||
} | ||
|
||
if (message.startsWith("dontgo")) { | ||
authenticated = false; | ||
completer.complete((false, null)); | ||
} | ||
} | ||
}, onError: (error) => sc.addError(error), onDone: () => sc.close()); | ||
return completer.future; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import 'dart:io'; | ||
import 'dart:isolate'; | ||
|
||
import 'package:socket_connector/socket_connector.dart'; | ||
|
||
void main(List<String> arguments) async { | ||
int portA = 8000; | ||
int portB = 9000; | ||
Future<void> connect() async { | ||
SocketConnector connector = await SocketConnector.serverToServer( | ||
addressA: InternetAddress.anyIPv4, | ||
addressB: InternetAddress.anyIPv4, | ||
portA: portA, | ||
portB: portB, | ||
verbose: true, | ||
timeout: Duration(milliseconds: 500), | ||
); | ||
print('${DateTime.now()} | SocketConnector ready:' | ||
' senderPort: ${connector.sideAPort}' | ||
' receiverPort: ${connector.sideBPort}'); | ||
await connector.done; | ||
print('${DateTime.now()} | SocketConnector done'); | ||
} | ||
|
||
try { | ||
await Isolate.run(connect); | ||
} on FormatException catch (e) { | ||
print(e.message); | ||
} | ||
} |
Oops, something went wrong.