ccae6e389adba79c592bbe3238ab8ffa60cfdeb9
[com/gs-lite.git] / src / lib / gscphftaaux / hfta_runtime_library.cc
1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7      http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License.
14  ------------------------------------------- */
15
16 #include <sys/types.h>
17 #include <iostream>
18 extern "C" {
19 #include "gsconfig.h"
20 #include "gstypes.h"
21 #include <regex.h>
22 #include <rdtsc.h>
23 #include <stringhash.h>
24 #include <errno.h>
25 #include <unistd.h>
26 }
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <vstring.h>
31 #include <host_tuple.h>
32 #include <fta.h>
33
34 // for htonl,ntohl
35 #include <netinet/in.h>
36
37 #define MAX_PATTERN_LEN 1024
38
39 // Defined here to avoid link errors as this array is auto generated for the lfta and referenced in the clearinghouse library which gets linked against the hfta
40 extern "C" gs_sp_t fta_names[]={0};
41
42
43 //              Only used to construct constant strings ...
44 gs_retval_t Vstring_Constructor(vstring *tmp, gs_csp_t str) {
45         tmp->length = strlen(str);
46         if(tmp->length)
47                 tmp->offset = (gs_p_t)strdup(str);
48         tmp->reserved = SHALLOW_COPY;
49         return 0;
50 }
51
52 //              Assume str is INTERNAL or SHALLOW_COPY.
53 void hfta_vstr_destroy(vstring * str) {
54         if (str->length && str->reserved == INTERNAL) {
55                 free((gs_sp_t)str->offset);
56         }
57         str->length = 0;
58 }
59
60
61 gs_retval_t hfta_vstr_length(vstring *str) {
62         return str->length;
63 }
64
65 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
66 void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target, vstring * src,
67         gs_sp_t data_offset,  gs_retval_t int_offset) {
68         target->length = src->length;
69         target->offset = int_offset;
70         target->reserved = PACKED;
71         if ( src->length)
72                 memcpy(data_offset, (gs_sp_t)src->offset, src->length);
73 }
74
75 //              Ted wrote the following function.
76 //              make deep copy of src.  Assume that dst is already empty.
77 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
78 void hfta_vstr_assign_with_copy(vstring *dst, vstring *src){
79         dst->length=src->length;
80         if(src->length){
81                 dst->offset=(gs_p_t)malloc(dst->length);
82                 memcpy((gs_sp_t)(dst->offset),(gs_sp_t)(src->offset),dst->length);
83         }
84         dst->reserved=INTERNAL;
85 }
86
87 //              Ted wrote the following function.
88 //              Make a deep copy of src.  garbage collect dst if needed.
89 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
90 void hfta_vstr_replace(vstring *dst, vstring *src){
91         hfta_vstr_destroy(dst);
92         hfta_vstr_assign_with_copy(dst,src);
93 }
94
95 #define HFTA_VSTR_LHASHFUNC_PRIME 12916008961267169387ull
96 gs_uint64_t hfta_vstr_long_hashfunc(const vstring *s) {
97         gs_uint64_t hash_code;
98         gs_int32_t n_steps;
99         gs_int32_t substr_len;
100         gs_int32_t j, k;
101         gs_uint64_t sub_hash;
102         gs_sp_t sv;
103
104         sv=(gs_sp_t)(s->offset);
105         hash_code = 0;
106         n_steps = s->length / 4;
107         if(4*n_steps < s->length) n_steps++;
108
109         for (j = 0; j <  n_steps; j++) {
110                 if(4*(j+1) < s->length) substr_len = 4;
111                 else                  substr_len = s->length - 4*j;
112
113                 sub_hash = 0;
114                 for(k=0;k<4;k++){
115                   if(k < substr_len)
116                         sub_hash = (sub_hash << 4) + *sv;
117                   else
118                         sub_hash = (sub_hash << 4);
119                   sv++;
120                 }
121
122                 hash_code = (sub_hash + hash_code * HFTA_VSTR_LHASHFUNC_PRIME);
123         }
124
125         return(hash_code);
126 }
127
128 #define HFTA_VSTR_HASHFUNC_PRIME 2995999
129 gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
130         gs_uint32_t hash_code;
131         gs_int32_t n_steps;
132         gs_int32_t substr_len;
133         gs_int32_t j;
134         gs_uint32_t k, sub_hash;
135         gs_sp_t sv;
136
137         sv=(gs_sp_t)(s->offset);
138         hash_code = 0;
139         n_steps = s->length / 4;
140         if(4*n_steps < s->length) n_steps++;
141
142         for (j = 0; j <  n_steps; j++) {
143                 if(4*(j+1) < s->length) substr_len = 4;
144                 else                  substr_len = s->length - 4*j;
145
146                 sub_hash = 0;
147                 for(k=0;k<4;k++){
148                   if(k < substr_len)
149                         sub_hash = (sub_hash << 4) + *sv;
150                   else
151                         sub_hash = (sub_hash << 4);
152                   sv++;
153                 }
154
155                 hash_code = (sub_hash + hash_code * HFTA_VSTR_HASHFUNC_PRIME);
156         }
157
158         return(hash_code);
159 }
160
161
162 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
163 gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
164         gs_int32_t minlen,cmp_ret;
165         minlen=(s1->length<s2->length?s1->length:s2->length);
166         cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,minlen);
167
168         if(cmp_ret) return cmp_ret;
169         return(s1->length - s2->length);
170 }
171
172
173
174 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
175     regex_t * reg;
176     gs_int32_t res;
177
178     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
179         gslog(LOG_EMERG, "No memory for regular expression %s\n",
180                 (gs_sp_t)(pattern->offset));
181         return 0;
182     }
183
184     if (regcomp(reg,(char*)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
185         gslog(LOG_EMERG, "Illegal regular expression %s\n",
186                 (gs_sp_t)(pattern->offset));
187         return 0;
188     }
189     return (gs_param_handle_t) reg;
190 }
191
192 gs_uint32_t str_regex_match(vstring* str, gs_param_handle_t pattern_handle) {
193     regex_t * reg = (regex_t *) pattern_handle ;
194     gs_int32_t res;
195     static gs_sp_t d=0;
196     static gs_uint32_t dlen=0;
197     // grow our static buffer to the longest string we ever see
198     if ((str->length+1) >= dlen) {
199         if (d!=0) free((void*)d);
200         dlen=0;
201         d=0;
202         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
203         dlen=str->length+1;
204     }
205     
206     if (str->length==0) return 0;
207     
208     // copy the string and 0 terminate it
209     memcpy((void *)d,(void *) str->offset, str->length);
210     d[str->length]=0;
211     
212     res = REG_NOMATCH;
213     res = regexec(reg, d, 0, NULL, 0);
214     return (res==REG_NOMATCH)?0:1;
215 }
216
217 gs_retval_t deregister_handle_for_str_regex_match_slot_1(gs_param_handle_t handle) {
218     regex_t * x = (regex_t *) handle;
219     regfree(x);
220     if (x!=0) free(x);
221     return 0;
222 }
223
224 gs_param_handle_t register_handle_for_str_partial_regex_match_slot_1(vstring* pattern) {
225     regex_t * reg;
226     gs_int32_t res;
227
228     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
229         gslog(LOG_EMERG, "No memory for regular expression %s\n",
230                 (gs_sp_t)(pattern->offset));
231         return 0;
232     }
233
234     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
235         gslog(LOG_EMERG, "Illegal regular expression %s\n",
236                 (gs_sp_t)(pattern->offset));
237         return 0;
238     }
239     return (gs_param_handle_t) reg;
240 }
241
242 gs_uint32_t str_partial_regex_match(vstring* str, gs_param_handle_t pattern_handle,
243                              uint maxlen) {
244     regex_t * reg = (regex_t *) pattern_handle ;
245     gs_int32_t res;
246     gs_int32_t end;
247     static gs_sp_t d=0;
248     static gs_uint32_t dlen=0;
249     // grow our static buffer to the longest string we ever see
250     if ((str->length+1) >= dlen) {
251         if (d!=0) free((void*)d);
252         dlen=0;
253         d=0;
254         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
255         dlen=str->length+1;
256     }
257     
258     if (str->length==0) return 0;
259     
260     end=(maxlen>(str->length))?(str->length):maxlen;
261     
262     // copy the string and 0 terminate it
263     memcpy((void *)d,(void *) str->offset, end);
264     d[end]=0;
265  
266     res = REG_NOMATCH;
267     res = regexec(reg, d,0, NULL, 0);
268     return (res==REG_NOMATCH)?0:1;
269 }
270
271
272 gs_retval_t deregister_handle_for_str_partial_regex_match_slot_1(
273                                              gs_param_handle_t handle) {
274     regex_t * x = (regex_t *) handle;
275     regfree(x);
276     if (x!=0) free(x);
277     return 0;
278 }
279
280 gs_param_handle_t register_handle_for_str_extract_regex_slot_1(vstring* pattern) {
281     regex_t * reg;
282     
283     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
284         gslog(LOG_EMERG, "No memory for regular expression %s\n",
285               (gs_sp_t)(pattern->offset));
286         return 0;
287     }
288     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_EXTENDED)!=0) {
289         gslog(LOG_EMERG, "Illegal regular expression %s\n",
290               (gs_sp_t)(pattern->offset));
291         return 0;
292     }
293     return (gs_param_handle_t) reg;
294 }
295
296
297 /* partial function return 0 if the value is valid */
298 gs_retval_t str_extract_regex( vstring * result, vstring * str, gs_param_handle_t handle) {
299     regex_t * reg = (regex_t *) handle ;
300     gs_sp_t source = (gs_sp_t)(str->offset);
301     gs_retval_t res;
302     regmatch_t match;
303     static gs_sp_t d=0;
304     static gs_uint32_t dlen=0;
305     // grow our static buffer to the longest string we ever see
306     if ((str->length+1) >= dlen) {
307         if (d!=0) free((void*)d);
308         dlen=0;
309         d=0;
310         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 1;
311         dlen=str->length+1;
312     }
313     
314     if (str->length==0) return 1;
315     
316     // copy the string and 0 terminate it
317     memcpy((void *)d,(void *) str->offset, str->length);
318     d[str->length]=0;
319
320     res = REG_NOMATCH;
321     res = regexec(reg, d, 1, &match, 0);
322     if (res==REG_NOMATCH) return 1;
323     result->offset= (gs_p_t) &source[match.rm_so];
324     result->length=match.rm_eo-match.rm_so;
325     result->reserved = SHALLOW_COPY;
326     return 0;
327 }
328
329 gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t handle) {
330     regex_t * x = (regex_t *) handle;
331     regfree(x);
332     if (x!=0) free(x);
333     return 0;
334 }
335
336
337 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
338         gs_uint8_t * s = (gs_uint8_t *)(str->offset);
339         int v = 0;
340         *res = 0;
341         while(*offset<str->length) {
342                 if ((s[*offset]>='0') && (s[*offset]<='9')) {
343                         v=1;
344                         *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
345                 } else {
346                         if (v!=0) { // got some valid result
347                                 return 1;
348                         } // otherwise skip leading grabage
349                 }
350                 (*offset)++;
351         }
352         return v;
353 }
354
355 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
356 {
357         gs_uint32_t offset;
358         offset=0;
359         if (nextint(s,&offset,r)==0) return 1;
360         return 0;
361 }
362
363 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
364         gs_uint32_t offset,r;
365         offset=0;
366         if (nextint(istr,&offset,&r)!=0)
367                 return (gs_param_handle_t) r;
368         return (gs_param_handle_t) 0;
369 }
370 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
371         return 0;
372 }
373
374
375 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
376 {
377         gs_uint32_t ip1,ip2,ip3,ip4,offset;
378         offset=0;
379         if (nextint(s,&offset,&ip1)==0) return 1;
380         //fprintf (stderr, "1 %u %u\n",ip1,offset);
381         if (nextint(s,&offset,&ip2)==0) return 1;
382         //fprintf (stderr, "2 %u %u\n",ip2,offset);
383         if (nextint(s,&offset,&ip3)==0) return 1;
384         //fprintf (stderr, "3 %u %u\n",ip3,offset);
385         if (nextint(s,&offset,&ip4)==0) return 1;
386         //fprintf (stderr, "4 %u %u\n",ip4,offset);
387         *r=ip1<<24|ip2<<16|ip3<<8|ip4;
388         return 0;
389 }
390
391 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
392         gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
393         offset=0;
394         if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
395         if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
396         if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
397         if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
398         r=ip1<<24|ip2<<16|ip3<<8|ip4;
399                 return (gs_param_handle_t)r;
400 }
401 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
402         return 0;
403 }
404
405 gs_uint32_t partn_hash(  gs_uint32_t ip1, gs_uint32_t ip2) {
406     return (ip1^ip2);
407 }
408
409 gs_uint32_t rand_hash() {
410     return rand();
411 }
412
413 ///////////////////////////////////////
414 //              IPv6 fcns.
415 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
416 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
417     if(i1.v[0] > i2.v[0])
418         return 1;
419     if(i1.v[0] < i2.v[0])
420         return -1;
421     if(i1.v[1] > i2.v[1])
422         return 1;
423     if(i1.v[1] < i2.v[1])
424         return -1;
425     if(i1.v[2] > i2.v[2])
426         return 1;
427     if(i1.v[2] < i2.v[2])
428         return -1;
429     if(i1.v[3] > i2.v[3])
430         return 1;
431     if(i1.v[3] < i2.v[3])
432         return -1;
433
434     return 0;
435 }
436
437 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
438         hfta_ipv6_str ret;
439         ret.v[0] = i1.v[0] & i2.v[0];
440         ret.v[1] = i1.v[1] & i2.v[1];
441         ret.v[2] = i1.v[2] & i2.v[2];
442         ret.v[3] = i1.v[3] & i2.v[3];
443         return ret;
444 }
445
446 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
447         hfta_ipv6_str ret;
448         ret.v[0] = i1.v[0] | i2.v[0];
449         ret.v[1] = i1.v[1] | i2.v[1];
450         ret.v[2] = i1.v[2] | i2.v[2];
451         ret.v[3] = i1.v[3] | i2.v[3];
452         return ret;
453 }
454
455 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
456         return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
457 }
458
459 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
460         hfta_ipv6_str ret;
461
462 //      ret.v[0] = htonl(s.v[0]);
463 //      ret.v[1] = htonl(s.v[1]);
464 //      ret.v[2] = htonl(s.v[2]);
465 //      ret.v[3] = htonl(s.v[3]);
466         ret.v[0] = s.v[0];
467         ret.v[1] = s.v[1];
468         ret.v[2] = s.v[2];
469         ret.v[3] = s.v[3];
470         return ret;
471 }
472
473 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
474         hfta_ipv6_str ret;
475 //      ret.v[0] = ntohl(s.v[0]);
476 //      ret.v[1] = ntohl(s.v[1]);
477 //      ret.v[2] = ntohl(s.v[2]);
478 //      ret.v[3] = ntohl(s.v[3]);
479         ret.v[0] = s.v[0];
480         ret.v[1] = s.v[1];
481         ret.v[2] = s.v[2];
482         ret.v[3] = s.v[3];
483         return ret;
484 }
485
486 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
487         gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
488         sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
489         s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
490         s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
491         s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
492         s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
493     return(0);
494 }
495
496 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
497 {
498   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
499   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
500   gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
501   gs_uint8_t len1 = s1->length-s2->length;
502   gs_uint8_t len2 = s2->length;
503   gs_uint8_t x,y;
504
505   for (x=0; x<len1 ; x++)
506   {
507       if (st1[x]== *s2f)
508         {
509           for (y=0; y<len2 && st1[x+y]==st2[y];y++);
510           if (y==len2)
511               return 1;
512         }
513   }
514   return 0;
515 }
516
517 gs_retval_t str_compare(vstring *s1,vstring *s2)
518 {
519   return hfta_vstr_compare(s1,s2);
520 }
521
522 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
523 {
524   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
525   gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
526   gs_int32_t x;
527   gs_int32_t len2 = s2->length-offset;
528   gs_int32_t len1 = s1->length;
529
530   if (len2 < len1)
531     return 0;
532
533   for(x = 0; x < len1; x++)
534     {
535       if (st1[x] != st2[x])
536         return 0;
537     }
538   return 1;
539 }
540
541 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
542 {
543   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
544   gs_uint8_t v = (unsigned char) val;
545
546 //  if ((s2->length <= offset)||(offset<0))
547   if (s2->length <= offset)
548       return 0;
549
550   return (st2[offset]==v)?1:0;
551 }
552
553