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.

146 lines
3.8 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package server
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "net"
  7. "strings"
  8. "sync"
  9. . "github.com/tendermint/go-common"
  10. "github.com/tendermint/tmsp/types"
  11. )
  12. // var maxNumberConnections = 2
  13. func StartListener(protoAddr string, app types.Application) (net.Listener, error) {
  14. var mtx sync.Mutex // global mutex
  15. parts := strings.SplitN(protoAddr, "://", 2)
  16. proto, addr := parts[0], parts[1]
  17. ln, err := net.Listen(proto, addr)
  18. if err != nil {
  19. return nil, err
  20. }
  21. // A goroutine to accept a connection.
  22. go func() {
  23. // semaphore := make(chan struct{}, maxNumberConnections)
  24. for {
  25. // semaphore <- struct{}{}
  26. // Accept a connection
  27. fmt.Println("Waiting for new connection...")
  28. conn, err := ln.Accept()
  29. if err != nil {
  30. Exit("Failed to accept connection")
  31. } else {
  32. fmt.Println("Accepted a new connection")
  33. }
  34. closeConn := make(chan error, 2) // Push to signal connection closed
  35. responses := make(chan *types.Response, 1000) // A channel to buffer responses
  36. // Read requests from conn and deal with them
  37. go handleRequests(&mtx, app, closeConn, conn, responses)
  38. // Pull responses from 'responses' and write them to conn.
  39. go handleResponses(closeConn, responses, conn)
  40. go func() {
  41. // Wait until signal to close connection
  42. errClose := <-closeConn
  43. if errClose != nil {
  44. fmt.Printf("Connection error: %v\n", errClose)
  45. } else {
  46. fmt.Println("Connection was closed.")
  47. }
  48. // Close the connection
  49. err := conn.Close()
  50. if err != nil {
  51. fmt.Printf("Error in closing connection: %v\n", err)
  52. }
  53. // <-semaphore
  54. }()
  55. }
  56. }()
  57. return ln, nil
  58. }
  59. // Read requests from conn and deal with them
  60. func handleRequests(mtx *sync.Mutex, app types.Application, closeConn chan error, conn net.Conn, responses chan<- *types.Response) {
  61. var count int
  62. var bufReader = bufio.NewReader(conn)
  63. for {
  64. var req = &types.Request{}
  65. err := types.ReadMessage(bufReader, req)
  66. if err != nil {
  67. if err == io.EOF {
  68. closeConn <- fmt.Errorf("Connection closed by client")
  69. } else {
  70. closeConn <- fmt.Errorf("Error in handleRequests: %v", err.Error())
  71. }
  72. return
  73. }
  74. mtx.Lock()
  75. count++
  76. handleRequest(app, req, responses)
  77. mtx.Unlock()
  78. }
  79. }
  80. func handleRequest(app types.Application, req *types.Request, responses chan<- *types.Response) {
  81. switch req.Type {
  82. case types.MessageType_Echo:
  83. responses <- types.ResponseEcho(string(req.Data))
  84. case types.MessageType_Flush:
  85. responses <- types.ResponseFlush()
  86. case types.MessageType_Info:
  87. data := app.Info()
  88. responses <- types.ResponseInfo(data)
  89. case types.MessageType_SetOption:
  90. logStr := app.SetOption(req.Key, req.Value)
  91. responses <- types.ResponseSetOption(logStr)
  92. case types.MessageType_AppendTx:
  93. code, result, logStr := app.AppendTx(req.Data)
  94. responses <- types.ResponseAppendTx(code, result, logStr)
  95. case types.MessageType_CheckTx:
  96. code, result, logStr := app.CheckTx(req.Data)
  97. responses <- types.ResponseCheckTx(code, result, logStr)
  98. case types.MessageType_GetHash:
  99. hash, logStr := app.GetHash()
  100. responses <- types.ResponseGetHash(hash, logStr)
  101. case types.MessageType_Query:
  102. code, result, logStr := app.Query(req.Data)
  103. responses <- types.ResponseQuery(code, result, logStr)
  104. default:
  105. responses <- types.ResponseException("Unknown request")
  106. }
  107. }
  108. // Pull responses from 'responses' and write them to conn.
  109. func handleResponses(closeConn chan error, responses <-chan *types.Response, conn net.Conn) {
  110. var count int
  111. var bufWriter = bufio.NewWriter(conn)
  112. for {
  113. var res = <-responses
  114. err := types.WriteMessage(res, bufWriter)
  115. if err != nil {
  116. closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error())
  117. return
  118. }
  119. if res.Type == types.MessageType_Flush {
  120. err = bufWriter.Flush()
  121. if err != nil {
  122. closeConn <- fmt.Errorf("Error in handleResponses: %v", err.Error())
  123. return
  124. }
  125. }
  126. count++
  127. }
  128. }