1st ver
This commit is contained in:
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user