You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

149 lines
3.4 KiB

  1. package client
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "strconv"
  7. )
  8. // Response handler
  9. type ResponseHandler func(*Response)
  10. // response
  11. type Response struct {
  12. DataType uint32
  13. Data, UID []byte
  14. Handle string
  15. }
  16. // Extract the Response's result.
  17. // if data == nil, err != nil, then worker failing to execute job
  18. // if data != nil, err != nil, then worker has a exception
  19. // if data != nil, err == nil, then worker complate job
  20. // after calling this method, the Response.Handle will be filled
  21. func (resp *Response) Result() (data []byte, err error) {
  22. switch resp.DataType {
  23. case dtWorkFail:
  24. resp.Handle = string(resp.Data)
  25. err = ErrWorkFail
  26. return
  27. case dtWorkException:
  28. err = ErrWorkException
  29. fallthrough
  30. case dtWorkComplete:
  31. data = resp.Data
  32. default:
  33. err = ErrDataType
  34. }
  35. return
  36. }
  37. // Extract the job's update
  38. func (resp *Response) Update() (data []byte, err error) {
  39. if resp.DataType != dtWorkData &&
  40. resp.DataType != dtWorkWarning {
  41. err = ErrDataType
  42. return
  43. }
  44. data = resp.Data
  45. if resp.DataType == dtWorkWarning {
  46. err = ErrWorkWarning
  47. }
  48. return
  49. }
  50. // Decode a job from byte slice
  51. func decodeResponse(data []byte) (resp *Response, l int, err error) {
  52. a := len(data)
  53. if a < minPacketLength { // valid package should not less 12 bytes
  54. err = fmt.Errorf("Invalid data: %v", data)
  55. return
  56. }
  57. dl := int(binary.BigEndian.Uint32(data[8:12]))
  58. if a < minPacketLength+dl {
  59. err = fmt.Errorf("Invalid data: %v", data)
  60. return
  61. }
  62. dt := data[minPacketLength : dl+minPacketLength]
  63. if len(dt) != int(dl) { // length not equal
  64. err = fmt.Errorf("Invalid data: %v", data)
  65. return
  66. }
  67. resp = getResponse()
  68. resp.DataType = binary.BigEndian.Uint32(data[4:8])
  69. switch resp.DataType {
  70. case dtJobCreated:
  71. resp.Handle = string(dt)
  72. case dtStatusRes, dtWorkData, dtWorkWarning, dtWorkStatus,
  73. dtWorkComplete, dtWorkFail, dtWorkException:
  74. s := bytes.SplitN(dt, []byte{'\x00'}, 2)
  75. if len(s) >= 2 {
  76. resp.Handle = string(s[0])
  77. resp.Data = s[1]
  78. } else {
  79. err = fmt.Errorf("Invalid data: %v", data)
  80. return
  81. }
  82. case dtEchoRes:
  83. fallthrough
  84. default:
  85. resp.Data = dt
  86. }
  87. l = dl + minPacketLength
  88. return
  89. }
  90. func (resp *Response) Status() (status *Status, err error) {
  91. data := bytes.SplitN(resp.Data, []byte{'\x00'}, 2)
  92. if len(data) != 2 {
  93. err = fmt.Errorf("Invalid data: %v", resp.Data)
  94. return
  95. }
  96. status = &Status{}
  97. status.Handle = resp.Handle
  98. status.Known = true
  99. status.Running = true
  100. status.Numerator, err = strconv.ParseUint(string(data[0]), 10, 0)
  101. if err != nil {
  102. err = fmt.Errorf("Invalid Integer: %s", data[0])
  103. return
  104. }
  105. status.Denominator, err = strconv.ParseUint(string(data[1]), 10, 0)
  106. if err != nil {
  107. err = fmt.Errorf("Invalid Integer: %s", data[1])
  108. return
  109. }
  110. return
  111. }
  112. // status handler
  113. func (resp *Response) _status() (status *Status, err error) {
  114. data := bytes.SplitN(resp.Data, []byte{'\x00'}, 4)
  115. if len(data) != 4 {
  116. err = fmt.Errorf("Invalid data: %v", resp.Data)
  117. return
  118. }
  119. status = &Status{}
  120. status.Handle = resp.Handle
  121. status.Known = (data[0][0] == '1')
  122. status.Running = (data[1][0] == '1')
  123. status.Numerator, err = strconv.ParseUint(string(data[2]), 10, 0)
  124. if err != nil {
  125. err = fmt.Errorf("Invalid Integer: %s", data[2])
  126. return
  127. }
  128. status.Denominator, err = strconv.ParseUint(string(data[3]), 10, 0)
  129. if err != nil {
  130. err = fmt.Errorf("Invalid Integer: %s", data[3])
  131. return
  132. }
  133. return
  134. }
  135. func getResponse() (resp *Response) {
  136. // TODO add a pool
  137. resp = &Response{}
  138. return
  139. }