support for x2x and barrier KVM
This commit is contained in:
28
README.md
28
README.md
@@ -24,15 +24,31 @@ https://github.com/Akilan1999/laplace/tree/keyboard_mouse
|
||||
|
||||
|
||||
### Installation required to share keyboard and mouse
|
||||
We need to ensure that the client has SSH client installed.
|
||||
We use the popular open repository known as [x2x](https://github.com/dottedmag/x2x).
|
||||
|
||||
Note: x2x runs on top of SSH.
|
||||
Currently, you can either use [x2x](https://github.com/dottedmag/x2x) or [Barrier KVM]()
|
||||
We need to ensure that the client has SSH client installed or Barrierc.
|
||||
|
||||
#### What is x2x?
|
||||
x2x allows the keyboard, mouse on one X display to be used to control another X
|
||||
display. It also shares X clipboards between the displays.
|
||||
|
||||
Note: x2x runs on top of SSH.
|
||||
|
||||
#### What is Barrier kvm?
|
||||
|
||||
Barrier is software that mimics the functionality of a KVM switch, which historically would allow you to use a single
|
||||
keyboard and mouse to control multiple computers by physically turning a dial on the box to switch the machine you're
|
||||
controlling at any given moment. Barrier does this in software, allowing you to tell it which machine to control by
|
||||
moving your mouse to the edge of the screen, or by using a keypress to switch focus to a different system.
|
||||
|
||||
#### Barrier KVM build status and links to install
|
||||
|Platform |Build Status|
|
||||
| --:|:-- |
|
||||
|Linux |[](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)|
|
||||
|Mac |[](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)|
|
||||
|Windows Debug |[](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)|
|
||||
|Windows Release|[](https://dev.azure.com/debauchee/Barrier/_build/latest?definitionId=1&branchName=master)|
|
||||
|Snap |[](https://build.snapcraft.io/user/debauchee/barrier)|
|
||||
|
||||
|
||||
### Build from source
|
||||
|
||||
@@ -51,6 +67,8 @@ apt install -y git
|
||||
apt install -y openssh-server
|
||||
## Installing x2x
|
||||
apt install -y x2x
|
||||
## Installing barrier
|
||||
apt install -y barrier
|
||||
## Installing chromium
|
||||
wget https://github.com/RobRich999/Chromium_Clang/releases/download/v94.0.4585.0-r904940-linux64-deb-avx/chromium-browser-unstable_94.0.4585.0-1_amd64.deb
|
||||
apt install -y ./chromium-browser-unstable_94.0.4585.0-1_amd64.deb
|
||||
@@ -117,11 +135,13 @@ cd /path/.local/share/Steam/steamapps/common/X-Plane\ 11/
|
||||
```
|
||||
#### Open config file
|
||||
```bash
|
||||
|
||||
{
|
||||
"barrierhostname": "<barrier host name>",
|
||||
"ipaddress": "0.0.0.0",
|
||||
"rooms": "<path to room.json file>",
|
||||
"scripttoexecute": "<path to script to execute (In case the Xplane 11 script)>",
|
||||
"sshpassword": "<SSH password for x2x>",
|
||||
"systemusername": "<system username>"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -47,7 +47,7 @@ func SetDefaults() error {
|
||||
defaultPath = curDir + "/"
|
||||
|
||||
// Get system username
|
||||
user ,err := user.Current()
|
||||
user, err := user.Current()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func SetDefaults() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ConfigInit()(*Config,error) {
|
||||
func ConfigInit() (*Config, error) {
|
||||
|
||||
curDir := os.Getenv("REMOTEGAMING")
|
||||
//Setting current directory to default path
|
||||
@@ -97,7 +97,7 @@ func ConfigInit()(*Config,error) {
|
||||
configPaths = append(configPaths, defaultPath)
|
||||
|
||||
//Add all possible configurations paths
|
||||
for _,v := range configPaths {
|
||||
for _, v := range configPaths {
|
||||
viper.AddConfigPath(v)
|
||||
}
|
||||
|
||||
@@ -105,23 +105,23 @@ func ConfigInit()(*Config,error) {
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
// If the error thrown is config file not found
|
||||
//Sets default configuration to viper
|
||||
for k,v := range defaults {
|
||||
viper.SetDefault(k,v)
|
||||
for k, v := range defaults {
|
||||
viper.SetDefault(k, v)
|
||||
}
|
||||
viper.SetConfigName(configName)
|
||||
viper.SetConfigFile(configFile)
|
||||
viper.SetConfigType(configType)
|
||||
|
||||
if err = viper.WriteConfig(); err != nil {
|
||||
return nil,err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Adds configuration to the struct
|
||||
var config Config
|
||||
if err := viper.Unmarshal(&config); err != nil {
|
||||
return nil,err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &config,nil
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
@@ -6,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
func TestConfigInit(t *testing.T) {
|
||||
_,err := ConfigInit()
|
||||
_, err := ConfigInit()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"laplace/config"
|
||||
"github.com/Akilan1999/remotegameplay/config"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@ type Barrier struct {
|
||||
}
|
||||
|
||||
// CreateBarrierSession Command to run "barrier.barrierc --debug INFO -f 192.168.0.175"
|
||||
func (b *Barrier)CreateBarrierSession() error {
|
||||
func (b *Barrier) CreateBarrierSession() error {
|
||||
//Checks if barrier client exists
|
||||
|
||||
if err := DetectBarrier(); err != nil {
|
||||
@@ -31,7 +31,7 @@ func (b *Barrier)CreateBarrierSession() error {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.Command("sudo","-u",configResp.SystemUsername,"barrierc","-f","--debug", "DEBUG" ,"--log", "/tmp/barrier.log",b.IPAddress)
|
||||
cmd := exec.Command("sudo", "-u", configResp.SystemUsername, "barrierc", "-f", "--debug", "DEBUG", "--log", "/tmp/barrier.log", b.IPAddress)
|
||||
|
||||
// USE THE FOLLOWING TO DEBUG
|
||||
//cmdReader, err := cmd.StdoutPipe()
|
||||
@@ -62,16 +62,15 @@ func (b *Barrier)CreateBarrierSession() error {
|
||||
|
||||
println(cmd.Path)
|
||||
|
||||
|
||||
// Saves the state of the command in the struct
|
||||
b.Process = cmd
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteBarrierSession Deletes barrier client session running
|
||||
func (b *Barrier)DeleteBarrierSession() error {
|
||||
func (b *Barrier) DeleteBarrierSession() error {
|
||||
// Halts the process
|
||||
cmd := exec.Command("pkill" ,"barrierc")
|
||||
cmd := exec.Command("pkill", "barrierc")
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package core
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/Akilan1999/remotegameplay/config"
|
||||
"github.com/gorilla/websocket"
|
||||
"io/ioutil"
|
||||
"laplace/config"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -89,7 +89,7 @@ func (room *Room) newSessionID() string {
|
||||
}
|
||||
|
||||
// Write to rooms.json file
|
||||
func (room *Room)writeToFile() error {
|
||||
func (room *Room) writeToFile() error {
|
||||
file, err := json.MarshalIndent(room, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -114,15 +114,14 @@ func (room *Room)writeToFile() error {
|
||||
func ReadRoomsFile() (*Room, error) {
|
||||
config, err := config.ConfigInit()
|
||||
if err != nil {
|
||||
return nil,err
|
||||
return nil, err
|
||||
}
|
||||
jsonFile, err := os.Open(config.Rooms)
|
||||
// if we os.Open returns an error then handle it
|
||||
if err != nil {
|
||||
return nil,err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
// defer the closing of our jsonFile so that we can parse it later on
|
||||
defer jsonFile.Close()
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Akilan1999/remotegameplay/config"
|
||||
"github.com/gorilla/websocket"
|
||||
"laplace/config"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -23,11 +23,11 @@ var upgrader = websocket.Upgrader{
|
||||
func sendHeartBeatWS(ticker *time.Ticker, conn *websocket.Conn, quit chan struct{}) {
|
||||
for {
|
||||
select {
|
||||
case <- ticker.C:
|
||||
case <-ticker.C:
|
||||
_ = conn.WriteJSON(WSMessage{
|
||||
Type: "beat",
|
||||
})
|
||||
case <- quit:
|
||||
case <-quit:
|
||||
log.Println("heartbeat stopped")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,19 +3,20 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>Laplace</title>
|
||||
<title>RemoteGamePlay</title>
|
||||
<link rel="stylesheet" href="/static/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/main.css?v=0.0.5">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar">
|
||||
<a class="navbar-brand text-dark" href="/">Laplace</a>
|
||||
<a class="navbar-brand text-dark" href="/">RemoteGamePlay</a>
|
||||
<span class="navbar-brand header-room" id="room-text"></span>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<div class="panel" id="panel">
|
||||
<p> based on the open source project Laplace </p>
|
||||
<p class="help-text">
|
||||
<b>Laplace</b> is an open-source project to enable screen sharing directly via browser.
|
||||
Made possible using WebRTC for low latency peer-to-peer connections,
|
||||
@@ -45,18 +46,18 @@
|
||||
<div class="form-group">
|
||||
<input id="inputRoomID" type="text" class="form-control form-control-lg text-center" placeholder="Enter room ID" required>
|
||||
</div>
|
||||
<!-- <h4>Connect to Barrier KVM (Beta)</h4>-->
|
||||
<!-- <p class="help-text">-->
|
||||
<!-- This is a feature is still on beta testing. This feature will ensure that you can share the keyboard-->
|
||||
<!-- and mouse of the server machine.-->
|
||||
<!-- <br>-->
|
||||
<!-- <span class="text-success font-weight-bold"> Note: This only works if the laplace server has barrierc installed and the room name you are connecting-->
|
||||
<!-- too belongs to the server.</span>-->
|
||||
<!-- </p>-->
|
||||
<!-- <h6>Host Name: <span id="hostname"> Not detected </span></h6>-->
|
||||
<!-- <div class="form-group">-->
|
||||
<!-- <input id="barrierIP" type="text" class="form-control form-control-lg text-center" placeholder="IPV6 or IPV4 address">-->
|
||||
<!-- </div>-->
|
||||
<h4>Connect to Barrier KVM (Beta)</h4>
|
||||
<p class="help-text">
|
||||
This is a feature is still on beta testing. This feature will ensure that you can share the keyboard
|
||||
and mouse of the server machine.
|
||||
<br>
|
||||
<span class="text-success font-weight-bold"> Note: This only works if the laplace server has Barrierc installed and the room name you are connecting
|
||||
too belongs to the server.</span>
|
||||
</p>
|
||||
<h6>Host Name: <span id="hostname"> Not detected </span></h6>
|
||||
<div class="form-group">
|
||||
<input id="barrierIP" type="text" class="form-control form-control-lg text-center" placeholder="IPV6 or IPV4 address">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-dark btn-block" value="submit">Join</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -181,8 +182,8 @@
|
||||
<div class="container">
|
||||
<hr>
|
||||
<div class="text-center small" id="footer">
|
||||
<span>Laplace Project by Adam Jordan.</span>
|
||||
<a href="https://github.com/adamyordan/laplace">Source Code</a>
|
||||
<span><a href="https://github.com/Akilan1999/remotegameplay">RemoteGamePlay</a> Project by <a href="https://akilan.io">Akilan Selvacoumar</a> based on the fork
|
||||
of <a href="https://github.com/Akilan1999/laplace/tree/keyboard_mouse">Laplace</a>.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
2
go.mod
2
go.mod
@@ -1,4 +1,4 @@
|
||||
module laplace
|
||||
module github.com/Akilan1999/remotegameplay
|
||||
|
||||
go 1.16
|
||||
|
||||
|
||||
17
main.go
17
main.go
@@ -4,8 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"laplace/config"
|
||||
"laplace/core"
|
||||
"github.com/Akilan1999/remotegameplay/config"
|
||||
"github.com/Akilan1999/remotegameplay/core"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
func main() {
|
||||
addr := flag.String("addr", "0.0.0.0:443", "Listen address")
|
||||
port := flag.String("port", "8888", "port for running the server")
|
||||
tls := flag.Bool("tls", false, "Use TLS")
|
||||
setconfig := flag.Bool("setconfig", false, "Generates a config file")
|
||||
certFile := flag.String("certFile", "files/server.crt", "TLS cert file")
|
||||
@@ -23,7 +24,7 @@ func main() {
|
||||
roomInfo := flag.Bool("roomInfo", false, "Getting room id of headless server")
|
||||
killServer := flag.Bool("killServer", false, "Kills the laplace")
|
||||
killChromium := flag.Bool("killChromium", false, "Kills all chromuim")
|
||||
BinaryToExcute := flag.String("BinaryToExecute","","Providing path (i.e Absolute path) of binary to execute")
|
||||
BinaryToExcute := flag.String("BinaryToExecute", "", "Providing path (i.e Absolute path) of binary to execute")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
@@ -47,7 +48,6 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Running in headless mode
|
||||
if *headless {
|
||||
Config, err := config.ConfigInit()
|
||||
@@ -75,7 +75,7 @@ func main() {
|
||||
}
|
||||
|
||||
// Starting screen share headless
|
||||
cmd := exec.Command("chromium-browser" ,"--no-sandbox","--auto-select-desktop-capture-source=Entire screen","--url","https://" + Addr + ":8888/?mode=headless","--ignore-certificate-errors")
|
||||
cmd := exec.Command("chromium-browser", "--no-sandbox", "--auto-select-desktop-capture-source=Entire screen", "--url", "https://"+Addr+":"+*port+"/?mode=headless", "--ignore-certificate-errors")
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
@@ -96,7 +96,7 @@ func main() {
|
||||
|
||||
// kills laplace server
|
||||
if *killServer {
|
||||
cmd := exec.Command("pkill" ,"laplace")
|
||||
cmd := exec.Command("pkill", "remotegameplay")
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@@ -104,14 +104,13 @@ func main() {
|
||||
}
|
||||
// kills chromium server
|
||||
if *killChromium {
|
||||
cmd := exec.Command("pkill" ,"chromium")
|
||||
cmd := exec.Command("pkill", "chromium")
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if *tls {
|
||||
log.Println("Listening on TLS:", *addr)
|
||||
if err := http.ListenAndServeTLS(*addr, *certFile, *keyFile, server); err != nil {
|
||||
@@ -155,7 +154,7 @@ func Ip4or6(s string) string {
|
||||
|
||||
func RunTask(task string) error {
|
||||
// Halts the process
|
||||
cmd := exec.Command("sh",task)
|
||||
cmd := exec.Command("sh", task)
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
10
run.sh
10
run.sh
@@ -1,11 +1,11 @@
|
||||
# Starts server and runs it silently (i.e no output in the terminal)
|
||||
./laplace -tls -addr 0.0.0.0:8888 > /dev/null 2>&1 &
|
||||
./remotegameplay -tls -addr 0.0.0.0:${2} > /dev/null 2>&1 &
|
||||
# Starts chromium browser and runs it silently (i.e no output in the terminal)
|
||||
./laplace -headless -addr ${1} > /dev/null 2>&1 &
|
||||
./remotegameplay -headless -addr ${1} -port ${2} > /dev/null 2>&1 &
|
||||
# Lets the script sleep for 2 seconds
|
||||
sleep 2
|
||||
# Gets roomInfo and stores in the tmp directory as JSON
|
||||
./laplace -headless -roomInfo > /tmp/output.txt
|
||||
./remotegameplay -headless -roomInfo > /tmp/output.txt
|
||||
# Gets the room ID from the JSON file and outputs to tmp directory as text
|
||||
jq .id /tmp/output.txt > /tmp/test.txt
|
||||
# Gets roomID from tmp directory as text
|
||||
@@ -15,9 +15,9 @@ roomID=$(echo "$roomID" | tr -d '"')
|
||||
|
||||
# Checks if the IP address is a IPV6 or IPV4 address
|
||||
if [ "$1" != "${1#*[0-9].[0-9]}" ]; then
|
||||
echo "https://"${1}":8888/?roomID="${roomID}
|
||||
echo "https://"${1}":${2}/?roomID="${roomID}
|
||||
elif [ "$1" != "${1#*:[0-9a-fA-F]}" ]; then
|
||||
echo "https://["${1}"]:8888/?roomID="${roomID}
|
||||
echo "https://["${1}"]:${2}/?roomID="${roomID}
|
||||
else
|
||||
echo "Unrecognized IP format '$1'"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user