Module: sip-router
Branch: master
Commit: 6335d07c4c77ed60fb8c2b5acc84d7c4b503221c
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6335d07…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)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