static int parse_packet()

in ncrx/libncrx.c [195:278]


static int parse_packet(const char *payload, struct ncrx_msg *msg)
{
	char buf[1024];
	char *p, *tok;
	int idx;

	memset(msg, 0, sizeof(*msg));

	p = strchr(payload, ';');
	if (!p || p - payload >= (signed)sizeof(buf))
		goto einval;
	memcpy(buf, payload, p - payload);
	buf[p - payload] = '\0';

	msg->text = p + 1;
	msg->text_len = strlen(msg->text);
	if (msg->text_len > NCRX_LINE_MAX)
		msg->text_len = NCRX_LINE_MAX;

	/* <level>,<sequnum>,<timestamp>,<contflag>[,KEY=VAL]* */
	idx = 0;
	p = buf;
	while ((tok = strsep(&p, ","))) {
		char *endp, *key, *val;
		unsigned long long v;

		switch (idx++) {
		case 0:
			v = strtoul(tok, &endp, 0);
			if (*endp != '\0' || v > UINT8_MAX)
				goto einval;
			msg->facility = v >> 3;
			msg->level = v & ((1 << 3) - 1);
			continue;
		case 1:
			v = strtoull(tok, &endp, 0);
			if (*endp != '\0')
				goto einval;
			msg->seq = v;
			continue;
		case 2:
			v = strtoull(tok, &endp, 0);
			if (*endp != '\0')
				goto einval;
			msg->ts_usec = v;
			continue;
		case 3:
			if (tok[0] == 'c')
				msg->cont_start = 1;
			else if (tok[0] == '+')
				msg->cont = 1;
			continue;
		}

		val = tok;
		key = strsep(&val, "=");
		if (!val)
			continue;
		if (!strcmp(key, "ncfrag")) {
			unsigned nf_off, nf_len;

			if (sscanf(val, "%u/%u", &nf_off, &nf_len) != 2)
				goto einval;
			if (!msg->text_len ||
			    nf_len >= NCRX_LINE_MAX ||
			    nf_off + msg->text_len > nf_len)
				goto einval;

			msg->ncfrag_off = nf_off;
			msg->ncfrag_len = msg->text_len;
			msg->ncfrag_left = nf_len - msg->ncfrag_len;
			msg->text_len = nf_len;
		} else if (!strcmp(key, "ncemg")) {
			v = strtoul(val, &endp, 0);
			if (*endp != '\0')
				goto einval;
			msg->emg = v;
		}
	}
	return 0;
einval:
	errno = EINVAL;
	return -1;
}