BinaryResponseData.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //
  2. // Created by xcbosa on 2023/1/28.
  3. //
  4. #include "BinaryResponseData.h"
  5. #include "../webuiconf.h"
  6. namespace xc {
  7. namespace utils {
  8. BinaryResponseData::BinaryResponseData(int statusCode, uint8_t *body, int bodySize, string contentType): headers() {
  9. this->statusCode = statusCode;
  10. this->body = body;
  11. this->bodySize = bodySize;
  12. this->headers["Server"] = "XCHttpServer";
  13. this->headers["Transfer-Encoding"] = "chunked";
  14. this->headers["Content-Type"] = contentType;
  15. this->headers["keepalive"] = "false";
  16. this->filePath = nullptr;
  17. }
  18. BinaryResponseData::BinaryResponseData(int statusCode, string filePath, string contentType): headers() {
  19. this->statusCode = statusCode;
  20. this->body = nullptr;
  21. this->bodySize = 0;
  22. this->headers["Server"] = "XCHttpServer";
  23. this->headers["Transfer-Encoding"] = "chunked";
  24. this->headers["Content-Type"] = contentType;
  25. this->headers["keepalive"] = "false";
  26. this->filePath = filePath;
  27. }
  28. void BinaryResponseData::setHeader(string headerName, string value) {
  29. this->headers[headerName] = value;
  30. }
  31. void BinaryResponseData::writeTo(::FILE *fp) const {
  32. ::fprintf(fp, "HTTP/1.1 %d FRPCWebUI\r\n", this->statusCode);
  33. for (auto item : this->headers) {
  34. ::fprintf(fp, "%s: %s\r\n", item.first.c_str(), item.second.c_str());
  35. }
  36. ::fputs("\r\n", fp);
  37. int mtu = conf::mtu;
  38. if (this->isWriteFromMemory()) {
  39. int writeTimes = this->bodySize / mtu;
  40. if (this->bodySize % mtu) {
  41. writeTimes++;
  42. }
  43. ::uint8_t *cursor = this->body;
  44. ::uint8_t *endNextCursor = this->body + this->bodySize;
  45. for (int i = 0; i < writeTimes; i++) {
  46. long writeSize = min((long)mtu, endNextCursor - cursor);
  47. ::fprintf(fp, "%x\r\n", writeSize);
  48. ::fwrite(cursor, 1, writeSize, fp);
  49. ::fprintf(fp, "\r\n");
  50. cursor += writeSize;
  51. }
  52. ::fprintf(fp, "0\r\n\r\n");
  53. }
  54. if (this->isWriteFromFile()) {
  55. string filePath = this->filePath;
  56. ::FILE *inputFile = ::fopen(filePath.c_str(), "rb");
  57. if (inputFile) {
  58. ::uint8_t buff[mtu];
  59. long readPerPack;
  60. while ((readPerPack = ::fread(buff, 1, mtu, inputFile)) > 0) {
  61. ::fprintf(fp, "%x\r\n", readPerPack);
  62. ::fwrite(buff, 1, readPerPack, fp);
  63. ::fprintf(fp, "\r\n");
  64. }
  65. ::fprintf(fp, "0\r\n\r\n");
  66. } else {
  67. cerr << "[FileIOError]: " << ::strerror(errno) << endl;
  68. }
  69. }
  70. ::fflush(fp);
  71. }
  72. void BinaryResponseData::writeResponseBodyTo(ostream &fp) const {
  73. int mtu = conf::mtu;
  74. if (this->isWriteFromMemory()) {
  75. for (int i = 0; i < this->bodySize; i++) {
  76. fp.put(this->body[i]);
  77. }
  78. }
  79. if (this->isWriteFromFile()) {
  80. string filePath = this->filePath;
  81. ::FILE *inputFile = ::fopen(filePath.c_str(), "rb");
  82. if (inputFile) {
  83. ::uint8_t buff[mtu];
  84. long readPerPack;
  85. while ((readPerPack = ::fread(buff, 1, mtu, inputFile)) > 0) {
  86. for (int i = 0; i < readPerPack; i++) {
  87. fp.put(buff[i]);
  88. }
  89. }
  90. } else {
  91. cerr << "[FileIOError]: " << ::strerror(errno) << endl;
  92. }
  93. }
  94. }
  95. bool BinaryResponseData::isWriteFromFile() const {
  96. return !this->isWriteFromMemory();
  97. }
  98. bool BinaryResponseData::isWriteFromMemory() const {
  99. return this->bodySize > 0;
  100. }
  101. } // xc
  102. } // utils