ranges.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * RFC7233 ranges parser
  5. *
  6. * Copyright (C) 2016 Andy Green <andy@warmcat.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation:
  11. * version 2.1 of the License.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  21. * MA 02110-1301 USA
  22. */
  23. #include "private-libwebsockets.h"
  24. /*
  25. * RFC7233 examples
  26. *
  27. * o The first 500 bytes (byte offsets 0-499, inclusive):
  28. *
  29. * bytes=0-499
  30. *
  31. * o The second 500 bytes (byte offsets 500-999, inclusive):
  32. *
  33. * bytes=500-999
  34. *
  35. * o The final 500 bytes (byte offsets 9500-9999, inclusive):
  36. *
  37. * bytes=-500
  38. *
  39. * Or:
  40. *
  41. * bytes=9500-
  42. *
  43. * o The first and last bytes only (bytes 0 and 9999):
  44. *
  45. * bytes=0-0,-1
  46. *
  47. * o Other valid (but not canonical) specifications of the second 500
  48. * bytes (byte offsets 500-999, inclusive):
  49. *
  50. * bytes=500-600,601-999
  51. * bytes=500-700,601-999
  52. */
  53. /*
  54. * returns 1 if the range struct represents a usable range
  55. * if no ranges header, you get one of these for the whole
  56. * file. Otherwise you get one for each valid range in the
  57. * header.
  58. *
  59. * returns 0 if no further valid range forthcoming; rp->state
  60. * may be LWSRS_SYNTAX or LWSRS_COMPLETED
  61. */
  62. int
  63. lws_ranges_next(struct lws_range_parsing *rp)
  64. {
  65. static const char * const beq = "bytes=";
  66. char c;
  67. while (1) {
  68. c = rp->buf[rp->pos];
  69. switch (rp->state) {
  70. case LWSRS_SYNTAX:
  71. case LWSRS_COMPLETED:
  72. return 0;
  73. case LWSRS_NO_ACTIVE_RANGE:
  74. rp->state = LWSRS_COMPLETED;
  75. return 0;
  76. case LWSRS_BYTES_EQ: // looking for "bytes="
  77. if (c != beq[rp->pos]) {
  78. rp->state = LWSRS_SYNTAX;
  79. return -1;
  80. }
  81. if (rp->pos == 5)
  82. rp->state = LWSRS_FIRST;
  83. break;
  84. case LWSRS_FIRST:
  85. rp->start = 0;
  86. rp->end = 0;
  87. rp->start_valid = 0;
  88. rp->end_valid = 0;
  89. rp->state = LWSRS_STARTING;
  90. // fallthru
  91. case LWSRS_STARTING:
  92. if (c == '-') {
  93. rp->state = LWSRS_ENDING;
  94. break;
  95. }
  96. if (!(c >= '0' && c <= '9')) {
  97. rp->state = LWSRS_SYNTAX;
  98. return 0;
  99. }
  100. rp->start = (rp->start * 10) + (c - '0');
  101. rp->start_valid = 1;
  102. break;
  103. case LWSRS_ENDING:
  104. if (c == ',' || c == '\0') {
  105. rp->state = LWSRS_FIRST;
  106. if (c == ',')
  107. rp->pos++;
  108. /* by the end of this, start and end are always valid if the range still is */
  109. if (!rp->start_valid) { /* eg, -500 */
  110. if (rp->end > rp->extent)
  111. rp->end = rp->extent;
  112. rp->start = rp->extent - rp->end;
  113. rp->end = rp->extent - 1;
  114. } else
  115. if (!rp->end_valid)
  116. rp->end = rp->extent - 1;
  117. rp->did_try = 1;
  118. /* end must be >= start or ignore it */
  119. if (rp->end < rp->start) {
  120. if (c == ',')
  121. break;
  122. rp->state = LWSRS_COMPLETED;
  123. return 0;
  124. }
  125. return 1; /* issue range */
  126. }
  127. if (!(c >= '0' && c <= '9')) {
  128. rp->state = LWSRS_SYNTAX;
  129. return 0;
  130. }
  131. rp->end = (rp->end * 10) + (c - '0');
  132. rp->end_valid = 1;
  133. break;
  134. }
  135. rp->pos++;
  136. }
  137. }
  138. void
  139. lws_ranges_reset(struct lws_range_parsing *rp)
  140. {
  141. rp->pos = 0;
  142. rp->ctr = 0;
  143. rp->start = 0;
  144. rp->end = 0;
  145. rp->start_valid = 0;
  146. rp->end_valid = 0;
  147. rp->state = LWSRS_BYTES_EQ;
  148. }
  149. /*
  150. * returns count of valid ranges
  151. */
  152. int
  153. lws_ranges_init(struct lws *wsi, struct lws_range_parsing *rp,
  154. unsigned long long extent)
  155. {
  156. rp->agg = 0;
  157. rp->send_ctr = 0;
  158. rp->inside = 0;
  159. rp->count_ranges = 0;
  160. rp->did_try = 0;
  161. lws_ranges_reset(rp);
  162. rp->state = LWSRS_COMPLETED;
  163. rp->extent = extent;
  164. if (lws_hdr_copy(wsi, (char *)rp->buf, sizeof(rp->buf),
  165. WSI_TOKEN_HTTP_RANGE) <= 0)
  166. return 0;
  167. rp->state = LWSRS_BYTES_EQ;
  168. while (lws_ranges_next(rp)) {
  169. rp->count_ranges++;
  170. rp->agg += rp->end - rp->start + 1;
  171. }
  172. lwsl_debug("%s: count %d\n", __func__, rp->count_ranges);
  173. lws_ranges_reset(rp);
  174. if (rp->did_try && !rp->count_ranges)
  175. return -1; /* "not satisfiable */
  176. lws_ranges_next(rp);
  177. return rp->count_ranges;
  178. }