src/server/safs/service.c

changeset 54
3a1d5a52adfc
parent 48
37a512d7b8f6
child 55
b7908bf38f9f
equal deleted inserted replaced
53:5ec9abba1027 54:3a1d5a52adfc
32 32
33 #include "service.h" 33 #include "service.h"
34 #include "../util/io.h" 34 #include "../util/io.h"
35 #include "../util/pblock.h" 35 #include "../util/pblock.h"
36 #include "../daemon/protocol.h" 36 #include "../daemon/protocol.h"
37 #include "../daemon/vfs.h"
37 38
38 #include <sys/sendfile.h> 39 #include <sys/sendfile.h>
39 #include "../util/strbuf.h" 40 #include "../util/strbuf.h"
40 41
41 #include <errno.h> 42 #include <errno.h>
52 /* 53 /*
53 * prepares for servicing a file 54 * prepares for servicing a file
54 * 55 *
55 * adds content-length header and starts the response 56 * adds content-length header and starts the response
56 * 57 *
57 * return the file descriptor or -1 58 * return the opened file
58 */ 59 */
59 int prepare_service_file(Session *sn, Request *rq) { 60 SYS_FILE prepare_service_file(Session *sn, Request *rq, struct stat *s) {
60 char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars); 61 char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars);
61 62
62 /* open the file */ 63 /* open the file */
63 int fd = open(ppath, O_RDONLY); 64 VFSContext *vfs = vfs_request_context(sn, rq);
64 if(fd < 0) { 65 SYS_FILE fd = vfs_open(vfs, ppath, O_RDONLY);
65 //perror("prepare_service_file: open"); 66 if(!fd) {
66 67 // vfs_open sets http status code
67 int status = 500; 68 return NULL;
68 int en = errno;
69 switch(en) {
70 case EACCES: {
71 status = 403;
72 break;
73 }
74 case ENOENT: {
75 status = 404;
76 break;
77 }
78 }
79 protocol_status(sn, rq, status, NULL);
80 return -1;
81 } 69 }
82 70
83 /* get stat */ 71 /* get stat */
84 struct stat stat; 72 if (vfs_fstat(vfs, fd, s) != 0) {
85 if (fstat(fd, &stat) != 0) {
86 //perror("prepare_service_file: stat"); 73 //perror("prepare_service_file: stat");
87
88 protocol_status(sn, rq, 500, NULL); 74 protocol_status(sn, rq, 500, NULL);
89 return -1; 75 return NULL;
90 } 76 }
91 77
92 /* add content-length header*/ 78 /* add content-length header*/
93 char contentLength[32]; 79 char contentLength[32];
94 int len = snprintf(contentLength, 32, "%d", stat.st_size); 80 int len = snprintf(contentLength, 32, "%d", s->st_size);
95 81
96 pblock_kvinsert(pb_key_content_length, contentLength, len, rq->srvhdrs); 82 pblock_kvinsert(pb_key_content_length, contentLength, len, rq->srvhdrs);
97 83
98 /* start response */ 84 /* start response */
99 protocol_status(sn, rq, 200, NULL); 85 protocol_status(sn, rq, 200, NULL);
101 87
102 return fd; 88 return fd;
103 } 89 }
104 90
105 int send_file(pblock *pb, Session *sn, Request *rq) { 91 int send_file(pblock *pb, Session *sn, Request *rq) {
106 int fd = prepare_service_file(sn, rq); 92 struct stat s;
107 if(fd < 0) { 93 SYS_FILE fd = prepare_service_file(sn, rq, &s);
94 if(!fd) {
108 // if an error occurs, prepare_service_file sets the http status code 95 // if an error occurs, prepare_service_file sets the http status code
109 // we can just return REQ_ABORTED 96 // we can just return REQ_ABORTED
110 return REQ_ABORTED; 97 return REQ_ABORTED;
111 } 98 }
99
100 // send file
101 sendfiledata sfd;
102 sfd.fd = fd;
103 sfd.len = s.st_size;
104 sfd.offset = 0;
105 sfd.header = NULL;
106 sfd.trailer = NULL;
107 net_sendfile(sn->csd, &sfd);
108
109 vfs_close(fd);
110
112 111
113 /* send file*/ 112 /* send file*/
114 SystemIOStream *io = (SystemIOStream*) sn->csd; 113 //SystemIOStream *io = (SystemIOStream*) sn->csd;
115 114 //off_t fileoffset = 0;
116 off_t fileoffset = 0; 115 //int len = atoi(pblock_findkeyval(pb_key_content_length, rq->srvhdrs));
117 int len = atoi(pblock_findkeyval(pb_key_content_length, rq->srvhdrs)); 116 //sendfile(io->fd, fd->fd, &fileoffset, len);
118 sendfile(io->fd, fd, &fileoffset, len); 117
119 118 //close(fd);
120 close(fd);
121 119
122 return REQ_PROCEED; 120 return REQ_PROCEED;
123 } 121 }
124 122
125 int service_hello(pblock *pb, Session *sn, Request *rq) { 123 int service_hello(pblock *pb, Session *sn, Request *rq) {

mercurial