#include "sdp.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if defined(OS_WINDOWS)
#define strdup _strdup
#define strcasecmp _stricmp
#endif
enum { SDP_M_MEDIA_UNKOWN=0, SDP_M_MEDIA_AUDIO, SDP_M_MEDIA_VIDEO, SDP_M_MEDIA_TEXT, SDP_M_MEDIA_APPLICATION, SDP_M_MEDIA_MESSAGE };
enum { SDP_M_PROTO_UKNOWN=0, SDP_M_PROTO_UDP, SDP_M_PROTO_RTP_AVP, SDP_M_PROTO_RTP_SAVP };
#define N_EMAIL 1
#define N_PHONE 1
#define N_CONNECTION 1
#define N_BANDWIDTH 1
#define N_TIMING 1
#define N_REPEAT 1
#define N_TIMEZONE 1
#define N_REPEAT_OFFSET 1
#define N_ATTRIBUTE 5
#define N_MEDIA 3 // audio/video/whiteboard
#define N_MEDIA_FORMAT 5
struct sdp_connection
{
char* network;
char* addrtype;
char* address;
};
struct sdp_origin
{
char* username;
char* session;
char* session_version;
struct sdp_connection c;
};
struct sdp_email
{
char* email;
};
struct sdp_phone
{
char* phone;
};
struct sdp_bandwidth
{
char* bwtype;
char* bandwidth;
};
struct bandwidths
{
size_t count;
struct sdp_bandwidth bandwidths[N_BANDWIDTH];
struct sdp_bandwidth *ptr;
size_t capacity;
};
struct sdp_repeat
{
char* interval;
char* duration;
struct offset
{
size_t count;
char *offsets[N_REPEAT_OFFSET];
char **ptr;
size_t capacity;
} offsets;
};
struct sdp_timezone
{
char* time;
char* offset;
};
struct sdp_timing
{
char* start;
char* stop;
struct repeat
{
size_t count;
struct sdp_repeat repeats[N_REPEAT];
struct sdp_repeat *ptr;
size_t capacity;
} r;
struct timezone_t
{
size_t count;
struct sdp_timezone timezones[N_TIMEZONE];
struct sdp_timezone *ptr;
size_t capacity;
} z;
};
struct sdp_encryption
{
char* method;
char* key;
};
struct sdp_attribute
{
char* name;
char* value;
};
struct attributes
{
size_t count;
struct sdp_attribute attrs[N_ATTRIBUTE];
struct sdp_attribute *ptr;
size_t capacity;
};
struct sdp_media
{
char* media; //audio, video, text, application, message
char* port;
char* proto; // udp, RTP/AVP, RTP/SAVP
struct format
{
size_t count;
char *formats[N_MEDIA_FORMAT];
char **ptr;
size_t capacity;
} fmt;
char* i;
struct connection
{
size_t count;
struct sdp_connection connections[N_EMAIL];
struct sdp_connection *ptr;
size_t capacity;
} c;
struct attributes a;
struct bandwidths b;
struct sdp_encryption k;
};
struct sdp_t
{
char *raw; // raw source string
size_t offset; // parse offset
int v;
struct sdp_origin o;
char* s;
char* i;
char* u;
struct email
{
size_t count;
struct sdp_email emails[N_EMAIL];
struct sdp_email *ptr;
size_t capacity;
} e;
struct phone
{
size_t count;
struct sdp_phone phones[N_PHONE];
struct sdp_phone *ptr;
size_t capacity;
} p;
struct sdp_connection c;
struct bandwidths b;
struct timing
{
size_t count;
struct sdp_timing times[N_TIMING];
struct sdp_timing *ptr;
size_t capacity;
} t;
struct sdp_encryption k;
struct attributes a;
struct media
{
size_t count;
struct sdp_media medias[N_MEDIA];
struct sdp_media *ptr;
size_t capacity;
} m;
};
static inline void sdp_skip_space(struct sdp_t* sdp)
{
char c = sdp->raw[sdp->offset];
while(' ' == c || '\t' == c)
c = sdp->raw[++sdp->offset];
}
static inline size_t sdp_token_word(struct sdp_t* sdp, const char* escape)
{
size_t n = sdp->offset;
sdp->offset += strcspn(sdp->raw + sdp->offset, escape);
return sdp->offset - n;
}
static inline int sdp_token_crlf(struct sdp_t* sdp)
{
if('\r' == sdp->raw[sdp->offset])
++sdp->offset;
if('\n' == sdp->raw[sdp->offset])
{
++sdp->offset;
return 0;
}
// sdp end line
if('\0' == sdp->raw[sdp->offset])
return 0;
return -1;
}
static inline void trim_right(const char* s, size_t *len)
{
//// left trim
//while(*len > 0 && isspace(s[*pos]))
//{
// --*len;
// ++*pos;
//}
// right trim
while(*len > 0 && ' '==(s[*len - 1]))
{
--*len;
}
}
static inline struct sdp_timing* sdp_get_timing(struct sdp_t* sdp, size_t idx)
{
if(idx >= sdp->t.count)
return NULL;
return idx >= N_TIMING ? &sdp->t.ptr[idx - N_TIMING] : &sdp->t.times[idx];
}
static inline struct sdp_media* sdp_get_media(struct sdp_t* sdp, size_t idx)
{
if(idx >= sdp->m.count)
return NULL;
return idx >= N_MEDIA ? &sdp->m.ptr[idx - N_MEDIA] : &sdp->m.medias[idx];
}
// RFC4566 5.1
static int sdp_parse_version(struct sdp_t* sdp)
{
char c;
assert(sdp);
if(!sdp) return -1;
sdp->v = 0;
sdp_skip_space(sdp);
c = sdp->raw[sdp->offset];
while('0' <= c && c <= '9')
{
sdp->v = sdp->v * 10 + (c - '0');
c = sdp->raw[++sdp->offset];
}
return sdp_token_crlf(sdp);
}
// RFC4566 5.2
// o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
// <username> "-" if the originating host does not support the concept of user IDs.
// <sess-id> is a numeric string
// <sess-version> is a version number for this session description
// <nettype> IN
// <addrtype> IP4/IP6
static int sdp_parse_origin(struct sdp_t* sdp)
{
size_t n[6];
struct sdp_origin *o;
o = &sdp->o;
memset(o, 0, sizeof(struct sdp_origin));
memset(n, 0, sizeof(n));
sdp_skip_space(sdp);
o->username = sdp->raw + sdp->offset;
n[0] = sdp_token_word(sdp, " \t\r\n");
sdp_skip_space(sdp);
o->session = sdp->raw + sdp->offset;
n[1] = sdp_token_word(sdp, " \t\r\n");
sdp_skip_space(sdp);
o->session_version = sdp->raw + sdp->offset;
n[2] = sdp_token_word(sdp, " \t\r\n");
sdp_skip_space(sdp);
o->c.network = sdp->raw + sdp->offset;
n[3] = sdp_token_word(sdp, " \t\r\n");
sdp_skip_space(sdp);
o->c.addrtype = sdp->raw + sdp->offset;
n[4] = sdp_token_word(sdp, " \t\r\n");
sdp_skip_space(sdp);
o->c.address = sdp->raw + sdp->offset;
n[5] = sdp_token_word(sdp, " \t\r\n");
// check before assign '\0'
if(0==sdp_token_crlf(sdp) && n[0]>0 && n[1]>0 && n[2]>0 && n[3]>0 && n[4]>0 && n[5]>0)
{
o->username[n[0]] = '\0';
o->session[n[1]] = '\0';
o->session_version[n[2]] = '\0';
o->c.network[n[3]] = '\0';
o->c.addrtype[n[4]] = '\0';
o->c.address[n[5]] = '\0';
return 0;
}
return -1;
}
// RFC4566 5.3
// s=<session name>
// There MUST be one and only one "s=" field per session description. can be empty
static int sdp_parse_session(struct sdp_t* sdp)
{
size_t n = 0;
sdp->s = sdp->raw + sdp->offset;
n = sdp_token_word(sdp, "\r\n");
if(0 != sdp_token_crlf(sdp))
return -1;
sdp->s[n] = '\0';
return 0;
}
// RFC4566 5.4
// i=<session description>
// There MUST be at most one session-level "i=" field per session description,
// and at most one "i=" field per media.
// default UTF-8
static int sdp_parse_information(struct sdp_t* sdp)
{
size_t n = 0;
char **i;
if(sdp->m.count > 0)
{
i = &sdp_get_media(sdp, sdp->m.count-1)->i;
}
else
{
i = &sdp->i;
}
*i = sdp->raw + sdp->offset;
n = sdp_token_word(sdp, "\r\n");
if(0 != sdp_token_crlf(sdp))
return -1;
(*i)[n] = '\0';
return 0;
}
// RFC4566 5.5
// u=<uri>
// This field is OPTIONAL, but if it is present it MUST be
// specified before the first media field.
static int sdp_parse_uri(struct sdp_t* sdp)
{
size_t n = 0;
// No more than one URI field is allowed per session description.
assert(!sdp->u);
sdp->u = sdp->raw + sdp->offset;
n = sdp_token_word(sdp, "\r\n");
if(0 != sdp_token_crlf(sdp))
return -1;
sdp->u[n] = '\0';
return 0;
}
// RFC4566 5.6
// e=<email-address>
// p=<phone-number>
// OPTIONAL, If an email address or phone number is present, it MUST be specified
// before the first media field. More than one email or phone field can
// be given for a session description.
// p=+1 617 555-6011
// [email protected] (Jane Doe)
// e=Jane Doe <[email protected]>
static int sdp_parse_email(struct sdp_t* sdp)
{
size_t n = 0;
struct sdp_email *e;
if(sdp->e.count >= N_EMAIL)
{
if(sdp->e.count - N_EMAIL >= sdp->e.capacity)
{
void* ptr;
ptr = (struct sdp_email*)realloc(sdp->e.ptr, (sdp->e.capacity+8)*sizeof(struct sdp_email));
if(!ptr)
return ENOMEM;
sdp->e.ptr = ptr;
sdp->e.capacity += 8;
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论


















收起资源包目录





































































































共 415 条
- 1
- 2
- 3
- 4
- 5
资源评论

- zyl-20192022-06-07用户下载后在一定时间内未进行评价,系统默认好评。

missiletcy
- 粉丝: 40
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- geekai-Go资源
- Admin.NET-C#资源
- MDword-PHP资源
- mybatis-mate-examples-SQL资源
- 计算机二级习题-计算机二级资源
- 医院感染三级网络建设及应用.ppt
- 电子科技16春《网络互连与路由技术》在线作业2.doc
- Graduation Project Client-毕业设计资源
- 基于STC12C5A16S2单片机的PWM电机调速系统.doc
- 数据库原理课程设计-毕业设计-超市物流管理系统.doc
- matlab语音识别系统(源代码).doc
- 计算机多媒体技术在提高中职数学教学有效性中的作用分析.docx
- 计算机辅助工程分析.docx
- 操作系统硕士研究生入学考试模拟试题参考答案(电子).doc
- PLC四层电梯自动控制系统课程设计分析方案-欧姆龙-武汉工程大学版.doc
- (2025)土建质检员考试题库及答案.doc
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



安全验证
文档复制为VIP权益,开通VIP直接复制
