1 #include <stdio.h>
2 #include "parse_next_hop.h"
3 #include "parse_common.h"
4 #include "log.h"
5 
parse_next_hop(const cstring & next_hop,list<sip_destination> & dest_list)6 int parse_next_hop(const cstring& next_hop,
7 		   list<sip_destination>& dest_list)
8 {
9   enum {
10     IPL_BEG=0,
11     IPL_HOST,
12     IPL_V6,
13     IPL_HOST_SEP,
14     IPL_PORT,
15     IPL_TRSP
16   };
17 
18   int st = IPL_BEG;
19 
20   const char* c = next_hop.s;
21   const char* end = c + next_hop.len;
22   const char* beg = NULL;
23 
24   sip_destination dest;
25 
26   for(;c<end; c++) {
27 
28     switch(st){
29 
30     case IPL_BEG:
31       switch(*c){
32       case SP:
33       case HTAB:
34 	continue;
35       default:
36 	beg = c;
37 	st = IPL_HOST;
38 	dest.host.clear();
39 	dest.port = 0;
40 	break;
41       }
42       // fall-through trap
43     case IPL_HOST:
44       switch(*c){
45       case '[':
46 	st = IPL_V6;
47 	beg = c+1;
48 	break;
49       case ':':
50 	st = IPL_PORT;
51 	dest.host.set(beg,c-beg);
52 	break;
53       case '/':
54 	st = IPL_TRSP;
55 	dest.host.set(beg,c-beg);
56 	beg = c+1;
57 	break;
58       case ',':
59 	st = IPL_BEG;
60 	dest.host.set(beg,c-beg);
61 	dest_list.push_back(dest);
62 	break;
63       case SP:
64       case HTAB:
65 	st = IPL_HOST_SEP;
66 	dest.host.set(beg,c-beg);
67 	break;
68       default:
69 	break;
70       }
71       break;
72 
73     case IPL_V6:
74       switch(*c){
75       case ']':
76 	st = IPL_HOST_SEP;
77 	dest.host.set(beg,c-beg);
78 	break;
79       default:
80 	break;
81       }
82       break;
83 
84     case IPL_HOST_SEP:
85       switch(*c){
86       case ':':
87 	st = IPL_PORT;
88 	break;
89       case ',':
90 	st = IPL_BEG;
91 	dest_list.push_back(dest);
92 	break;
93       case '/':
94 	st = IPL_TRSP;
95 	beg = c+1;
96 	break;
97       default:
98 	// syntax error
99 	DBG("error: unexpected character '%c' in IPL_HOST_SEP state.\n",*c);
100 	return -1;
101       }
102       break;
103 
104     case IPL_PORT:
105       switch(*c){
106       case '/':
107 	st = IPL_TRSP;
108 	beg = c+1;
109 	break;
110       case ',':
111 	st = IPL_BEG;
112 	dest_list.push_back(dest);
113 	break;
114       case SP:
115       case HTAB:
116 	break;
117       default:
118 	if(*c < '0' && *c > '9'){
119 	  DBG("error: unexpected character '%c' in IPL_PORT state.\n",*c);
120 	  return -1;
121 	}
122 	dest.port = dest.port*10 + (*c - '0');
123 	break;
124       }
125       break;
126 
127 
128     case IPL_TRSP:
129       switch(*c){
130       case ',':
131 	st = IPL_BEG;
132 	dest.trsp.set(beg,c-beg);
133 	dest_list.push_back(dest);
134 	break;
135       default:
136 	if( (*c >= 'a' && *c <= 'z') ||
137 	    (*c >= 'A' && *c <= 'Z') ) {
138 	  continue;
139 	}
140 	// syntax error
141 	DBG("error: unexpected character '%c' in IPL_TRSP state.\n",*c);
142 	return -1;
143       }
144       break;
145     }
146   }
147 
148   switch(st){
149   case IPL_BEG:
150     // no host at all
151     // possibly, the string was empty
152     break;
153   case IPL_HOST:
154     dest.host.set(beg,c-beg);
155     dest_list.push_back(dest);
156     break;
157   case IPL_V6:
158   case IPL_HOST_SEP:
159   case IPL_PORT:
160     dest_list.push_back(dest);
161     break;
162   case IPL_TRSP:
163     dest.trsp.set(beg,c-beg);
164     dest_list.push_back(dest);
165     break;
166   }
167 
168   return 0;
169 }
170