Access conn.RemoteAddr() in registered RPC service

258 views
Skip to first unread message

Marc

unread,
Aug 26, 2014, 8:41:27 PM8/26/14
to golan...@googlegroups.com
Hi,

I have a service that records heartbeats from several nodes via RPC. I need to log the IP address of the node together with a lot of other information. But I could not access the IP address inside the RPC service. Of course, I can tell the node to submit the IP address as an argument to the RPC service, but I have no real control over the nodes, so I find it insecure to let the node read, set and transmit the IP. Yes, I know that you can fake IP addresses, but I do not need 100% of safety I only need some sort of basic prevention of submitting the wrong IP address and manipulating the logging.

How do I access the IP address inside the registered Heartbeat RPC service?

func main() {
    rpc.Register(new(Heartbeat))

  tcpAddr, err := net.ResolveTCPAddr("tcp", ":8080")
  if err != nil {
    log.Fatal("could not resolve address:", err)
  }
  listener, err := net.ListenTCP("tcp", tcpAddr)
  if err != nil {
    log.Fatal("could not listen:", err)
  }

  for {
    conn, err := listener.Accept()
    if err != nil {
      log.Fatal("could not accept connection:", err)
    }
    // I need this IP address inside the Heartbeat service
    log.Println(conn.RemoteAddr().String())
    go rpc.ServeConn(conn)
  }
}

Thanks in advance,
Marc

egon

unread,
Aug 27, 2014, 4:34:40 AM8/27/14
to golan...@googlegroups.com, marc....@gmail.com
I've looked over the rpc package and I saw no easy way to accomplishing that. Why not implement a simple text based tcp server without rpc package?


+ egon


chai2010

unread,
Aug 27, 2014, 5:58:33 AM8/27/14
to egon, golang-nuts, marc....@gmail.com
You can create one RpcServer to one RpcClient.
Then the every RpcServer has the client conn field,
you can log the conn.RemoteAddr.

type Heartbeat struct {
conn net.Conn
}
func NewHeartbeat(conn net.Conn) *Heartbeat {
return &Heartbeat{ conn }
}
func (p *Heartbeat) Foo() {
log.Print(p.conn.RemoteAddr())
}
func acceptClient(lis net.Listener) {
heartbeat := new(Heartbeat)
for {
conn, err := lis.Accept()
if err != nil {
break
}
srv := rpc.NewServer()
if err := src.Register(NewHeartbeat(conn)); err != nil {
log.Fatal(err)
}
go srv.ServeCodec(jsonrpc.NewServerCodec(conn))
}
}




--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

marc....@gmail.com

unread,
Aug 27, 2014, 10:13:55 AM8/27/14
to golan...@googlegroups.com, marc....@gmail.com
Hi Egon,

thanks for your answer. Typically your way would make sense and is the preferred way, but I have several other methods sitting in my RPC services that need to get called from the nodes. So I'd like to stick with RPC.

Thanks Marc

marc....@gmail.com

unread,
Aug 27, 2014, 10:20:23 AM8/27/14
to golan...@googlegroups.com, egon...@gmail.com, marc....@gmail.com
Thank you for suggesting to register a Heatbeat service every time a connection is made. But do you think this performs well under load? What happens if there are a lot of concurrent calls to the Heartbeat method? Will the registry, holding the registered methods, will get confused or will leak, because of so many new service registrations?

I've tried to take RPC implementation in Go and modified it to provide a third parameter, called context to the registered methods. Context will include the remote address and so other useful information. It's not my preferred implementation, because I don't like duplication code, but it seems to be the only possibility ATM.

egon

unread,
Aug 27, 2014, 11:08:51 AM8/27/14
to golan...@googlegroups.com, egon...@gmail.com, marc....@gmail.com


On Wednesday, 27 August 2014 17:20:23 UTC+3, marc....@gmail.com wrote:
Thank you for suggesting to register a Heatbeat service every time a connection is made. But do you think this performs well under load? What happens if there are a lot of concurrent calls to the Heartbeat method? Will the registry, holding the registered methods, will get confused or will leak, because of so many new service registrations?

When in doubt, measure. I would expect that it won't be a bottleneck. A simple measurement for creating a new RPC server, and registering a method got 2.055µs/call.

GC should handle freeing registered methods when the connection dies.

I would recommend doing the "stupid" thing first, and if it doesn't hold up to the load, then optimize.
Reply all
Reply to author
Forward
0 new messages