subuser *checkrecv(ape_socket *co, acetables *g_ape) { unsigned int op; http_state *http = co->parser.data; subuser *user = NULL; clientget cget; if (http->host == NULL) { shutdown(co->fd, 2); return NULL; } if (gettransport(http->uri) == TRANSPORT_WEBSOCKET) { char *origin = get_header_line(http->hlines, "Origin"); websocket_state *websocket; if (origin == NULL) { shutdown(co->fd, 2); return NULL; } PACK_TCP(co->fd); sendbin(co->fd, CONST_STR_LEN(WEBSOCKET_HARDCODED_HEADERS), 0, g_ape); sendbin(co->fd, CONST_STR_LEN("WebSocket-Origin: "), 0, g_ape); sendbin(co->fd, origin, strlen(origin), 0, g_ape); sendbin(co->fd, CONST_STR_LEN("\r\nWebSocket-Location: ws://"), 0, g_ape); sendbin(co->fd, http->host, strlen(http->host), 0, g_ape); sendbin(co->fd, http->uri, strlen(http->uri), 0, g_ape); sendbin(co->fd, CONST_STR_LEN("\r\n\r\n"), 0, g_ape); FLUSH_TCP(co->fd); co->parser = parser_init_stream(co); websocket = co->parser.data; websocket->http = http; /* keep http data */ return NULL; } if (http->data == NULL) { sendbin(co->fd, HEADER_DEFAULT, HEADER_DEFAULT_LEN, 0, g_ape); sendbin(co->fd, CONST_STR_LEN(CONTENT_NOTFOUND), 0, g_ape); safe_shutdown(co->fd, g_ape); return NULL; } cget.client = co; cget.ip_get = co->ip_client; cget.get = http->data; cget.host = http->host; cget.hlines = http->hlines; op = checkcmd(&cget, gettransport(http->uri), &user, g_ape); switch (op) { case CONNECT_SHUTDOWN: safe_shutdown(co->fd, g_ape); break; case CONNECT_KEEPALIVE: break; } return user; }
int process_cmd(json_item *ijson, struct _cmd_process *pc, subuser **iuser, acetables *g_ape) { callback *cmdback, tmpback = {handle_bad_cmd, NEED_NOTHING}; json_item *rjson = json_lookup(ijson->jchild.child, "cmd"), *jchl; subuser *sub = pc->sub; unsigned int flag; unsigned short int attach = 1; if (rjson != NULL && rjson->jval.vu.str.value != NULL) { callbackp cp; cp.client = NULL; cp.cmd = rjson->jval.vu.str.value; cp.data = NULL; cp.hlines = NULL; json_item *jsid; if ((cmdback = (callback *)hashtbl_seek(g_ape->hCallback, rjson->jval.vu.str.value)) == NULL) { cmdback = &tmpback; } if ((pc->guser == NULL && (jsid = json_lookup(ijson->jchild.child, "sessid")) != NULL && jsid->jval.vu.str.value != NULL)) { pc->guser = seek_user_id(jsid->jval.vu.str.value, g_ape); } if (cmdback->need != NEED_NOTHING || pc->guser != NULL) { // We process the connection like a "NEED_SESSID" if the user provide its key if (pc->guser == NULL) { RAW *newraw; json_item *jlist = json_new_object(); json_set_property_strZ(jlist, "code", "004"); json_set_property_strZ(jlist, "value", "BAD_SESSID"); newraw = forge_raw(RAW_ERR, jlist); send_raw_inline(pc->client, pc->transport, newraw, g_ape); return (CONNECT_SHUTDOWN); } else if (sub == NULL) { sub = getsubuser(pc->guser, pc->host); if (sub != NULL && sub->client->fd != pc->client->fd && sub->state == ALIVE) { /* The user open a new connection while he already has one openned */ struct _transport_open_same_host_p retval = transport_open_same_host(sub, pc->client, pc->guser->transport); if (retval.client_close != NULL) { // Send CLOSE if no response has been sent yet if (!sub->headers.sent) { RAW *newraw; json_item *jlist = json_new_object(); json_set_property_strZ(jlist, "value", "null"); newraw = forge_raw("CLOSE", jlist); send_raw_inline((retval.client_close->fd == pc->client->fd ? pc->client : sub->client), pc->transport, newraw, g_ape); } // It's not safe to leave the subuser pointer in co->attach anymore // since subuser could subsequently be deleted, leaving a pointer into free heap. // So, let this socket finish up on its own and pretend its already finished. sub->state = ADIED; sub->headers.sent = 0; http_headers_free(sub->headers.content); sub->headers.content = NULL; sub->burn_after_writing = 0; g_ape->co[retval.client_close->fd]->attach = NULL; safe_shutdown(retval.client_close->fd, g_ape); } sub->client = cp.client = retval.client_listener; sub->state = retval.substate; attach = retval.attach; } else if (sub == NULL) { sub = addsubuser(pc->client, pc->host, pc->guser, g_ape); if (sub != NULL) { subuser_restor(sub, g_ape); } } else if (sub != NULL) { sub->client = pc->client; } pc->guser->idle = (long int)time(NULL); // update user idle sub->idle = pc->guser->idle; // Update subuser idle } } if (pc->guser != NULL && sub != NULL && (jchl = json_lookup(ijson->jchild.child, "chl")) != NULL /*&& jchl->jval.vu.integer_value > sub->current_chl*/) { sub->current_chl = jchl->jval.vu.integer_value; } #if 0 else if (pc->guser != NULL && sub != NULL) { /* if a bad challenge is detected, we are stoping walking on cmds */ send_error(pc->guser, "BAD_CHL", "250", g_ape); sub->state = ALIVE; return (CONNECT_KEEPALIVE); } #endif cp.param = json_lookup(ijson->jchild.child, "params"); cp.client = (cp.client != NULL ? cp.client : pc->client); cp.call_user = pc->guser; cp.call_subuser = sub; cp.g_ape = g_ape; cp.host = pc->host; cp.ip = pc->ip; cp.chl = (sub != NULL ? sub->current_chl : 0); cp.transport = pc->transport; cp.hlines = pc->hlines; /* Little hack to access user object on connect hook callback (preallocate an user) */ if (strncasecmp(cp.cmd, "CONNECT", 7) == 0 && cp.cmd[7] == '\0') { pc->guser = cp.call_user = adduser(cp.client, cp.host, cp.ip, NULL, g_ape); pc->guser->transport = pc->transport; sub = cp.call_subuser = cp.call_user->subuser; } if ((flag = call_cmd_hook(cp.cmd, &cp, g_ape)) == RETURN_CONTINUE) { flag = cmdback->func(&cp); } if (flag & RETURN_NULL) { pc->guser = NULL; } else if (flag & RETURN_BAD_PARAMS) { RAW *newraw; json_item *jlist = json_new_object(); if (cp.chl) { json_set_property_intN(jlist, "chl", 3, cp.chl); } json_set_property_strZ(jlist, "code", "001"); json_set_property_strZ(jlist, "value", "BAD_PARAMS"); newraw = forge_raw(RAW_ERR, jlist); if (cp.call_user != NULL) { //cp.call_user->istmp = 0; if (sub == NULL) { sub = getsubuser(pc->guser, pc->host); } post_raw_sub(newraw, sub, g_ape); } else { send_raw_inline(pc->client, pc->transport, newraw, g_ape); } //guser = NULL; } else if (flag & RETURN_BAD_CMD) { RAW *newraw; json_item *jlist = json_new_object(); if (cp.chl) { json_set_property_intN(jlist, "chl", 3, cp.chl); } json_set_property_strZ(jlist, "code", "003"); json_set_property_strZ(jlist, "value", "BAD_CMD"); newraw = forge_raw(RAW_ERR, jlist); if (cp.call_user != NULL) { if (sub == NULL) { sub = getsubuser(pc->guser, pc->host); } post_raw_sub(newraw, sub, g_ape); } else { send_raw_inline(pc->client, pc->transport, newraw, g_ape); } } if (pc->guser != NULL) { if (sub == NULL) { sub = getsubuser(pc->guser, pc->host); } if (iuser != NULL) { *iuser = (attach ? sub : NULL); } /* If tmpfd is set, we do not have any reasons to change its state */ sub->state = ALIVE; if (flag & RETURN_HANG || flag & RETURN_BAD_PARAMS) { return (CONNECT_KEEPALIVE); } } else if (flag & RETURN_HANG) { /* Doesn't need sessid */ return (CONNECT_KEEPALIVE); } else { return (CONNECT_SHUTDOWN); } } else { RAW *newraw; json_item *jlist = json_new_object(); json_set_property_strZ(jlist, "code", "003"); json_set_property_strZ(jlist, "value", "NO_CMD"); newraw = forge_raw(RAW_ERR, jlist); send_raw_inline(pc->client, pc->transport, newraw, g_ape); //printf("Cant find %s\n", rjson->jval.vu.str.value); return (CONNECT_SHUTDOWN); } return -1; }
void safe_shutdown_and_die(int code) { safe_shutdown(); exit(code); }