unsigned int cmd_script(callbackp *callbacki) { char *domain = CONFIG_VAL(Server, domain, callbacki->g_ape->srv); char *script = NULL; int alloc = 0; APE_PARAMS_INIT(); if (domain == NULL) { send_error(callbacki->call_user, "NO_DOMAIN", "201", callbacki->g_ape); } else { char *autodom; if (strcmp(domain, "auto") == 0 && (autodom = JSTR(domain)) != NULL) { domain = autodom; #if 0 /* http://geekandpoke.typepad.com/.a/6a00d8341d3df553ef0120a6d65b8a970b-pi */ struct _http_header_line *hlines; for (hlines = callbacki->client->http.hlines; hlines != NULL; hlines = hlines->next) { if (strcasecmp(hlines->key.val, "host") == 0) { char *loc; char *newdom = xmalloc(sizeof(char) * (hlines->value.len + 1)); memset(newdom, '\0', hlines->value.len + 1); if ((loc = strrchr(hlines->value.val, '.')) != NULL) { int i, pos = 0; for (i = 0; i < hlines->value.len; i++, pos++) { newdom[pos] = hlines->value.val[i]; if (newdom[pos] == ':') { newdom[pos] = '\0'; break; } if (hlines->value.val[i] == '.' && &hlines->value.val[i] < loc) { pos = -1; } } newdom[pos] = '\0'; domain = newdom; alloc = 1; } } } #endif } sendf(callbacki->client->fd, callbacki->g_ape, "%s<html>\n<head>\n\t<script>\n\t\tdocument.domain=\"%s\"\n\t</script>\n", HEADER_DEFAULT, domain); if (alloc) { free(domain); } JFOREACH(scripts, script) { sendf(callbacki->client->fd, callbacki->g_ape, "\t<script type=\"text/javascript\" src=\"%s\"></script>\n", script); } sendbin(callbacki->client->fd, "</head>\n<body>\n</body>\n</html>", 30, 0, callbacki->g_ape); }
void proxy_write(ape_proxy *proxy, char *data, acetables *g_ape) { char *b64; int len; if (proxy->state != PROXY_CONNECTED) { return; } b64 = xmalloc(strlen(data)+1); len = base64_decode(b64, data, strlen(data)+1); sendbin(proxy->sock.fd, b64, len, 0, g_ape); free(b64); }
unsigned int cmd_script(callbackp *callbacki) { char *domain = CONFIG_VAL(Server, domain, callbacki->g_ape->srv); if (domain == NULL) { send_error(callbacki->call_user, "NO_DOMAIN", "201", callbacki->g_ape); } else { int i; sendf(callbacki->fdclient, callbacki->g_ape, "%s<html>\n<head>\n\t<script>\n\t\tdocument.domain=\"%s\"\n\t</script>\n", HEADER, domain); for (i = 1; i <= callbacki->nParam; i++) { sendf(callbacki->fdclient, callbacki->g_ape, "\t<script type=\"text/javascript\" src=\"%s\"></script>\n", callbacki->param[i]); } sendbin(callbacki->fdclient, "</head>\n<body>\n</body>\n</html>", 30, callbacki->g_ape); } return (FOR_NOTHING); }
int sendf(int sock, acetables *g_ape, char *buf, ...) { char *buff; int len; int finish; va_list val; va_start(val, buf); len = vasprintf(&buff, buf, val); va_end(val); finish = sendbin(sock, buff, len, 0, g_ape); free(buff); return finish; }
/* Send queue to socket */ int send_raws(subuser *user, acetables *g_ape) { int finish = 1, state = 0; struct _raw_pool *pool; struct _transport_properties *properties; if (user->raw_pools.nraw == 0) { return 1; } PACK_TCP(user->client->fd); /* Activate TCP_CORK */ properties = transport_get_properties(user->user->transport, g_ape); if (!user->headers.sent) { user->headers.sent = 1; switch(user->user->transport) { case TRANSPORT_XHRSTREAMING: finish &= http_send_headers(user->headers.content, HEADER_XHR, HEADER_XHR_LEN, user->client, g_ape); break; case TRANSPORT_SSE_LONGPOLLING: finish &= http_send_headers(user->headers.content, HEADER_SSE, HEADER_SSE_LEN, user->client, g_ape); break; case TRANSPORT_WEBSOCKET: case TRANSPORT_WEBSOCKET_IETF: break; default: finish &= http_send_headers(user->headers.content, HEADER_DEFAULT, HEADER_DEFAULT_LEN, user->client, g_ape); break; } } if (properties != NULL && properties->padding.left.val != NULL) { finish &= sendbin(user->client->fd, properties->padding.left.val, properties->padding.left.len, 0, g_ape); } if (user->raw_pools.high.nraw) { pool = user->raw_pools.high.rawfoot->prev; } else { pool = user->raw_pools.low.rawhead; state = 1; } if (user->user->transport == TRANSPORT_WEBSOCKET_IETF) { char payload_head[32] = { 0x84 }; int payload_size = raws_size(user); /* TODO: fragmentation? */ int payload_length = 0; if (payload_size <= 125) { payload_head[1] = (unsigned char)payload_size & 0x7F; payload_length = 2; } else if (payload_size <= 65535) { unsigned short int s = htons(payload_size); payload_head[1] = 126; memcpy(&payload_head[2], &s, 2); payload_length = 4; } else if (payload_size <= 0xFFFFFFFF) { unsigned int s = htonl(payload_size); payload_head[1] = 127; payload_head[2] = 0; payload_head[3] = 0; payload_head[4] = 0; payload_head[5] = 0; memcpy(&payload_head[6], &s, 4); payload_length = 10; } finish &= sendbin(user->client->fd, payload_head, payload_length, 0, g_ape); } finish &= sendbin(user->client->fd, "[", 1, 0, g_ape); while (pool->raw != NULL) { struct _raw_pool *pool_next = (state ? pool->next : pool->prev); finish &= sendbin(user->client->fd, pool->raw->data, pool->raw->len, 0, g_ape); if ((pool_next != NULL && pool_next->raw != NULL) || (!state && user->raw_pools.low.nraw)) { finish &= sendbin(user->client->fd, ",", 1, 0, g_ape); } else { finish &= sendbin(user->client->fd, "]", 1, 0, g_ape); if (properties != NULL && properties->padding.right.val != NULL) { finish &= sendbin(user->client->fd, properties->padding.right.val, properties->padding.right.len, 0, g_ape); } } free_raw(pool->raw); pool->raw = NULL; pool = pool_next; if ((pool == NULL || pool->raw == NULL) && !state) { pool = user->raw_pools.low.rawhead; state = 1; } } user->raw_pools.high.nraw = 0; user->raw_pools.low.nraw = 0; user->raw_pools.nraw = 0; user->raw_pools.high.rawfoot = user->raw_pools.high.rawhead; user->raw_pools.low.rawfoot = user->raw_pools.low.rawhead; FLUSH_TCP(user->client->fd); return finish; }
int send_raw_inline(ape_socket *client, transport_t transport, RAW *raw, acetables *g_ape) { struct _transport_properties *properties; int finish = 1; properties = transport_get_properties(transport, g_ape); switch(transport) { case TRANSPORT_XHRSTREAMING: finish &= http_send_headers(NULL, HEADER_XHR, HEADER_XHR_LEN, client, g_ape); break; case TRANSPORT_SSE_LONGPOLLING: finish &= http_send_headers(NULL, HEADER_SSE, HEADER_SSE_LEN, client, g_ape); break; case TRANSPORT_WEBSOCKET: case TRANSPORT_WEBSOCKET_IETF: break; default: finish &= http_send_headers(NULL, HEADER_DEFAULT, HEADER_DEFAULT_LEN, client, g_ape); break; } if (properties != NULL && properties->padding.left.val != NULL) { finish &= sendbin(client->fd, properties->padding.left.val, properties->padding.left.len, 0, g_ape); } if (transport == TRANSPORT_WEBSOCKET_IETF) { char payload_head[32] = { 0x84 }; int payload_size = raw->len+2; /* TODO: fragmentation? */ int payload_length = 0; if (payload_size <= 125) { payload_head[1] = (unsigned char)payload_size & 0x7F; payload_length = 2; } else if (payload_size <= 65535) { unsigned short int s = htons(payload_size); payload_head[1] = 126; memcpy(&payload_head[2], &s, 2); payload_length = 4; } else if (payload_size <= 0xFFFFFFFF) { unsigned int s = htonl(payload_size); payload_head[1] = 127; payload_head[2] = 0; payload_head[3] = 0; payload_head[4] = 0; payload_head[5] = 0; memcpy(&payload_head[6], &s, 4); payload_length = 10; } finish &= sendbin(client->fd, payload_head, payload_length, 0, g_ape); } finish &= sendbin(client->fd, "[", 1, 0, g_ape); finish &= sendbin(client->fd, raw->data, raw->len, 0, g_ape); finish &= sendbin(client->fd, "]", 1, 0, g_ape); if (properties != NULL && properties->padding.right.val != NULL) { finish &= sendbin(client->fd, properties->padding.right.val, properties->padding.right.len, 0, g_ape); } free_raw(raw); return finish; }
static void process_websocket_frame(ape_socket *co, acetables *g_ape) { ape_buffer *buffer = &co->buffer_in; websocket_state *websocket = co->parser.data; ape_parser *parser = &co->parser; unsigned char *pData; for (pData = (unsigned char *)&buffer->data[websocket->offset]; websocket->offset < buffer->length; websocket->offset++, pData++) { switch(websocket->step) { case WS_STEP_KEY: /* Copy the xor key (32 bits) */ websocket->key.val[websocket->key.pos] = *pData; if (++websocket->key.pos == 4) { websocket->step = WS_STEP_DATA; } break; case WS_STEP_START: /* Contain fragmentaiton infos & opcode (+ reserved bits) */ websocket->frame_payload.start = *pData; websocket->step = WS_STEP_LENGTH; break; case WS_STEP_LENGTH: /* Check for MASK bit */ if (!(*pData & 0x80)) { return; } switch (*pData & 0x7F) { /* 7bit length */ case 126: /* Following 16bit are length */ websocket->step = WS_STEP_SHORT_LENGTH; break; case 127: /* Following 64bit are length */ websocket->step = WS_STEP_EXTENDED_LENGTH; break; default: /* We have the actual length */ websocket->frame_payload.extended_length = *pData & 0x7F; websocket->step = WS_STEP_KEY; break; } break; case WS_STEP_SHORT_LENGTH: memcpy(((char *)&websocket->frame_payload)+(websocket->frame_pos), pData, 1); if (websocket->frame_pos == 3) { websocket->frame_payload.extended_length = ntohs(websocket->frame_payload.short_length); websocket->step = WS_STEP_KEY; } break; case WS_STEP_EXTENDED_LENGTH: memcpy(((char *)&websocket->frame_payload)+(websocket->frame_pos), pData, 1); if (websocket->frame_pos == 9) { websocket->frame_payload.extended_length = ntohl(websocket->frame_payload.extended_length >> 32); websocket->step = WS_STEP_KEY; } break; case WS_STEP_DATA: if (websocket->data_pos == 0) { websocket->data_pos = websocket->offset; } *pData ^= websocket->key.val[(websocket->frame_pos - websocket->data_pos) % 4]; if (--websocket->frame_payload.extended_length == 0) { unsigned char saved; websocket->data = &buffer->data[websocket->data_pos]; websocket->step = WS_STEP_START; websocket->frame_pos = -1; websocket->frame_payload.extended_length = 0; websocket->data_pos = 0; websocket->key.pos = 0; switch(websocket->frame_payload.start & 0x0F) { case 0x8: { /* Close frame Reply by a close response */ char payload_head[2] = { 0x88, 0x00 }; sendbin(co->fd, payload_head, 2, 0, g_ape); return; } case 0x9: { int body_length = &buffer->data[websocket->offset+1] - websocket->data; char payload_head[2] = { 0x8a, body_length & 0x7F }; /* All control frames MUST be 125 bytes or less */ if (body_length > 125) { payload_head[0] = 0x88; payload_head[1] = 0x00; sendbin(co->fd, payload_head, 2, 1, g_ape); return; } PACK_TCP(co->fd); sendbin(co->fd, payload_head, 2, 0, g_ape); if (body_length) { sendbin(co->fd, websocket->data, body_length, 0, g_ape); } FLUSH_TCP(co->fd); break; } case 0xA: /* Never called as long as we never ask for pong */ break; default: /* Data frame */ saved = buffer->data[websocket->offset+1]; buffer->data[websocket->offset+1] = '\0'; parser->onready(parser, g_ape); buffer->data[websocket->offset+1] = saved; break; } if (websocket->offset+1 == buffer->length) { websocket->offset = 0; buffer->length = 0; websocket->frame_pos = 0; websocket->key.pos = 0; return; } } break; default: break; } websocket->frame_pos++; }
unsigned int checkcmd(clientget *cget, subuser **iuser, acetables *g_ape) { char *param[64+1], *cmd; callback *cmdback; size_t nTok; unsigned int flag; USERS *guser = NULL; subuser *sub = NULL; nTok = explode('&', cget->get, param, 64); if (nTok < 1) { cmd = NULL; } else { cmd = param[0]; } /* TODO: Making a simple chainlist can be more efficient since we do not have many cmds */ cmdback = (callback *)hashtbl_seek(g_ape->hCallback, cmd); if (cmdback != NULL) { if ((nTok-1) == cmdback->nParam || (cmdback->nParam < 0 && (nTok-1) >= (cmdback->nParam*-1) && (cmdback->nParam*-1) <= 16)) { int tmpfd = 0; callbackp cp; switch(cmdback->need) { case NEED_SESSID: guser = seek_user_id(param[1], g_ape); break; case NEED_NOTHING: guser = NULL; break; } if (cmdback->need != NEED_NOTHING) { if (guser == NULL) { SENDH(cget->fdclient, ERR_BAD_SESSID, g_ape); return (CONNECT_SHUTDOWN); } else { sub = getsubuser(guser, cget->host); if (sub != NULL && sub->fd != cget->fdclient && sub->state == ALIVE) { if (guser->transport == TRANSPORT_IFRAME) { /* iframe is already open on "sub" */ tmpfd = sub->fd; /* Forward data directly to iframe */ CLOSE(cget->fdclient, g_ape); shutdown(cget->fdclient, 2); /* Immediatly close controller */ } else { /* Only one connection is allowed per user/host */ CLOSE(sub->fd, g_ape); shutdown(sub->fd, 2); sub->state = ADIED; sub->fd = cget->fdclient; } } else if (sub == NULL) { sub = addsubuser(cget->fdclient, cget->host, guser); if (sub != NULL) { subuser_restor(sub, g_ape); } } else if (sub != NULL) { sub->fd = cget->fdclient; } guser->idle = (long int)time(NULL); // update user idle sub->idle = guser->idle; // Update subuser idle } } cp.param = param; cp.fdclient = (tmpfd ? tmpfd : cget->fdclient); cp.call_user = guser, cp.g_ape = g_ape; cp.nParam = nTok-1; cp.host = cget->host; flag = cmdback->func(&cp); if (flag & FOR_NULL) { guser = NULL; } else if (flag & FOR_LOGIN) { guser = cp.call_user; } if (guser != NULL) { if (sub == NULL && (sub = getsubuser(guser, cget->host)) == NULL) { if ((sub = addsubuser(cget->fdclient, cget->host, guser)) == NULL) { return (CONNECT_SHUTDOWN); } subuser_restor(sub, g_ape); if (guser->transport == TRANSPORT_IFRAME) { sendbin(sub->fd, HEADER, strlen(HEADER), g_ape); } } *iuser = (tmpfd ? NULL : sub); if (flag & FOR_UPDATE_IP) { strncpy(guser->ip, cget->ip_get, 16); } /* If tmpfd is set, we do not have reasons to change this state */ if (!tmpfd) { sub->state = ALIVE; } return (CONNECT_KEEPALIVE); } return (CONNECT_SHUTDOWN); } else { SENDH(cget->fdclient, ERR_BAD_PARAM, g_ape); } } else { // unregistered CMD SENDH(cget->fdclient, ERR_BAD_CMD, g_ape); } return (CONNECT_SHUTDOWN); }
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 http_send_headers(http_headers_response *headers, const char *default_h, unsigned int default_len, ape_socket *client, acetables *g_ape) { char code[4]; int finish = 1; struct _http_headers_fields *fields; //HTTP/1.1 200 OK\r\n if (headers == NULL) { finish &= sendbin(client->fd, (char *)default_h, default_len, 0, g_ape); } else { /* We have a lot of write syscall here. TODO : use of writev */ itos(headers->code, code, 4); finish &= sendbin(client->fd, "HTTP/1.1 ", 9, 0, g_ape); finish &= sendbin(client->fd, code, 3, 0, g_ape); finish &= sendbin(client->fd, " ", 1, 0, g_ape); finish &= sendbin(client->fd, headers->detail.val, headers->detail.len, 0, g_ape); finish &= sendbin(client->fd, "\r\n", 2, 0, g_ape); for (fields = headers->fields; fields != NULL; fields = fields->next) { finish &= sendbin(client->fd, fields->key.val, fields->key.len, 0, g_ape); finish &= sendbin(client->fd, ": ", 2, 0, g_ape); finish &= sendbin(client->fd, fields->value.val, fields->value.len, 0, g_ape); finish &= sendbin(client->fd, "\r\n", 2, 0, g_ape); fields = fields->next; } finish &= sendbin(client->fd, "\r\n", 2, 0, g_ape); } return finish; }
void sendbmp() { printf("sending the bmp\n"); sendconst(bmphdr); // Now Send a header sendbin(starshipbmp);//and the binary data! }
void sendfavicon() { printf("sending the icon\n"); sendconst(iconhdr); // Now Send a header sendbin(starshipicon);//and the binary data! }