/* 解析SIP消息 */
int sip_message_parse(struct sip_message *msg, const char *data, U32 length)
{
char *line, *saveptr;
char *data_copy;
if (!msg || !data || length == 0)
return -EINVAL;
sip_message_init(msg);
/* 复制消息数据 */
data_copy = malloc(length + 1);
if (!data_copy)
return -ENOMEM;
memcpy(data_copy, data, length);
data_copy[length] = '\0';
/* 解析起始行 */
line = strtok_r(data_copy, "\r\n", &saveptr);
if (!line)
{
free(data_copy);
return -EINVAL;
}
/* 判断消息类型 */
if (strncmp(line, "SIP/2.0", 7) == 0)
{
/* 响应消息 */
msg->type = 1;
if (sscanf(line, "SIP/2.0 %hu", &msg->status_code) == 1)
{
/* 提取原因短语 */
char *reason_start = strchr(line, ' ');
if (reason_start)
{
reason_start = strchr(reason_start + 1, ' ');
if (reason_start)
{
strlcpy(msg->reason_phrase, reason_start + 1,
sizeof(msg->reason_phrase));
}
}
}
}
else
{
/* 请求消息 */
msg->type = 0;
/* 提取方法 */
char method_str[16];
if (sscanf(line, "%15s", method_str) == 1)
{
msg->method = sip_string_to_method(method_str);
}
/* 提取Request-URI */
char *uri_start = strchr(line, ' ');
if (uri_start)
{
char *uri_end = strchr(uri_start + 1, ' ');
if (uri_end)
{
char uri[256];
U32 uri_len = uri_end - uri_start - 1;
if (uri_len < sizeof(uri))
{
strncpy(uri, uri_start + 1, uri_len);
uri[uri_len] = '\0';
sip_uri_parse(&msg->request_uri, uri);
}
}
}
}
/* 解析头部字段 */
while ((line = strtok_r(NULL, "\r\n", &saveptr)) != NULL)
{
if (strlen(line) == 0)
{
break; /* 空行,头部结束 */
}
if (strncasecmp(line, "From:", 5) == 0)
{
char *uri_start = strchr(line, '<');
if (uri_start)
{
char *uri_end = strchr(uri_start + 1, '>');
if (uri_end)
{
char uri[256];
U32 uri_len = uri_end - uri_start - 1;
if (uri_len < sizeof(uri))
{
strncpy(uri, uri_start + 1, uri_len);
uri[uri_len] = '\0';
sip_uri_parse(&msg->headers.from, uri);
}
}
char *tag_start = strstr(uri_end, ";tag=");
if (tag_start)
{
tag_start += 5; // 跳过";tag="
char *tag_end = tag_start;
while (*tag_end && *tag_end != ';' && *tag_end != ' ' && *tag_end != '\r' && *tag_end != '\n')
{
tag_end++;
}
size_t tag_len = tag_end - tag_start;
if (tag_len > 0 && tag_len < sizeof(msg->headers.from.parameters))
{
strncpy(msg->headers.from.parameters, tag_start, tag_len);
msg->headers.from.parameters[tag_len] = '\0';
}
}
}
}
else if (strncasecmp(line, "To:", 3) == 0)
{
char *uri_start = strchr(line, '<');
if (uri_start)
{
char *uri_end = strchr(uri_start + 1, '>');
if (uri_end)
{
char uri[256];
U32 uri_len = uri_end - uri_start - 1;
if (uri_len < sizeof(uri))
{
strncpy(uri, uri_start + 1, uri_len);
uri[uri_len] = '\0';
sip_uri_parse(&msg->headers.to, uri);
}
}
char *tag_start = strstr(uri_end, ";tag=");
if (tag_start)
{
tag_start += 5; // 跳过";tag="
char *tag_end = tag_start;
while (*tag_end && *tag_end != ';' && *tag_end != ' ' && *tag_end != '\r' && *tag_end != '\n')
{
tag_end++;
}
size_t tag_len = tag_end - tag_start;
if (tag_len > 0 && tag_len < sizeof(msg->headers.to.parameters))
{
strncpy(msg->headers.to.parameters, tag_start, tag_len);
msg->headers.to.parameters[tag_len] = '\0';
}
}
}
}
else if (strncasecmp(line, "Contact:", 8) == 0)
{
char *uri_start = strchr(line, '<');
if (uri_start)
{
char *uri_end = strchr(uri_start + 1, '>');
if (uri_end)
{
char uri[256];
U32 uri_len = uri_end - uri_start - 1;
if (uri_len < sizeof(uri))
{
sip_uri *contact = malloc(sizeof(sip_uri));
strncpy(uri, uri_start + 1, uri_len);
uri[uri_len] = '\0';
sip_uri_parse(contact, uri);
memset(contact,0,sizeof(sip_uri));
sip_uri_parse(contact, uri);
INIT_LIST_HEAD(&contact->list);
list_add_tail(&contact->list, &msg->headers.contact);
}
}
}
}
else if (strncasecmp(line, "Call-ID:", 8) == 0)
{
char *id_start = line + 8;
while (*id_start == ' ')
id_start++;
strlcpy(msg->headers.call_id, id_start, sizeof(msg->headers.call_id));
}
else if (strncasecmp(line, "Expires:", 8) == 0)
{
msg->headers.Expires = strtoul(line + 8, NULL, 10);
}
else if (strncasecmp(line, "CSeq:", 5) == 0)
{
char method_str[16];
if (sscanf(line + 5, "%u %15s", &msg->headers.cseq, method_str) == 2)
{
msg->headers.cseq_method = sip_string_to_method(method_str);
}
}
else if (strncasecmp(line, "Content-Type:", 13) == 0)
{
char *type_start = line + 13;
while (*type_start == ' ')
type_start++;
strlcpy(msg->headers.content_type, type_start,
sizeof(msg->headers.content_type));
}
else if (strncasecmp(line, "Content-Length:", 15) == 0)
{
msg->headers.content_length = strtoul(line + 15, NULL, 10);
}
else if (strncasecmp(line, "Via:", 4) == 0)
{
/* 创建临时存储结构 */
struct sip_via *via_temp = malloc(sizeof(sip_via));
memset(via_temp,0,sizeof(sip_via));
char *via_start = line + 4;
while (*via_start == ' ' || *via_start == '\t') via_start++; // 跳过空白
/* 提取协议和传输层 */
char *slash = strchr(via_start, '/');
if (slash) {
size_t proto_len = slash - via_start;
if (proto_len < sizeof(via_temp->protocol)) {
strncpy(via_temp->protocol, via_start, proto_len);
via_temp->protocol[proto_len] = '\0';
}
char *space = strchr(slash + 1, ' ');
if (space) {
size_t trans_len = space - (slash + 1);
if (trans_len < sizeof(via_temp->transport)) {
strncpy(via_temp->transport, slash + 1, trans_len);
via_temp->transport[trans_len] = '\0';
}
via_start = space + 1;
}
}
/* 提取主机地址 */
char *host_start = via_start;
char *host_end = strchr(host_start, ';');
if (!host_end) host_end = strchr(host_start, ':');
if (!host_end) host_end = strchr(host_start, ' ');
if (!host_end) host_end = host_start + strlen(host_start);
if (host_end > host_start) {
size_t host_len = host_end - host_start;
if (host_len < sizeof(via_temp->host)) {
strncpy(via_temp->host, host_start, host_len);
via_temp->host[host_len] = '\0';
}
via_start = host_end;
}
/* 提取端口号 (如果有) */
if (*via_start == ':') {
via_temp->port = (U16)atoi(via_start + 1);
} else {
via_temp->port = 5060; // 默认SIP端口
}
/* 提取参数 (branch, received, rport) */
char *params_start = strchr(via_start, ';');
while (params_start) {
params_start++; // 跳过';'
if (strncasecmp(params_start, "branch=", 7) == 0) {
char *value = params_start + 7;
char *end = strpbrk(value, ";\r\n ");
size_t len = end ? (end - value) : strlen(value);
if (len < sizeof(via_temp->branch)) {
strncpy(via_temp->branch, value, len);
via_temp->branch[len] = '\0';
}
}
else if (strncasecmp(params_start, "received=", 9) == 0) {
char *value = params_start + 9;
char *end = strpbrk(value, ";\r\n ");
size_t len = end ? (end - value) : strlen(value);
if (len < sizeof(via_temp->received)) {
strncpy(via_temp->received, value, len);
via_temp->received[len] = '\0';
}
}
else if (strncasecmp(params_start, "rport", 5) == 0) {
char *eq = strchr(params_start, '=');
if (eq) {
via_temp->rport = (U16)atoi(eq + 1);
} else {
via_temp->rport = 0; // 标记存在rport但无值
}
}
// 移动到下一个参数
params_start = strpbrk(params_start, ";");
}
INIT_LIST_HEAD(&via_temp->list);
list_add_tail(&via_temp->list, &msg->headers.vias);
}
/* 在解析头部字段的循环中添加 Record-Route 分支 */
else if (strncasecmp(line, "Record-Route:", 13) == 0)
{
char *uri_start = strchr(line, '<');
if (uri_start)
{
char *uri_end = strchr(uri_start + 1, '>');
if (uri_end)
{
char uri[256];
U32 uri_len = uri_end - uri_start - 1;
if (uri_len < sizeof(uri))
{
strncpy(uri, uri_start + 1, uri_len);
uri[uri_len] = '\0';
sip_uri *uri_tmp=malloc(sizeof(sip_uri));
sip_uri_parse(uri_tmp, uri);
INIT_LIST_HEAD(&uri_tmp->list);
list_add_tail(&uri_tmp->list, &msg->headers.record_route);
}
}
}
}
else if (strncasecmp(line, "WWW-Authenticate: Digest", 24) == 0)
{
char *ptr = line + 24, *key, *value;
while (*ptr != '\r')
{
// 跳过空格和逗号
while (*ptr == ' ' || *ptr == ',')
ptr++;
// 提取键
key = ptr;
while (*ptr && *ptr != '=')
ptr++;
if (*ptr != '=')
break;
*ptr++ = '\0';
// 提取值
if (*ptr == '"')
{
ptr++;
value = ptr;
while (*ptr && *ptr != '"')
ptr++;
if (*ptr == '"')
*ptr++ = '\0';
}
else
{
value = ptr;
while (*ptr && *ptr != ' ' && *ptr != ',')
ptr++;
if (*ptr)
*ptr++ = '\0';
}
// 保存参数
if (strcmp(key, "realm") == 0)
{
strncpy(msg->headers.auth.realm, value, sizeof(msg->headers.auth.realm) - 1);
}
else if (strcmp(key, "nonce") == 0)
{
strncpy(msg->headers.auth.nonce, value, sizeof(msg->headers.auth.nonce) - 1);
}
else if (strcmp(key, "algorithm") == 0)
{
strncpy(msg->headers.auth.algorithm, value, sizeof(msg->headers.auth.algorithm) - 1);
}
else if (strcmp(key, "qop") == 0)
{
strncpy(msg->headers.auth.qop, value, sizeof(msg->headers.auth.qop) - 1);
}
else if (strcmp(key, "opaque") == 0)
{
strncpy(msg->headers.auth.opaque, value, sizeof(msg->headers.auth.opaque) - 1);
}
else if (strcmp(key, "stale") == 0)
{
msg->headers.auth.stale = (strcmp(value, "true") == 0);
}
}
}
}
/* 解析消息体 */
if (msg->headers.content_length > 0)
{
char *body_start = strstr(data, "\r\n\r\n");
if (body_start)
{
body_start += 4; /* 跳过空行 */
msg->body.content = malloc(msg->headers.content_length);
#ifdef MALLOC_PRINT
SIP_ERROR("malloc trans: %d\n", msg->headers.content_length);
#endif
if (msg->body.content)
{
memcpy(msg->body.content, body_start, msg->headers.content_length);
msg->body.content[msg->headers.content_length] = '\0';
msg->body.length = msg->headers.content_length;
strlcpy(msg->body.type, msg->headers.content_type,
sizeof(msg->body.type));
}
}
}
free(data_copy);
return 0;
}
/* SIP方法定义 */
typedef enum sip_method
{
SIP_METHOD_INVITE = 0,
SIP_METHOD_ACK,
SIP_METHOD_BYE,
SIP_METHOD_CANCEL,
SIP_METHOD_REGISTER,
SIP_METHOD_MAX
} sip_method;
增加一段解析allow的程序
最新发布