示例#1
0
NdbCCurve * nodedb_c_curve_create(NodeCurve *node, VLayerID curve_id, const char *name, uint8 dimensions)
{
	NdbCCurve	*curve;

	if(node == NULL || name == NULL || dimensions > 4)
		return NULL;
	if(node->curves == NULL)
	{
		node->curves = dynarr_new(sizeof (NdbCCurve), 4);
		dynarr_set_default_func(node->curves, cb_curve_default, NULL);
	}
	if(curve_id == (VLayerID) ~0)
		curve = dynarr_append(node->curves, NULL, NULL);
	else
		curve = dynarr_set(node->curves, curve_id, NULL);
	if(curve != NULL)
	{
		curve->id = curve_id;
		stu_strncpy(curve->name, sizeof curve->name, name);
		curve->dimensions = dimensions;
		curve->keys = NULL;
		printf("Curve curve %u.%u %s created, dim=%u\n", node->node.id, curve_id, name, curve->dimensions);
	}
	return curve;
}
示例#2
0
static int sync_text_buffer(const NodeText *n, const NdbTBuffer *buffer,
			    const NodeText *target, const NdbTBuffer *tbuffer)
{
	int		sync = 1, d;
	DynArr		*edit;
	DiffEdit	*ed;
	const char	*text, *ttext;
	size_t		len, tlen;

	text  = textbuf_text(buffer->text);
	len   = textbuf_length(buffer->text);
	ttext = textbuf_text(tbuffer->text);
	tlen  = textbuf_length(tbuffer->text);
	if(len == tlen && strcmp(text, ttext) == 0)	/* Avoid allocating memory and running diff if equal. */
		return sync;

	edit  = dynarr_new(sizeof (*ed), 8);

/*	printf("  text: '%s' (%u)\n", text, len);
	printf("target: '%s' (%u)\n", ttext, tlen);
*/	d = diff_compare_simple(ttext, tlen, text, len, edit);
/*	printf("Edit distance: %d\n", d);*/
	if(d > 0)
	{
		unsigned int	i, pos = 0;

		for(i = 0; (ed = dynarr_index(edit, i)) != NULL; i++)
		{
			if(ed->op == DIFF_MATCH)
			{
				pos = ed->off + ed->len;
			}
			else if(ed->op == DIFF_DELETE)
			{
				verse_send_t_text_set(target->node.id, tbuffer->id, ed->off, ed->len, NULL);
				pos = ed->off;
			}
			else if(ed->op == DIFF_INSERT)	/* Split inserts into something Verse can handle. */
			{
				char	temp[1024];
				size_t	off, chunk;

				for(off = ed->off, len = ed->len; len > 0; off += chunk, len -= chunk)
				{
					chunk = len > sizeof temp - 1 ? sizeof temp - 1 : len;
					stu_strncpy(temp, chunk + 1, text + off);
					temp[chunk] = '\0';
					verse_send_t_text_set(target->node.id, tbuffer->id, pos, 0, temp);
					pos += chunk - 1;
				}
			}
		}
		sync = 0;
	}
	dynarr_destroy(edit);
	return sync;
}
示例#3
0
Plugin * plugin_new(const char *name)
{
	Plugin	*p;

	if(name == NULL)
		return NULL;

	if((p = mem_alloc(sizeof *p)) != NULL)
	{
		p->id = 0;
		stu_strncpy(p->name, sizeof p->name, name);
		p->library = NULL;
		p->input = NULL;
		p->meta = NULL;
		p->compute = NULL;
		p->state = NULL;
	}
	return p;
}
示例#4
0
void plugin_set_input(Plugin *p, int index, PValueType type, const char *name, va_list taglist)
{
	if(p == NULL)
		return;
	if(index < 0)
	{
		LOG_ERR(("Plug-in \"%s\" attempted to set input with negative index--ignored", p->name));
		return;
	}
	if((p->input == NULL && index != 0) || (p->input != NULL && (size_t) index != dynarr_size(p->input)))
	{
		LOG_ERR(("Plug-in \"%s\" attempted to set input \"%s\" with bad index %d--ignored", p->name, name, index));
		return;
	}
	if(type < P_VALUE_BOOLEAN || type > P_VALUE_MODULE)
	{
		LOG_ERR(("Plug-in \"%s\" attempted to set input %d with bad type %d--ignored", p->name, index, type));
		return;
	}
	if(p->input == NULL)
		p->input = dynarr_new(sizeof (Input), 2);
	if(p->input != NULL)
	{
		Input	i;

		stu_strncpy(i.name, sizeof i.name, name);
		i.type = type;
		i.spec.req = i.spec.def = i.spec.min = i.spec.max = 0;
		i.spec.enums = NULL;
		i.desc = NULL;
		value_init(&i.spec.min_val);
		value_init(&i.spec.max_val);
		value_init(&i.spec.def_val);
		
		for(;;)
		{
			int	tag = va_arg(taglist, int);
	
			if(tag == P_INPUT_TAG_DONE)
				break;
			else if(tag < P_INPUT_TAG_DONE || tag > P_INPUT_TAG_DESC)	/* Generous. */
			{
				LOG_WARN(("Aborting on bad tag value for %s.%s: %d", p->name, i.name, tag));
				break;
			}
			else if(tag == P_INPUT_TAG_REQUIRED)
				i.spec.req = 1;
			else if(tag == P_INPUT_TAG_MIN)
				i.spec.min = value_set_defminmax_va(&i.spec.min_val, i.type, &taglist);
			else if(tag == P_INPUT_TAG_MAX)
				i.spec.max = value_set_defminmax_va(&i.spec.max_val, i.type, &taglist);
			else if(tag == P_INPUT_TAG_DEFAULT)
				i.spec.def = value_set_defminmax_va(&i.spec.def_val, i.type, &taglist);
			else if(tag == P_INPUT_TAG_ENUM)
			{
				const char	*st;

				if(i.spec.enums == NULL)
					i.spec.enums = dynstr_new_sized(64);
				st = dynstr_string(i.spec.enums);
				if(st != NULL && *st != '\0' && st[strlen(st) - 1] != '|')	/* Make sure there are separators. */
					dynstr_append_c(i.spec.enums, '|');
				dynstr_append(i.spec.enums, va_arg(taglist, char *));
			}
			else if(tag == P_INPUT_TAG_DESC)
				i.desc = va_arg(taglist, char *);
		}
static void
stu_http_request_handler(stu_event_t *wev) {
	stu_http_request_t *r;
	stu_connection_t   *c;
	stu_channel_t      *ch;
	stu_buf_t          *buf;
	stu_table_elt_t    *accept;
	stu_table_elt_t    *protocol;
	stu_int_t           n;

	c = (stu_connection_t *) wev->data;

	//stu_mutex_lock(&c->lock);
	if (c->fd == (stu_socket_t) -1) {
		return;
	}

	stu_event_del(&c->write, STU_WRITE_EVENT, 0);

	buf = &c->buffer;
	buf->last = buf->start;
	stu_memzero(buf->start, buf->end - buf->start);

	r = (stu_http_request_t *) c->data;
	accept = r->headers_out.sec_websocket_accept;
	protocol = r->headers_out.sec_websocket_protocol;

	if (r->headers_out.status == STU_HTTP_SWITCHING_PROTOCOLS) {
		buf->last = stu_sprintf(buf->last, "HTTP/1.1 101 Switching Protocols" CRLF);
		buf->last = stu_sprintf(buf->last, "Server: " __NAME "/" __VERSION CRLF);
		buf->last = stu_sprintf(buf->last, "Upgrade: websocket" CRLF);
		buf->last = stu_sprintf(buf->last, "Connection: upgrade" CRLF);
		buf->last = stu_strncpy(buf->last, accept->key.data, accept->key.len);
		buf->last = stu_sprintf(buf->last, ": ");
		buf->last = stu_strncpy(buf->last, accept->value.data, accept->value.len);
		buf->last = stu_sprintf(buf->last, CRLF);
		if (protocol) {
			buf->last = stu_strncpy(buf->last, protocol->key.data, protocol->key.len);
			buf->last = stu_sprintf(buf->last, ": ");
			buf->last = stu_strncpy(buf->last, protocol->value.data, protocol->value.len);
			buf->last = stu_sprintf(buf->last, CRLF);
		}
		buf->last = stu_sprintf(buf->last, CRLF);
	} else {
		buf->last = stu_sprintf(buf->last, "HTTP/1.1 400 Bad Request" CRLF);
		buf->last = stu_sprintf(buf->last, "Server: " __NAME "/" __VERSION CRLF);
		buf->last = stu_sprintf(buf->last, "Content-type: text/html" CRLF);
		buf->last = stu_sprintf(buf->last, "Content-length: %d" CRLF, stu_strlen(__NAME "/" __VERSION "\n"));
		buf->last = stu_sprintf(buf->last, "Connection: close" CRLF CRLF);
		buf->last = stu_sprintf(buf->last, __NAME "/" __VERSION "\n");
	}

	n = send(c->fd, buf->start, buf->last - buf->start, 0);
	if (n == -1) {
		stu_log_error(stu_errno, "Failed to send data: fd=%d.", c->fd);
		goto failed;
	}

	stu_log_debug(4, "sent: fd=%d, bytes=%d.", c->fd, n); // str=\n%s, buf->start

	if (r->headers_out.status == STU_HTTP_SWITCHING_PROTOCOLS) {
		if (stu_http_switch_protocol(r) == STU_ERROR) {
			stu_log_error(0, "Failed to switch protocol: fd=%d.", c->fd);
			goto failed;
		}
	}

	return;

failed:

	c->read.active = 0;
	stu_event_del(&c->read, STU_READ_EVENT, 0);

	ch = c->user.channel;
	if (ch) {
		stu_channel_remove(ch, c);
	}

	stu_http_close_connection(c);

//done:

	//stu_mutex_unlock(&c->lock);
}
void
stu_http_process_request(stu_http_request_t *r) {
	stu_int_t           rc;
	stu_connection_t   *c;
	stu_table_elt_t    *protocol;
	stu_int_t           m, n, size, extened;
	stu_str_t           cid, name, icon, role, state;
	u_char             *d, *s, *p, opcode, temp[STU_HTTP_REQUEST_DEFAULT_SIZE], buf[STU_USER_ID_MAX_LEN];
	stu_channel_t      *ch;

	c = r->connection;

	rc = stu_http_process_request_headers(r);
	if (rc == STU_AGAIN) {
		stu_log_debug(4, "Wait to receive.");
		return;
	}

	if (rc != STU_OK) {
		stu_log_error(0, "Failed to process request headers.");
		stu_http_finalize_request(r, STU_HTTP_BAD_REQUEST);
		goto failed;
	}

	if (r->headers_in.upgrade == NULL) {
		stu_log_error(0, "Not an upgrade request.");
		stu_http_finalize_request(r, STU_HTTP_NOT_IMPLEMENTED);
		goto failed;
	}

	if (stu_cycle->config.edition == PREVIEW) {
		goto preview;
	}

	// enterprise
	if (stu_upstream_create(c, STU_HTTP_UPSTREAM_IDENT.data, STU_HTTP_UPSTREAM_IDENT.len) == STU_ERROR) {
		stu_log_error(0, "Failed to create http upstream \"ident\".");
		stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
		goto failed;
	}

	c->upstream->read_event_handler = stu_http_upstream_read_handler;
	c->upstream->write_event_handler = stu_http_upstream_write_handler;

	c->upstream->create_request_pt = stu_http_upstream_create_request;
	c->upstream->reinit_request_pt = stu_http_upstream_reinit_request;
	c->upstream->generate_request_pt = stu_http_upstream_ident_generate_request;
	c->upstream->process_response_pt = stu_http_upstream_process_response;
	c->upstream->analyze_response_pt = stu_http_upstream_ident_analyze_response;
	c->upstream->finalize_handler_pt = stu_http_upstream_finalize_handler;
	c->upstream->cleanup_pt = stu_http_upstream_cleanup;

	if (stu_upstream_init(c) == STU_ERROR) {
		stu_log_error(0, "Failed to init upstream.");
		stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
		goto failed;
	}

	return;

preview:

	// get channel ID
	cid.data = stu_calloc(r->target.len + 1);
	if (cid.data == NULL) {
		stu_log_error(0, "Failed to pcalloc memory for channel id, fd=%d.", c->fd);
		stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
		goto failed;
	}
	stu_strncpy(cid.data, r->target.data, r->target.len);
	cid.len = r->target.len;

	// reset user ID
	s = stu_sprintf(buf, "%ld", stu_preview_auto_id++);
	*s = '\0';

	c->user.id.len = s - buf;
	c->user.id.data = stu_calloc(c->user.id.len + 1);
	if (c->user.id.data == NULL) {
		stu_log_error(0, "Failed to pcalloc memory for user id, fd=%d.", c->fd);
		stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
		goto failed;
	}
	stu_strncpy(c->user.id.data, buf, c->user.id.len);

	// reset user name
	if (stu_http_arg(r, STU_PROTOCOL_NAME.data, STU_PROTOCOL_NAME.len, &name) != STU_OK) {
		stu_log_error(0, "User name not specified, fd=%d.", c->fd);
		stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
		goto failed;
	}

	d = s = name.data;
	stu_unescape_uri(&d, &s, name.len, 0);
	name.len = d - name.data;

	c->user.name.data = stu_calloc(name.len + 1);
	if (c->user.name.data == NULL) {
		stu_log_error(0, "Failed to pcalloc memory for user name, fd=%d.", c->fd);
		stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
		goto failed;
	}
	stu_strncpy(c->user.name.data, name.data, name.len);
	c->user.name.len = name.len;

	// reset user icon
	if (stu_http_arg(r, STU_PROTOCOL_ICON.data, STU_PROTOCOL_ICON.len, &icon) == STU_OK) {
		c->user.icon.data = stu_calloc(icon.len + 1);
		if (c->user.icon.data == NULL) {
			stu_log_error(0, "Failed to pcalloc memory for user icon, fd=%d.", c->fd);
			stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
			goto failed;
		}
		stu_strncpy(c->user.icon.data, icon.data, icon.len);
		c->user.icon.len = icon.len;
	}

	// reset user role
	c->user.role = STU_USER_ROLE_NORMAL;
	if (stu_http_arg(r, STU_PROTOCOL_ROLE.data, STU_PROTOCOL_ROLE.len, &role) == STU_OK) {
		m = atoi((const char *) role.data);
		stu_user_set_role(&c->user, m & 0xFF);
	}

	// insert user into channel
	if (stu_channel_insert(&cid, c) == STU_ERROR) {
		stu_log_error(0, "Failed to insert connection: fd=%d.", c->fd);
		stu_http_finalize_request(r, STU_HTTP_INTERNAL_SERVER_ERROR);
		goto failed;
	}

	ch = c->user.channel;

	if (stu_http_arg(r, STU_PROTOCOL_STATE.data, STU_PROTOCOL_STATE.len, &state) == STU_OK) {
		if (c->user.role & 0xF0) {
			m = atoi((const char *) state.data);
			ch->state = m & 0xFF;
		}
	}

	// finalize request
	protocol = r->headers_out.sec_websocket_protocol;
	if (protocol && stu_strncmp("binary", protocol->value.data, protocol->value.len) == 0) {
		opcode = STU_WEBSOCKET_OPCODE_BINARY;
	} else {
		opcode = STU_WEBSOCKET_OPCODE_TEXT;
	}

	stu_http_finalize_request(r, STU_HTTP_SWITCHING_PROTOCOLS);

	p = stu_sprintf(
			(u_char *) temp + 10, (const char *) STU_HTTP_UPSTREAM_IDENT_RESPONSE.data,
			c->user.id.data, c->user.name.data, c->user.icon.data, c->user.role,
			ch->id.data, ch->state, ch->userlist.length
		);
	*p = '\0';

	size = p - temp - 10;
	p = stu_websocket_encode_frame(opcode, temp, size, &extened);

	n = send(c->fd, p, size + 2 + extened, 0);
	if (n == -1) {
		stu_log_debug(4, "Failed to send \"ident\" frame: fd=%d.", c->fd);
		goto failed;
	}

	stu_log_debug(4, "sent: fd=%d, bytes=%d.", c->fd, n);

	return;

failed:

	c->read.active = 0;
	stu_event_del(&c->read, STU_READ_EVENT, 0);

	stu_http_close_connection(c);
}