[sr-dev] git:master: core: helper functions to lookup local socket from proto:host: port

Daniel-Constantin Mierla miconda at gmail.com
Wed Jul 17 12:28:33 CEST 2013


Module: sip-router
Branch: master
Commit: 6335d07c4c77ed60fb8c2b5acc84d7c4b503221c
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6335d07c4c77ed60fb8c2b5acc84d7c4b503221c

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Wed Jul 17 12:22:31 2013 +0200

core: helper functions to lookup local socket from proto:host:port

---

 main.c        |    2 +-
 socket_info.c |   94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 socket_info.h |   10 ++++++
 3 files changed, 105 insertions(+), 1 deletions(-)

diff --git a/main.c b/main.c
index 05f45b5..24d3dc8 100644
--- a/main.c
+++ b/main.c
@@ -924,7 +924,7 @@ error:
 
 /* returns -1 on error, 0 on success
  * sets proto */
-static int parse_proto(unsigned char* s, long len, int* proto)
+int parse_proto(unsigned char* s, long len, int* proto)
 {
 #define PROTO2UINT3(a, b, c) ((	(((unsigned int)(a))<<16)+ \
 								(((unsigned int)(b))<<8)+  \
diff --git a/socket_info.c b/socket_info.c
index b489c8e..3314014 100644
--- a/socket_info.c
+++ b/socket_info.c
@@ -2057,3 +2057,97 @@ void init_proto_order()
 }
 
 
+/**
+ * parse '[port:]host[:port]' string to a broken down structure
+ */
+int parse_protohostport(str* ins, sr_phostp_t *r)
+{
+	char* first; /* first ':' occurrence */
+	char* second; /* second ':' occurrence */
+	char* p;
+	int bracket;
+	char* tmp;
+
+	first=second=0;
+	bracket=0;
+	memset(r, 0, sizeof(sr_phostp_t));
+
+	/* find the first 2 ':', ignoring possible ipv6 addresses
+	 * (substrings between [])
+	 */
+	for(p=ins->s; p<ins->s+ins->len; p++){
+		switch(*p){
+			case '[':
+				bracket++;
+				if (bracket>1) goto error_brackets;
+				break;
+			case ']':
+				bracket--;
+				if (bracket<0) goto error_brackets;
+				break;
+			case ':':
+				if (bracket==0){
+					if (first==0) first=p;
+					else if( second==0) second=p;
+					else goto error_colons;
+				}
+				break;
+		}
+	}
+	if (p==ins->s) return -1;
+	if (*(p-1)==':') goto error_colons;
+
+	if (first==0) { /* no ':' => only host */
+		r->host.s=ins->s;
+		r->host.len=(int)(p-ins->s);
+		goto end;
+	}
+	if (second) { /* 2 ':' found => check if valid */
+		if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0)
+			goto error_proto;
+		r->port=strtol(second+1, &tmp, 10);
+		if ((tmp==0)||(*tmp)||(tmp==second+1)) goto error_port;
+		r->host.s=first+1;
+		r->host.len=(int)(second-r->host.s);
+		goto end;
+	}
+	/* only 1 ':' found => it's either proto:host or host:port */
+	r->port=strtol(first+1, &tmp, 10);
+	if ((tmp==0)||(*tmp)||(tmp==first+1)){
+		/* invalid port => it's proto:host */
+		if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0)
+			goto error_proto;
+		r->host.s=first+1;
+		r->host.len=(int)(p-r->host.s);
+	}else{
+		/* valid port => its host:port */
+		r->host.s=ins->s;
+		r->host.len=(int)(first-r->host.s);
+	}
+end:
+	return 0;
+error_brackets:
+	LOG(L_ERR, "too many brackets in %.*s\n", ins->len, ins->s);
+	return -1;
+error_colons:
+	LOG(L_ERR, "too many colons in %.*s\n", ins->len, ins->s);
+	return -1;
+error_proto:
+	LOG(L_ERR, "bad protocol in %.*s\n", ins->len, ins->s);
+	return -1;
+error_port:
+	LOG(L_ERR, "bad port number in %.*s\n", ins->len, ins->s);
+	return -1;
+}
+
+/**
+ * lookup a local socket by '[port:]host[:port]' string
+ */
+struct socket_info* lookup_local_socket(str *phostp)
+{
+	sr_phostp_t r;
+	if(parse_protohostport(phostp, &r)<0)
+		return NULL;
+	return grep_sock_info(&r.host, (unsigned short)r.port,
+			(unsigned short)r.proto);
+}
diff --git a/socket_info.h b/socket_info.h
index 926b317..ea0ab8b 100644
--- a/socket_info.h
+++ b/socket_info.h
@@ -105,6 +105,8 @@ struct socket_info** get_sock_info_list(unsigned short proto);
 int parse_phostport(char* s, char** host, int* hlen,
 								 int* port, int* proto);
 
+int parse_proto(unsigned char* s, long len, int* proto);
+
 char* get_valid_proto_name(unsigned short proto);
 
 /* helper function:
@@ -142,5 +144,13 @@ inline static struct socket_info* get_first_socket(void)
 	return 0;
 }
 
+/* structure to break down 'proto:host:port' */
+typedef struct _sr_phostp {
+	int proto;
+	str host;
+	int port;
+} sr_phostp_t;
+
+struct socket_info* lookup_local_socket(str *phostp);
 
 #endif




More information about the sr-dev mailing list