summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/HttpRangeUtils.h
blob: 7e0b66de1bf7a033ae4a0150f4daf9092bca0b51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 *  Copyright (C) 2015-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include <stdint.h>
#include <string>
#include <vector>

class CHttpRange
{
public:
  CHttpRange() = default;
  CHttpRange(uint64_t firstPosition, uint64_t lastPosition);
  virtual ~CHttpRange() = default;

  bool operator<(const CHttpRange &other) const;
  bool operator==(const CHttpRange &other) const;
  bool operator!=(const CHttpRange &other) const;

  virtual uint64_t GetFirstPosition() const { return m_first; }
  virtual void SetFirstPosition(uint64_t firstPosition) { m_first = firstPosition; }
  virtual uint64_t GetLastPosition() const { return m_last; }
  virtual void SetLastPosition(uint64_t lastPosition) { m_last = lastPosition; }

  virtual uint64_t GetLength() const;
  virtual void SetLength(uint64_t length);

  virtual bool IsValid() const;

protected:
  uint64_t m_first = 1;
  uint64_t m_last = 0;
};

typedef std::vector<CHttpRange> HttpRanges;

class CHttpResponseRange : public CHttpRange
{
public:
  CHttpResponseRange();
  CHttpResponseRange(uint64_t firstPosition, uint64_t lastPosition);
  CHttpResponseRange(const void* data, uint64_t firstPosition, uint64_t lastPosition);
  CHttpResponseRange(const void* data, uint64_t length);
  ~CHttpResponseRange() override = default;

  bool operator==(const CHttpResponseRange &other) const;
  bool operator!=(const CHttpResponseRange &other) const;

  const void* GetData() const { return m_data; }
  void SetData(const void* data) { m_data = data; }
  void SetData(const void* data, uint64_t length);
  void SetData(const void* data, uint64_t firstPosition, uint64_t lastPosition);

  bool IsValid() const override;

protected:
  const void* m_data;
};

typedef std::vector<CHttpResponseRange> HttpResponseRanges;

class CHttpRanges final
{
public:
  CHttpRanges();
  explicit CHttpRanges(const HttpRanges& httpRanges);

  const HttpRanges& Get() const { return m_ranges; }
  bool Get(size_t index, CHttpRange& range) const;
  bool GetFirst(CHttpRange& range) const;
  bool GetLast(CHttpRange& range) const;
  size_t Size() const { return m_ranges.size(); }
  bool IsEmpty() const { return m_ranges.empty(); }

  bool GetFirstPosition(uint64_t& position) const;
  bool GetLastPosition(uint64_t& position) const;
  uint64_t GetLength() const;

  bool GetTotalRange(CHttpRange& range) const;

  void Add(const CHttpRange& range);
  void Remove(size_t index);
  void Clear();

  HttpRanges::const_iterator Begin() const { return m_ranges.begin(); }
  HttpRanges::const_iterator End() const { return m_ranges.end(); }

  bool Parse(const std::string& header);
  bool Parse(const std::string& header, uint64_t totalLength);

protected:
  void SortAndCleanup();

  HttpRanges m_ranges;
};

class HttpRangeUtils
{
public:
  /*!
  * \brief Generates a valid Content-Range HTTP header value for the given HTTP
  * range definition.
  *
  * \param range HTTP range definition used to generate the Content-Range HTTP header
  * \return Content-Range HTTP header value
  */
  static std::string GenerateContentRangeHeaderValue(const CHttpRange* range);

  /*!
  * \brief Generates a valid Content-Range HTTP header value for the given HTTP
  * range properties.
  *
  * \param start Start position of the HTTP range
  * \param end Last/End position of the HTTP range
  * \param total Total length of original content (not just the range)
  * \return Content-Range HTTP header value
  */
  static std::string GenerateContentRangeHeaderValue(uint64_t start, uint64_t end, uint64_t total);

#ifdef HAS_WEB_SERVER
  /*!
   * \brief Generates a multipart boundary that can be used in ranged HTTP
   * responses.
   *
   * \return Multipart boundary that can be used in ranged HTTP responses
   */
  static std::string GenerateMultipartBoundary();

  /*!
  * \brief Generates the multipart/byteranges Content-Type HTTP header value
  * containing the given multipart boundary for a ranged HTTP response.
  *
  * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response
  * \return multipart/byteranges Content-Type HTTP header value
  */
  static std::string GenerateMultipartBoundaryContentType(const std::string& multipartBoundary);

  /*!
  * \brief Generates a multipart boundary including the Content-Type HTTP
  * header value with the (actual) given content type of the original
  * content.
  *
  * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response
  * \param contentType (Actual) Content type of the original content
  * \return Multipart boundary (including the Content-Type HTTP header) value that can be used in ranged HTTP responses
  */
  static std::string GenerateMultipartBoundaryWithHeader(const std::string& multipartBoundary, const std::string& contentType);

  /*!
  * \brief Generates a multipart boundary including the Content-Type HTTP
  * header value with the (actual) given content type of the original
  * content and the Content-Range HTTP header value for the given range.
  *
  * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response
  * \param contentType (Actual) Content type of the original content
  * \param range HTTP range definition used to generate the Content-Range HTTP header
  * \return Multipart boundary (including the Content-Type and Content-Range HTTP headers) value that can be used in ranged HTTP responses
  */
  static std::string GenerateMultipartBoundaryWithHeader(const std::string& multipartBoundary, const std::string& contentType, const CHttpRange* range);

  /*!
  * \brief Generates a multipart boundary including the Content-Type HTTP
  * header value with the (actual) given content type of the original
  * content and the Content-Range HTTP header value for the given range.
  *
  * \param multipartBoundaryWithContentType Multipart boundary (already including the Content-Type HTTP header value) to be used in the ranged HTTP response
  * \param range HTTP range definition used to generate the Content-Range HTTP header
  * \return Multipart boundary (including the Content-Type and Content-Range HTTP headers) value that can be used in ranged HTTP responses
  */
  static std::string GenerateMultipartBoundaryWithHeader(const std::string& multipartBoundaryWithContentType, const CHttpRange* range);

  /*!
  * \brief Generates a multipart boundary end that can be used in ranged HTTP
   * responses.
  *
  * \param multipartBoundary Multipart boundary to be used in the ranged HTTP response
  * \return Multipart boundary end that can be used in a ranged HTTP response
  */
  static std::string GenerateMultipartBoundaryEnd(const std::string& multipartBoundary);
#endif // HAS_WEB_SERVER
};