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.

150 lines
3.3 KiB

  1. package weed_server
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "strings"
  9. "github.com/chrislusf/seaweedfs/weed/glog"
  10. "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
  11. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  12. "github.com/chrislusf/seaweedfs/weed/util"
  13. )
  14. func (vs *VolumeServer) HandleTcpConnection(conn net.Conn) error {
  15. // println("handle tcp conn", conn.RemoteAddr())
  16. tcpMessage := &volume_server_pb.TcpRequestHeader{}
  17. if err := util.ReadMessage(conn, tcpMessage); err != nil {
  18. return fmt.Errorf("read message: %v", err)
  19. }
  20. if tcpMessage.Get != nil {
  21. vs.handleFileGet(conn, tcpMessage.Get)
  22. }
  23. err := util.WriteMessageEOF(conn)
  24. // println("processed", tcpMessage.Get.FileId)
  25. return err
  26. }
  27. func (vs *VolumeServer) handleFileGet(conn net.Conn, req *volume_server_pb.FileGetRequest) error {
  28. headResponse := &volume_server_pb.FileGetResponse{}
  29. n := new(needle.Needle)
  30. commaIndex := strings.LastIndex(req.FileId, ",")
  31. vid := req.FileId[:commaIndex]
  32. fid := req.FileId[commaIndex+1:]
  33. volumeId, err := needle.NewVolumeId(vid)
  34. if err != nil {
  35. headResponse.ErrorCode = http.StatusBadRequest
  36. return util.WriteMessage(conn, headResponse)
  37. }
  38. err = n.ParsePath(fid)
  39. if err != nil {
  40. headResponse.ErrorCode = http.StatusBadRequest
  41. return util.WriteMessage(conn, headResponse)
  42. }
  43. hasVolume := vs.store.HasVolume(volumeId)
  44. _, hasEcVolume := vs.store.FindEcVolume(volumeId)
  45. if !hasVolume && !hasEcVolume {
  46. headResponse.ErrorCode = http.StatusMovedPermanently
  47. return util.WriteMessage(conn, headResponse)
  48. }
  49. cookie := n.Cookie
  50. var count int
  51. if hasVolume {
  52. count, err = vs.store.ReadVolumeNeedle(volumeId, n)
  53. } else if hasEcVolume {
  54. count, err = vs.store.ReadEcShardNeedle(context.Background(), volumeId, n)
  55. }
  56. if err != nil || count < 0 {
  57. headResponse.ErrorCode = http.StatusNotFound
  58. return util.WriteMessage(conn, headResponse)
  59. }
  60. if n.Cookie != cookie {
  61. headResponse.ErrorCode = http.StatusNotFound
  62. return util.WriteMessage(conn, headResponse)
  63. }
  64. if n.LastModified != 0 {
  65. headResponse.LastModified = n.LastModified
  66. }
  67. headResponse.Etag = n.Etag()
  68. if n.HasPairs() {
  69. pairMap := make(map[string]string)
  70. err = json.Unmarshal(n.Pairs, &pairMap)
  71. if err != nil {
  72. glog.V(0).Infoln("Unmarshal pairs error:", err)
  73. }
  74. headResponse.Headers = pairMap
  75. }
  76. /*
  77. // skip this, no redirection
  78. if vs.tryHandleChunkedFile(n, filename, w, r) {
  79. return
  80. }
  81. */
  82. if n.NameSize > 0 {
  83. headResponse.Filename = string(n.Name)
  84. }
  85. mtype := ""
  86. if n.MimeSize > 0 {
  87. mt := string(n.Mime)
  88. if !strings.HasPrefix(mt, "application/octet-stream") {
  89. mtype = mt
  90. }
  91. }
  92. headResponse.ContentType = mtype
  93. headResponse.IsGzipped = n.IsGzipped()
  94. if n.IsGzipped() && req.AcceptGzip {
  95. if n.Data, err = util.UnGzipData(n.Data); err != nil {
  96. glog.V(0).Infof("ungzip %s error: %v", req.FileId, err)
  97. }
  98. }
  99. headResponse.ContentLength = uint32(len(n.Data))
  100. bytesToRead := len(n.Data)
  101. bytesRead := 0
  102. t := headResponse
  103. for bytesRead < bytesToRead {
  104. stopIndex := bytesRead + BufferSizeLimit
  105. if stopIndex > bytesToRead {
  106. stopIndex = bytesToRead
  107. }
  108. if t == nil {
  109. t = &volume_server_pb.FileGetResponse{}
  110. }
  111. t.Data = n.Data[bytesRead:stopIndex]
  112. err = util.WriteMessage(conn, t)
  113. t = nil
  114. if err != nil {
  115. return err
  116. }
  117. bytesRead = stopIndex
  118. }
  119. return nil
  120. }