source: benchmark/io/http/worker.cfa @ 0aec496

arm-ehjacob/cs343-translationnew-astnew-ast-unique-expr
Last change on this file since 0aec496 was 0aec496, checked in by Thierry Delisle <tdelisle@…>, 15 months ago

First attempt at webserver, no option support yet

  • Property mode set to 100644
File size: 3.7 KB
Line 
1#include "worker.hfa"
2
3#define __USE_GNU
4
5#include <errno.h>
6#include <stdio.h>
7#include <string.h>
8extern "C" {
9        #include <sys/socket.h>
10        #include <sys/types.h>
11        #include <linux/fcntl.h>
12        #include <linux/stat.h>
13        #include <netinet/in.h>
14}
15
16#include <iofwd.hfa>
17
18#include "options.hfa"
19#include "protocol.hfa"
20#include "filecache.hfa"
21
22extern "C" {
23// extern ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
24extern ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
25}
26
27ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count) {
28        return splice(in_fd, offset, out_fd, 0p, count, 0);
29}
30
31
32//=============================================================================================
33// Worker Thread
34//=============================================================================================
35void sendfile( Worker & this, int fd, int ans_fd, size_t count ) {
36        off_t offset = 0;
37        ssize_t ret;
38        SPLICE1: while(count > 0) {
39                ret = cfa_splice(ans_fd, &offset, this.pipe[1], 0p, count, 5);
40                if( ret < 0 ) {
41                        if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE1;
42                        abort( "splice [0] error: (%d) %s\n", (int)errno, strerror(errno) );
43                }
44
45                count -= ret;
46                offset += ret;
47                size_t in_pipe = ret;
48                SPLICE2: while(in_pipe > 0) {
49                        ret = cfa_splice(this.pipe[0], 0p, fd, 0p, in_pipe, 5);
50                        if( ret < 0 ) {
51                                if( errno != EAGAIN && errno != EWOULDBLOCK) continue SPLICE2;
52                                abort( "splice [1] error: (%d) %s\n", (int)errno, strerror(errno) );
53                        }
54                        in_pipe -= ret;
55                }
56
57        }
58}
59
60void ?{}( Worker & this ) {
61        ((thread&)this){ "Server Worker Thread", *options.the_cluster };
62        int ret = pipe(this.pipe);
63        if( ret < 0 ) { abort( "pipe error: (%d) %s\n", (int)errno, strerror(errno) ); }
64}
65
66void main( Worker & this ) {
67        CONNECTION:
68        while( int fd = take(wait_connect); fd >= 0) {
69            printf("New connection, waiting for requests\n");
70                REQUEST:
71                for() {
72                        bool closed;
73                        HttpCode code;
74                        const char * file;
75                        size_t name_size;
76
77                        // Read the http request
78                        size_t len = 1024;
79                        char buffer[len];
80                        printf("Reading request\n");
81                        [code, closed, file, name_size] = http_read(fd, buffer, len);
82
83                        // if we are done, break out of the loop
84                        if( closed ) {
85                                printf("Connection closed\n");
86                                continue CONNECTION;
87                        }
88
89                        // If this wasn't a request retrun 400
90                        if( code != OK200 ) {
91                                printf("Invalid Request\n");
92                                answer_error(fd, code);
93                                continue REQUEST;
94                        }
95
96                        printf("Request for file %.*s\n", name_size, file);
97
98                        // Get the fd from the file cache
99                        int ans_fd;
100                        size_t count;
101                        [ans_fd, count] = get_file( file, name_size );
102
103                        // If we can't find the file, return 404
104                        if( ans_fd < 0 ) {
105                                printf("File Not Found\n");
106                                answer_error(fd, E404);
107                                continue REQUEST;
108                        }
109
110                        // Send the header
111                        answer_header(fd, count);
112
113                        // Send the desired file
114                        sendfile( this, fd, ans_fd, count);
115
116                        printf("File sent\n");
117                }
118        }
119}
120
121//=============================================================================================
122// Acceptor Thread
123//=============================================================================================
124void ?{}( Acceptor & this, int sockfd, struct sockaddr * addr, socklen_t * addrlen, int flags ) {
125        ((thread&)this){ "Acceptor Thread", *options.the_cluster };
126        this.sockfd  = sockfd;
127        this.addr    = addr;
128        this.addrlen = addrlen;
129        this.flags   = flags;
130}
131
132void main( Acceptor & this ) {
133        for() {
134                int ret = cfa_accept4( this.[sockfd, addr, addrlen, flags] );
135                if(ret < 0) {
136                        if( errno == ECONNABORTED ) break;
137                        abort( "accept error: (%d) %s\n", (int)errno, strerror(errno) );
138                }
139
140            printf("New connection accepted\n");
141                put( wait_connect, ret );
142      }
143}
Note: See TracBrowser for help on using the repository browser.