src/server/service.c

changeset 6
ce8fecc9847d
parent 4
998844b5ed25
child 8
f4d56bf9de40
equal deleted inserted replaced
5:dbc01588686e 6:ce8fecc9847d
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <errno.h>
30 31
31 #include "service.h" 32 #include "service.h"
32 #include "io.h" 33 #include "io.h"
33 #include "pblock.h" 34 #include "pblock.h"
34 #include "protocol.h" 35 #include "protocol.h"
35 36
37 #include <sys/sendfile.h>
38
39 // TODO: system sendfile Abstraktionen in neue Datei auslagern
40 /*
41 ssize_t sys_sendfile(int out_fd, int in_fd, off_t *off, size_t len) {
42
43 }
44 */
45 #define sys_sendfile sendfile
46
47
48 /*
49 * prepares for servicing a file
50 *
51 * adds content-length header and starts the response
52 *
53 * return the file descriptor or an error code
54 */
55 int prepare_service_file(Session *sn, Request *rq) {
56 char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars);
57
58 /* open the file */
59 int fd = open(ppath, O_RDONLY);
60 if(fd < 0) {
61 perror("prepare_service_file: open");
62
63 int status = 500;
64 switch(errno) {
65 case EACCES: {
66 status = 403;
67 break;
68 }
69 case ENOENT: {
70 status = 404;
71 break;
72 }
73 }
74 protocol_status(sn, rq, status, NULL);
75 return -1;
76 }
77
78 /* get stat */
79 struct stat stat;
80 if (fstat(fd, &stat) != 0) {
81 perror("prepare_service_file: stat");
82
83 protocol_status(sn, rq, 500, NULL);
84 return -1;
85 }
86
87 /* add content-length header*/
88 char contentLength[32];
89 int len = snprintf(contentLength, 32, "%d", stat.st_size);
90
91 pblock_kvinsert(pb_key_content_length, contentLength, len, rq->srvhdrs);
92
93 /* start response */
94 protocol_status(sn, rq, 200, NULL);
95 http_start_response(sn, rq);
96
97 return fd;
98 }
99
36 int test_service(pblock *pb, Session *sn, Request *rq) { 100 int test_service(pblock *pb, Session *sn, Request *rq) {
37 printf("test_service\n"); 101 printf("test_service\n");
38 102
103 int fd = prepare_service_file(sn, rq);
104 if(fd < 0) {
105 /* TODO: service error */
106 http_start_response(sn, rq);
107 return REQ_PROCEED;
108 }
109
110 /* send file*/
39 SystemIOStream *io = (SystemIOStream*) sn->csd; 111 SystemIOStream *io = (SystemIOStream*) sn->csd;
40 char *ppath = pblock_findkeyval(pb_key_ppath, rq->vars);
41 FILE *out = fdopen(io->fd, "w");
42 FILE *in = fopen(ppath, "r");
43 printf("open path: %s\n", ppath);
44 112
45 protocol_status(sn, rq, 200, NULL); 113 off_t fileoffset = 0;
114 int len = atoi(pblock_findkeyval(pb_key_content_length, rq->srvhdrs));
115 printf("content-length: %d\n", len);
116 sendfile(io->fd, fd, &fileoffset, len);
46 117
47 http_start_response(sn, rq); 118 close(fd);
48
49 /*
50 fprintf(out, "HTTP/1.1 200 OK\n");
51 fprintf(out, "Server: Webserver Pre-Alpha\n");
52 fprintf(out, "Concent-Length: 27\n");
53 fprintf(out, "Connection: close\n\n");
54 fflush(out);
55 */
56
57 char buffer[128];
58 int r;
59 while((r = fread(buffer, 1, 64, in)) > 0) {
60 fwrite(buffer, 1, r, out);
61 }
62 fflush(out);
63 fclose(in);
64 fclose(out);
65 119
66 return REQ_PROCEED; 120 return REQ_PROCEED;
67 } 121 }

mercurial