--- /dev/null
+/****************************************************************************
+ Copyright (c) 2012, AudioScience, Inc
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "parse.h"
+
+int parse(const char *s, struct parse_param *specs, int *err_index)
+{
+ int err = 0;
+ char *param;
+ char *data;
+ char *delimiter;
+ char *guard;
+ int v_int;
+ unsigned int v_uint;
+ uint64_t v_uint64;
+ int result;
+ int count = 0;
+
+ guard = s + strlen(s);
+
+ while (specs->name && !err) {
+ param = strstr(s, specs->name);
+ data = param + strlen(specs->name);
+
+ /* temporarily terminate string at next delimiter */
+ delimiter = data;
+ while ((*delimiter != PARSE_DELIMITER) && (delimiter < guard))
+ *delimiter++;
+ if (delimiter < guard)
+ *delimiter = 0;
+
+ switch (specs->type) {
+ case parse_null:
+ break;
+ case parse_u8:
+ result = sscanf(data, "%d", &v_uint);
+ if (result == 1)
+ *(uint8_t *) specs->v = (uint8_t) v_uint;
+ break;
+ case parse_u16:
+ result = sscanf(data, "%d", &v_uint);
+ if (result == 1)
+ *(uint16_t *) specs->v = (uint16_t) v_uint;
+ break;
+ case parse_u32:
+ result = sscanf(data, "%d", &v_uint);
+ if (result == 1)
+ *(uint32_t *) specs->v = v_uint;
+ break;
+ case parse_u64:
+ result = sscanf(data, "%" SCNu64, &v_uint64);
+ if (result == 1)
+ *(uint64_t *) specs->v = v_uint64;
+ break;
+ case parse_h64:
+ result = sscanf(data, "%" SCNx64, &v_uint64);
+ if (result == 1)
+ *(uint64_t *) specs->v = v_uint64;
+ break;
+ case parse_c64:
+ /* read as uint64_t, then unpack to array */
+ result = sscanf(data, "%" SCNx64, &v_uint64);
+ if (result == 1) {
+ int i;
+ uint8_t *p = (uint8_t *) specs->v;
+ for (i = 0; i < 8; i++) {
+ int shift = (7 - i) * 8;
+ p[i] = (uint8_t) (v_uint64 >> shift);
+ }
+ }
+ break;
+ case parse_mac:
+ /* read as uint64_t, then unpack to array */
+ result = sscanf(data, "%" SCNx64, &v_uint64);
+ if (result == 1) {
+ int i;
+ uint8_t *p = (uint8_t *) specs->v;
+ for (i = 0; i < 6; i++) {
+ int shift = (5 - i) * 8;
+ p[i] = (uint8_t) (v_uint64 >> shift);
+ }
+ }
+ break;
+ }
+ if (result != 1) {
+ *err_index = count + 1;
+ return -1;
+ }
+
+ if (delimiter < guard)
+ s = delimiter + 1;
+ specs++;
+ count++;
+ }
+ *err_index = 0;
+ return 0;
+}
--- /dev/null
+/****************************************************************************
+ Copyright (c) 2012, AudioScience, Inc
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#ifndef PARSE_H_
+#define PARSE_H_
+
+enum parse_types {
+ parse_null,
+ parse_u8, /* uint8_t v */
+ parse_u16, /* uint16_t v */
+ parse_u32, /* uint32_t v */
+ parse_u64, /* uint64_t v */
+ parse_h64, /* uint64_t v */
+ parse_c64, /* uint8_t a[8] */
+ parse_mac /* uint8_t m[6] */
+};
+
+#define PARSE_DELIMITER ':'
+#define PARSE_ASSIGN ":"
+
+struct parse_param {
+ char *name;
+ enum parse_types type;
+ void *v;
+};
+
+int parse(const char *s, struct parse_param *specs, int *err_index);
+
+#endif /* PARSE_H_ */
#include <stddef.h>
#include <string.h>
+#include "parse.h"
#include "mrpd.h"
#include "mrp.h"
#include "msrp.h"
}
+
+int msrp_test_cmd_parse_join_or_new_stream(
+ char *buf, int buflen,
+ struct msrpdu_talker_fail *talker_ad
+)
+{
+ int err, err_index;
+
+ struct parse_param specs[] = {
+ {"S" PARSE_ASSIGN, parse_c64, talker_ad->StreamID},
+ {"A" PARSE_ASSIGN, parse_mac, talker_ad->DataFrameParameters.Dest_Addr},
+ {"V" PARSE_ASSIGN, parse_u16, &talker_ad->DataFrameParameters.Vlan_ID},
+ {"Z" PARSE_ASSIGN, parse_u16, &talker_ad->TSpec.MaxFrameSize},
+ {"I" PARSE_ASSIGN, parse_u16, &talker_ad->TSpec.MaxIntervalFrames},
+ {"P" PARSE_ASSIGN, parse_u8, &talker_ad->PriorityAndRank},
+ {"L" PARSE_ASSIGN, parse_u32, &talker_ad->AccumulatedLatency},
+ {0, parse_null, 0}
+ };
+ memset(talker_ad, 0, sizeof(*talker_ad));
+ return parse(buf, specs, &err_index);
+}
+
+/* S+? - (re)JOIN a stream */
+/* S++ - NEW a stream */
+
+int msrp_cmd_parse_join_or_new_stream(
+ char *buf, int buflen,
+ struct msrpdu_talker_fail *talker_ad
+)
+{
+ char *stream_str = NULL;
+ char *daddr_str = NULL;
+ char *vlan_str = NULL;
+ char *size_str = NULL;
+ char *interval_str = NULL;
+ char *prio_str = NULL;
+ char *latency_str = NULL;
+ uint8_t streamid_firstval[8];
+ uint8_t macvec_firstval[6];
+ uint8_t macvec_parsestr[64];
+ unsigned vlan, size, interval, prio, latency;
+ int i, rc;
+
+ memset(talker_ad, 0, sizeof(*talker_ad));
+ /*
+ * create or join a stream
+ * interesting to note the spec doesn't talk about
+ * what happens if two talkers attempt to define the identical
+ * stream twice - does the bridge report STREAM_CHANGE error?
+ */
+
+ if (buflen < 22) {
+ return -1;
+ }
+ /*
+ buf[] should look similar to "S:%02x%02x%02x%02x%02x%02x%02x%02x"
+ ":A:%02x%02x%02x%02x%02x%02x"
+ ":V:%04x" \
+ ":Z:%d" \
+ ":I:%d" \
+ ":P:%d" \
+ ":L:%d" \
+ */
+
+ i = 0;
+
+ while (i < buflen) {
+ if (buf[i] == ':') {
+ stream_str = &(buf[i + 1]);
+ i++;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= buflen) {
+ return -1;
+ }
+
+ while (i < (buflen - 3)) {
+ if ((buf[i] == ':') && (buf[i + 1] == 'A')
+ && (buf[i + 2] == ':')) {
+ buf[i] = '\0';
+ daddr_str = &(buf[i + 3]);
+ i += 4;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= (buflen - 3)) {
+ return -1;
+ }
+
+ while (i < (buflen - 3)) {
+ if ((buf[i] == ':') && (buf[i + 1] == 'V')
+ && (buf[i + 2] == ':')) {
+ buf[i] = '\0';
+ vlan_str = &(buf[i + 3]);
+ i += 4;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= (buflen - 3)) {
+ return -1;
+ }
+
+ while (i < (buflen - 3)) {
+ if ((buf[i] == ':') && (buf[i + 1] == 'Z')
+ && (buf[i + 2] == ':')) {
+ buf[i] = '\0';
+ size_str = &(buf[i + 3]);
+ i += 4;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= (buflen - 3)) {
+ return -1;
+ }
+
+ while (i < (buflen - 3)) {
+ if ((buf[i] == ':') && (buf[i + 1] == 'I')
+ && (buf[i + 2] == ':')) {
+ buf[i] = '\0';
+ interval_str = &(buf[i + 3]);
+ i += 4;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= (buflen - 3)) {
+ return -1;
+ }
+
+ while (i < (buflen - 3)) {
+ if ((buf[i] == ':') && (buf[i + 1] == 'P')
+ && (buf[i + 2] == ':')) {
+ buf[i] = '\0';
+ prio_str = &(buf[i + 3]);
+ i += 4;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= (buflen - 3)) {
+ return -1;
+ }
+
+ while (i < (buflen - 3)) {
+ if ((buf[i] == ':') && (buf[i + 1] == 'L')
+ && (buf[i + 2] == ':')) {
+ buf[i] = '\0';
+ latency_str = &(buf[i + 3]);
+ i += 4;
+ break;
+ }
+ i++;
+ }
+
+ if (i >= (buflen - 3)) {
+ return -1;
+ }
+
+ memset(macvec_parsestr, 0, sizeof(macvec_parsestr));
+
+ for (i = 0; i < 8; i++) {
+ macvec_parsestr[0] = stream_str[i * 2];
+ macvec_parsestr[1] = stream_str[i * 2 + 1];
+
+ rc = sscanf((char *)macvec_parsestr, "%hhx",
+ &streamid_firstval[i]);
+ if (0 == rc) {
+ return -1;
+ }
+ }
+
+ memset(macvec_parsestr, 0, sizeof(macvec_parsestr));
+ for (i = 0; i < 6; i++) {
+ macvec_parsestr[0] = daddr_str[i * 2];
+ macvec_parsestr[1] = daddr_str[i * 2 + 1];
+
+ rc = sscanf((char *)macvec_parsestr, "%hhx",
+ &macvec_firstval[i]);
+ if (0 == rc) {
+ return -1;
+ }
+ }
+
+ rc = sscanf((char *)vlan_str, "%x", &vlan);
+ if (0 == rc) {
+ return -1;
+ }
+
+ rc = sscanf((char *)size_str, "%d", &size);
+ if (0 == rc) {
+ return -1;
+ }
+
+ rc = sscanf((char *)interval_str, "%d", &interval);
+ if (0 == rc) {
+ return -1;
+ }
+
+ rc = sscanf((char *)prio_str, "%d", &prio);
+ if (0 == rc) {
+ return -1;
+ }
+
+ rc = sscanf((char *)latency_str, "%d", &latency);
+ if (0 == rc) {
+ return -1;
+ }
+
+ memcpy(talker_ad->StreamID,
+ streamid_firstval, 8);
+ memcpy(talker_ad->DataFrameParameters.Dest_Addr, macvec_firstval,
+ 6);
+ talker_ad->DataFrameParameters.Vlan_ID = vlan;
+ talker_ad->TSpec.MaxFrameSize = size;
+ talker_ad->TSpec.MaxIntervalFrames = interval;
+ talker_ad->PriorityAndRank = prio;
+ talker_ad->AccumulatedLatency = latency;
+
+
+ return 0;
+}
+
+/*
+ * Required fields are:
+ * talker_ad->StreamID
+ * talker_ad->DataFrameParameters.Dest_Addr
+ * talker_ad->DataFrameParameters.Vlan_ID
+ * talker_ad->TSpec.MaxFrameSize
+ * talker_ad->TSpec.MaxIntervalFrames
+ * talker_ad->PriorityAndRank
+ * talker_ad->AccumulatedLatency
+ *
+ */
+
+int msrp_cmd_join_or_new_stream(
+ int join,
+ struct msrpdu_talker_fail *talker_ad
+)
+{
+ struct msrp_attribute *attrib;
+
+ attrib = msrp_alloc();
+ if (NULL == attrib) {
+ return -1;
+ }
+ attrib->type = MSRP_TALKER_ADV_TYPE;
+ attrib->attribute.talk_listen = *talker_ad;
+ memset(attrib->registrar.macaddr, 0, 6);
+
+ if (join)
+ msrp_event(MRP_EVENT_JOIN, attrib);
+ else
+ msrp_event(MRP_EVENT_NEW, attrib);
+
+ return 0;
+}
+
/*
Future
-int msrp_cmd_parse_join_stream();
-int msrp_cmd_parse_new_stream();
+
int msrp_cmd_parse_leave_stream();
int msrp_cmd_parse_report_listener_status();
int msrp_cmd_parse_withdraw_listener_status();
int msrp_cmd_parse_report_domain_status();
int msrp_cmd_parse_withdraw_domain_status();
-int msrp_cmd_join_stream();
-int msrp_cmd_new_stream();
int msrp_cmd_leave_stream();
int msrp_cmd_report_listener_status();
int msrp_cmd_withdraw_listener_status();
uint8_t macvec_parsestr[64];
unsigned vlan, size, interval, prio, latency;
int i;
+ //struct msrpdu_talker_fail t0,t1;
if (NULL == MSRP_db) {
snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
if (buflen < 18) {
snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s",
buf);
- mrpd_send_ctl_msg(client, respbuf,
- sizeof(respbuf));
+ mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
goto out;
}
/* buf[] should look similar to 'S-D:C:%d:P:%d:V:%04x" */
attrib->attribute.talk_listen.AccumulatedLatency =
latency;
+ /*
+ msrp_cmd_parse_join_or_new_stream(buf, buflen, &t0);
+ msrp_test_cmd_parse_join_or_new_stream(buf+3, buflen, &t1);
+
+ if(memcmp(&t0, &t1, sizeof(t0))==0)
+ printf("parse match\n");
+ if(memcmp(&t0,&attrib->attribute.talk_listen,sizeof(t0)))
+ printf("old and new parse match\n");
+ */
+
if (join)
msrp_event(MRP_EVENT_JOIN, attrib);
else