瀏覽代碼

Content-Type header's body is no longer parse in get_hdr_field(). For this
there is a new function available - parse_content_type_hdr(struct sip_msg*).
Content-Length's body parser is still in parse in get_hdr_field(). This
parser is very fast and it does not affect the overall perfs.i

Bogdan-Andrei Iancu 22 年之前
父節點
當前提交
695ff13f83
共有 4 個文件被更改,包括 84 次插入40 次删除
  1. 0 10
      parser/msg_parser.c
  2. 1 1
      parser/msg_parser.h
  3. 48 27
      parser/parse_content.c
  4. 35 2
      parser/parse_content.h

+ 0 - 10
parser/msg_parser.c

@@ -153,16 +153,6 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 			DBG("DEBUG: get_hdr_body : content_length=%d\n",(int)hdr->parsed);
 			break;
 		case HDR_CONTENTTYPE:
-			hdr->body.s=tmp;
-			tmp=parse_content_type(tmp,end, &integer);
-			if (tmp==0){
-				LOG(L_ERR, "ERROR:get_hdr_field: bad content_type header\n");
-				goto error;
-			}
-			hdr->parsed=(void*)integer;
-			hdr->body.len=tmp-hdr->body.s;
-			DBG("DEBUG: get_hdr_body : content_type=%d\n",(int)hdr->parsed);
-			break;
 		case HDR_FROM:
 		case HDR_CALLID:
 		case HDR_CONTACT:

+ 1 - 1
parser/msg_parser.h

@@ -129,7 +129,7 @@ struct sip_msg {
 	
 	str new_uri; /* changed first line uri*/
 
-        str dst_uri; /* Destination URI, must be forwarded to this URI if len != 0 */
+	str dst_uri; /* Destination URI, must be forwarded to this URI if len != 0 */
 
 	int parsed_uri_ok; /* 1 if parsed_uri is valid, 0 if not */
 	struct sip_uri parsed_uri; /* speed-up > keep here the parsed uri*/

+ 48 - 27
parser/parse_content.c

@@ -36,15 +36,23 @@
 #include "../ut.h"
 #include "parse_content.h"
 
-
+/*
+ * Node of the type's tree; this tree contains all the known types;
+ */
 typedef struct type_node_s {
-	char c;
-	unsigned char final;
-	unsigned char nr_sons;
-	int next;
+	char c;                      /* char contained by this node */
+	unsigned char final;         /* says what to be done if the mached string
+	                              * ends at this node: -1-> dead end (unknown
+	                              * type) or the index of the sub-type that
+	                              * follows (for types) or the  final type (for
+	                              * sub-types)*/
+	unsigned char nr_sons;       /* the number of sub-nodes */
+	int next;                    /* the next sibling node */
 }type_node_t;
 
 
+
+
 char* parse_content_length( char* buffer, char* end, int* length)
 {
 	int number;
@@ -89,7 +97,8 @@ error:
 
 
 
-char* parse_content_type( char* buffer, char* end, int* type)
+
+int parse_content_type_hdr( struct sip_msg *msg )
 {
 	static type_node_t type_tree[] = {
 		{'t',-1,1,4}, {'e',-1,1,-1}, {'x',-1,1,-1}, {'t',0,0,-1},
@@ -109,9 +118,28 @@ char* parse_content_type( char* buffer, char* end, int* type)
 	};
 	int node;
 	int mime;
-	char *p;
+	char *mark;
+	char *p, *end;
+
+	/* is the header already found? */
+	if ( msg->content_type==0 ) {
+		/* if not, found it */
+		if ( parse_headers(msg,HDR_CONTENTTYPE,0)==-1)
+			return -1;
+		if ( msg->content_type==0 ) {
+			LOG(L_ERR,"ERROR:parse_content_type_header: missing Content-Type"
+					"header\n");
+			return -1;
+		}
+	}
 
-	p = buffer;
+	/* maybe the header is already parsed! */
+	if ( get_content_type(msg)!=CONTENT_TYPE_UNPARSED)
+		return get_content_type(msg);
+
+	/* it seams we have to parse it! :-( */
+	p = msg->content_type->body.s;
+	end = p + msg->content_type->body.len;
 	mime = CONTENT_TYPE_UNKNOWN;
 
 	/* search the begining of the type */
@@ -123,6 +151,7 @@ char* parse_content_type( char* buffer, char* end, int* type)
 
 	/* parse the type */
 	node = 0;
+	mark = p;
 	while (p<end && ((*p>='a' && *p<='z') || (*p>='A' && *p<='Z')) ) {
 		while ( node!=-1 && type_tree[node].c!=*p && type_tree[node].c+32!=*p){
 			node = type_tree[node].next;
@@ -131,7 +160,7 @@ char* parse_content_type( char* buffer, char* end, int* type)
 			node++;
 		p++;
 	}
-	if (p==end || node==0)
+	if (p==end || mark==p)
 		goto error;
 	if (node!=-1)
 		node = type_tree[node].final;
@@ -151,6 +180,7 @@ char* parse_content_type( char* buffer, char* end, int* type)
 		goto error;
 
 	/* parse the sub-type */
+	mark = p;
 	while (p<end && ((*p>='a' && *p<='z') || (*p>='A' && *p<='Z')) ) {
 		while(node!=-1&&subtype_tree[node].c!=*p&&subtype_tree[node].c+32!=*p)
 			node = subtype_tree[node].next;
@@ -158,7 +188,7 @@ char* parse_content_type( char* buffer, char* end, int* type)
 			node++;
 		p++;
 	}
-	if (p==end || node==0)
+	if (p==mark)
 		goto error;
 	if (node!=-1)
 		mime = subtype_tree[node].final;
@@ -167,27 +197,18 @@ char* parse_content_type( char* buffer, char* end, int* type)
 	while ( p<end && (*p==' ' || *p=='\t' ||
 	(*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) ))
 		p++;
-	if (p==end)
-		goto error;
-
-	/* if there are params, eat everything to the end */
-	if (*p==';') {
-		while ( p<end && (*p!='\n' || (*(p+1)==' '||*(p+1)=='\t')) )
-			p++;
-		if (p==end)
-			goto error;
-	}
 
-	/* the header ends proper? */
-	if ( (*(p++)!='\n') && (*(p-1)!='\r' || *(p++)!='\n' ) )
+	/* is this the end? if there are params, ignore them!! */
+	if ( *p!=';' && p!=end )
 		goto error;
 
-	*type = mime;
-	return p;
+	mime = ((mime==-1)?CONTENT_TYPE_UNKNOWN:mime);
+	(int)(msg->content_type->parsed) = mime;
+	return mime;
 error:
-	LOG(L_ERR,"ERROR:parse_content_type: parse error near char [%d][%c]\n",
-		*p,*p);
-	return 0;
+	LOG(L_ERR,"ERROR:parse_content_type: parse error near char [%d][%c] "
+		"offset=%d\n",*p,*p,p-msg->content_type->body.s);
+	return -1;
 }
 
 

+ 35 - 2
parser/parse_content.h

@@ -29,13 +29,46 @@
 #ifndef _PARSE_CONTENT_H
 #define _PARSE_CONTENT_H
 
-#define CONTENT_TYPE_UNKNOWN         0
+#include "msg_parser.h"
+
+/*
+ * Types for Content-Type header that are recognize
+ */
+#define CONTENT_TYPE_UNPARSED        0
 #define CONTENT_TYPE_TEXT_PLAIN      1
 #define CONTENT_TYPE_MESSAGE_CPIM    2
 #define CONTENT_TYPE_APPLICATION_SDP 3
+#define CONTENT_TYPE_UNKNOWN         0x7fff
+
+
+
+/*
+ * returns the content-length value of a sip_msg as an integer
+ */
+#define get_content_length(_msg_)   ((int)((_msg_)->content_length->parsed))
 
 
-char* parse_content_type( char* buffer, char* end, int* type);
+/*
+ * returns the content-type value of a sip_msg as an integer
+ */
+#define get_content_type(_msg_)   ((int)((_msg_)->content_type->parsed))
+
+
+
+/*
+ * parse the the body of the Content-Type header. It's value is also converted
+ * as int.
+ * Returns:   n (n>0)  : the found type
+ *           -1        : error (parse error or hdr not found)
+ */
+int parse_content_type_hdr( struct sip_msg *msg);
+
+
+/*
+ *  parse the body of a Content_-Length header. Also tryes to recognize the
+ *  type specified by this header (see th above defines).
+ *  Returns the first chr after the end of the header.
+ */
 char* parse_content_length( char* buffer, char* end, int* len);
 
 #endif