1
0

Socket+File.swift 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. //
  2. // Socket+File.swift
  3. // Swifter
  4. //
  5. // Created by Damian Kolakowski on 13/07/16.
  6. //
  7. import Foundation
  8. #if os(iOS) || os(tvOS) || os (Linux)
  9. // swiftlint:disable type_name function_parameter_count
  10. struct sf_hdtr { }
  11. private func sendfileImpl(_ source: UnsafeMutablePointer<FILE>, _ target: Int32, _: off_t, _: UnsafeMutablePointer<off_t>, _: UnsafeMutablePointer<sf_hdtr>, _: Int32) -> Int32 {
  12. var buffer = [UInt8](repeating: 0, count: 1024)
  13. while true {
  14. let readResult = fread(&buffer, 1, buffer.count, source)
  15. guard readResult > 0 else {
  16. return Int32(readResult)
  17. }
  18. var writeCounter = 0
  19. while writeCounter < readResult {
  20. let writeResult = buffer.withUnsafeBytes { (ptr) -> Int in
  21. let start = ptr.baseAddress! + writeCounter
  22. let len = readResult - writeCounter
  23. #if os(Linux)
  24. return send(target, start, len, Int32(MSG_NOSIGNAL))
  25. #else
  26. return write(target, start, len)
  27. #endif
  28. }
  29. guard writeResult > 0 else {
  30. return Int32(writeResult)
  31. }
  32. writeCounter += writeResult
  33. }
  34. }
  35. }
  36. #endif
  37. extension Socket {
  38. public func writeFile(_ file: String.File) throws {
  39. var offset: off_t = 0
  40. var sf: sf_hdtr = sf_hdtr()
  41. #if os(iOS) || os(tvOS) || os (Linux)
  42. let result = sendfileImpl(file.pointer, self.socketFileDescriptor, 0, &offset, &sf, 0)
  43. #else
  44. let result = sendfile(fileno(file.pointer), self.socketFileDescriptor, 0, &offset, &sf, 0)
  45. #endif
  46. if result == -1 {
  47. throw SocketError.writeFailed("sendfile: " + Errno.description())
  48. }
  49. }
  50. }