client.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package goSam
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. "github.com/cryptix/go/debug"
  7. )
  8. // A Client represents a single Connection to the SAM bridge
  9. type Client struct {
  10. host string
  11. port string
  12. SamConn net.Conn
  13. rd *bufio.Reader
  14. inLength uint
  15. inVariance int
  16. inQuantity uint
  17. inBackups uint
  18. outLength uint
  19. outVariance int
  20. outQuantity uint
  21. outBackups uint
  22. dontPublishLease bool
  23. encryptLease bool
  24. reduceIdle bool
  25. reduceIdleTime uint
  26. reduceIdleQuantity uint
  27. closeIdle bool
  28. closeIdleTime uint
  29. debug bool
  30. }
  31. // NewDefaultClient creates a new client, connecting to the default host:port at localhost:7656
  32. func NewDefaultClient() (*Client, error) {
  33. return NewClient("localhost:7656")
  34. }
  35. // NewClient creates a new client, connecting to a specified port
  36. func NewClient(addr string) (*Client, error) {
  37. return NewClientFromOptions(SetAddr(addr))
  38. }
  39. // NewClientFromOptions creates a new client, connecting to a specified port
  40. func NewClientFromOptions(opts ...func(*Client) error) (*Client, error) {
  41. var c Client
  42. c.host = "127.0.0.1"
  43. c.port = "7656"
  44. c.inLength = 3
  45. c.inVariance = 0
  46. c.inQuantity = 4
  47. c.inBackups = 2
  48. c.outLength = 3
  49. c.outVariance = 0
  50. c.outQuantity = 4
  51. c.outBackups = 2
  52. c.dontPublishLease = true
  53. c.encryptLease = false
  54. c.reduceIdle = false
  55. c.reduceIdleTime = 300000
  56. c.reduceIdleQuantity = 4
  57. c.closeIdle = true
  58. c.closeIdleTime = 600000
  59. c.debug = false
  60. for _, o := range opts {
  61. if err := o(&c); err != nil {
  62. return nil, err
  63. }
  64. }
  65. conn, err := net.Dial("tcp", c.samaddr())
  66. if err != nil {
  67. return nil, err
  68. }
  69. if c.debug {
  70. conn = debug.WrapConn(conn)
  71. }
  72. c.SamConn = conn
  73. c.rd = bufio.NewReader(conn)
  74. return &c, c.hello()
  75. }
  76. //return the combined host:port of the SAM bridge
  77. func (c *Client) samaddr() string {
  78. return fmt.Sprintf("%s:%s", c.host, c.port)
  79. }
  80. // send the initial handshake command and check that the reply is ok
  81. func (c *Client) hello() error {
  82. r, err := c.sendCmd("HELLO VERSION MIN=3.0 MAX=3.2\n")
  83. if err != nil {
  84. return err
  85. }
  86. if r.Topic != "HELLO" {
  87. return fmt.Errorf("Unknown Reply: %+v\n", r)
  88. }
  89. if r.Pairs["RESULT"] != "OK" || !(r.Pairs["VERSION"] == "3.0" || r.Pairs["VERSION"] == "3.1" || r.Pairs["VERSION"] == "3.2") {
  90. return fmt.Errorf("Handshake did not succeed\nReply:%+v\n", r)
  91. }
  92. return nil
  93. }
  94. // helper to send one command and parse the reply by sam
  95. func (c *Client) sendCmd(str string, args ...interface{}) (*Reply, error) {
  96. if _, err := fmt.Fprintf(c.SamConn, str, args...); err != nil {
  97. return nil, err
  98. }
  99. line, err := c.rd.ReadString('\n')
  100. if err != nil {
  101. return nil, err
  102. }
  103. return parseReply(line)
  104. }
  105. // Close the underlying socket to SAM
  106. func (c *Client) Close() error {
  107. c.rd = nil
  108. return c.SamConn.Close()
  109. }