#include "./include/public.h" #include "./include/pub_sdp.h" /*@ignore@*/ void pub_replace_all_lws(char *msg) { char *tmp; if (msg == NULL) return; tmp = msg; for (; tmp[0] != '\0'; tmp++) { if (('\0' == tmp[0]) || ('\0' == tmp[1]) || ('\0' == tmp[2]) || ('\0' == tmp[3])) return; if ((('\r' == tmp[0]) && ('\n' == tmp[1]) && ('\r' == tmp[2]) && ('\n' == tmp[3])) || (('\r' == tmp[0]) && ('\r' == tmp[1])) || (('\n' == tmp[0]) && ('\n' == tmp[1]))) return; if ((('\r' == tmp[0]) && ('\n' == tmp[1]) && ((' ' == tmp[2]) || ('\t' == tmp[2]))) || (('\r' == tmp[0]) && ((' ' == tmp[1]) || ('\t' == tmp[1]))) || (('\n' == tmp[0]) && ((' ' == tmp[1]) || ('\t' == tmp[1])))) { // Replace line end and TAB symbols by SP tmp[0] = ' '; tmp[1] = ' '; tmp = tmp + 2; // Replace all following TAB symbols for (; ('\t' == tmp[0] || ' ' == tmp[0]); ) { tmp[0] = ' '; tmp++; } } } } char *pub_strncpy(char *dest, const char *src, WORD length) { strncpy(dest, src, length); dest[length] = '\0'; return dest; } int pub_set_next_token(char *dest, char *buf, int endSeparator, char **next) { char *sep; // separator *next = NULL; sep = buf; while ((*sep != endSeparator) && (*sep != '\0') && (*sep != '\r') && (*sep != '\n')) sep++; if ((*sep == '\r') || (*sep == '\n')) { // we should continue normally only if this is the separator asked! if (*sep != endSeparator) return -1; } if (*sep == '\0') return -1; // value must not end with this separator! if (sep == buf) return -1; // empty value (or several space!) pub_strncpy(dest, buf, sep - buf); *next = sep + 1; // return the position right after the separator return 0; } int pub_sdp_msg_init(PUB_SDP_MSG *sdp) { if (sdp == NULL) return -1; memset((BYTE *)sdp, 0, sizeof(PUB_SDP_MSG)); return 0; } int pub_sdp_net_type_conv(char *str, BYTE *netType, BYTE flag) { if (flag == PUB_SDP_STR_TO_API) { if (strncmp(str, "IN", 2) == 0) *netType = PUB_SDP_NET_TYPE_IN; return 0; } else { switch (*netType) { case PUB_SDP_NET_TYPE_IN: strcpy(str, "IN"); break; default: return -1; } return 0; } return -1; } int pub_sdp_addr_type_conv(char *str, BYTE *addrType, BYTE flag) { if (flag == PUB_SDP_STR_TO_API) { if (strncmp(str, "IP4", 3) == 0) *addrType = PUB_SDP_ADDR_TYPE_IPV4; return 0; } else { switch (*addrType) { case PUB_SDP_ADDR_TYPE_IPV4: strcpy(str, "IP4"); break; default: return -1; } return 0; } return -1; } int pub_sdp_attr_type_conv(char *str, BYTE *attrType, BYTE flag) { int ret = 0; if (flag == PUB_SDP_STR_TO_API) { if (strncmp(str, "rtpmap", 6) == 0) *attrType = PUB_SDP_ATTR_TYPE_RTPMAP; else if (strncmp(str, "ptime", 5) == 0) *attrType = PUB_SDP_ATTR_TYPE_PTIME; else if (strncmp(str, "fmtp", 4) == 0) *attrType = PUB_SDP_ATTR_TYPE_FMTP; else { ret = -2; } return ret; } else { switch (*attrType) { case PUB_SDP_ATTR_TYPE_RTPMAP: strcpy(str, "rtpmap"); break; case PUB_SDP_ATTR_TYPE_PTIME: strcpy(str, "ptime"); break; case PUB_SDP_ATTR_TYPE_FMTP: strcpy(str, "fmtp"); break; default: return -2; } return 0; } return -1; } int pub_sdp_media_type_conv(char *str, BYTE *mediaType, BYTE flag) { if (flag == PUB_SDP_STR_TO_API) { if (strncmp(str, "audio", 6) == 0) { *mediaType = PUB_SDP_MEDIA_TYPE_AUDIO; return 0; } else return -2; } else { switch (*mediaType) { case PUB_SDP_MEDIA_TYPE_AUDIO: strcpy(str, "audio"); break; default: return -1; } return 0; } return -1; } int pub_sdp_proto_type_conv(char *str, BYTE *protoType, BYTE flag) { if (flag == PUB_SDP_STR_TO_API) { if (strncmp(str, "RTP/AVP", 7) == 0) *protoType = PUB_SDP_PROTO_TYPE_RTP_AVP; return 0; } else { switch (*protoType) { case PUB_SDP_PROTO_TYPE_RTP_AVP: strcpy(str, "RTP/AVP"); break; default: return -1; } return 0; } return -1; } int pub_sdp_parse_v(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; char value[8]; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; if (equal == buf) return -1; // check if header is "v" if (equal[-1] != 'v') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if ((flag & PUB_SDP_FLAG_V) == PUB_SDP_FLAG_V) { pub_strncpy(value, equal + 1, crlf - (equal + 1)); sdp->v.value = atoi(value); } if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("v: %d\n", sdp->v.value); sdp->flag |= PUB_SDP_FLAG_V; return 0; } int pub_sdp_parse_o(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; char *tmp; char *tmpNext; char value[16]; int i; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "o" if (equal[-1] != 'o') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; /* o=\r ?? bad header */ if ((flag & PUB_SDP_FLAG_V) == PUB_SDP_FLAG_V) { tmp = equal + 1; // o=username sess-id sess-version nettype addrtype addr // useranme can contain any char (ascii) except "space" and CRLF if (pub_set_next_token(sdp->o.userName, tmp, ' ', &tmpNext) < 0) return -1; tmp = tmpNext; // sess_id contains only numeric characters if (pub_set_next_token(sdp->o.sessId, tmp, ' ', &tmpNext) < 0) return -1; tmp = tmpNext; // sess_version contains only numeric characters if (pub_set_next_token (sdp->o.sessVer, tmp, ' ', &tmpNext) < 0) return -1; tmp = tmpNext; // nettype is "IN" but will surely be extented!!! assume it's some alpha-char if (pub_set_next_token (value, tmp, ' ', &tmpNext) < 0) return -1; if (pub_sdp_net_type_conv(value, &sdp->o.netType, PUB_SDP_STR_TO_API) < 0) return -1; tmp = tmpNext; // addrtype is "IP4" or "IP6" but will surely be extented!!! if (pub_set_next_token (value, tmp, ' ', &tmpNext) < 0) return -1; if (pub_sdp_addr_type_conv(value, &sdp->o.addrType, PUB_SDP_STR_TO_API) < 0) return -1; tmp = tmpNext; // addr is "IP4" or "IP6" but will surely be extented!!! i = pub_set_next_token(sdp->o.addr, tmp, '\r', &tmpNext); if (i != 0) { /* could it be "\n" only??? rfc says to accept CR or LF instead of CRLF */ if (pub_set_next_token(sdp->o.addr, tmp, '\n', &tmpNext) < 0) return -1; } } if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("o: %s, %s, %s, %d, %d, %s\n", sdp->o.userName, sdp->o.sessId, sdp->o.sessVer, sdp->o.netType, sdp->o.addrType, sdp->o.addr); sdp->flag |= PUB_SDP_FLAG_O; return 0; } int pub_sdp_parse_s(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "s" if (equal[-1] != 's') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // o=\r ?? bad header if ((flag & PUB_SDP_FLAG_S) == PUB_SDP_FLAG_S) pub_strncpy(sdp->s.sessName, equal + 1, crlf - (equal + 1)); if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("s: %s\n", sdp->s.sessName); sdp->flag |= PUB_SDP_FLAG_S; return 0; } int pub_sdp_parse_i(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "i" if (equal[-1] != 'i') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // o=\r ?? bad header if ((flag & PUB_SDP_FLAG_I) == PUB_SDP_FLAG_I) pub_strncpy(sdp->i.info, equal + 1, crlf - (equal + 1)); if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("i: %s\n", sdp->i.info); if (sdp->medias.num == 0) sdp->flag |= PUB_SDP_FLAG_I; else sdp->medias.medias[sdp->medias.num - 1].flag |= PUB_SDP_FLAG_I; return 0; } int pub_sdp_parse_u(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "u" if (equal[-1] != 'u') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } int pub_sdp_parse_e(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "e" if (equal[-1] != 'e') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } int pub_sdp_parse_p(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "p" if (equal[-1] != 'p') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } int pub_sdp_parse_c(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; char *tmp; char *tmpNext; char value[16]; char *slash; PUB_SDP_C *cHeader; int i; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "c" if (equal[-1] != 'c') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // c=\r ?? bad header if ((flag & PUB_SDP_FLAG_C) == PUB_SDP_FLAG_C) { tmp = equal + 1; // c=nettype addrtype (multicastaddr | addr) // nettype is "IN" and will be extended if (pub_set_next_token (value, tmp, ' ', &tmpNext) < 0) return -1; if (pub_sdp_net_type_conv(value, &sdp->c.netType, PUB_SDP_STR_TO_API) < 0) return -1; tmp = tmpNext; // nettype is "IP4" or "IP6" and will be extended if (pub_set_next_token(value, tmp, ' ', &tmpNext) < 0) return -1; if (pub_sdp_addr_type_conv(value, &sdp->c.addrType, PUB_SDP_STR_TO_API) < 0) return -1; tmp = tmpNext; /* there we have a multicast or unicast address */ /* multicast can be ip/ttl [/integer] */ /* unicast is FQDN or ip (no ttl, no integer) */ slash = strchr (tmp, '/'); cHeader = &sdp->c; if (slash != NULL && slash < crlf) // it's a multicast address! { // Not supported for the moment } else { // in this case, we have a unicast address i = pub_set_next_token(cHeader->addr, tmp, '\r', &tmpNext); if (i != 0) { if (pub_set_next_token(cHeader->addr, tmp, '\n', &tmpNext) < 0) return -1; } } } if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("c: %d, %d, %s\n", sdp->c.netType, sdp->c.addrType, sdp->c.addr); if (sdp->medias.num == 0) sdp->flag |= PUB_SDP_FLAG_C; else sdp->medias.medias[sdp->medias.num - 1].flag |= PUB_SDP_FLAG_C; return 0; } int pub_sdp_parse_b(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "b" if (equal[-1] != 'b') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } int pub_sdp_parse_t(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; char *tmp; char *tmpNext; char value[16]; int i; PUB_SDP_T *tHeader; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "t" if (equal[-1] != 't') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; /* t=\r ?? bad header */ if ((flag & PUB_SDP_FLAG_T) == PUB_SDP_FLAG_T) { tmp = equal + 1; // t = start_time stop_time tHeader = &sdp->t; if (pub_set_next_token(value, tmp, ' ', &tmpNext) < 0) return -1; tHeader->startTime = atoi(value); tmp = tmpNext; i = pub_set_next_token(value, tmp, '\r', &tmpNext); if (i != 0) { if (pub_set_next_token(value, tmp, '\n', &tmpNext) < 0) return -1; tHeader->stopTime = atoi(value); } } if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("t: %ld, %ld\n", sdp->t.startTime, sdp->t.stopTime); sdp->flag |= PUB_SDP_FLAG_T; return 0; } int pub_sdp_parse_r(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "r" if (equal[-1] != 'r') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } int pub_sdp_parse_z(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "z" if (equal[-1] != 'z') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } int pub_sdp_parse_k(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "k" if (equal[-1] != 'k') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; // v=\r ?? bad header if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } int pub_sdp_parse_a(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; char *tmp; char *tmpNext; char value[32]; int i, ret; BYTE num, mediaNum; PUB_SDP_A *a; char *colon; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "a" if (equal[-1] != 'a') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; /* a=\r ?? bad header */ if ((flag & PUB_SDP_FLAG_A) == PUB_SDP_FLAG_A) { tmp = equal + 1; mediaNum = sdp->medias.num; num = sdp->medias.medias[mediaNum - 1].attrs.num; a = &sdp->medias.medias[mediaNum - 1].attrs.attrs[num]; // a=att-field[:att-value] // is there any att-value? colon = strchr (equal + 1, ':'); if ((colon != NULL) && (colon < crlf)) { // att-field is alpha-numeric if (pub_set_next_token(value, tmp, ':', &tmpNext) < 0) return -1; if ((ret = pub_sdp_attr_type_conv(value, &a->aType, PUB_SDP_STR_TO_API)) == -1) return -1; else if (ret == -2) { if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } tmp = tmpNext; i = pub_set_next_token(a->aValue, tmp, '\r', &tmpNext); if (i != 0) { if (pub_set_next_token(a->aValue, tmp, '\n', &tmpNext) < 0) return -1; } } else { i = pub_set_next_token(a->aValue, tmp, '\r', &tmpNext); if (i != 0) { if (pub_set_next_token(a->aValue, tmp, '\n', &tmpNext) < 0) return -1; } } sdp->medias.medias[sdp->medias.num - 1].attrs.num++; } if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("a: %d, %s\n", a->aType, a->aValue); if (sdp->medias.num == 0) sdp->flag |= PUB_SDP_FLAG_A; else sdp->medias.medias[sdp->medias.num - 1].flag |= PUB_SDP_FLAG_A; return 0; } int pub_sdp_parse_m(PUB_SDP_MSG *sdp, char *buf, char **next, DWORD flag) { char *equal; char *crlf; char *tmp; char *tmpNext; char value[32]; int i; PUB_SDP_M *mHeader; BYTE num; char *slash; char *space; int moreSpace; int ret; *next = buf; equal = buf; while ((*equal != '=') && (*equal != '\0')) equal++; if (*equal == '\0') return -1; // check if header is "m" if (equal[-1] != 'm') return -2; crlf = equal + 1; while ((*crlf != '\r') && (*crlf != '\n') && (*crlf != '\0')) crlf++; if (*crlf == '\0') return -1; if (crlf == equal + 1) return -1; /* a=\r ?? bad header */ if ((flag & PUB_SDP_FLAG_M) == PUB_SDP_FLAG_M) { tmp = equal + 1; num = sdp->medias.num; mHeader = &sdp->medias.medias[num].m; // m=media port ["/"integer] proto *(payload_number) // media is "audio" "video" "application" "data" or other... if (pub_set_next_token(value, tmp, ' ', &tmpNext) < 0) return -1; if ((ret = pub_sdp_media_type_conv(value, &mHeader->media, PUB_SDP_STR_TO_API)) < 0) { if (-2 == ret) { if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; return 0; } return -1; } tmp = tmpNext; slash = strchr (tmp, '/'); space = strchr (tmp, ' '); if ((slash != NULL) && (slash < space)) { /* a number of port is specified! */ if (pub_set_next_token(value, tmp, '/', &tmpNext) < 0) return -1; mHeader->port = atoi(value); tmp = tmpNext; if (pub_set_next_token(value, tmp, ' ', &tmpNext) < 0) return -1; mHeader->portNum = atoi(value); tmp = tmpNext; } else { if (pub_set_next_token(value, tmp, ' ', &tmpNext) < 0) return -1; mHeader->port = atoi(value); tmp = tmpNext; } if (pub_set_next_token(value, tmp, ' ', &tmpNext) < 0) return -1; if (pub_sdp_proto_type_conv(value, &mHeader->proto, PUB_SDP_STR_TO_API) < 0) return -1; tmp = tmpNext; space = strchr(tmp + 1, ' '); if (space == NULL) moreSpace = 1; else if ((space != NULL) && (space > crlf)) moreSpace = 1; else moreSpace = 0; while(moreSpace == 0) { if (pub_set_next_token(value, tmp, ' ', &tmpNext) < 0) return -1; mHeader->payloads[mHeader->plNum++] = atoi(value); tmp = tmpNext; space = strchr(tmp + 1, ' '); if (space == NULL) moreSpace = 1; else if ((space != NULL) && (space > crlf)) moreSpace = 1; else moreSpace = 0; } if (tmpNext < crlf) { // tmpNext is still less than clrf: no space i = pub_set_next_token(value, tmp, '\r', &tmpNext); if (i != 0) { if (pub_set_next_token(value, tmp, '\n', &tmpNext) < 0) return -1; } mHeader->payloads[mHeader->plNum++] = atoi(value); } } if (crlf[1] == '\n') *next = crlf + 2; else *next = crlf + 1; // printf("m: %d, %d, %d, %d, %d, %d, %d\n", mHeader->media, mHeader->port, mHeader->portNum, mHeader->proto, mHeader->plNum, mHeader->payloads[0], mHeader->payloads[1]); sdp->medias.medias[sdp->medias.num].flag |= PUB_SDP_FLAG_M; sdp->flag |= PUB_SDP_FLAG_M; sdp->medias.num++; return 0; } int pub_sdp_check_ending(char *ptr, char **nextbuf) { *nextbuf = ptr; if ((*ptr == '\0') || (*ptr == '\r') || (*ptr == '\n')) { return 0; } else if (((ptr[0] == '.') && (ptr[1] == '\r') && (ptr[2] == '\n'))) { *nextbuf = ptr + 3; return 1; } else return -1; } int pub_sdp_parse(PUB_SDP_MSG *sdp, char *buf, char **nextMsg, DWORD flag) { // In SDP, headers must be in the right order /* This is a simple example v=0 o=user1 53655765 2353687637 IN IP4 128.3.4.5 s=Mbone Audio i=Discussion of Mbone Engineering Issues e=mbone@somewhere.com c=IN IP4 224.2.0.1/127 t=0 0 m=audio 3456 RTP/AVP 0 a=rtpmap:0 PCMU/8000 */ char *nextBuf; char *ptr; int i; int ret; int moreHeader = 1; pub_sdp_msg_init(sdp); ptr = (char *) buf; // mandatory if (pub_sdp_parse_v(sdp, ptr, &nextBuf, flag) == -1) return -1; ptr = nextBuf; // mandatory if (pub_sdp_parse_o(sdp, ptr, &nextBuf, flag) == -1) return -1; ptr = nextBuf; // mandatory if (pub_sdp_parse_s(sdp, ptr, &nextBuf, flag) == -1) return -1; ptr = nextBuf; // optional if (pub_sdp_parse_i(sdp, ptr, &nextBuf, flag) == -1) return -1; ptr = nextBuf; // optional if (pub_sdp_parse_u(sdp, ptr, &nextBuf, flag) == -1) return -1; ptr = nextBuf; // optional i = 0; while (i == 0) { if ((i = pub_sdp_parse_e(sdp, ptr, &nextBuf, flag)) == -1) return -1; ptr = nextBuf; } // optional i = 0; while (i == 0) { if ((i = pub_sdp_parse_p(sdp, ptr, &nextBuf, flag)) == -1) return -1; ptr = nextBuf; } // optional if (pub_sdp_parse_c(sdp, ptr, &nextBuf, flag) == -1) return -1; ptr = nextBuf; // optional i = 0; while (i == 0) { if ((i = pub_sdp_parse_b(sdp, ptr, &nextBuf, flag)) == -1) return -1; ptr = nextBuf; } // mandatory if (pub_sdp_parse_t(sdp, ptr, &nextBuf, flag) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; // optional i = 0; while (i == 0) { if ((i = pub_sdp_parse_r(sdp, ptr, &nextBuf, flag)) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; } // optional if (pub_sdp_parse_t(sdp, ptr, &nextBuf, flag) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; while (moreHeader == 1) { i = 0; while (i == 0) // is a "r" header { if ((i = pub_sdp_parse_r(sdp, ptr, &nextBuf, flag)) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; } if ((i = pub_sdp_parse_t(sdp, ptr, &nextBuf, flag)) == -1) return -1; else if (i == -2) moreHeader = 0; // no more "t" headers else moreHeader = 1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; } // optional if (pub_sdp_parse_z(sdp, ptr, &nextBuf, flag) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; // optional if (pub_sdp_parse_k(sdp, ptr, &nextBuf, flag) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; // optional // 0 or more "a" header i = 0; while (i == 0) // no more "a" header { if ((i = pub_sdp_parse_a(sdp, ptr, &nextBuf, flag)) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; } moreHeader = 0; while (moreHeader == 0) { // optional if ((moreHeader = pub_sdp_parse_m(sdp, ptr, &nextBuf, flag)) == -1) return -1; else if (moreHeader == -2) break; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; // optional if (pub_sdp_parse_i (sdp, ptr, &nextBuf, flag) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; // optional i = 0; while (i == 0) { if ((i = pub_sdp_parse_c(sdp, ptr, &nextBuf, flag)) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; } // optional i = 0; while (i == 0) { if ((i = pub_sdp_parse_b(sdp, ptr, &nextBuf, flag)) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; } // optional if (pub_sdp_parse_k(sdp, ptr, &nextBuf, flag) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; // optional i = 0; while (i == 0) { if ((i = pub_sdp_parse_a(sdp, ptr, &nextBuf, flag)) == -1) return -1; if ((ret = pub_sdp_check_ending(nextBuf, &nextBuf)) >= 0) { *nextMsg = nextBuf; return ret; } ptr = nextBuf; } } return 0; } // SDP Encode int pub_sdp_encode_v(PUB_SDP_V *v, char *dest) { sprintf(dest, "v=%d\r\n", v->value); return 0; } int pub_sdp_encode_o(PUB_SDP_O *o, char *dest) { char origin[128]; char netType[8]; char addrType[8]; if (pub_sdp_net_type_conv(netType, &o->netType, PUB_SDP_API_TO_STR) < 0) return -1; if (pub_sdp_addr_type_conv(addrType, &o->addrType, PUB_SDP_API_TO_STR) < 0) return -1; sprintf(origin, "o=%s %s %s %s %s %s\r\n", o->userName, o->sessId, o->sessVer, netType, addrType, o->addr); strcat(dest, origin); return 0; } int pub_sdp_encode_s(PUB_SDP_S *s, char *dest) { char sess[64]; sprintf(sess, "s=%s\r\n", s->sessName); strcat(dest, sess); return 0; } int pub_sdp_encode_i(PUB_SDP_I *i, char *dest) { char info[64]; sprintf(info, "i=%s\r\n", i->info); strcat(dest, info); return 0; } int pub_sdp_encode_c(PUB_SDP_C *c, char *dest) { char conn[128]; char netType[8]; char addrType[8]; if (pub_sdp_net_type_conv(netType, &c->netType, PUB_SDP_API_TO_STR) < 0) return -1; if (pub_sdp_addr_type_conv(addrType, &c->addrType, PUB_SDP_API_TO_STR) < 0) return -1; sprintf(conn, "c=%s %s %s\r\n", netType, addrType, c->addr); strcat(dest, conn); return 0; } int pub_sdp_encode_t(PUB_SDP_T *t, char *dest) { char time[64]; sprintf(time, "t=%ld %ld\r\n", t->startTime, t->stopTime); strcat(dest, time); return 0; } int pub_sdp_encode_m(PUB_SDP_M *m, char *dest, WORD flag) { char media[128]; char mediaType[8]; char proto[8]; char payload[64]; BYTE i; if (pub_sdp_media_type_conv(mediaType, &m->media, PUB_SDP_API_TO_STR) < 0) return -1; if (pub_sdp_proto_type_conv(proto, &m->proto, PUB_SDP_API_TO_STR) < 0) return -1; sprintf(media, "m=%s %d %s", mediaType, m->port, proto); if ((flag & PUB_MGCP_PARA_FLAG_TFO) == PUB_MGCP_PARA_FLAG_TFO) { sprintf(payload, " %d", 8); strcat(media, payload); } for (i = 0; i < m->plNum; i++) { if (i >= PUB_SDP_MAX_PAYLOAD_NUM) break; sprintf(payload, " %d", m->payloads[i]); strcat(media, payload); } strcat(media, "\r\n"); strcat(dest, media); return 0; } int pub_sdp_encode_a(PUB_SDP_A *a, char *dest) { char attr[128]; char attrType[8]; int ret; if ((ret = pub_sdp_attr_type_conv(attrType, &a->aType, PUB_SDP_API_TO_STR)) == -1) return -1; if (ret == -2) { sprintf(attr, "a=%s\r\n", a->aValue); } else { sprintf(attr, "a=%s:%s\r\n", attrType, a->aValue); } strcat(dest, attr); return 0; } int pub_sdp_encode(PUB_SDP_MSG *sdp, char *dest, WORD flag) { BYTE i, j; BYTE mediaNum, attrNum; PUB_SDP_MEDIA *media; PUB_SDP_A *a; if ((sdp->flag & PUB_SDP_FLAG_V) == PUB_SDP_FLAG_V) { if (pub_sdp_encode_v(&sdp->v, dest) < 0) return -1; } if ((sdp->flag & PUB_SDP_FLAG_O) == PUB_SDP_FLAG_O) { if (pub_sdp_encode_o(&sdp->o, dest) < 0) return -1; } if ((sdp->flag & PUB_SDP_FLAG_S) == PUB_SDP_FLAG_S) { if (pub_sdp_encode_s(&sdp->s, dest) < 0) return -1; } if ((sdp->flag & PUB_SDP_FLAG_I) == PUB_SDP_FLAG_I) { if (pub_sdp_encode_i(&sdp->i, dest) < 0) return -1; } if ((sdp->flag & PUB_SDP_FLAG_C) == PUB_SDP_FLAG_C) { if (pub_sdp_encode_c(&sdp->c, dest) < 0) return -1; } if ((sdp->flag & PUB_SDP_FLAG_T) == PUB_SDP_FLAG_T) { if (pub_sdp_encode_t(&sdp->t, dest) < 0) return -1; } if ((sdp->flag & PUB_SDP_FLAG_M) == PUB_SDP_FLAG_M) { mediaNum = sdp->medias.num; for (i = 0; i < mediaNum; i++) { media = &sdp->medias.medias[i]; if (pub_sdp_encode_m(&media->m, dest, flag) < 0) return -1; if ((media->flag & PUB_SDP_FLAG_A) == PUB_SDP_FLAG_A) { attrNum = media->attrs.num; for (j = 0; j < attrNum; j++) { a = &media->attrs.attrs[j]; if (pub_sdp_encode_a(a, dest) < 0) return -1; } } } } return 0; } /*@end@*/