Kaynağa Gözat

RFC3903 SIP-If-Match parsing from Gregory McGarry

Jamey Hicks 21 yıl önce
ebeveyn
işleme
3c736126b0

+ 31 - 0
parser/case_sip.h

@@ -0,0 +1,31 @@
+#ifndef CASE_SIP_H
+#define CASE_SIP_H
+
+#define atch_CASE                            \
+        switch(LOWER_DWORD(val)) {          \
+        case _atch_:                        \
+		DBG("end of SIP-If-Match\n"); \
+                hdr->type = HDR_SIPIFMATCH; \
+                p += 4;                     \
+                goto dc_end;                \
+        }
+
+
+#define ifm_CASE				\
+	switch(LOWER_DWORD(val)) {		\
+	case _ifm_:				\
+		DBG("middle of SIP-If-Match: yet=0x%04x\n",LOWER_DWORD(val)); \
+		p += 4;				\
+		val = READ(p);			\
+		atch_CASE;			\
+		goto other;			\
+	}
+		
+#define sip_CASE          \
+	DBG("beginning of SIP-If-Match: yet=0x%04x\n",LOWER_DWORD(val)); \
+        p += 4;           \
+        val = READ(p);    \
+        ifm_CASE;         \
+        goto other;
+
+#endif /* CASE_SIP_H */

+ 7 - 0
parser/hf.c

@@ -45,6 +45,8 @@
 #include "parse_rr.h"
 #include "contact/parse_contact.h"
 #include "parse_disposition.h"
+#include "parse_allow.h"
+#include "parse_sipifmatch.h"
 #include "../ut.h"
 
 
@@ -118,6 +120,7 @@ void clean_hdr_field(struct hdr_field* hf)
 			break;
 
 		case HDR_ALLOW:
+			free_allow((unsigned int **)(&(hf->parsed)));
 			break;
 
 		case HDR_EVENT:
@@ -158,6 +161,10 @@ void clean_hdr_field(struct hdr_field* hf)
 			free_to(hf->parsed);
 			break;
 
+		case HDR_SIPIFMATCH:
+			free_sipifmatch((str**)(&(hf->parsed)));
+			break;
+
 		default:
 			LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
 			    hf->type);

+ 2 - 1
parser/hf.h

@@ -73,7 +73,8 @@
 #define HDR_CONTENTDISPOSITION (1 << 27)  /* Content-Disposition hdr field */
 #define HDR_DIVERSION          (1 << 28)  /* Diversion header field */
 #define HDR_RPID               (1 << 29)  /* Remote-Party-ID header field */
-#define HDR_OTHER              (1 << 30)  /* Some other header field */
+#define HDR_SIPIFMATCH         (1 << 30)  /* SIP-If-Match header field */
+#define HDR_OTHER              (1 << 31)  /* Some other header field */
 
 
 /* returns true if the header links allocated memory on parse field */

+ 3 - 0
parser/keys.h

@@ -47,6 +47,9 @@
 #define _oriz_ 0x7a69726f   /* "oriz" */
 #define _atio_ 0x6f697461   /* "atio" */
 #define _call_ 0x6c6c6163   /* "call" */
+#define _sip_  0x2d706973   /* "sip-" */
+#define _ifm_  0x6d2d6669   /* "if-m" */
+#define _atch_ 0x68637461   /* "atch" */
 #define __id2_ 0x2064692d   /* "-id " */
 #define __id1_ 0x3a64692d   /* "-id:" */
 #define _cont_ 0x746e6f63   /* "cont" */

+ 8 - 1
parser/msg_parser.c

@@ -204,6 +204,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 	        case HDR_ACCEPTDISPOSITION:
 	        case HDR_DIVERSION:
 	        case HDR_RPID:
+	        case HDR_SIPIFMATCH:
 		case HDR_OTHER:
 			/* just skip over it */
 			hdr->body.s=tmp;
@@ -364,7 +365,7 @@ int parse_headers(struct sip_msg* msg, int flags, int next)
 				msg->parsed_flag|=HDR_ALLOW;
 				break;
 			case HDR_EVENT:
-				if (msg->allow==0) msg->event = hf;
+				if (msg->event==0) msg->event = hf;
 				msg->parsed_flag|=HDR_EVENT;
 				break;
 		        case HDR_ACCEPT:
@@ -425,6 +426,12 @@ int parse_headers(struct sip_msg* msg, int flags, int next)
 					DBG("parse_headers: this is the second via\n");
 				}
 				break;
+			case HDR_SIPIFMATCH:
+				if (msg->sipifmatch==0)
+					msg->sipifmatch=hf;
+
+				msg->parsed_flag|=HDR_SIPIFMATCH;
+				break;
 			default:
 				LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
 							hf->type);

+ 1 - 0
parser/msg_parser.h

@@ -193,6 +193,7 @@ struct sip_msg {
 	struct hdr_field* accept_disposition;
 	struct hdr_field* diversion;
 	struct hdr_field* rpid;
+	struct hdr_sipifmatch* sipifmatch;
 
 	char* eoh;        /* pointer to the end of header (if found) or null */
 	char* unparsed;   /* here we stopped parsing*/

+ 2 - 1
parser/parse_hname2.c

@@ -84,7 +84,7 @@ static inline char* skip_ws(char* p, unsigned int size)
 #include "case_supp.h"     /* Supported */
 #include "case_dive.h"     /* Diversion */
 #include "case_remo.h"     /* Remote-Party-ID */
-
+#include "case_sip.h"      /* SIP-If-Match */
 
 #define READ(val) \
 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
@@ -111,6 +111,7 @@ static inline char* skip_ws(char* p, unsigned int size)
         case _acce_: acce_CASE; \
         case _orga_: orga_CASE; \
         case _prio_: prio_CASE; \
+        case _sip_:  sip_CASE; \
         case _subj_: subj_CASE; \
         case _user_: user_CASE; \
         case _dive_: dive_CASE; \

+ 85 - 0
parser/parse_sipifmatch.c

@@ -0,0 +1,85 @@
+#include <string.h>
+
+#include "parse_sipifmatch.h"
+#include "../dprint.h"
+#include "parse_def.h"
+#include "../mem/mem.h"
+#include "../trim.h"
+
+static inline char* skip_token(char* _b, int _l)
+{
+        int i = 0;
+
+        for(i = 0; i < _l; i++) {
+                switch(_b[i]) {
+                case ' ':
+                case '\r':
+                case '\n':
+                case '\t':
+                case ';':
+                        return _b + i;
+                }
+        }
+
+        return _b + _l;
+}
+
+
+int
+etag_parser(char *_s, int _l, str *_e)
+{
+        char* end;
+
+        _e->s = _s;
+        _e->len = _l;
+
+        trim_leading(_e);
+
+        if (_e->len == 0) {
+                LOG(L_ERR, "etag_parser(): Empty body\n");
+                return -1;
+        }
+
+        end = skip_token(_e->s, _e->len);
+        _e->len = end - _e->s;
+
+	return 0;
+}
+
+
+int
+parse_sipifmatch(struct hdr_field* _h)
+{
+	str *e;
+
+	DBG("parse_sipifmatch() called\n");
+
+        if (_h->parsed != 0) {
+                return 0;
+        }
+
+        e = (str*)pkg_malloc(sizeof(str));
+        if (e == 0) {
+                LOG(L_ERR, "parse_ifsipmatch(): No memory left\n");
+                return -1;
+        }
+
+        memset(e, 0, sizeof(str));
+
+        if (etag_parser(_h->body.s, _h->body.len, e) < 0) {
+                LOG(L_ERR, "parse_sipifmatch(): Error in tag_parser\n");
+                pkg_free(e);
+                return -2;
+        }
+
+        _h->parsed = (void*)e;
+        return 0;
+}
+
+
+void free_sipifmatch(str** _e)
+{
+	if (*_e)
+		pkg_free(*_e);
+	*_e = 0;
+}

+ 24 - 0
parser/parse_sipifmatch.h

@@ -0,0 +1,24 @@
+#ifndef PARSE_SIPIFMATCH_H
+#define PARSE_SIPIFMATCH_H
+
+#include "../str.h"
+#include "hf.h"
+
+typedef struct etag {
+	str text;       /* Original string representation */
+} etag_t;
+
+
+/*
+ * Parse Sipifmatch HF body
+ */
+int parse_sipifmatch(struct hdr_field* _h);
+
+
+/*
+ * Release memory
+ */
+void free_sipifmatch(str** _e);
+
+
+#endif /* PARSE_SIPIFMATCH_H */