Ejemplo n.º 1
0
int bb_socketio_push(struct bb_session *bbs, char type, char *buf, size_t len) {

    char *message = bb_alloc(4 + len);
    if (!message) {
        bb_error("malloc()");
        return -1;
    }

    message[0] = type;
    message[1] = ':';
    message[2] = ':';
    message[3] = ':';

    memcpy(message+4, buf, len);

    if (bbs->sio_realtime) {
        return bb_websocket_reply(bbs, message, len+4);
    }


    struct bb_socketio_message *last_bbsm=NULL,*bbsm = bbs->sio_queue;

    while(bbsm) {
        last_bbsm = bbsm;
        bbsm = bbsm->next;
    }

    bbsm = bb_alloc(sizeof(struct bb_socketio_message));
    if (!bbsm) {
        bb_free(message, len+4);
        bb_error("malloc()");
        return -1;
    }
    memset(bbsm, 0, sizeof(struct bb_socketio_message));
    bbsm->buf = message;
    bbsm->len = 4+len;
    if (last_bbsm) {
        last_bbsm->next = bbsm;
    }
    else {
        bbs->sio_queue = bbsm;
    }

    //is a poller attached to the session ?
    if (bbs->sio_poller) {
        ev_feed_event(blastbeat.loop, &bbs->death_timer, EV_TIMER);
    }

    return 0;
}
Ejemplo n.º 2
0
static int cache_header_value_cb(http_parser *parser, const char *buf, size_t len) {
	struct bb_cache_item *bbci = (struct bb_cache_item *) parser->data;

        if (bbci->headers_len + len > MAX_HEADERS_SIZE) return -1;
        int pos = bbci->headers_count-1;

        if (!bbci->last_was_value) {
                bbci->headers[pos].value = bb_alloc(len);
		if (!bbci->headers[pos].value) {
			return -1;
		}
                memcpy(bbci->headers[pos].value, buf, len);
                bbci->headers[pos].vallen = len;

		bbci->headers_len+=len;
        }
        else {
		char *tmp_buf = bb_realloc(bbci->headers[pos].value, bbci->headers[pos].vallen, len);	
		if (!tmp_buf) {
			return -1;
		}
		bbci->headers[pos].value = tmp_buf;
                memcpy(bbci->headers[pos].value + bbci->headers[pos].vallen, buf, len);
                bbci->headers[pos].vallen += len;

		bbci->headers_len+=len;
        }
        bbci->last_was_value = 1;
        return 0;
}
Ejemplo n.º 3
0
static int cache_header_field_cb(http_parser *parser, const char *buf, size_t len) {
        struct bb_cache_item *bbci = (struct bb_cache_item *) parser->data;

        if (bbci->headers_len + len > MAX_HEADERS_SIZE) return -1;

        if (bbci->last_was_value) {
		if (bbci->headers_count + 1 > blastbeat.max_headers) return -1;
		struct bb_http_header *bbhh = bb_realloc(bbci->headers, sizeof(struct bb_http_header)*bbci->headers_count, sizeof(struct bb_http_header));
		if (!bbhh) {
			return -1;
		}
		bbci->headers_len += sizeof(struct bb_http_header);
		// is it the first header ?
		if (bbci->headers_count == 0) {
			bbci->http_end_of_first_line = (char *) buf-2;
		}
		bbci->headers = bbhh;
		int pos = bbci->headers_count;
                bbci->headers_count++;

		bbci->headers[pos].value = NULL;
		bbci->headers[pos].vallen = 0;
		bbci->headers[pos].keylen = 0;

                bbci->headers[pos].key = bb_alloc(len);
		if (!bbci->headers[pos].key) {
			return -1;
		}

                memcpy(bbci->headers[pos].key, buf, len);
		bbci->headers[pos].keylen = len;

		bbci->headers_len += len;
        }
        else {
		int pos = bbci->headers_count-1;
		char *tmp_buf = bb_realloc(bbci->headers[pos].key, bbci->headers[pos].keylen, len);
		if (!tmp_buf) {
			return -1;
		}
		bbci->headers[pos].key = tmp_buf;
                memcpy(bbci->headers[pos].key + bbci->headers[pos].keylen, buf, len);
                bbci->headers[pos].keylen += len;

		bbci->headers_len+= len;
        }
        bbci->last_was_value = 0;
        return 0;
}
Ejemplo n.º 4
0
Archivo: cfg.c Proyecto: berkus/lang-e
/* bb_finalize: finish the basic block b ending at cp.
   If there is more code (cp+step < lp), return a new basic block to hold it.
   If link is true, make b a predecessor of the new basic block. */
static inline i_bb_t bb_finalize (i_bb_t b, icode_t cp, icode_t lp, 
				  unsigned step, unsigned link) {
     assert(!b->init);
     b->init = 1;
     b->t = cp;
     if (cp+step < lp) {
	  i_bb_t newbb = bb_alloc();
	  newbb->h = cp + step;
	  b->lnext = newbb;
	  newbb->lprev = b;
	  if (link)
	       bb_linkbb(b, newbb);
	  return newbb;
     }
     return b;
}
Ejemplo n.º 5
0
int bb_socketio_send(struct bb_session *bbs, char *buf, size_t len) {

    char *cl = bb_alloc(MAX_CONTENT_LENGTH);
    if (!cl) {
        bb_error("unable to allocate memory for socket.io message: malloc()");
        return -1;
    }
    int chunk_len = snprintf(cl, MAX_CONTENT_LENGTH, "%llu\r\n\r\n", (unsigned long long) len);

    if (bb_wq_push(bbs, (char *)message_headers, strlen(message_headers), 0)) return -1;
    if (bb_wq_push(bbs, (char *)cl, chunk_len, BB_WQ_FREE)) return -1;

    if (bb_wq_push(bbs, (char *)buf, len, BB_WQ_FREE)) return -1;

    return 0;
}
Ejemplo n.º 6
0
Archivo: cfg.c Proyecto: berkus/lang-e
i_bb_t i_bb_new (unsigned maxlen, i_bb_t lprev) {
     i_bb_t b = bb_alloc();
     
     if (lprev) {
	  lprev->lnext = b;
	  b->lprev = lprev;
	  if (lprev == i_fg_tail)
	       i_fg_tail = b;
     } else {
	  b->lnext = i_fg_root;
	  i_fg_root->lprev = b;
	  i_fg_root = b;
     }

     NEW(i_ip, maxlen);
     i_buf = i_ip;
     i_lim = i_buf+maxlen;

     return b;
}
Ejemplo n.º 7
0
static int bb_ssl_servername(SSL *ssl,int *ad, void *arg) {
	const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
	if (!servername) return SSL_TLSEXT_ERR_NOACK;
	struct bb_connection *bbc = SSL_get_ex_data(ssl, blastbeat.ssl_index);
	struct bb_acceptor *bba = bbc->acceptor;
	size_t servername_len = strlen(servername);

	struct bb_virtualhost *vhost = NULL;
	struct bb_hostname *bbhn = NULL;

	if (bba->addr.in4.sin_port != htons(443) && !strchr(servername, ':')) {
		size_t port_len = strlen(bba->port_str);
		char *new_sn = bb_alloc(servername_len+port_len);
		if (!new_sn) return SSL_TLSEXT_ERR_NOACK;
		memcpy(new_sn, servername, servername_len);
		memcpy(new_sn + servername_len, bba->port_str, port_len);

		vhost = bb_vhost_get(new_sn, servername_len+port_len, &bbhn);
		bb_free(new_sn, servername_len+port_len);
	}
	else {
		vhost = bb_vhost_get((char *)servername, servername_len, &bbhn);
	}

	if (!vhost) return SSL_TLSEXT_ERR_NOACK;
	// per vhost-context is required to decrypt keys sent by dealers
	if (!vhost->ctx) return SSL_TLSEXT_ERR_NOACK;

	// prefer dealer-defined context
	if (bbhn->ctx) {
		SSL_set_SSL_CTX(ssl, bbhn->ctx);
		return SSL_TLSEXT_ERR_OK;
	}


	SSL_set_SSL_CTX(ssl, vhost->ctx);

	return SSL_TLSEXT_ERR_OK;
}
Ejemplo n.º 8
0
Archivo: cfg.c Proyecto: berkus/lang-e
void i_fg_build (void) {
     unsigned i;
     i_puint32 cp = i_buf;	/* Start of code to analyze */
     i_puint32 lp = i_lim;	/* End of code to analyze */
     i_uint32 op;		/* Current opcode */
     i_bb_t b;			/* Current basic block */

     num_bb = 0;
     b = bb_alloc();
     b->h = cp;

     if (i_ralloctype == RA_EZ) {
	  i_fg_root = i_fg_tail = b;
	  b->t = lp - i_isize;
	  return;
     }

     i_calls_cur = i_calls_lim = 0;
     NEW0(lbl2bb, i_lab_cur); 
     NEW(fwdrefs, i_nbb); fwdref_cur = 0;

     i_fg_root = b;
     do {
	  assert(b && !b->init);
	  op = get_op(cp);
	  switch(i_op2class[op]) {
	  case I_BOP:	  case I_BOPF:
	  case I_MOPR:	  case I_MOPRF:
	       assert(!isimmed(op));
	       markuse(b, get_rs(cp));
	       markuse(b, get_rs2(cp));
	       markdef(b, get_rd(cp));
	       break;
	  case I_BOPI:	  case I_MOPRI:	case I_MOPRIF:
	       assert(isimmed(op));
	       markuse(b, get_rs(cp));
	       markdef(b, get_rd(cp));
	       break;
	  case I_MOPW:	  case I_MOPWF:
	       assert(!isimmed(op));
	       markuse(b, get_rd(cp));
	       markuse(b, get_rs(cp));
	       markuse(b, get_rs2(cp));
	       break;
	  case I_MOPWI:	  case I_MOPWIF:
	       assert(isimmed(op));
	       markuse(b, get_rd(cp));
	       markuse(b, get_rs(cp));
	       break;
	  case I_UOP:     case I_UOPF:
	       assert(!isimmed(op));
	       markuse(b, get_rs(cp));
	       markdef(b, get_rd(cp));
	       break;
	  case I_UOPI:
	       assert(isimmed(op));
	       markdef(b, get_rd(cp));
	       break;
	  case I_SET:	   case I_SETF:
	       markdef(b, get_rd(cp));
	       break;
	  case I_LEA:	   case I_LEAF:
	       SCLASS(get_rs(cp)) = STACK;
	       markuse(b, get_rs(cp));
	       markdef(b, get_rd(cp));
	       break;
	  case I_RET:	   case I_RETF:
	       if (op != i_op_retv)
		    markuse(b, get_rd(cp));
	  case I_RETI:
	       b = bb_finalize(b, cp, lp, i_isize, false);
	       break;
	  case I_BR:	  case I_BRF:
	       markuse(b, get_rs2(cp));
	  case I_BRI:
	       markuse(b, get_rs(cp));
	       bb_linklbl(b, get_rd(cp));
	       b = bb_finalize(b, cp, lp, i_isize, true);
	       break;
	  case I_CALL:	  case I_CALLF:
	       markuse(b, get_rs(cp));
	  case I_CALLI:	  case I_CALLIF:
	       if (op != i_op_callv && op != i_op_callvi)
		    markdef(b, get_rd(cp));
	       markcall(cp);
	       b = bb_finalize(b, cp, lp, 2*i_isize, true);
	       cp += i_isize;	/* Calls are 2x as long as other insns */
	       break;
	  case I_ARG:	  case I_ARGF:
	       markuse(b, get_rd(cp));
	       break;
	  case I_JMP:
	       assert(get_rd(cp) < num_i);
	       markuse(b, get_rd(cp));
	       b = bb_finalize(b, cp, lp, i_isize, false);
	       break;
	  case I_JMPI:
	       bb_linklbl(b, get_imm(cp));
	       b = bb_finalize(b, cp, lp, i_isize, false);
	       break;
	  case I_MISC:
	       switch (op) {
	       case i_op_lbl:
		    if (cp > b->h) /* If not at head of current block ... */
				/* ... make this the head of a new block */
			 b = bb_finalize(b, cp-i_isize, lp, i_isize, true);
		    lbl2bb[get_rd(cp)] = b;
		    break;
	       default:		/* refmul, refdiv, self, nop */
		    break;
	       }
	       break;
	  default:
	       assert(0);
	  }
     } while ((cp += i_isize) < lp);
     i_fg_tail = b;
     for (i = 0; i < fwdref_cur; i++)
	  bb_linkbb(fwdrefs[i].src, lbl2bb[fwdrefs[i].dst]);
#ifndef NDEBUG
     for (i = 0, b = i_fg_root; b; b = b->lnext) i++;
     assert(i == num_bb);
#endif
}
Ejemplo n.º 9
0
/*
here we run 2 parsers:

the first one will split options

key expires flags\r\n

if key is right and the body is present (an empty body, means: destroy the item)
the second one will run a http parser, if it is valid the cache_item is added to the hashtable

*/
void bb_cache_store(struct bb_session *bbs, char *buf, size_t len, int frag) {
	if (bbs->vhost->cache_size == 0) return;

	// check for space
	if (bbs->vhost->allocated_cache + (sizeof(struct bb_cache_item) + len) > bbs->vhost->cache_size) {
		fprintf(stderr,"!!! cache for virtualhost \"%.*s\" is full !!!\n", (int) bbs->vhost->len, bbs->vhost->name);
		return;
	}

	// 0->key 1->expires 2->flags 3->uninteresting 4->end
	int status = 0;
	uint32_t cht_pos;

	char *key = buf;
	char *expires = NULL;
	char *flags = NULL;
	size_t keylen = 0;
	size_t expires_len = 0;
	size_t flags_len = 0;

	size_t i;
	for(i=0;i<len;i++) {
		if (buf[i] == ' ') {
			if (status == 0) { keylen = i; status = 1; }
			else if (status == 1) { expires_len = i; status = 2;}
			else if (status == 2) { flags_len = i; status = 3;}
		}
		else if (buf[i] == '\n') {
			if (status == 4) break;
			if (status == 0) { keylen = i; status = 1; }
			else if (status == 1) { expires_len = i; status = 2;}
			else if (status == 2) { flags_len = i; status = 3;}
			break;
		}
		else if (buf[i] == '\r') {
			if (status == 4) break;
			if (status == 0) { keylen = i; status = 1; }
			else if (status == 1) { expires_len = i; status = 2;}
			else if (status == 2) { flags_len = i; status = 3;}
			status = 4;
		}
		else {
			if (status == 1 && !expires) { expires = buf+i; }
			else if (status == 2 && !flags) { flags = buf+i;}
		}
	}

	if (keylen == 0) return;

	// fix size
	if (expires_len > 0) {
		expires_len -= expires-buf;
	}
	if (flags_len > 0) {
		flags_len -= flags-buf;
	}

	uint64_t expires_num = bb_str2num(expires, expires_len);
	uint32_t flags_num = bb_str2num(flags, flags_len);

	struct bb_cache_item *already = bb_cache_get(bbs->vhost, key, keylen, frag);
	if (already) {
		// empty body, destroy the item
		if (len-(i+1) <= 0) {
			bb_cache_destroy(already);
			return ;
		}
		// by default ignore updates
		if (flags_num == 0) return;

		bb_cache_destroy(already);
	}

	char *http_buf = buf+(i+1);
	size_t http_buf_len = len-(i+1);

	struct bb_cache_item *bbci = bb_alloc(sizeof(struct bb_cache_item));
	if (!bbci) {
		return;
	}
	memset(bbci, 0, sizeof(struct bb_cache_item));

	if (frag) {
		bbci->body = bb_alloc(http_buf_len);
		if (!bbci->body) {
			goto clear;
		}		
		memcpy(bbci->body, http_buf, http_buf_len);
		bbci->body_len = http_buf_len;
		goto store;
	}

	http_parser parser;
	http_parser_init(&parser, HTTP_RESPONSE);

	bbci->last_was_value = 1;
	parser.data = bbci;

	int res = http_parser_execute(&parser, &bb_http_cache_parser_settings, http_buf, http_buf_len);
	if (!bbci->valid && res != http_buf_len) goto clear;

	bbci->status[0] = (parser.status_code/100) + '0';
        bbci->status[1] = ((parser.status_code%100)/10) + '0';
        bbci->status[2] = ((parser.status_code%100)%10) + '0';

	memcpy(bbci->protocol, http_buf, 8);

	bbci->http_first_line_len = bbci->http_end_of_first_line-http_buf;
	bbci->http_first_line = bb_alloc(bbci->http_first_line_len);
	if (!bbci->http_first_line) {
		goto clear;
	}
	memcpy(bbci->http_first_line, http_buf, bbci->http_first_line_len);

store:
        // get the hash
        cht_pos = djb2_hash_cache(key, keylen, bbs->vhost->cht_size);
        // get the ht entry
        struct bb_cache_entry *bbce = &bbs->vhost->cache[cht_pos];

        bbci->key = bb_alloc(keylen);
	if (!bbci->key) {
		goto clear;
	}

	memcpy(bbci->key, key, keylen);
        bbci->keylen = keylen;
	bbci->frag = frag;
	bbci->entry = bbce;
        bbci->next = NULL;
	bbci->len = sizeof(struct bb_cache_item) + bbci->body_len + bbci->http_first_line_len + keylen + bbci->headers_len;
	bbci->expires_num = expires_num;
	bbci->vhost = bbs->vhost;

        // append cache item to entry
        if (!bbce->head) {
                bbci->prev = NULL;
                bbce->head = bbci;
        }
        else {
                bbci->prev = bbce->tail;
                bbce->tail->next = bbci;
        }
        bbce->tail = bbci;

	if (expires_num > 0) {
        	ev_timer_init(&bbci->expires, cache_expires_cb, expires_num, 0.0);
		ev_timer_start(blastbeat.loop, &bbci->expires);
	}

	bbs->vhost->allocated_cache += bbci->len;
	blastbeat.cache_memory += bbci->len;
	
	return;

clear:
	bb_cache_clear(bbci);
}