BinaryResponseData.cpp 4.2 KB

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