This commit is contained in:
2021-09-29 21:00:49 -03:00
commit fdb5553bd7
20 changed files with 1584 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
package ipcmux
import (
"context"
"log"
"net"
"net/http"
"os"
"runtime"
"strings"
)
const (
ENV_IPC = "IPC"
ENV_ROOTPID = "ROOT_PID"
)
var listenNet func(path string) (net.Listener, error)
var dialNet func(path string) (net.Conn, error)
func Dial(p string) (net.Conn, error) {
return dialNet(p)
}
func SetName(n string) {
os.Setenv(ENV_IPC, n)
}
func ResolveBinName() string {
bin := os.Getenv(ENV_IPC)
if bin == "" {
bin = os.Args[0]
if runtime.GOOS == "windows" {
bin = strings.Replace(bin, "\\", "/", -1)
}
parts := strings.Split(bin, "/")
bin = parts[len(parts)-1]
bin = strings.Replace(bin, ".exe", "", 1)
log.Printf("No IPC env var found, using %s to bind ipc", bin)
}
return bin
}
func Listen(p string) (net.Listener, error) {
log.Printf("IPC:: Will listen on: [%s]", p)
return listenNet(p)
}
func NewClient() *http.Client {
ret := &http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, b string) (net.Conn, error) {
ps := strings.Split(b, ":")
return dialNet(ps[0])
},
},
}
return ret
}
func Serve(mux *http.ServeMux) error {
go CheckRoot()
bin := ResolveBinName()
l, err := Listen(bin)
if err != nil {
return err
}
server := http.Server{
Handler: mux,
}
err = server.Serve(l)
return err
}
func ServeNamed(n string, mux *http.ServeMux) error {
go CheckRoot()
l, err := Listen(n)
if err != nil {
return err
}
server := http.Server{
Handler: mux,
}
err = server.Serve(l)
return err
}
func ServeDefault() error {
return Serve(http.DefaultServeMux)
}
+76
View File
@@ -0,0 +1,76 @@
//go:build !windows
// +build !windows
package ipcmux
import (
"github.com/mitchellh/go-ps"
"log"
"net"
"os"
libpath "path"
"strconv"
"time"
)
func init() {
listenNet = func(path string) (net.Listener, error) {
ipc_root := os.Getenv("IPC_ROOT")
if ipc_root == "" {
ipc_root = os.TempDir()
}
path = "replayme_" + path
path = libpath.Join(ipc_root, path)
err := os.Remove(path)
if err != nil {
if !os.IsNotExist(err) {
log.Printf("Err removing old uds: %s", err.Error())
}
}
l, err := net.Listen("unix", path)
log.Printf("UnixSocket::%s=>%v", path, err)
return l, err
}
dialNet = func(path string) (net.Conn, error) {
ipc_root := os.Getenv("IPC_ROOT")
if ipc_root == "" {
ipc_root = os.TempDir()
}
path = "replayme_" + path
path = libpath.Join(ipc_root, path)
conn, err := net.Dial("unix", path)
return conn, err
}
}
const (
PRCTL_SYSCALL = 157
PR_SET_PDEATHSIG = 1
)
func CheckRoot() {
time.Sleep(time.Second)
rootpid := os.Getenv(ENV_ROOTPID)
rootpidi, err := strconv.Atoi(rootpid)
if err != nil {
log.Printf("No root process found")
return
}
if rootpidi == 0 || rootpidi == os.Getpid() {
log.Printf("%s is set to zero, no monitoring on root will take place", ENV_ROOTPID)
return
}
for {
p, err := ps.FindProcess(rootpidi)
if p == nil || err != nil {
log.Printf("aborting")
os.Exit(1)
}
time.Sleep(time.Second)
}
}
+116
View File
@@ -0,0 +1,116 @@
//go:build windows
// +build windows
package ipcmux
import (
"errors"
"github.com/Microsoft/go-winio"
"log"
"net"
"os"
"strconv"
"strings"
"time"
)
func init() {
listenNet = func(path string) (net.Listener, error) {
path = strings.Replace(path, "/", "\\", -1)
log.Printf("Listening to: " + path)
chcon := make(chan bool)
var conn net.Listener
var err error
go func() {
path = "\\\\.\\pipe\\" + path
conn, err = winio.ListenPipe(path, &winio.PipeConfig{
SecurityDescriptor: "",
MessageMode: false,
InputBufferSize: 0,
OutputBufferSize: 0,
})
if err != nil {
log.Printf("ipcmux::listenNet: %s", err.Error())
}
go func() {
go func() {
to := time.Second * time.Duration(3)
fconn, err := winio.DialPipe(path, &to)
if err != nil {
log.Printf("Error on pipe warm up: %s", err.Error())
} else {
fconn.Close()
}
log.Printf("Pipe warm up done")
}()
}()
chcon <- true
}()
select {
case <-chcon:
return conn, err
case <-time.After(time.Second * 5):
err = errors.New("Timeout exceeded for Listening: " + path)
return nil, err
}
return conn, err
}
dialNet = func(path string) (net.Conn, error) {
path = strings.Replace(path, "/", "\\", -1)
path = "\\\\.\\pipe\\" + path
chcon := make(chan bool)
var conn net.Conn
var err error
//Log("Dialing to: " + path)
go func() {
to := time.Second * time.Duration(15)
conn, err = winio.DialPipe(path, &to)
//conn, err = npipe.Dial(path)
chcon <- true
}()
select {
case <-chcon:
return conn, err
case <-time.After(time.Second * 5):
err = errors.New("Timeout exceeded for conn: " + path)
return nil, err
}
return conn, err
}
}
func CheckRoot() {
time.Sleep(time.Second)
rootpid := os.Getenv(ENV_ROOTPID)
rootpidi, err := strconv.Atoi(rootpid)
if err != nil {
log.Printf("No root process found")
}
if rootpidi == 0 || rootpidi == os.Getpid() {
log.Printf("%s is set to zero, no monitoring on root will take place", ENV_ROOTPID)
return
}
p, err := os.FindProcess(rootpidi)
if err != nil {
log.Printf("Error finding process: %s", err.Error())
os.Exit(1)
}
if p == nil {
log.Printf("Process not found.")
os.Exit(1)
}
_, err = p.Wait()
if err != nil {
log.Printf(err.Error())
}
log.Printf("Parent process %s is gone. Finishing here.", os.Getenv(ENV_ROOTPID))
os.Exit(0)
}