Rename the tty-sender to tty-share

The rename came with quite a lot of changes, including some refactoring
in the Makefile which wouldn't make any more sense after the rename.
pull/14/merge v0.4
Vasile Popescu 5 years ago
parent f358a30a55
commit 16e464da9b

1
.gitignore vendored

@ -9,3 +9,4 @@ tty_sender*
tty_server*
tmp-*
tty-server/assets_bundle.go
out/

@ -1,5 +1,6 @@
TTY_SERVER=./out/tty-server
TTY_SENDER=./out/tty-sender
DEST_DIR=./out
TTY_SERVER=$(DEST_DIR)/tty-server
TTY_SHARE=$(DEST_DIR)/tty-share
# We need to make sure the assets_bundle is in the list only onces in both these two special cases:
# a) first time, when the assets_bundle.go is generated, and b) when it's already existing there,
@ -7,51 +8,58 @@ TTY_SENDER=./out/tty-sender
# Unfortunately, the assets_bundle.go seems to have to be in the same folder as the rest of the
# server sources, so that's why all this mess
TTY_SERVER_SRC=$(filter-out ./tty-server/assets_bundle.go, $(wildcard ./tty-server/*.go)) ./tty-server/assets_bundle.go
TTY_SENDER_SRC=$(wildcard ./tty-sender/*.go)
EXTRA_BUILD_DEPS=$(wildcard ./common/*go)
TTY_SHARE_SRC=$(wildcard ./tty-share/*.go)
COMMON_SRC=$(wildcard ./common/*go)
TTY_SERVER_ASSETS=$(wildcard frontend/public/*)
all: $(TTY_SERVER) $(TTY_SENDER)
## tty-share command (the client/sender side)
all: $(TTY_SHARE) # do this by default, so no need to mess up with building the frontend
@echo "All done"
$(TTY_SERVER): $(TTY_SERVER_SRC) $(EXTRA_BUILD_DEPS)
# Building the server and tty-share
$(TTY_SERVER): $(TTY_SERVER_SRC) $(COMMON_SRC)
go build -o $@ $(TTY_SERVER_SRC)
$(TTY_SENDER): $(TTY_SENDER_SRC) $(EXTRA_BUILD_DEPS)
go build -o $@ $(TTY_SENDER_SRC)
$(TTY_SHARE): $(TTY_SHARE_SRC) $(COMMON_SRC)
go build -o $@ $(TTY_SHARE_SRC)
tty-server/assets_bundle.go: $(TTY_SERVER_ASSETS)
go-bindata --prefix frontend/public/ -o $@ $^
# We only care about creating release binaries for the sender side
dist: frontend ./out/tty-sender.linux.zip ./out/tty-sender.osx.zip
%.zip: %
zip $@ $^
./out/tty-sender.osx: $(TTY_SENDER_SRC) $(EXTRA_BUILD_DEPS)
GOOS=darwin go build -o $@ $(TTY_SENDER_SRC)
frontend: force
cd frontend && npm run build && cd -
force:
# Other different targets
./out/tty-sender.linux: $(TTY_SENDER_SRC) $(EXTRA_BUILD_DEPS)
GOOS=linux go build -o $@ $(TTY_SENDER_SRC)
## tty-share release binaries for Linux and OSX
# tty-share: $(OUT_DIR)/tty-share.osx $(OUT_DIR)/tty-share.linux
release: $(TTY_SHARE).osx.zip $(TTY_SHARE).lin.zip
@echo "Done: " $@
frontend: FORCE
cd frontend && npm run build && cd -
$(TTY_SHARE).lin: $(TTY_SHARE_SRC) $(COMMON_SRC)
GOOS=linux go build -o $@ $(TTY_SHARE_SRC)
$(TTY_SHARE).osx: $(TTY_SHARE_SRC) $(COMMON_SRC)
GOOS=darwin go build -o $@ $(TTY_SHARE_SRC)
clean:
rm -f $(TTY_SERVER) $(TTY_SENDER)
rm -fr frontend/out/
rm -fr out/
rm -fr frontend/public
@echo "Cleaned"
# Runs the server, without TLS/HTTPS (no need for localhost testing)
runs: $(TTY_SERVER)
./$(TTY_SERVER) --url http://localhost:9090 --web_address :9090 --sender_address :7654 -frontend_path ./frontend/public
## Server release binarires
# Runs the sender, without TLS (no need for localhost testing)
runc: $(TTY_SENDER)
./$(TTY_SENDER) --useTLS=false --server localhost:7654
## Development helper targets
### Runs the server, without TLS/HTTPS (no need for localhost testing)
runs: $(TTY_SERVER)
$(TTY_SERVER) --url http://localhost:9090 --web_address :9090 --sender_address :7654 -frontend_path ./frontend/public
### Runs the sender, without TLS (no need for localhost testing)
runc: $(TTY_SHARE)
$(TTY_SHARE) --useTLS=false --server localhost:7654
test:
@go test github.com/elisescu/tty-share/testing -v
FORCE:

@ -4,11 +4,11 @@ It is a very simple command line tool that gives remote access to a UNIX termina
The most important part about it is that it requires **no setup** on the remote end. All I need to give remote access to the terminal (a bash/shell session) is the binary tool, and the remote person only needs to open a secret URL in their browser.
The project consists of two command line utilities: `tty-sender` and `tty-server`.
The project consists of two command line utilities: `tty-share` and `tty-server`.
The `tty-sender` is used on the machine that wants to share the terminal, and it connects to the server to generate a secret URL, over which the terminal can be viewed in the browser.
The `tty-share` is used on the machine that wants to share the terminal, and it connects to the server to generate a secret URL, over which the terminal can be viewed in the browser.
The server runs at [tty-share.com](https://tty-share.com), so you only need the `tty-server1` binary if you want to host it yourself.
The server runs at [tty-share.com](https://tty-share.com), so you only need the `tty-server` binary if you want to host it yourself.
![demo](doc/demo.gif)
@ -18,24 +18,24 @@ The documentation is very poor now. More will follow. [This](doc/architecture.md
## Running
Download the latest `tty-sender` binary [release](https://github.com/elisescu/tty-share/releases), and run it:
Download the latest `tty-share` binary [release](https://github.com/elisescu/tty-share/releases), and run it:
```
bash$ tty-sender
bash$ tty-share
Web terminal: https://go.tty-share.com/s/J5U6FAwChWNP0I9VQ9XyPqVD6m6IpI8-sBLRiz98XMA=
bash$
```
## Building `tty-sender` locally
## Building `tty-share` locally
If you want to just build the tool that shares your terminal, and not the server, then simply do a
```
make out/tty-sender
make out/tty-share
```
This way you don't have to bother about the server side, nor about building the frontend, and you will get only the `tty-sender` cmd line tool, inside `out` folder.
This way you don't have to bother about the server side, nor about building the frontend, and you will get only the `tty-share` cmd line tool, inside `out` folder.
## Building and running everything
@ -65,7 +65,7 @@ make runc
Will run the sender and connect it to the server running on the local host (so the above command has
to be ran first).
For more info, on how to run, see the Makefile, or the help of the two binaries (`tty-sender` and `tty_receiver`)
For more info, on how to run, see the Makefile, or the help of the two binaries (`tty-share` and `tty_receiver`)
The project didn't follow the typical way of building go applications, because everything is put in one single project and package, for the ease of development, and also because the bundle containing the frontend has to be built as well. Perhaps there's a better way, but this works for now.
@ -73,7 +73,7 @@ The project didn't follow the typical way of building go applications, because e
## TLS and HTTPS
At the moment the `tty-sender` supports connecting over a TLS connection to the server, but the server doesn't have that implemented yet. However, the server can easily run behind a proxy which can take care of encrypting the connections from the senders and receivers (doing both TLS and HTTPS), without the server knowing about it.
At the moment the `tty-share` supports connecting over a TLS connection to the server, but the server doesn't have that implemented yet. However, the server can easily run behind a proxy which can take care of encrypting the connections from the senders and receivers (doing both TLS and HTTPS), without the server knowing about it.
The server at [tty-share](https://tty-share.com) is using both TLS and https for both sides, relying on nginx reverse proxy.
@ -84,11 +84,11 @@ However, the `tty-server` should maybe also have native support for being able t
There are several improvements, and additions that can be done further:
* Update and write more tests.
* Add support for listening on sender connections over TLS.
* React on the `tty-receiver` window size as well. For now, the size of the terminal window is decided by the `tty-sender`, but perhaps both the sender and receiver should have a say in this.
* React on the `tty-receiver` window size as well. For now, the size of the terminal window is decided by the `tty-share`, but perhaps both the sender and receiver should have a say in this.
* Read only sessions, where the `tty_receiver` side can only watch, and cannot interact with the terminal session.
* Command line `tty_receiver` can be implemented as well, without the need of a browser.
* End-to-end encryption. Right now, the server can see what messages the sender and receiver are exchanging, but an end-to-end encryption layer can be built on top of this. It has been thought from the beginning, but it's just not implemented. The terminal IO messages are packed in protocol messages, and the payload can be easily encrypted with a shared key derived from a password that only the sender and receiver know.
* Notify the `tty-sender` user when a `tty-receiver` got connected (when the remote person opened the URL in their browser).
* Notify the `tty-share` user when a `tty-receiver` got connected (when the remote person opened the URL in their browser).
* Many other

@ -5,20 +5,20 @@ High level architecture
```
Alice
+-tty_sender--------------+ +-tty_server----------------+ Bob
+-tty-share---------------+ +-tty-server----------------+ Bob
| | | | https:// +------------+
| +------+ +-----+ | TLS | +------+ +---------+ | wss:// |tty_receiver|
| +------+ +-----+ | TLS | +------+ +---------+ | wss:// |tty-receiver|
| | bash | <-+-> |proto| <---------------> | proto| <-> | session | +-----+------> | 1 |
| +------+ | +-----+ | | +------+ +---------+ | | +------------+
| | | | | |
| +-> pty | +---------------------------+ | +------------+
+-------------------------+ +------> |tty_receiver|
+-------------------------+ +------> |tty-receiver|
| 2 |
+------------+
```
Alice wants to share a terminal session with Bob, so she starts `tty_sender` on her machine, inside the terminal. `tty_sender` then connects to the `tty_server` and starts inside a `bash` process. It then puts the terminal in which it was started in RAW mode, and the stdin and stdout are multiplexed to/from the `bash` process it started, and the remote connection to the `tty_server`. On the server side, a session is created, which connects the `tty_sender` connection with the future `tty_receiver` instances, running in the browser. The `tty_receiver` runs inside the browser, on top of [xterm.js](https://xtermjs.org/), and is served by the server, via a unique session URL. Alice has to send this unique URL to Bob.
Alice wants to share a terminal session with Bob, so she starts `tty-share` on her machine, inside the terminal. `tty-share` then connects to the `tty-server` and starts inside a `bash` process. It then puts the terminal in which it was started in RAW mode, and the stdin and stdout are multiplexed to/from the `bash` process it started, and the remote connection to the `tty-server`. On the server side, a session is created, which connects the `tty-share` connection with the future `tty-receiver` instances, running in the browser. The `tty-receiver` runs inside the browser, on top of [xterm.js](https://xtermjs.org/), and is served by the server, via a unique session URL. Alice has to send this unique URL to Bob.
Once the connection is established, Bob can then interact inside the browser with the `bash` session started by Alice. When Bob presses, for example, the key `a`, this is detected by `xterm.js` and sent via a websockets connection to the server side. From there, it is sent to the `tty_sender` which sends it to the pseudo terminal attached to the `bash` process started inside `tty_sender`. Then character `a` is received via the standard output of the `bash` command, and is sent from there both to the standard output of the `tty_sender`, so Alice can see it, and also to the `tty_receiver` (via the server), so Bob can see it too.
Once the connection is established, Bob can then interact inside the browser with the `bash` session started by Alice. When Bob presses, for example, the key `a`, this is detected by `xterm.js` and sent via a websockets connection to the server side. From there, it is sent to the `tty-share` which sends it to the pseudo terminal attached to the `bash` process started inside `tty-share`. Then character `a` is received via the standard output of the `bash` command, and is sent from there both to the standard output of the `tty-share`, so Alice can see it, and also to the `tty-receiver` (via the server), so Bob can see it too.
More specific details on how this is implemented, can be seen in the source code of the `tty_sender`.
More specific details on how this is implemented, can be seen in the source code of the `tty-share`.

@ -1,60 +0,0 @@
Information here might not be accurate, as this file was used as a dump of all random ideas that came at the beginning of the project. Many of them are not implemented, or were abandoned.
## Architecture
```
B
A +-------------+
+-----------------+ | | C
| tty_sender(cmd) | <+-> | tty_server | +-------------------+
+-----------------+ | | <-+->| tty_receiver(web) |
| | +-------------------+
| |
| | D
| | +-------------------+
| | <-+->| tty_receiver(ssh) |
| | +-------------------+
| |
M | | N
+-----------------+ | | +-------------------+
| tty_sender(cmd) | <+-> | | <-+->| tty_receiver(web) |
+-----------------+ +-------------+ +-------------------+
```
##
```
A <-> C, D
M <-> N
```
### A
Where A is the tty_sender, which will be used by the user Alice to share her terminal session. She will start it in the command line, with something like:
```
tty-share bash
```
If everything is successful, A will output to stdout 3 URLs, which, something like:
```
1. read-only: https://tty-share.io/s/0ENHQGjqaB
2. write: https://tty-share.io/s/4HGFN8jahg
3. terminal: ssh://0ENHQGjqaB@tty-share.io.com -p1234
4. admin: http://localhost:5456/admin
```
Url number 1. will provide read-only access to the command shared. Which means the user will not be able to interact with the terminal.
Url number 2. will allow the user to interact with the terminale.
Url number 3. ssh access, to follow the remote command from a remote terminal.
Url number 4. provides an interface to control various options related to sharing.
### B
B is the tty_server, which will be publicly accessible and to which the tty_sender will connect to. On the tty_server will be created te sessions (read-only and write), and URLs will be returned back to A. Whent the command that A started exits, the session will end, so C should know.
### C
C is the browser via which user Chris will receive the terminal which Alice has shared.
### Corner cases
Corner cases to test for:
* AB connection cannot be done
* AB is established, but CB can't be done
* AB connection can go down
* CB connection can go down:
- The websocket connection can go down
- The browser refreshed. Command is still running, so the session is still valid
* All users from the C side close their connection
* The commmand finishes

@ -13,7 +13,7 @@ var MainLogger = logrus.New()
func main() {
webAddress := flag.String("web_address", ":80", "The bind address for the web interface")
senderAddress := flag.String("sender_address", ":6543", "The bind address for the tty_sender connections")
senderAddress := flag.String("sender_address", ":6543", "The bind address for the tty-share connections")
url := flag.String("url", "http://localhost", "The public web URL the server will be accessible at")
frontendPath := flag.String("frontend_path", "", "The path to the frontend resources")
flag.Parse()

@ -159,14 +159,14 @@ func (session *ttyShareSession) HandleReceiver(rawConn *WSConnection) {
// Sending the initial size of the window, if we have one
rcvProtoConn.WriteRawData(lastWindowSize)
// Notify the tty-sender that we got a new receiver connected
// Notify the tty-share that we got a new receiver connected
msgRcvConnected, err := MarshalMsg(MsgTTYSenderNewReceiverConnected{
Name: rawConn.Address(),
})
senderConn.WriteRawData(msgRcvConnected)
if err != nil {
log.Errorf("Cannot notify tty-sender. Error: %s", err.Error())
log.Errorf("Cannot notify tty sender. Error: %s", err.Error())
}
// Wait until the TTYReceiver will close the connection on its end

@ -76,7 +76,7 @@ func main() {
// Wait until the user presses Enter
fmt.Printf("Web terminal: %s\n\n\r", reply.URLWebReadWrite)
//TODO: if the user on the remote side presses keys, and so messages are sent back to the
// tty_sender, they will be delivered all at once, after Enter has been pressed. Fix that.
// tty sender, they will be delivered all at once, after Enter has been pressed. Fix that.
ptyMaster := ptyMasterNew()
ptyMaster.Start(*commandName, strings.Fields(*commandArgs), func(cols, rows int) {

@ -30,7 +30,7 @@ func (pty *ptyMaster) Start(command string, args []string, winChangedCB onWindow
pty.windowChangedCB = winChangedCB
// Save the initial state of the terminal, before making it RAW. Note that this terminal is the
// terminal under which the tty_sender command has been started, and it's identified via the
// terminal under which the tty-share command has been started, and it's identified via the
// stdin file descriptor (0 in this case)
// We need to make this terminal RAW so that when the command (passed here as a string, a shell
// usually), is receiving all the input, including the special characters:
@ -117,7 +117,7 @@ func onWindowChanges(winChangedCb func(cols, rows int)) {
winChangedSig := make(chan os.Signal, 1)
signal.Notify(winChangedSig, syscall.SIGWINCH)
// The interface for getting window changes from the pty slave to its process, is via signals.
// In our case here, the tty_sender command (built in this project) is the client, which should
// In our case here, the tty-share command (built in this project) is the client, which should
// get notified if the terminal window in which it runs has changed. To get that, it needs to
// register for SIGWINCH signal, which is used by the kernel to tell process that the window
// has changed its dimentions.
Loading…
Cancel
Save