ipc_unix.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
  17. package comms
  18. import (
  19. "net"
  20. "os"
  21. "path/filepath"
  22. "github.com/ethereum/go-ethereum/logger"
  23. "github.com/ethereum/go-ethereum/logger/glog"
  24. "github.com/ethereum/go-ethereum/rpc/codec"
  25. "github.com/ethereum/go-ethereum/rpc/shared"
  26. "github.com/ethereum/go-ethereum/rpc/useragent"
  27. )
  28. func newIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
  29. c, err := net.DialUnix("unix", nil, &net.UnixAddr{cfg.Endpoint, "unix"})
  30. if err != nil {
  31. return nil, err
  32. }
  33. coder := codec.New(c)
  34. msg := shared.Request{
  35. Id: 0,
  36. Method: useragent.EnableUserAgentMethod,
  37. Jsonrpc: shared.JsonRpcVersion,
  38. Params: []byte("[]"),
  39. }
  40. coder.WriteResponse(msg)
  41. coder.Recv()
  42. return &ipcClient{cfg.Endpoint, c, codec, coder}, nil
  43. }
  44. func (self *ipcClient) reconnect() error {
  45. self.coder.Close()
  46. c, err := net.DialUnix("unix", nil, &net.UnixAddr{self.endpoint, "unix"})
  47. if err == nil {
  48. self.coder = self.codec.New(c)
  49. msg := shared.Request{
  50. Id: 0,
  51. Method: useragent.EnableUserAgentMethod,
  52. Jsonrpc: shared.JsonRpcVersion,
  53. Params: []byte("[]"),
  54. }
  55. self.coder.WriteResponse(msg)
  56. self.coder.Recv()
  57. }
  58. return err
  59. }
  60. func startIpc(cfg IpcConfig, codec codec.Codec, initializer func(conn net.Conn) (shared.EthereumApi, error)) error {
  61. // Ensure the IPC path exists and remove any previous leftover
  62. if err := os.MkdirAll(filepath.Dir(cfg.Endpoint), 0751); err != nil {
  63. return err
  64. }
  65. os.Remove(cfg.Endpoint)
  66. l, err := net.ListenUnix("unix", &net.UnixAddr{Name: cfg.Endpoint, Net: "unix"})
  67. if err != nil {
  68. return err
  69. }
  70. os.Chmod(cfg.Endpoint, 0600)
  71. go func() {
  72. for {
  73. conn, err := l.AcceptUnix()
  74. if err != nil {
  75. glog.V(logger.Error).Infof("Error accepting ipc connection - %v\n", err)
  76. continue
  77. }
  78. id := newIpcConnId()
  79. glog.V(logger.Debug).Infof("New IPC connection with id %06d started\n", id)
  80. api, err := initializer(conn)
  81. if err != nil {
  82. glog.V(logger.Error).Infof("Unable to initialize IPC connection - %v\n", err)
  83. conn.Close()
  84. continue
  85. }
  86. go handle(id, conn, api, codec)
  87. }
  88. os.Remove(cfg.Endpoint)
  89. }()
  90. glog.V(logger.Info).Infof("IPC service started (%s)\n", cfg.Endpoint)
  91. return nil
  92. }