Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d076f16 in mainline


Ignore:
Timestamp:
2017-09-28T17:01:16Z (3 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
91b60499
Parents:
7b616e2
Message:

Websrv cannot use global buffers to handle HTTP requests concurrently.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/websrv/websrv.c

    r7b616e2 rd076f16  
    7575static uint16_t port = DEFAULT_PORT;
    7676
    77 static char rbuf[BUFFER_SIZE];
    78 static size_t rbuf_out;
    79 static size_t rbuf_in;
    80 
    81 static char lbuf[BUFFER_SIZE + 1];
    82 static size_t lbuf_used;
    83 
    84 static char fbuf[BUFFER_SIZE];
     77typedef struct {
     78        tcp_conn_t *conn;
     79
     80        char rbuf[BUFFER_SIZE];
     81        size_t rbuf_out;
     82        size_t rbuf_in;
     83
     84        char lbuf[BUFFER_SIZE + 1];
     85        size_t lbuf_used;
     86} recv_t;
    8587
    8688static bool verbose = false;
     
    131133    "</html>\r\n";
    132134
     135
     136static int recv_create(tcp_conn_t *conn, recv_t **rrecv)
     137{
     138        recv_t *recv;
     139       
     140        recv = calloc(1, sizeof(recv_t));
     141        if (recv == NULL)
     142                return ENOMEM;
     143       
     144        recv->conn = conn;
     145        recv->rbuf_out = 0;
     146        recv->rbuf_in = 0;
     147        recv->lbuf_used = 0;
     148       
     149        *rrecv = recv;
     150        return EOK;
     151}
     152
     153static void recv_destroy(recv_t *recv)
     154{
     155        free(recv);
     156}
     157
    133158/** Receive one character (with buffering) */
    134 static int recv_char(tcp_conn_t *conn, char *c)
     159static int recv_char(recv_t *recv, char *c)
    135160{
    136161        size_t nrecv;
    137162        int rc;
    138163       
    139         if (rbuf_out == rbuf_in) {
    140                 rbuf_out = 0;
    141                 rbuf_in = 0;
    142                
    143                 rc = tcp_conn_recv_wait(conn, rbuf, BUFFER_SIZE, &nrecv);
     164        if (recv->rbuf_out == recv->rbuf_in) {
     165                recv->rbuf_out = 0;
     166                recv->rbuf_in = 0;
     167               
     168                rc = tcp_conn_recv_wait(recv->conn, recv->rbuf, BUFFER_SIZE, &nrecv);
    144169                if (rc != EOK) {
    145170                        fprintf(stderr, "tcp_conn_recv() failed (%d)\n", rc);
     
    147172                }
    148173               
    149                 rbuf_in = nrecv;
    150         }
    151        
    152         *c = rbuf[rbuf_out++];
     174                recv->rbuf_in = nrecv;
     175        }
     176       
     177        *c = recv->rbuf[recv->rbuf_out++];
    153178        return EOK;
    154179}
    155180
    156181/** Receive one line with length limit */
    157 static int recv_line(tcp_conn_t *conn)
    158 {
    159         char *bp = lbuf;
     182static int recv_line(recv_t *recv, char **rbuf)
     183{
     184        char *bp = recv->lbuf;
    160185        char c = '\0';
    161186       
    162         while (bp < lbuf + BUFFER_SIZE) {
     187        while (bp < recv->lbuf + BUFFER_SIZE) {
    163188                char prev = c;
    164                 int rc = recv_char(conn, &c);
     189                int rc = recv_char(recv, &c);
    165190               
    166191                if (rc != EOK)
     
    172197        }
    173198       
    174         lbuf_used = bp - lbuf;
     199        recv->lbuf_used = bp - recv->lbuf;
    175200        *bp = '\0';
    176201       
    177         if (bp == lbuf + BUFFER_SIZE)
     202        if (bp == recv->lbuf + BUFFER_SIZE)
    178203                return ELIMIT;
    179204       
     205        *rbuf = recv->lbuf;
    180206        return EOK;
    181207}
     
    218244static int uri_get(const char *uri, tcp_conn_t *conn)
    219245{
     246        char *fbuf = NULL;
     247        char *fname = NULL;
     248        int rc;
     249        int fd = -1;
     250       
     251        fbuf = calloc(BUFFER_SIZE, 1);
     252        if (fbuf == NULL) {
     253                rc = ENOMEM;
     254                goto out;
     255        }
     256       
    220257        if (str_cmp(uri, "/") == 0)
    221258                uri = "/index.html";
    222259       
    223         char *fname;
    224         int rc = asprintf(&fname, "%s%s", WEB_ROOT, uri);
    225         if (rc < 0)
    226                 return ENOMEM;
    227        
    228         int fd = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ);
     260        rc = asprintf(&fname, "%s%s", WEB_ROOT, uri);
     261        if (rc < 0) {
     262                rc = ENOMEM;
     263                goto out;
     264        }
     265       
     266        fd = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ);
    229267        if (fd < 0) {
    230268                rc = send_response(conn, msg_not_found);
    231                 free(fname);
    232                 return rc;
     269                goto out;
    233270        }
    234271       
    235272        free(fname);
     273        fname = NULL;
    236274       
    237275        rc = send_response(conn, msg_ok);
    238276        if (rc != EOK)
    239                 return rc;
     277                goto out;
    240278       
    241279        aoff64_t pos = 0;
     
    246284               
    247285                if (nr < 0) {
    248                         vfs_put(fd);
    249                         return EIO;
     286                        rc = EIO;
     287                        goto out;
    250288                }
    251289               
     
    253291                if (rc != EOK) {
    254292                        fprintf(stderr, "tcp_conn_send() failed\n");
    255                         vfs_put(fd);
    256                         return rc;
     293                        goto out;
    257294                }
    258295        }
    259296       
    260         vfs_put(fd);
    261        
    262         return EOK;
    263 }
    264 
    265 static int req_process(tcp_conn_t *conn)
    266 {
    267         int rc = recv_line(conn);
     297        rc = EOK;
     298out:
     299        if (fd >= 0)
     300                vfs_put(fd);
     301        free(fname);
     302        free(fbuf);
     303        return rc;
     304}
     305
     306static int req_process(tcp_conn_t *conn, recv_t *recv)
     307{
     308        char *reqline = NULL;
     309
     310        int rc = recv_line(recv, &reqline);
    268311        if (rc != EOK) {
    269312                fprintf(stderr, "recv_line() failed\n");
     
    272315       
    273316        if (verbose)
    274                 fprintf(stderr, "Request: %s", lbuf);
    275        
    276         if (str_lcmp(lbuf, "GET ", 4) != 0) {
     317                fprintf(stderr, "Request: %s", reqline);
     318       
     319        if (str_lcmp(reqline, "GET ", 4) != 0) {
    277320                rc = send_response(conn, msg_not_implemented);
    278321                return rc;
    279322        }
    280323       
    281         char *uri = lbuf + 4;
     324        char *uri = reqline + 4;
    282325        char *end_uri = str_chr(uri, ' ');
    283326        if (end_uri == NULL) {
    284                 end_uri = lbuf + lbuf_used - 2;
     327                end_uri = reqline + str_size(reqline) - 2;
    285328                assert(*end_uri == '\r');
    286329        }
     
    300343static void usage(void)
    301344{
    302         printf("Skeletal server\n"
     345        printf("Simple web server\n"
    303346            "\n"
    304347            "Usage: " NAME " [options]\n"
     
    363406{
    364407        int rc;
     408        recv_t *recv = NULL;
    365409       
    366410        if (verbose)
    367411                fprintf(stderr, "New connection, waiting for request\n");
    368412       
    369         rbuf_out = 0;
    370         rbuf_in = 0;
    371        
    372         rc = req_process(conn);
     413        rc = recv_create(conn, &recv);
     414        if (rc != EOK) {
     415                fprintf(stderr, "Out of memory.\n");
     416                goto error;
     417        }
     418       
     419        rc = req_process(conn, recv);
    373420        if (rc != EOK) {
    374421                fprintf(stderr, "Error processing request (%s)\n",
    375422                    str_error(rc));
    376                 return;
    377         }
    378 
     423                goto error;
     424        }
     425       
    379426        rc = tcp_conn_send_fin(conn);
    380427        if (rc != EOK) {
    381428                fprintf(stderr, "Error sending FIN.\n");
    382                 return;
    383         }
     429                goto error;
     430        }
     431
     432        recv_destroy(recv);
     433        return;
     434error:
     435        rc = tcp_conn_reset(conn);
     436        if (rc != EOK)
     437                fprintf(stderr, "Error resetting connection.\n");
     438       
     439        recv_destroy(recv);
    384440}
    385441
Note: See TracChangeset for help on using the changeset viewer.