コード例 #1
0
ファイル: http.c プロジェクト: mcspring/blastbeat
static int bb_session_headers_complete(http_parser *parser) {
        //printf("headers parsed\n");
        struct bb_session_request *bbsr = (struct bb_session_request *) parser->data;
        off_t i;
        //printf("%s %.*s HTTP/%d.%d\n", http_method_str(parser->method), (int) bbsr->headers[0].keylen, bbsr->headers[0].key, parser->http_major, parser->http_minor);
        /*
        for(i=1;i<=bbsr->header_pos;i++) {
                printf("%.*s: %.*s\n", (int) bbsr->headers[i].keylen, bbsr->headers[i].key, (int)bbsr->headers[i].vallen, bbsr->headers[i].value);
        }
        */

        // ok get the Host header
        struct bb_http_header *bbhh = bb_http_req_header(bbsr, "Host", 4);
        if (!bbhh) {
                return -1;
        }

        if (!bbsr->bbs->dealer) {
                bbsr->bbs->dealer = bb_get_dealer(bbsr->bbs->acceptor, bbhh->value, bbhh->vallen);
        	if (!bbsr->bbs->dealer) {
                	return -1;
        	}
        }

        if (parser->upgrade) {
                struct bb_http_header *bbhh = bb_http_req_header(bbsr, "Upgrade", 7);
                if (bbhh) {
                        if (!bb_stricmp("websocket", 9, bbhh->value, bbhh->vallen)) {
                                bbsr->type = BLASTBEAT_TYPE_WEBSOCKET;
                                bb_send_websocket_handshake(bbsr);
				goto msg;
                        }
                }
        }

        if (!http_should_keep_alive(parser)) {
                //printf("NO KEEP ALIVE !!!\n");
                bbsr->close = 1;
        }

msg:
        // now encode headers in a uwsgi packet and send it as "headers" message
	if (bb_uwsgi(bbsr)) {
		return -1;
	}
        bb_zmq_send_msg(bbsr->bbs->dealer->identity, bbsr->bbs->dealer->len, (char *) &bbsr->bbs->uuid_part1, BB_UUID_LEN, "uwsgi", 5, bbsr->uwsgi_buf, bbsr->uwsgi_pos);
        return 0;
}
コード例 #2
0
ファイル: socketio.c プロジェクト: unbit/blastbeat
int bb_manage_socketio(struct bb_session *bbs, char *method, size_t method_len, char *url, size_t url_len) {

    char *query_string = memchr(url, '?', url_len);
    size_t query_string_len = 0;
    if (query_string) {
        query_string_len = url_len - (query_string-url);
        url_len = query_string-url;
    }

    //fprintf(stderr,"SOCKET.IO %p %.*s %.*s\n", bbs, method_len, method, url_len, url);

    // handshake
    // /socket.io/1/
    if (url_len == 13) {

        char handshake[36+3+3+1+21];

        uuid_t *session_uuid = (uuid_t *) &bbs->uuid_part1;
        uuid_unparse(*session_uuid, handshake);

        if (bbs->stream_id > 0) {
            // only websockets are supported under SPDY
            char *supported = "websocket";
            memcpy(handshake+36, ":30:60:", 7);
            memcpy(handshake+36+7, supported, 9);
            if (bb_spdy_raw_send_headers(bbs, 7, (struct bb_http_header *) handshake_spdy_headers, "200", "HTTP/1.1", 0)) return -1;
            if (bb_spdy_send_body(bbs, handshake, 52)) return -1;
            if (bb_spdy_send_end(bbs)) return -1;
        }
        else {
            char *supported = "websocket,xhr-polling";
            memcpy(handshake+36, ":30:60:", 7);
            memcpy(handshake+36+7, supported, 21);
            if (bb_wq_push(bbs, (char *)handshake_headers, strlen(handshake_headers), 0)) return -1;
            if (bb_wq_push_copy(bbs, handshake, 64, BB_WQ_FREE)) return -1;
            // close the connection too... (simplify resource management)
            if (bb_wq_push_close(bbs)) return -1;
        }

        // mark the session as persistent
        bbs->persistent = 1;

        // 30 seconds from now to finalize the handshake
        bb_session_reset_timer(bbs, 30, NULL);

        // now send the uwsgi pocket, to allow the dealer to close the session
        return 0;

    }

    // now we try to get the transport and session
    off_t i;
    char *transport = NULL;
    size_t transport_len = 0;

    for(i=13; i<url_len; i++) {
        if (url[i] == '/') {
            transport = url+13;
            transport_len = i-13;
            break;
        }
    }

    if (!transport) return -1;

    char *session_id = NULL;
    size_t session_id_len = 0;
    for(i=13+transport_len+1; i<url_len; i++) {
        if (url[i] == '/') {
            session_id = transport+transport_len+1;
            session_id_len = i-(13+transport_len+1);
            break;
        }
    }

    if (!session_id) {
        session_id = transport+transport_len+1;
        session_id_len = url_len - (13+transport_len+1);
    }

    if (session_id_len == 0 || session_id_len > 36) return -1;

    uuid_t sio_uuid;
    char tmp_uuid[37];
    memcpy(tmp_uuid, session_id, session_id_len);
    tmp_uuid[36] = 0;
    if (uuid_parse(tmp_uuid, sio_uuid)) return -1;

    struct bb_session *persistent_bbs = bb_sht_get((char *)sio_uuid);
    if (!persistent_bbs) return -1;

    // destroy the session !!!
    // check for non-persisten-sessions or non-vhost matching too
    if (transport_len == 0 || !bb_strcmp(query_string, query_string_len, "?disconnect", 12) || !persistent_bbs->persistent || persistent_bbs->vhost != bbs->vhost) {
        persistent_bbs->persistent = 0;
        // DANGER !!! avoid destroying the current session too early
        if (persistent_bbs != bbs) {
            bb_session_close(persistent_bbs);
        }
        return -1;
    }

    // already the right session
    if (persistent_bbs == bbs) goto ready;
    // do not report 'end' message on end of session
    bbs->stealth = 1;
ready:

    if (!bb_strcmp(transport, transport_len, "websocket", 9)) {

        // map the connection to allow sending from the persistent session
        // to the current connection
        struct bb_connection *bbc = bbs->connection;
        persistent_bbs->connection = bbc;

        bbs->connection->func = bb_websocket_func;
        // set the persistent session
        bbs->sio_session = persistent_bbs;

        bb_send_websocket_handshake(bbs);
        bb_websocket_reply(bbs, "1::", 3);

        persistent_bbs->sio_connected = 1;
        persistent_bbs->sio_realtime = 1;

        bb_session_reset_timer(persistent_bbs, 20, socketio_heartbeat);
        bbs->request.no_uwsgi = 1;

        return 0;
    }


    if (!bb_strcmp(transport, transport_len, "xhr-polling", 11)) {

        // sending messages does not require remapping the session
        if (!bb_strcmp(method, method_len, "POST",4)) {
            if (!persistent_bbs->sio_connected) return -1;
            if (bb_wq_push(bbs, (char *)post_headers, strlen(post_headers), 0)) return -1;
            //if (bb_wq_push_close(bbs)) return -1;
            if (bbs->request.parser.content_length != ULLONG_MAX && bbs->request.parser.content_length > 0) {
                bbs->sio_session = persistent_bbs;
                //bbs->sio_bbs = persistent_bbs;
                bbs->request.no_uwsgi = 1;
                // set socket.io hooks
                bbs->recv_body = bb_socketio_recv_body;
                bbs->recv_complete = bb_socketio_recv_complete;
                // do not report session death
                bbs->stealth = 1;
                return 0;
            }
            return -1;
        }

        // ok we are ready
        if (!bb_strcmp(method, method_len, "GET", 3)) {
            // already handshaked, this is a poll
            if (persistent_bbs->sio_connected) {


                // check if a poller is already running
                if (persistent_bbs->sio_poller) return -1;

                // ...and map the connection
                struct bb_connection *bbc = bbs->connection;
                persistent_bbs->connection = bbc;

                // do not forward the request to the dealer
                bbs->request.no_uwsgi = 1;
                struct bb_socketio_message *bbsm = persistent_bbs->sio_queue;
                if (bbsm) {
                    if (bb_socketio_send(persistent_bbs, bbsm->buf, bbsm->len)) {
                        fprintf(stderr,"unable to deliver message\n");
                    }
                    persistent_bbs->sio_queue = bbsm->next;
                    bb_free(bbsm, sizeof(struct bb_socketio_message));
                    return 0;
                }
                // start the poller
                persistent_bbs->sio_poller = 1;
                bb_session_reset_timer(persistent_bbs, 30.0, socketio_poller);
                return 0;
            }
            else {
                if (bb_wq_push(bbs, (char *)connected_headers, strlen(connected_headers), 0)) return -1;
                if (bb_wq_push_close(bbs)) return -1;
                persistent_bbs->sio_connected = 1;
                // start the sio_timer
                bb_session_reset_timer(persistent_bbs, 60.0, NULL);
                return 0;
            }
        }
    }

    return -1;
}