Browse Source

- basic tel uri support (it's parsed, SIP_URI_T, SIPS_URI_T and TEL_URI_T
added)

Andrei Pelinescu-Onciul 20 years ago
parent
commit
2518c90022
6 changed files with 189 additions and 60 deletions
  1. 1 1
      Makefile.defs
  2. 3 2
      action.c
  3. 1 1
      modules/tm/ut.h
  4. 5 1
      parser/msg_parser.h
  5. 27 11
      parser/parse_uri.c
  6. 152 44
      test/p_uri.c

+ 1 - 1
Makefile.defs

@@ -53,7 +53,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 10
 SUBLEVEL =   99
-EXTRAVERSION = -dev1
+EXTRAVERSION = -dev2
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")

+ 3 - 2
action.c

@@ -174,10 +174,11 @@ int do_action(struct action* a, struct sip_msg* msg)
 							goto error_fwd_uri;
 					}
 #ifdef USE_TLS
-					if (u->secure){
+					if (u->type==SIPS_URI_T){
 						if (u->proto==PROTO_UDP){
 							LOG(L_ERR, "ERROR: do_action: forward: secure uri"
-									" incompatible with transport %d\n", u->proto);
+									" incompatible with transport %d\n",
+									u->proto);
 							ret=E_BAD_PROTO;
 							goto error_fwd_uri;
 						}

+ 1 - 1
modules/tm/ut.h

@@ -108,7 +108,7 @@ inline static struct proxy_l *uri2proxy( str *uri, int proto )
 		return 0;
 	}
 	
-	if (parsed_uri.secure){
+	if (parsed_uri.type==SIPS_URI_T){
 		if ((parsed_uri.proto!=PROTO_TCP) && (parsed_uri.proto!=PROTO_NONE)){
 			LOG(L_ERR, "ERROR: uri2proxy: bad transport  for sips uri: %d\n",
 					parsed_uri.proto);

+ 5 - 1
parser/msg_parser.h

@@ -37,6 +37,7 @@
  *  2003-04-12  added msg_flags to sip_msg (andrei)
  *  2003-11-02  added diversion header field to sip_msg (jh)
  *  2004-11-08  added force_send_socket (andrei)
+ *  2005-02-25  uri types added (sip, sips & tel)  (andrei)
  */
 
 
@@ -121,6 +122,9 @@ struct sip_uri {
 };
 #endif
 
+enum _uri_type{ERROR_URI_T=0, SIP_URI_T, SIPS_URI_T, TEL_URI_T};
+typedef enum _uri_type uri_type;
+
 struct sip_uri {
 	str user;     /* Username */
 	str passwd;   /* Password */
@@ -130,7 +134,7 @@ struct sip_uri {
 	str headers;  
 	unsigned short port_no;
 	unsigned short proto; /* from transport */
-	int secure; /* 1 if is a sips, 0 otherwise */
+	uri_type type; /* uri scheme */
 	/* parameters */
 	str transport;
 	str ttl;

+ 27 - 11
parser/parse_uri.c

@@ -33,6 +33,7 @@
  * 2003-04-11  ser_error is now set in parse_uri (andrei)
  * 2003-04-26  ZSW (jiri)
  * 2003-07-03  sips:, r2, lr=on support added (andrei)
+ * 2005-02-25  preliminary tel uri support (andrei)
  */
 
 
@@ -96,6 +97,11 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 	char* pass;
 	int found_user;
 	int error_headers;
+	unsigned int scheme;
+	
+#define SIP_SCH		0x3a706973
+#define SIPS_SCH	0x73706973
+#define TEL_SCH		0x3a6c6574
 	
 #define case_port( ch, var) \
 	case ch: \
@@ -315,15 +321,18 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 	port_no=0;
 	state=URI_INIT;
 	memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure*/
-	/*look for sip:*/
+	/*look for sip:, sips: or tel:*/
 	if (len<5) goto error_too_short;
-	if (! ( ((buf[0]|0x20)=='s')&&((buf[1]|0x20)=='i')&&((buf[2]|0x20)=='p')))
-		goto error_bad_uri;
-	if (buf[3]!=':'){
-		/* parse also sips: */
-		if  (((buf[3]|0x20)=='s')&&(buf[4]==':')) {p++; uri->secure=1;}
+	scheme=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24);
+	scheme|=0x20202020;
+	if (scheme==SIP_SCH){
+		uri->type=SIP_URI_T;
+	}else if(scheme==SIPS_SCH){
+		if(buf[4]==':'){ p++; uri->type=SIPS_URI_T;}
 		else goto error_bad_uri;
-	}
+	}else if (scheme==TEL_SCH){
+		uri->type=TEL_URI_T;
+	}else goto error_bad_uri;
 	
 	s=p;
 	for(;p<end; p++){
@@ -942,11 +951,18 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 		default:
 			goto error_bug;
 	}
-	
-#if EXTRA_DEBUG
+	if (uri->type==TEL_URI_T){
+		/* fix tel uris, move the number in uri and empty the host */
+		uri->user=uri->host;
+		uri->host.s="";
+		uri->host.len=0;
+	}
+#ifdef EXTRA_DEBUG
 	/* do stuff */
-	DBG("parsed uri:\n user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n host=<%.*s>(%d)\n"
-			" port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n headers=<%.*s>(%d)\n",
+	DBG("parsed uri:\n type=%d user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n"
+			" host=<%.*s>(%d)\n port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n"
+			" headers=<%.*s>(%d)\n",
+			uri->type,
 			uri->user.len, ZSW(uri->user.s), uri->user.len,
 			uri->passwd.len, ZSW(uri->passwd.s), uri->passwd.len,
 			uri->host.len, ZSW(uri->host.s), uri->host.len,

+ 152 - 44
test/p_uri.c

@@ -3,11 +3,23 @@
 #include <string.h>
 #include "../str.h"
 
+/* ser compat defs */
+
 #define DBG printf
 #define LOG(lev, fmt, args...) printf(fmt, ## args)
 
+#define EXTRA_DEBUG
+#define ZSW(s)	((s)?(s):"")
+#define E_BAD_URI -100
+
+int ser_error=0;
+
+
 enum {PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP };
 
+enum _uri_type{ERROR_URI_T=0, SIP_URI_T, SIPS_URI_T, TEL_URI_T};
+typedef enum _uri_type uri_type;
+
 struct sip_uri {
 	str user;     /* Username */
 	str passwd;   /* Password */
@@ -17,6 +29,7 @@ struct sip_uri {
 	str headers;  
 	unsigned short port_no;
 	unsigned short proto; /* from transport */
+	uri_type type; /* uri scheme */
 	/* parameters */
 	str transport;
 	str ttl;
@@ -24,16 +37,20 @@ struct sip_uri {
 	str maddr;
 	str method;
 	str lr;
+	str r2; /* ser specific rr parameter */
 	/* values */
 	str transport_val;
 	str ttl_val;
 	str user_param_val;
 	str maddr_val;
 	str method_val;
+	str lr_val; /* lr value placeholder for lr=on a.s.o*/
+	str r2_val;
 };
 
 
 
+
 int parse_uri(char* buf, int len, struct sip_uri* uri)
 {
 	enum states  {	URI_INIT, URI_USER, URI_PASSWORD, URI_PASSWORD_ALPHA,
@@ -53,7 +70,10 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 					/* maddr */
 					      PMA_A, PMA_D, PMA_D2, PMA_R, PMA_eq,
 					/* lr */
-					PLR_L, PLR_R_FIN,
+					PLR_L, PLR_R_FIN, PLR_eq,
+					/* r2 */
+					PR2_R, PR2_2_FIN, PR2_eq,
+					
 					/* transport values */
 					/* udp */
 					VU_U, VU_D, VU_P_FIN,
@@ -78,6 +98,11 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 	char* pass;
 	int found_user;
 	int error_headers;
+	unsigned int scheme;
+	
+#define SIP_SCH		0x3a706973
+#define SIPS_SCH	0x73706973
+#define TEL_SCH		0x3a6c6574
 	
 #define case_port( ch, var) \
 	case ch: \
@@ -297,14 +322,22 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 	port_no=0;
 	state=URI_INIT;
 	memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure*/
-	/*look for sip:*/
-	if (len<4) goto error_too_short;
-	if (! ( ((buf[0]|0x20)=='s')&&((buf[1]|0x20)=='i')&&((buf[2]|0x20)=='p')&&
-		     (buf[3]==':') ) ) goto error_bad_uri;
+	/*look for sip:, sips: or tel:*/
+	if (len<5) goto error_too_short;
+	scheme=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24);
+	scheme|=0x20202020;
+	if (scheme==SIP_SCH){
+		uri->type=SIP_URI_T;
+	}else if(scheme==SIPS_SCH){
+		if(buf[4]==':'){ p++; uri->type=SIPS_URI_T;}
+		else goto error_bad_uri;
+	}else if (scheme==TEL_SCH){
+		uri->type=TEL_URI_T;
+	}else goto error_bad_uri;
 	
 	s=p;
 	for(;p<end; p++){
-		switch(state){
+		switch((unsigned char)state){
 			case URI_INIT:
 				switch(*p){
 					case '[':
@@ -535,13 +568,17 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 						b=p;
 						state=PLR_L;
 						break;
+					case 'r':
+					case 'R':
+						b=p;
+						state=PR2_R;
 					default:
 						state=URI_PARAM_P;
 				}
 				break;
 			case URI_PARAM_P: /* ignore current param */
 				/* supported params:
-				 *  maddr, transport, ttl, lr, user, method  */
+				 *  maddr, transport, ttl, lr, user, method, r2  */
 				switch(*p){
 					param_common_cases;
 				};
@@ -677,6 +714,9 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 					case '@':
 						still_at_user; 
 						break;
+					case '=':
+						state=PLR_eq;
+						break;
 					semicolon_case; 
 						uri->lr.s=b;
 						uri->lr.len=(p-b);
@@ -691,7 +731,52 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 						state=URI_PARAM_P;
 				}
 				break;
-						
+				/* handle lr=something case */
+			case PLR_eq:
+				param=&uri->lr;
+				param_val=&uri->lr_val;
+				switch(*p){
+					param_common_cases;
+					default:
+						v=p;
+						state=URI_VAL_P;
+				}
+				break;
+			/* r2 */
+			param_switch1(PR2_R,  '2', PR2_2_FIN);
+			case PR2_2_FIN:
+				switch(*p){
+					case '@':
+						still_at_user; 
+						break;
+					case '=':
+						state=PR2_eq;
+						break;
+					semicolon_case; 
+						uri->r2.s=b;
+						uri->r2.len=(p-b);
+						break;
+					question_case; 
+						uri->r2.s=b;
+						uri->r2.len=(p-b);
+						break;
+					colon_case;
+						break;
+					default:
+						state=URI_PARAM_P;
+				}
+				break;
+				/* handle lr=something case */
+			case PR2_eq:
+				param=&uri->r2;
+				param_val=&uri->r2_val;
+				switch(*p){
+					param_common_cases;
+					default:
+						v=p;
+						state=URI_VAL_P;
+				}
+				break;
 				
 				
 			case URI_HEADERS:
@@ -800,16 +885,25 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 		case PM_D:
 		case PM_eq:
 		case PLR_L: /* lr */
+		case PR2_R:  /* r2 */
 			uri->params.s=s;
 			uri->params.len=p-s;
 			break;
 		/* fin param states */
 		case PLR_R_FIN:
+		case PLR_eq:
 			uri->params.s=s;
 			uri->params.len=p-s;
 			uri->lr.s=b;
 			uri->lr.len=p-b;
 			break;
+		case PR2_2_FIN:
+		case PR2_eq:
+			uri->params.s=s;
+			uri->params.len=p-s;
+			uri->r2.s=b;
+			uri->r2.len=p-b;
+			break;
 		case URI_VAL_P:
 		/* intermediate value states */
 		case VU_U:
@@ -858,74 +952,88 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 		default:
 			goto error_bug;
 	}
-	
+	if (uri->type==TEL_URI_T){
+		/* fix tel uris, move the number in uri and empty the host */
+		uri->user=uri->host;
+		uri->host.s="";
+		uri->host.len=0;
+	}
+#ifdef EXTRA_DEBUG
 	/* do stuff */
-	DBG("parsed uri:\n user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n host=<%.*s>(%d)\n"
-			" port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n headers=<%.*s>(%d)\n",
-			uri->user.len, uri->user.s, uri->user.len,
-			uri->passwd.len, uri->passwd.s, uri->passwd.len,
-			uri->host.len, uri->host.s, uri->host.len,
-			uri->port.len, uri->port.s, uri->port.len, uri->port_no,
-			uri->params.len, uri->params.s, uri->params.len,
-			uri->headers.len, uri->headers.s, uri->headers.len
+	DBG("parsed uri:\n type=%d user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n"
+			" host=<%.*s>(%d)\n port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n"
+			" headers=<%.*s>(%d)\n",
+			uri->type,
+			uri->user.len, ZSW(uri->user.s), uri->user.len,
+			uri->passwd.len, ZSW(uri->passwd.s), uri->passwd.len,
+			uri->host.len, ZSW(uri->host.s), uri->host.len,
+			uri->port.len, ZSW(uri->port.s), uri->port.len, uri->port_no,
+			uri->params.len, ZSW(uri->params.s), uri->params.len,
+			uri->headers.len, ZSW(uri->headers.s), uri->headers.len
 		);
 	DBG(" uri params:\n   transport=<%.*s>, val=<%.*s>, proto=%d\n",
-			uri->transport.len, uri->transport.s, uri->transport_val.len,
-			uri->transport_val.s, uri->proto);
+			uri->transport.len, ZSW(uri->transport.s), uri->transport_val.len,
+			ZSW(uri->transport_val.s), uri->proto);
 	DBG("   user-param=<%.*s>, val=<%.*s>\n",
-			uri->user_param.len, uri->user_param.s, uri->user_param_val.len,
-			uri->user_param_val.s);
+			uri->user_param.len, ZSW(uri->user_param.s), 
+			uri->user_param_val.len, ZSW(uri->user_param_val.s));
 	DBG("   method=<%.*s>, val=<%.*s>\n",
-			uri->method.len, uri->method.s, uri->method_val.len,
-			uri->method_val.s);
+			uri->method.len, ZSW(uri->method.s), 
+			uri->method_val.len, ZSW(uri->method_val.s));
 	DBG("   ttl=<%.*s>, val=<%.*s>\n",
-			uri->ttl.len, uri->ttl.s, uri->ttl_val.len,
-			uri->ttl_val.s);
+			uri->ttl.len, ZSW(uri->ttl.s), 
+			uri->ttl_val.len, ZSW(uri->ttl_val.s));
 	DBG("   maddr=<%.*s>, val=<%.*s>\n",
-			uri->maddr.len, uri->maddr.s, uri->maddr_val.len,
-			uri->maddr_val.s);
-	DBG("   lr=<%.*s>\n", uri->lr.len, uri->lr.s); 
+			uri->maddr.len, ZSW(uri->maddr.s), 
+			uri->maddr_val.len, ZSW(uri->maddr_val.s));
+	DBG("   lr=<%.*s>\n", uri->lr.len, ZSW(uri->lr.s)); 
+#endif
 	return 0;
 	
 error_too_short:
 	LOG(L_ERR, "ERROR: parse_uri: uri too short: <%.*s> (%d)\n",
-			len, buf, len);
-	return -1;
+			len, ZSW(buf), len);
+	ser_error=E_BAD_URI;
+	return E_BAD_URI;
 error_bad_char:
 	LOG(L_ERR, "ERROR: parse_uri: bad char '%c' in state %d"
 			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
-			*p, state, (p-buf), buf, (p-buf), len, buf, len);
-	return -1;
+			*p, state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
+	return E_BAD_URI;
 error_bad_host:
 	LOG(L_ERR, "ERROR: parse_uri: bad host in uri (error at char %c in"
 			" state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n",
-			*p, state, (p-buf), buf, (p-buf), len, buf, len);
-	return -1;
+			*p, state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
+	ser_error=E_BAD_URI;
+	return E_BAD_URI;
 error_bad_port:
 	LOG(L_ERR, "ERROR: parse_uri: bad port in uri (error at char %c in"
 			" state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n",
-			*p, state, (p-buf), buf, (p-buf), len, buf, len);
-	return -1;
+			*p, state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
+	ser_error=E_BAD_URI;
+	return E_BAD_URI;
 error_bad_uri:
 	LOG(L_ERR, "ERROR: parse_uri: bad uri,  state %d"
 			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
-			 state, (p-buf), buf, (p-buf), len, buf, len);
-	return -1;
+			 state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
+	ser_error=E_BAD_URI;
+	return E_BAD_URI;
 error_headers:
 	LOG(L_ERR, "ERROR: parse_uri: bad uri headers: <%.*s>(%d)"
 			" / <%.*s>(%d)\n",
-			uri->headers.len, uri->headers.s, uri->headers.len,
-			len, buf, len);
-	return -1;
+			uri->headers.len, ZSW(uri->headers.s), uri->headers.len,
+			len, ZSW(buf), len);
+	ser_error=E_BAD_URI;
+	return E_BAD_URI;
 error_bug:
 	LOG(L_CRIT, "BUG: parse_uri: bad  state %d"
 			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
-			 state, (p-buf), buf, (p-buf), len, buf, len);
-	return -1;
+			 state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
+	ser_error=E_BAD_URI;
+	return E_BAD_URI;
 }
 
 
-
 int main (int argc, char** argv)
 {