示例#1
0
/**
 * This function initializes the tcp context global instance to 0 except for
 * file descriptor descriptor for stdin, stdout and stderr.
 *
 * @author    Mohd Naushad Ahmed
 * @version   1.0
 * @param     none
 * @return    none
 */
int http_process_http_req ( int conn_id, char *http_req, int http_req_len )
{
  char http_header[1024];
  char http_body[2048];
  int http_header_len;
  
  memset((void*)&http_header, 0, sizeof(http_header));
  memset((void*)&http_body, 0, sizeof(http_body));
  http_parse_req(conn_id, http_req, http_req_len);

  if (!strcmp(g_http_ctx[conn_id].resource_name, "/prelogin.html") ||
      !strcmp(g_http_ctx[conn_id].resource_name, "/login_response.html"))
  {
    http_parse_qs(conn_id);
  }
  
  return (0);
}/* http_process_http_req */
示例#2
0
static void processor(const char *tx_addr, int port)
{
    sys_init(1);
    sys_log('E', "started port=%d, tx=%s\n", port, tx_addr);

    /* connect to the control thread */
    char addr[MAX_ADDR];
    sys_address(addr, port);
    IO *io = sys_connect(addr, IO_CHUNK);

    tx_attach(tx_addr);

    /* get env code from the tx */
    char *code = tx_program();
    char *res = mem_alloc(MAX_BLOCK);

    while (!io->stop) {
        sys_iready(io, -1);

        int status = -1;
        long long sid = 0LL, time = sys_millis();

        Env *env = NULL;
        Arg *arg = NULL;
        Vars *v = vars_new(0), *r = NULL, *w = NULL;

        Http_Req *req = http_parse_req(io);
        if (io->stop)
            goto exit;

        if (req == NULL) {
            status = http_400(io);
            goto exit;
        }

        if (req->method == OPTIONS) {
            status = http_opts(io);
            goto exit;
        }

        env = env_new("net", code);

        if (str_idx(req->path, "/fn") == 0) {
            int idx = (req->path[3] == '/') ? 4 : 3;
            int i = 0, len = 1, cnt = 0;
            Func **fns = env_funcs(env, req->path + idx, &cnt);

            status = http_200(io);
            while (status == 200 && len) {
                len = pack_fn2csv(fns, cnt, res, MAX_BLOCK, &i);
                status = http_chunk(io, res, len);
            }

            mem_free(fns);
            goto exit;
        }

        /* compare the request with the function defintion */
        Func *fn = env_func(env, req->path + 1);
        if (fn == NULL) {
            Error *err = error_new("unknown function '%s'", req->path + 1);
            status = http_404(io, err->msg);
            mem_free(err);
            goto exit;
        }

        if (fn->rp.name != NULL && req->method != POST) {
            status = http_405(io, POST);
            goto exit;
        }

        if (fn->rp.name == NULL && req->method == POST) {
            status = http_405(io, GET);
            goto exit;
        }

        /* TODO: think what to do with duplicate parameter values */
        for (int i = 0; i < req->args->len; ++i) {
            char *name = req->args->names[i];
            if (array_freq(req->args->names, req->args->len, name) > 1) {
                Error *err = error_new("duplicate parameter '%s' "
                                       "(not supported)",
                                       name);
                status = http_404(io, err->msg);
                mem_free(err);
                goto exit;
            }
        }

        if (fn->pp.len != req->args->len) {
            Error *err = error_new("expected %d primitive parameters, got %d",
                                   fn->pp.len, req->args->len);
            status = http_404(io, err->msg);
            mem_free(err);
            goto exit;
        }

        arg = mem_alloc(sizeof(Arg));
        for (int i = 0; i < fn->pp.len; ++i) {
            char *name = fn->pp.names[i];
            Type t = fn->pp.types[i];

            int idx = array_scan(req->args->names, req->args->len, name);
            if (idx < 0) {
                Error *err = error_new("unknown parameter '%s'", name);
                status = http_404(io, err->msg);
                mem_free(err);
                goto exit;
            }

            char *val = req->args->vals[idx];
            int error = 0;
            if (t == Int) {
                arg->vals[i].v_int = str_int(val, &error);
            } else if (t == Real)
                arg->vals[i].v_real = str_real(val, &error);
            else if (t == Long)
                arg->vals[i].v_long = str_long(val, &error);
            else if (t == String) {
                error = str_len(val) > MAX_STRING;
                if (!error)
                    str_cpy(arg->vals[i].v_str, val);
            }

            if (error) {
                Error *err = error_new("value '%s' (parameter '%s') "
                                       "is not of type '%s'",
                                       val, name, type_to_str(t));
                status = http_404(io, err->msg);
                mem_free(err);
                goto exit;
            }
        }

        if (fn->rp.name != NULL) {
            TBuf *body = NULL;
            if (req->len > 0) {
                Error *err = pack_csv2rel(req->body, fn->rp.head, &body);
                if (err != NULL) {
                    status = http_404(io, err->msg);
                    mem_free(err);
                    goto exit;
                }
            } else {
                body = tbuf_new();
            }

            vars_add(v, fn->rp.name, 0, body);

            /* project the parameter */
            Rel *param = rel_project(rel_load(fn->rp.head, fn->rp.name),
                                     fn->rp.head->names,
                                     fn->rp.head->len);

            rel_eval(param, v, arg);

            /* clean the previous version */
            tbuf_clean(body);
            tbuf_free(body);

            /* replace with the new body */
            int vpos = array_scan(v->names, v->len, fn->rp.name);
            v->vals[vpos] = param->body;

            param->body = NULL;
            rel_free(param);
        }

        /* start a transaction */
        r = vars_new(fn->r.len);
        w = vars_new(fn->w.len);
        for (int i = 0; i < fn->r.len; ++i)
            vars_add(r, fn->r.names[i], 0, NULL);
        for (int i = 0; i < fn->w.len; ++i)
            vars_add(w, fn->w.names[i], 0, NULL);

        sid = tx_enter(addr, r, w);

        /* prepare variables */
        for (int i = 0; i < r->len; ++i) {
            TBuf *body = vol_read(r->vols[i], r->names[i], r->vers[i]);
            vars_add(v, r->names[i], 0, body);
        }
        for (int i = 0; i < w->len; ++i) {
            int pos = array_scan(v->names, v->len, w->names[i]);
            if (pos < 0)
                vars_add(v, w->names[i], 0, NULL);
        }
        for (int i = 0; i < fn->t.len; ++i)
            vars_add(v, fn->t.names[i], 0, NULL);

        /* evaluate the function body */
        for (int i = 0; i < fn->slen; ++i)
            rel_eval(fn->stmts[i], v, arg);

        /* prepare the return value. note, the resulting relation
           is just a container for the body, so it is not freed */
        Rel *ret = NULL;
        if (fn->ret != NULL)
            ret = fn->stmts[fn->slen - 1];

        /* persist the global variables */
        for (int i = 0; i < w->len; ++i) {
            int idx = array_scan(v->names, v->len, w->names[i]);
            if (idx < 0) {
                status = http_500(io);
                goto exit;
            }

            vol_write(w->vols[i], v->vals[idx], w->names[i], w->vers[i]);
            tbuf_free(v->vals[idx]);
            v->vals[idx] = NULL;
        }

        /* confirm a success and send the result back */
        status = http_200(io);
        if (status != 200)
            goto exit;

        tx_commit(sid);

        /* N.B. there is no explicit revert as the transaction manager handles
           nested tx_enter and a connectivity failure as a rollback */

        int len = 1, i = 0;
        while (status == 200 && len) {
            len = pack_rel2csv(ret, res, MAX_BLOCK, i++);
            status = http_chunk(io, res, len);
        }
exit:
        if (status != -1)
            sys_log('E', "%016llX method %c, path %s, time %lldms - %3d\n",
                         sid,
                         (req == NULL) ? '?' : req->method,
                         (req == NULL) ? "malformed" : req->path,
                         sys_millis() - time,
                         status);


        if (r != NULL)
            vars_free(r);
        if (w != NULL)
            vars_free(w);
        if (arg != NULL)
            mem_free(arg);
        if (req != NULL)
            http_free_req(req);
        if (env != NULL)
            env_free(env);
        for (int i = 0; i < v->len; ++i)
            if (v->vals[i] != NULL) {
                tbuf_clean(v->vals[i]);
                tbuf_free(v->vals[i]);
            }
        vars_free(v);

        sys_term(io);
    }

    mem_free(code);
    mem_free(res);
    tx_detach();
    sys_close(io);
}