conn.go 16 KB

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