src/server/safs/service.c

changeset 415
d938228c382e
parent 346
784b24381bed
child 428
ab58e46b50a5
equal deleted inserted replaced
414:99a34860c105 415:d938228c382e
36 #include "../util/util.h" 36 #include "../util/util.h"
37 #include "../daemon/protocol.h" 37 #include "../daemon/protocol.h"
38 #include "../daemon/vfs.h" 38 #include "../daemon/vfs.h"
39 39
40 #include "../util/strbuf.h" 40 #include "../util/strbuf.h"
41 #include <ucx/string.h> 41 #include <cx/string.h>
42 #include <ucx/utils.h> 42 #include <cx/utils.h>
43 #include <cx/printf.h>
43 44
44 #include <errno.h> 45 #include <errno.h>
45 46
46 /* 47 /*
47 * prepares servicing a file 48 * prepares servicing a file
110 } 111 }
111 112
112 static HttpRange* parse_range(Session *sn, char *header, int *status) { 113 static HttpRange* parse_range(Session *sn, char *header, int *status) {
113 *status = PROTOCOL_OK; 114 *status = PROTOCOL_OK;
114 115
115 sstr_t range = sstrtrim(sstr(header)); 116 cxstring range = cx_strtrim(cx_str(header));
116 if(!sstrprefix(range, S("bytes="))) { 117 if(!cx_strprefix(range, (cxstring)CX_STR("bytes="))) {
117 // unknown range unit - ignore range header 118 // unknown range unit - ignore range header
118 return NULL; 119 return NULL;
119 } 120 }
120 121
121 // get byte-range-set 122 // get byte-range-set
122 range = sstrsubs(range, 6); 123 range = cx_strsubs(range, 6);
123 if(range.length < 1) { 124 if(range.length < 1) {
124 return NULL; 125 return NULL;
125 } 126 }
126 127
127 HttpRange *range_list = NULL; 128 HttpRange *range_list = NULL;
130 int start = 0; 131 int start = 0;
131 int hasbegin = 0; 132 int hasbegin = 0;
132 for(int i=0;i<=range.length;i++) { 133 for(int i=0;i<=range.length;i++) {
133 char c = range.ptr[i]; 134 char c = range.ptr[i];
134 if(c == '-') { 135 if(c == '-') {
135 sstr_t num = sstrsubsl(range, start, i-start); 136 cxstring num = cx_strsubsl(range, start, i-start);
136 if(num.length == 0) { 137 if(num.length == 0) {
137 // empty string before '-' is legal 138 // empty string before '-' is legal
138 hasbegin = 1; 139 hasbegin = 1;
139 begin = -1; 140 begin = -1;
140 start = i+1; 141 start = i+1;
150 // syntax error 151 // syntax error
151 free_range(sn, range_list); 152 free_range(sn, range_list);
152 return NULL; 153 return NULL;
153 } 154 }
154 } else if(c == ',' || c == '\0') { 155 } else if(c == ',' || c == '\0') {
155 sstr_t num = sstrsubsl(range, start, i-start); 156 cxstring num = cx_strsubsl(range, start, i-start);
156 if(hasbegin) { 157 if(hasbegin) {
157 long long n; 158 long long n;
158 if(num.length == 0) { 159 if(num.length == 0) {
159 // empty string after '-' is legal 160 // empty string after '-' is legal
160 n = -1; 161 n = -1;
493 494
494 return REQ_PROCESSING; 495 return REQ_PROCESSING;
495 } 496 }
496 497
497 struct multi_range_elm { 498 struct multi_range_elm {
498 sstr_t header; 499 cxmutstr header;
499 off_t offset; 500 off_t offset;
500 off_t length; 501 off_t length;
501 }; 502 };
502 503
503 static int send_multi_range(Session *sn, Request *rq, SYS_FILE fd, off_t filelen, HttpRange *range) { 504 static int send_multi_range(Session *sn, Request *rq, SYS_FILE fd, off_t filelen, HttpRange *range) {
505 CxAllocator *a = pool_allocator(sn->pool);
506
504 pb_param *content_type = pblock_remove("content-type", rq->srvhdrs); 507 pb_param *content_type = pblock_remove("content-type", rq->srvhdrs);
505 508
506 char sep[64]; 509 char sep[64];
507 int seplen = util_mime_separator(sep); 510 int seplen = util_mime_separator(sep);
508 511
509 sstr_t newct = ucx_sprintf("multipart/byteranges; boundary=%s", sep+4); 512 cxmutstr newct = cx_asprintf_a(a, "multipart/byteranges; boundary=%s", sep+4);
510 pblock_kvinsert( 513 pblock_kvinsert(
511 pb_key_content_type, 514 pb_key_content_type,
512 newct.ptr, 515 newct.ptr,
513 newct.length, 516 newct.length,
514 rq->srvhdrs); 517 rq->srvhdrs);
515 free(newct.ptr); 518 cxFree(a, newct.ptr);
516 519
517 // calculate content-length 520 // calculate content-length
518 off_t response_len = 0; 521 off_t response_len = 0;
519 522
520 int nrange = 0; 523 int nrange = 0;
522 while(rangeelm) { 525 while(rangeelm) {
523 nrange++; 526 nrange++;
524 rangeelm = rangeelm->next; 527 rangeelm = rangeelm->next;
525 } 528 }
526 529
527 struct multi_range_elm *r = calloc(nrange, sizeof(struct multi_range_elm)); 530 struct multi_range_elm *r = pool_calloc(sn->pool, nrange, sizeof(struct multi_range_elm));
528 rangeelm = range; 531 rangeelm = range;
529 int i=0; 532 int i=0;
530 while(rangeelm) { 533 while(rangeelm) {
531 range2off(rangeelm, filelen, &(r[i].offset), &(r[i].length)); 534 range2off(rangeelm, filelen, &(r[i].offset), &(r[i].length));
532 r[i].header = ucx_sprintf( 535 r[i].header = cx_asprintf_a(
536 a,
533 "%s\r\nContent-Type: %s\r\nContent-Range: bytes %lld-%lld/%lld\r\n\r\n", 537 "%s\r\nContent-Type: %s\r\nContent-Range: bytes %lld-%lld/%lld\r\n\r\n",
534 sep, 538 sep,
535 content_type->value, 539 content_type->value,
536 (long long)r[i].offset, 540 (long long)r[i].offset,
537 (long long)r[i].offset+r[i].length - 1, 541 (long long)r[i].offset+r[i].length - 1,
563 rangeelm = rangeelm->next; 567 rangeelm = rangeelm->next;
564 i++; 568 i++;
565 } 569 }
566 net_printf(sn->csd, "%s--\r\n", sep); 570 net_printf(sn->csd, "%s--\r\n", sep);
567 571
568 free(r); 572 pool_free(sn->pool, r);
569 return 0; 573 return 0;
570 } 574 }
571 575
572 int send_file(pblock *pb, Session *sn, Request *rq) { 576 int send_file(pblock *pb, Session *sn, Request *rq) {
573 struct stat s; 577 struct stat s;
614 pblock_kllinsert( 618 pblock_kllinsert(
615 pb_key_content_length, 619 pb_key_content_length,
616 (long long)length, 620 (long long)length,
617 rq->srvhdrs); 621 rq->srvhdrs);
618 622
619 sstr_t content_range = ucx_sprintf( 623 cxmutstr content_range = cx_asprintf(
620 "%lld-%lld/%lld", 624 "%lld-%lld/%lld",
621 (long long)offset, 625 (long long)offset,
622 (long long)offset+length - 1, 626 (long long)offset+length - 1,
623 s.st_size); 627 s.st_size);
624 pblock_kvinsert( 628 pblock_kvinsert(
694 //printf("service_index\n"); 698 //printf("service_index\n");
695 699
696 char *path = pblock_findkeyval(pb_key_path, rq->vars); 700 char *path = pblock_findkeyval(pb_key_path, rq->vars);
697 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); 701 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
698 702
699 sstr_t r_uri = sstr(uri); 703 cxstring r_uri = cx_str(uri);
700 704
701 // open the file 705 // open the file
702 VFSContext *vfs = vfs_request_context(sn, rq); 706 VFSContext *vfs = vfs_request_context(sn, rq);
703 VFS_DIR dir = vfs_opendir(vfs, path); 707 VFS_DIR dir = vfs_opendir(vfs, path);
704 if(!dir) { 708 if(!dir) {
715 sbuf_puts(out, "</h1><hr>\n\n"); 719 sbuf_puts(out, "</h1><hr>\n\n");
716 720
717 // list directory 721 // list directory
718 VFS_ENTRY f; 722 VFS_ENTRY f;
719 while(vfs_readdir(dir, &f)) { 723 while(vfs_readdir(dir, &f)) {
720 sstr_t filename = sstr(f.name); 724 cxstring filename = cx_str(f.name);
721 725
722 sbuf_puts(out, "<a href=\""); 726 sbuf_puts(out, "<a href=\"");
723 sbuf_append(out, r_uri); 727 sbuf_append(out, r_uri);
724 sbuf_append(out, filename); 728 sbuf_append(out, filename);
725 sbuf_puts(out, "\">"); 729 sbuf_puts(out, "\">");

mercurial