conn.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. package dbus
  2. import (
  3. "errors"
  4. "io"
  5. "os"
  6. "reflect"
  7. "strings"
  8. "sync"
  9. )
  10. const defaultSystemBusAddress = "unix:path=/var/run/dbus/system_bus_socket"
  11. var (
  12. systemBus *Conn
  13. systemBusLck sync.Mutex
  14. sessionBus *Conn
  15. sessionBusLck sync.Mutex
  16. sessionEnvLck sync.Mutex
  17. )
  18. // ErrClosed is the error returned by calls on a closed connection.
  19. var ErrClosed = errors.New("dbus: connection closed by user")
  20. // Conn represents a connection to a message bus (usually, the system or
  21. // session bus).
  22. //
  23. // Connections are either shared or private. Shared connections
  24. // are shared between calls to the functions that return them. As a result,
  25. // the methods Close, Auth and Hello must not be called on them.
  26. //
  27. // Multiple goroutines may invoke methods on a connection simultaneously.
  28. type Conn struct {
  29. transport
  30. busObj BusObject
  31. unixFD bool
  32. uuid string
  33. names []string
  34. namesLck sync.RWMutex
  35. serialLck sync.Mutex
  36. nextSerial uint32
  37. serialUsed map[uint32]bool
  38. calls map[uint32]*Call
  39. callsLck sync.RWMutex
  40. handlers map[ObjectPath]map[string]exportedObj
  41. handlersLck sync.RWMutex
  42. out chan *Message
  43. closed bool
  44. outLck sync.RWMutex
  45. signals []chan<- *Signal
  46. signalsLck sync.Mutex
  47. eavesdropped chan<- *Message
  48. eavesdroppedLck sync.Mutex
  49. }
  50. // SessionBus returns a shared connection to the session bus, connecting to it
  51. // if not already done.
  52. func SessionBus() (conn *Conn, err error) {
  53. sessionBusLck.Lock()
  54. defer sessionBusLck.Unlock()
  55. if sessionBus != nil {
  56. return sessionBus, nil
  57. }
  58. defer func() {
  59. if conn != nil {
  60. sessionBus = conn
  61. }
  62. }()
  63. conn, err = SessionBusPrivate()
  64. if err != nil {
  65. return
  66. }
  67. if err = conn.Auth(nil); err != nil {
  68. conn.Close()
  69. conn = nil
  70. return
  71. }
  72. if err = conn.Hello(); err != nil {
  73. conn.Close()
  74. conn = nil
  75. }
  76. return
  77. }
  78. // SessionBusPrivate returns a new private connection to the session bus.
  79. func SessionBusPrivate() (*Conn, error) {
  80. sessionEnvLck.Lock()
  81. defer sessionEnvLck.Unlock()
  82. address := os.Getenv("DBUS_SESSION_BUS_ADDRESS")
  83. if address != "" && address != "autolaunch:" {
  84. return Dial(address)
  85. }
  86. return sessionBusPlatform()
  87. }
  88. // SystemBus returns a shared connection to the system bus, connecting to it if
  89. // not already done.
  90. func SystemBus() (conn *Conn, err error) {
  91. systemBusLck.Lock()
  92. defer systemBusLck.Unlock()
  93. if systemBus != nil {
  94. return systemBus, nil
  95. }
  96. defer func() {
  97. if conn != nil {
  98. systemBus = conn
  99. }
  100. }()
  101. conn, err = SystemBusPrivate()
  102. if err != nil {
  103. return
  104. }
  105. if err = conn.Auth(nil); err != nil {
  106. conn.Close()
  107. conn = nil
  108. return
  109. }
  110. if err = conn.Hello(); err != nil {
  111. conn.Close()
  112. conn = nil
  113. }
  114. return
  115. }
  116. // SystemBusPrivate returns a new private connection to the system bus.
  117. func SystemBusPrivate() (*Conn, error) {
  118. address := os.Getenv("DBUS_SYSTEM_BUS_ADDRESS")
  119. if address != "" {
  120. return Dial(address)
  121. }
  122. return Dial(defaultSystemBusAddress)
  123. }
  124. // Dial establishes a new private connection to the message bus specified by address.
  125. func Dial(address string) (*Conn, error) {
  126. tr, err := getTransport(address)
  127. if err != nil {
  128. return nil, err
  129. }
  130. return newConn(tr)
  131. }
  132. // NewConn creates a new private *Conn from an already established connection.
  133. func NewConn(conn io.ReadWriteCloser) (*Conn, error) {
  134. return newConn(genericTransport{conn})
  135. }
  136. // newConn creates a new *Conn from a transport.
  137. func newConn(tr transport) (*Conn, error) {
  138. conn := new(Conn)
  139. conn.transport = tr
  140. conn.calls = make(map[uint32]*Call)
  141. conn.out = make(chan *Message, 10)
  142. conn.handlers = make(map[ObjectPath]map[string]exportedObj)
  143. conn.nextSerial = 1
  144. conn.serialUsed = map[uint32]bool{0: true}
  145. conn.busObj = conn.Object("org.freedesktop.DBus", "/org/freedesktop/DBus")
  146. return conn, nil
  147. }
  148. // BusObject returns the object owned by the bus daemon which handles
  149. // administrative requests.
  150. func (conn *Conn) BusObject() BusObject {
  151. return conn.busObj
  152. }
  153. // Close closes the connection. Any blocked operations will return with errors
  154. // and the channels passed to Eavesdrop and Signal are closed. This method must
  155. // not be called on shared connections.
  156. func (conn *Conn) Close() error {
  157. conn.outLck.Lock()
  158. if conn.closed {
  159. // inWorker calls Close on read error, the read error may
  160. // be caused by another caller calling Close to shutdown the
  161. // dbus connection, a double-close scenario we prevent here.
  162. conn.outLck.Unlock()
  163. return nil
  164. }
  165. close(conn.out)
  166. conn.closed = true
  167. conn.outLck.Unlock()
  168. conn.signalsLck.Lock()
  169. for _, ch := range conn.signals {
  170. close(ch)
  171. }
  172. conn.signalsLck.Unlock()
  173. conn.eavesdroppedLck.Lock()
  174. if conn.eavesdropped != nil {
  175. close(conn.eavesdropped)
  176. }
  177. conn.eavesdroppedLck.Unlock()
  178. return conn.transport.Close()
  179. }
  180. // Eavesdrop causes conn to send all incoming messages to the given channel
  181. // without further processing. Method replies, errors and signals will not be
  182. // sent to the appropiate channels and method calls will not be handled. If nil
  183. // is passed, the normal behaviour is restored.
  184. //
  185. // The caller has to make sure that ch is sufficiently buffered;
  186. // if a message arrives when a write to ch is not possible, the message is
  187. // discarded.
  188. func (conn *Conn) Eavesdrop(ch chan<- *Message) {
  189. conn.eavesdroppedLck.Lock()
  190. conn.eavesdropped = ch
  191. conn.eavesdroppedLck.Unlock()
  192. }
  193. // getSerial returns an unused serial.
  194. func (conn *Conn) getSerial() uint32 {
  195. conn.serialLck.Lock()
  196. defer conn.serialLck.Unlock()
  197. n := conn.nextSerial
  198. for conn.serialUsed[n] {
  199. n++
  200. }
  201. conn.serialUsed[n] = true
  202. conn.nextSerial = n + 1
  203. return n
  204. }
  205. // Hello sends the initial org.freedesktop.DBus.Hello call. This method must be
  206. // called after authentication, but before sending any other messages to the
  207. // bus. Hello must not be called for shared connections.
  208. func (conn *Conn) Hello() error {
  209. var s string
  210. err := conn.busObj.Call("org.freedesktop.DBus.Hello", 0).Store(&s)
  211. if err != nil {
  212. return err
  213. }
  214. conn.namesLck.Lock()
  215. conn.names = make([]string, 1)
  216. conn.names[0] = s
  217. conn.namesLck.Unlock()
  218. return nil
  219. }
  220. // inWorker runs in an own goroutine, reading incoming messages from the
  221. // transport and dispatching them appropiately.
  222. func (conn *Conn) inWorker() {
  223. for {
  224. msg, err := conn.ReadMessage()
  225. if err == nil {
  226. conn.eavesdroppedLck.Lock()
  227. if conn.eavesdropped != nil {
  228. select {
  229. case conn.eavesdropped <- msg:
  230. default:
  231. }
  232. conn.eavesdroppedLck.Unlock()
  233. continue
  234. }
  235. conn.eavesdroppedLck.Unlock()
  236. dest, _ := msg.Headers[FieldDestination].value.(string)
  237. found := false
  238. if dest == "" {
  239. found = true
  240. } else {
  241. conn.namesLck.RLock()
  242. if len(conn.names) == 0 {
  243. found = true
  244. }
  245. for _, v := range conn.names {
  246. if dest == v {
  247. found = true
  248. break
  249. }
  250. }
  251. conn.namesLck.RUnlock()
  252. }
  253. if !found {
  254. // Eavesdropped a message, but no channel for it is registered.
  255. // Ignore it.
  256. continue
  257. }
  258. switch msg.Type {
  259. case TypeMethodReply, TypeError:
  260. serial := msg.Headers[FieldReplySerial].value.(uint32)
  261. conn.callsLck.Lock()
  262. if c, ok := conn.calls[serial]; ok {
  263. if msg.Type == TypeError {
  264. name, _ := msg.Headers[FieldErrorName].value.(string)
  265. c.Err = Error{name, msg.Body}
  266. } else {
  267. c.Body = msg.Body
  268. }
  269. c.Done <- c
  270. conn.serialLck.Lock()
  271. delete(conn.serialUsed, serial)
  272. conn.serialLck.Unlock()
  273. delete(conn.calls, serial)
  274. }
  275. conn.callsLck.Unlock()
  276. case TypeSignal:
  277. iface := msg.Headers[FieldInterface].value.(string)
  278. member := msg.Headers[FieldMember].value.(string)
  279. // as per http://dbus.freedesktop.org/doc/dbus-specification.html ,
  280. // sender is optional for signals.
  281. sender, _ := msg.Headers[FieldSender].value.(string)
  282. if iface == "org.freedesktop.DBus" && sender == "org.freedesktop.DBus" {
  283. if member == "NameLost" {
  284. // If we lost the name on the bus, remove it from our
  285. // tracking list.
  286. name, ok := msg.Body[0].(string)
  287. if !ok {
  288. panic("Unable to read the lost name")
  289. }
  290. conn.namesLck.Lock()
  291. for i, v := range conn.names {
  292. if v == name {
  293. conn.names = append(conn.names[:i],
  294. conn.names[i+1:]...)
  295. }
  296. }
  297. conn.namesLck.Unlock()
  298. } else if member == "NameAcquired" {
  299. // If we acquired the name on the bus, add it to our
  300. // tracking list.
  301. name, ok := msg.Body[0].(string)
  302. if !ok {
  303. panic("Unable to read the acquired name")
  304. }
  305. conn.namesLck.Lock()
  306. conn.names = append(conn.names, name)
  307. conn.namesLck.Unlock()
  308. }
  309. }
  310. signal := &Signal{
  311. Sender: sender,
  312. Path: msg.Headers[FieldPath].value.(ObjectPath),
  313. Name: iface + "." + member,
  314. Body: msg.Body,
  315. }
  316. conn.signalsLck.Lock()
  317. for _, ch := range conn.signals {
  318. ch <- signal
  319. }
  320. conn.signalsLck.Unlock()
  321. case TypeMethodCall:
  322. go conn.handleCall(msg)
  323. }
  324. } else if _, ok := err.(InvalidMessageError); !ok {
  325. // Some read error occured (usually EOF); we can't really do
  326. // anything but to shut down all stuff and returns errors to all
  327. // pending replies.
  328. conn.Close()
  329. conn.callsLck.RLock()
  330. for _, v := range conn.calls {
  331. v.Err = err
  332. v.Done <- v
  333. }
  334. conn.callsLck.RUnlock()
  335. return
  336. }
  337. // invalid messages are ignored
  338. }
  339. }
  340. // Names returns the list of all names that are currently owned by this
  341. // connection. The slice is always at least one element long, the first element
  342. // being the unique name of the connection.
  343. func (conn *Conn) Names() []string {
  344. conn.namesLck.RLock()
  345. // copy the slice so it can't be modified
  346. s := make([]string, len(conn.names))
  347. copy(s, conn.names)
  348. conn.namesLck.RUnlock()
  349. return s
  350. }
  351. // Object returns the object identified by the given destination name and path.
  352. func (conn *Conn) Object(dest string, path ObjectPath) BusObject {
  353. return &Object{conn, dest, path}
  354. }
  355. // outWorker runs in an own goroutine, encoding and sending messages that are
  356. // sent to conn.out.
  357. func (conn *Conn) outWorker() {
  358. for msg := range conn.out {
  359. err := conn.SendMessage(msg)
  360. conn.callsLck.RLock()
  361. if err != nil {
  362. if c := conn.calls[msg.serial]; c != nil {
  363. c.Err = err
  364. c.Done <- c
  365. }
  366. conn.serialLck.Lock()
  367. delete(conn.serialUsed, msg.serial)
  368. conn.serialLck.Unlock()
  369. } else if msg.Type != TypeMethodCall {
  370. conn.serialLck.Lock()
  371. delete(conn.serialUsed, msg.serial)
  372. conn.serialLck.Unlock()
  373. }
  374. conn.callsLck.RUnlock()
  375. }
  376. }
  377. // Send sends the given message to the message bus. You usually don't need to
  378. // use this; use the higher-level equivalents (Call / Go, Emit and Export)
  379. // instead. If msg is a method call and NoReplyExpected is not set, a non-nil
  380. // call is returned and the same value is sent to ch (which must be buffered)
  381. // once the call is complete. Otherwise, ch is ignored and a Call structure is
  382. // returned of which only the Err member is valid.
  383. func (conn *Conn) Send(msg *Message, ch chan *Call) *Call {
  384. var call *Call
  385. msg.serial = conn.getSerial()
  386. if msg.Type == TypeMethodCall && msg.Flags&FlagNoReplyExpected == 0 {
  387. if ch == nil {
  388. ch = make(chan *Call, 5)
  389. } else if cap(ch) == 0 {
  390. panic("dbus: unbuffered channel passed to (*Conn).Send")
  391. }
  392. call = new(Call)
  393. call.Destination, _ = msg.Headers[FieldDestination].value.(string)
  394. call.Path, _ = msg.Headers[FieldPath].value.(ObjectPath)
  395. iface, _ := msg.Headers[FieldInterface].value.(string)
  396. member, _ := msg.Headers[FieldMember].value.(string)
  397. call.Method = iface + "." + member
  398. call.Args = msg.Body
  399. call.Done = ch
  400. conn.callsLck.Lock()
  401. conn.calls[msg.serial] = call
  402. conn.callsLck.Unlock()
  403. conn.outLck.RLock()
  404. if conn.closed {
  405. call.Err = ErrClosed
  406. call.Done <- call
  407. } else {
  408. conn.out <- msg
  409. }
  410. conn.outLck.RUnlock()
  411. } else {
  412. conn.outLck.RLock()
  413. if conn.closed {
  414. call = &Call{Err: ErrClosed}
  415. } else {
  416. conn.out <- msg
  417. call = &Call{Err: nil}
  418. }
  419. conn.outLck.RUnlock()
  420. }
  421. return call
  422. }
  423. // sendError creates an error message corresponding to the parameters and sends
  424. // it to conn.out.
  425. func (conn *Conn) sendError(e Error, dest string, serial uint32) {
  426. msg := new(Message)
  427. msg.Type = TypeError
  428. msg.serial = conn.getSerial()
  429. msg.Headers = make(map[HeaderField]Variant)
  430. if dest != "" {
  431. msg.Headers[FieldDestination] = MakeVariant(dest)
  432. }
  433. msg.Headers[FieldErrorName] = MakeVariant(e.Name)
  434. msg.Headers[FieldReplySerial] = MakeVariant(serial)
  435. msg.Body = e.Body
  436. if len(e.Body) > 0 {
  437. msg.Headers[FieldSignature] = MakeVariant(SignatureOf(e.Body...))
  438. }
  439. conn.outLck.RLock()
  440. if !conn.closed {
  441. conn.out <- msg
  442. }
  443. conn.outLck.RUnlock()
  444. }
  445. // sendReply creates a method reply message corresponding to the parameters and
  446. // sends it to conn.out.
  447. func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
  448. msg := new(Message)
  449. msg.Type = TypeMethodReply
  450. msg.serial = conn.getSerial()
  451. msg.Headers = make(map[HeaderField]Variant)
  452. if dest != "" {
  453. msg.Headers[FieldDestination] = MakeVariant(dest)
  454. }
  455. msg.Headers[FieldReplySerial] = MakeVariant(serial)
  456. msg.Body = values
  457. if len(values) > 0 {
  458. msg.Headers[FieldSignature] = MakeVariant(SignatureOf(values...))
  459. }
  460. conn.outLck.RLock()
  461. if !conn.closed {
  462. conn.out <- msg
  463. }
  464. conn.outLck.RUnlock()
  465. }
  466. // Signal registers the given channel to be passed all received signal messages.
  467. // The caller has to make sure that ch is sufficiently buffered; if a message
  468. // arrives when a write to c is not possible, it is discarded.
  469. //
  470. // Multiple of these channels can be registered at the same time.
  471. //
  472. // These channels are "overwritten" by Eavesdrop; i.e., if there currently is a
  473. // channel for eavesdropped messages, this channel receives all signals, and
  474. // none of the channels passed to Signal will receive any signals.
  475. func (conn *Conn) Signal(ch chan<- *Signal) {
  476. conn.signalsLck.Lock()
  477. conn.signals = append(conn.signals, ch)
  478. conn.signalsLck.Unlock()
  479. }
  480. // RemoveSignal removes the given channel from the list of the registered channels.
  481. func (conn *Conn) RemoveSignal(ch chan<- *Signal) {
  482. conn.signalsLck.Lock()
  483. for i := len(conn.signals) - 1; i >= 0; i-- {
  484. if ch == conn.signals[i] {
  485. copy(conn.signals[i:], conn.signals[i+1:])
  486. conn.signals[len(conn.signals)-1] = nil
  487. conn.signals = conn.signals[:len(conn.signals)-1]
  488. }
  489. }
  490. conn.signalsLck.Unlock()
  491. }
  492. // SupportsUnixFDs returns whether the underlying transport supports passing of
  493. // unix file descriptors. If this is false, method calls containing unix file
  494. // descriptors will return an error and emitted signals containing them will
  495. // not be sent.
  496. func (conn *Conn) SupportsUnixFDs() bool {
  497. return conn.unixFD
  498. }
  499. // Error represents a D-Bus message of type Error.
  500. type Error struct {
  501. Name string
  502. Body []interface{}
  503. }
  504. func NewError(name string, body []interface{}) *Error {
  505. return &Error{name, body}
  506. }
  507. func (e Error) Error() string {
  508. if len(e.Body) >= 1 {
  509. s, ok := e.Body[0].(string)
  510. if ok {
  511. return s
  512. }
  513. }
  514. return e.Name
  515. }
  516. // Signal represents a D-Bus message of type Signal. The name member is given in
  517. // "interface.member" notation, e.g. org.freedesktop.D-Bus.NameLost.
  518. type Signal struct {
  519. Sender string
  520. Path ObjectPath
  521. Name string
  522. Body []interface{}
  523. }
  524. // transport is a D-Bus transport.
  525. type transport interface {
  526. // Read and Write raw data (for example, for the authentication protocol).
  527. io.ReadWriteCloser
  528. // Send the initial null byte used for the EXTERNAL mechanism.
  529. SendNullByte() error
  530. // Returns whether this transport supports passing Unix FDs.
  531. SupportsUnixFDs() bool
  532. // Signal the transport that Unix FD passing is enabled for this connection.
  533. EnableUnixFDs()
  534. // Read / send a message, handling things like Unix FDs.
  535. ReadMessage() (*Message, error)
  536. SendMessage(*Message) error
  537. }
  538. var (
  539. transports = make(map[string]func(string) (transport, error))
  540. )
  541. func getTransport(address string) (transport, error) {
  542. var err error
  543. var t transport
  544. addresses := strings.Split(address, ";")
  545. for _, v := range addresses {
  546. i := strings.IndexRune(v, ':')
  547. if i == -1 {
  548. err = errors.New("dbus: invalid bus address (no transport)")
  549. continue
  550. }
  551. f := transports[v[:i]]
  552. if f == nil {
  553. err = errors.New("dbus: invalid bus address (invalid or unsupported transport)")
  554. continue
  555. }
  556. t, err = f(v[i+1:])
  557. if err == nil {
  558. return t, nil
  559. }
  560. }
  561. return nil, err
  562. }
  563. // dereferenceAll returns a slice that, assuming that vs is a slice of pointers
  564. // of arbitrary types, containes the values that are obtained from dereferencing
  565. // all elements in vs.
  566. func dereferenceAll(vs []interface{}) []interface{} {
  567. for i := range vs {
  568. v := reflect.ValueOf(vs[i])
  569. v = v.Elem()
  570. vs[i] = v.Interface()
  571. }
  572. return vs
  573. }
  574. // getKey gets a key from a the list of keys. Returns "" on error / not found...
  575. func getKey(s, key string) string {
  576. for _, keyEqualsValue := range strings.Split(s, ",") {
  577. keyValue := strings.SplitN(keyEqualsValue, "=", 2)
  578. if len(keyValue) == 2 && keyValue[0] == key {
  579. return keyValue[1]
  580. }
  581. }
  582. return ""
  583. }