Giter Site home page Giter Site logo

golang-ipc's People

Contributors

basnijholt avatar james-barrow avatar nickycakes avatar scrouthtv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

golang-ipc's Issues

Permissions on the socket file

I am trying to use this library to implement communications between a client running as a user and an elevated server running as root. e.g. I need to manipulate the network stack from a user app.

Everything works fine if both run as a user. But if the server runs as root, the socket file gets root permission and the client panics with a permission error.

Is there an undocumented way to have the socket created with write permission? For the moment, this is on Linux. But I am also hoping to use this on Windows and MacOS as well.

Race condition

A race condition happens when opening a client

Here's the error

==================
WARNING: DATA RACE
Write at 0x00c000136140 by goroutine 7:
  github.com/james-barrow/golang-ipc.startClient()
      /Users/thomas/go/pkg/mod/github.com/james-barrow/[email protected]/client_all.go:63 +0x38
  github.com/james-barrow/golang-ipc.StartClient.func1()
      /Users/thomas/go/pkg/mod/github.com/james-barrow/[email protected]/client_all.go:56 +0x34

Previous read at 0x00c000136140 by main goroutine:
  github.com/james-barrow/golang-ipc.(*Client).Write()
      /Users/thomas/go/pkg/mod/github.com/james-barrow/[email protected]/client_all.go:198 +0x4c
  main.startIPCClient()
      /Users/thomas/go/src/github.com/equals215/deepsentinel/agent/test-tbd/main.go:18 +0x9c
  main.main()
      /Users/thomas/go/src/github.com/equals215/deepsentinel/agent/test-tbd/main.go:10 +0x20

Goroutine 7 (running) created at:
  github.com/james-barrow/golang-ipc.StartClient()
      /Users/thomas/go/pkg/mod/github.com/james-barrow/[email protected]/client_all.go:56 +0x388
  main.startIPCClient()
      /Users/thomas/go/src/github.com/equals215/deepsentinel/agent/test-tbd/main.go:14 +0x58
  main.main()
      /Users/thomas/go/src/github.com/equals215/deepsentinel/agent/test-tbd/main.go:10 +0x20
==================
Found 1 data race(s)
exit status 66

Here's the code that trigger this race condition :

package main

import (
	"fmt"

	ipc "github.com/james-barrow/golang-ipc"
)

func main() {
	startIPCClient()
}

func startIPCClient() (*ipc.Client, error) {
	c, err := ipc.StartClient("testIPC", &ipc.ClientConfig{Timeout: 500})
	if err != nil {
		return nil, err
	}
	c.Write(1, []byte("ping"))
	resp, err := c.Read()
	if err != nil {
		return nil, err
	}

	if string(resp.Data) != "pong" {
		return nil, fmt.Errorf("unexpected response: %s", resp.Data)
	}
	return c, nil
}

This package needs documentation

I tried the code snippets in the README file and it does not work. Performing writes from the client or server results in a "Not Connected" error while performing reads from the client server results in a "Connecting" error. So what triggers an actual connection? There is no exposed interface for this and no documentation.

Pipe handle leaks when reconnecting

I noticed this using ProcessExplorer from Sysinternals on Windows, with this trivial program and v1.2.2:

func main() {
	if len(os.Args) == 2 {
		s, err := ipc.StartServer("sdtool_pipe", nil)
		if err != nil {
			fmt.Println(err)
			return
		}

		for {
			if msg, err := s.Read(); err != nil {
				fmt.Println(err)
				continue
			} else {
				fmt.Printf("CLIENT MSG: %+v\n", msg)
			}

			err = s.Write(1, []byte("PONG"))

			if err == nil {
				// handle error
				fmt.Println(err)
			}
		}
	} else {
		c, err := ipc.StartClient("sdtool_pipe", nil)
		if err != nil {
			fmt.Println(err)
			return
		}

		for i := 0; i < 10; i++ {
			message, err := c.Read() // client

			if err != nil {
				fmt.Println(err)
				continue
			}

			fmt.Printf("GOT MSG: %+v\n", message)
			// do something with the received messages

			err = c.Write(1, []byte("PING"))

			if err != nil {
				fmt.Println(err)
				continue
			}
		}
	}
}

Then, running app.exe serve only starts the server side, and lists two separate \Device\NamedPipe\sdtool_pipe entries in the open HANDLEs list of ProcessExplorer. I'm not sure why two, but that's not a big deal. Running app.exe will spin up a client to connect, and that adds another reference to the pipe in the server (which persists after the client exits). Running the client again will add a 4th reference, etc.

I suspect the problem is the server accept loop unconditionally overwriting the old connection with the new one:

s.conn = conn
If I add a .Close() first, then the open file count rises to 3 for the first client run, but stays there for the second and further client runs (and I can see on old entry being cleaned up and a new one being added):

		if s.status == Listening || s.status == ReConnecting {

			if s.conn != nil {
				s.conn.Close()
			}

			s.conn = conn

I'm not sure if there's a way to get rid of the reference when the first client goes away, but wouldn't it be easier if the accept part was something the API user does, and that creates a separate object that manages each connection? That would seem to be the only way to handle multiple clients attempting to connect.

Build error on Windows with v1.2.3

It looks like it broke in 71e822d with the refactor in types.go:

$ go1.20.2.exe build
# github.com/james-barrow/golang-ipc
C:\Users\Matt\go\pkg\mod\github.com\james-barrow\[email protected]\connect_windows.go:28:4: s.connChannel undefined (type *Server has no field or method connChannel)
C:\Users\Matt\go\pkg\mod\github.com\james-barrow\[email protected]\connect_windows.go:32:12: s.connectionTimer undefined (type *Server has no field or method connectionTimer)

No triggering

Hello,

I have been implementing this in 2 go executables

server.go:

package main

import (
	"fmt"
	"log"

	ipc "github.com/james-barrow/golang-ipc"
)

type PowerManagementCommand struct {
	Command string
}

func main() {
	sc, err := ipc.StartServer("echo", nil)
	if err != nil {
		log.Println(err)
		return
	}

	for {

		data, err := sc.Read()

		if err == nil {
			fmt.Print("Recieedede")
			log.Println("Server recieved: "+string(data.Data)+" - Message type: ", data.MsgType)
		} else {
			log.Println(err)
			break
		}
	}
}

client.go

package main

import (
	"log"

	ipc "github.com/james-barrow/golang-ipc"
)

func main() {
	cc, err := ipc.StartClient("echo", nil)
	if err != nil {
		log.Println(err)
		return
	}

	_ = cc.Write(5, []byte("Message from client"))
}

I confirm that a socket is created at /tmp/echo.sock, but everytime client.go is executed, nothing happens on server.go

Error returned from the client is:

Message exceeds maximum message length% 

Is there something I'm missing?

Thanks in advance

types.go Status Consts

This is not a bug, but idiomatic way to declare enumerated constant using iota.

https://go.dev/doc/effective_go#constants

`const (

// NotConnected - 0
NotConnected Status = iota
// Listening - 1
Listening
// Connecting - 2
Connecting
// Connected - 3
Connected
// ReConnecting - 4
ReConnecting
// Closed - 5
Closed
// Closing - 6
Closing
// Error - 7
Error
// Timeout - 8
Timeout
// Disconnected - 9
Disconnected

)`

support heartbeat?

i found the message type -1 is status change,so iwanna know if this can be used as heartbeat,or i nned implement th heartbeat myself?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.