bin.c

Go to the documentation of this file.
00001 /*
00002  * $Id: bin.c 161 2007-03-01 14:06:01Z vingarzan $
00003  *
00004  * Copyright (C) 2004-2007 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * It has to be noted that this Open Source IMS Core System is not
00026  * intended to become or act as a product in a commercial context! Its
00027  * sole purpose is to provide an IMS core reference implementation for
00028  * IMS technology testing and IMS application prototyping for research
00029  * purposes, typically performed in IMS test-beds.
00030  *
00031  * Users of the Open Source IMS Core System have to be aware that IMS
00032  * technology may be subject of patents and licence terms, as being
00033  * specified within the various IMS-related IETF, ITU-T, ETSI, and 3GPP
00034  * standards. Thus all Open IMS Core users have to take notice of this
00035  * fact and have to agree to check out carefully before installing,
00036  * using and extending the Open Source IMS Core System, if related
00037  * patents and licences may become applicable to the intended usage
00038  * context.
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00043  *
00044  */
00045 
00056 #include <stdio.h>
00057 #include <time.h>
00058 #include <errno.h>
00059 #include <sys/types.h>
00060 #include <dirent.h>
00061 #include <unistd.h>
00062 #include <stdlib.h>
00063 
00064 #include "bin.h"
00065 
00066 
00070 #define BIN_DEBUG 0
00071 
00077 #define BIN_DECODE_CHECKS 1
00078 
00079 inline int bin_alloc(bin_data *x, int max_len)
00080 {                                
00081     x->s = (char*)BIN_ALLOC_METHOD(max_len);     
00082     if (!x->s){
00083         LOG(L_ERR,"ERR:"M_NAME":bin_alloc: Error allocating %d bytes.\n",max_len);
00084         x->len=0;
00085         x->max=0;
00086         return 0;
00087     }
00088     x->len=0;
00089     x->max=max_len;
00090     return 1;
00091 }
00092 
00093 inline int bin_realloc(bin_data *x, int delta)
00094 {
00095 #if BIN_DEBUG
00096     LOG(L_INFO,"INFO:"M_NAME":bin_realloc: realloc %p from %d to + %d\n",x->s,x->max,delta);
00097 #endif  
00098     x->s=BIN_REALLOC_METHOD(x->s,x->max + delta);    
00099     if (x->s==NULL){                             
00100         LOG(L_ERR,"ERR:"M_NAME":bin_realloc: No more memory to expand %d with %d  \n",x->max,delta);
00101         return 0;
00102     }
00103     x->max += delta;
00104     return 1;
00105 }
00106 
00107 inline int bin_expand(bin_data *x, int delta)
00108 {
00109     if (x->max-x->len>=delta) return 1;
00110 #if BIN_DEBUG   
00111     LOG(L_INFO,"INFO:"M_NAME":bin_realloc: realloc %p from %d to + %d\n",x->s,x->max,delta);
00112 #endif  
00113     x->s=BIN_REALLOC_METHOD(x->s,x->max + delta);    
00114     if (x->s==NULL){                             
00115         LOG(L_ERR,"ERR:"M_NAME":bin_realloc: No more memory to expand %d with %d  \n",x->max,delta);
00116         return 0;
00117     }
00118     x->max += delta;
00119     return 1;
00120 }
00121 
00122 inline void bin_free(bin_data *x)
00123 {
00124     BIN_FREE_METHOD(x->s);
00125     x->s=0;x->len=0;x->max=0;
00126 }
00127 
00131 inline void bin_print(bin_data *x)
00132 {
00133     int i,j,w=16;
00134     char c;
00135     fprintf(stderr,"----------------------------------\nBinary form %d (max %d) bytes:\n",x->len,x->max);
00136     for(i=0;i<x->len;i+=w){
00137         fprintf(stderr,"%04X> ",i);
00138         for(j=0;j<w;j++){
00139             if (i+j<x->len) fprintf(stderr,"%02X ",(unsigned char)x->s[i+j]);
00140             else fprintf(stderr,"   ");
00141         }
00142         printf("\t");
00143         for(j=0;j<w;j++)if (i+j<x->len){
00144             if (x->s[i+j]>32) c=x->s[i+j];
00145             else c = '.';
00146             fprintf(stderr,"%c",c);
00147         }else fprintf(stderr," ");
00148         fprintf(stderr,"\n");
00149     }
00150     fprintf(stderr,"\n---------------------------------\n");
00151 }
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 /* basic data type reprezentation functions */
00160 
00161 
00162 
00163 
00167 inline int bin_encode_char(bin_data *x,char k) 
00168 { 
00169     if (!bin_expand(x,1)) return 0;
00170     x->s[x->len++]= k; 
00171 #if BIN_DEBUG   
00172     LOG(L_INFO,"INFO:"M_NAME":bin_encode_char: [%d]:[%.02x] new len %04x\n",k,x->s[x->len-1],x->len);
00173 #endif
00174     return 1;   
00175 }
00179 inline int bin_decode_char(bin_data *x,char *c)
00180 {
00181 #if BIN_DECODE_CHECKS
00182     if (x->max+1 > x->len) return 0;
00183 #endif  
00184     *c = x->s[x->max];
00185     x->max += 1;
00186 #if BIN_DEBUG   
00187     LOG(L_INFO,"INFO:"M_NAME":bin_decode_char: [%d] new pos %04x\n",*c,x->max);
00188 #endif
00189     return 1;
00190 }
00191 
00192 
00193 
00194 
00198 inline int bin_encode_uchar(bin_data *x,unsigned char k) 
00199 { 
00200     if (!bin_expand(x,1)) return 0;
00201     x->s[x->len++]= k; 
00202 #if BIN_DEBUG   
00203     LOG(L_INFO,"INFO:"M_NAME":bin_encode_uchar: [%u]:[%.02x] new len %04x\n",k,x->s[x->len-1],x->len);
00204 #endif
00205     return 1;   
00206 }
00210 inline int bin_decode_uchar(bin_data *x,unsigned char *c)
00211 {
00212 #if BIN_DECODE_CHECKS
00213     if (x->max+1 > x->len) return 0;
00214 #endif  
00215     *c = x->s[x->max];
00216     x->max += 1;
00217 #if BIN_DEBUG   
00218     LOG(L_INFO,"INFO:"M_NAME":bin_decode_uchar: [%u] new pos %04x\n",*c,x->max);
00219 #endif
00220     return 1;
00221 }
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00232 inline int bin_encode_short(bin_data *x,short k) 
00233 { 
00234     if (!bin_expand(x,2)) return 0;
00235     x->s[x->len++]=k & 0x00FF;    
00236     x->s[x->len++]=(k & 0xFF00) >> 8;   
00237 #if BIN_DEBUG   
00238     LOG(L_INFO,"INFO:"M_NAME":bin_encode_short: [%d]:[%.02x %.02x] new len %04x\n",k,x->s[x->len-2],x->s[x->len-1],x->len);
00239 #endif
00240     return 1;   
00241 }
00245 inline int bin_decode_short(bin_data *x,short *v)
00246 {
00247 #if BIN_DECODE_CHECKS
00248     if (x->max+2 > x->len) return 0;
00249 #endif
00250     *v =    (unsigned char)x->s[x->max  ]    |
00251             (unsigned char)x->s[x->max+1]<<8;
00252     x->max += 2;
00253 #if BIN_DEBUG   
00254     LOG(L_INFO,"INFO:"M_NAME":bin_decode_short: [%d] new pos %04x\n",*v,x->max);
00255 #endif
00256     return 1;
00257 }
00258 
00259 
00263 inline int bin_encode_ushort(bin_data *x,unsigned short k) 
00264 { 
00265     if (!bin_expand(x,2)) return 0;
00266     x->s[x->len++]=k & 0x00FF;    
00267     x->s[x->len++]=(k & 0xFF00) >> 8;   
00268 #if BIN_DEBUG   
00269     LOG(L_INFO,"INFO:"M_NAME":bin_encode_ushort: [%u]:[%.02x %.02x] new len %04x\n",k,x->s[x->len-2],x->s[x->len-1],x->len);
00270 #endif
00271     return 1;   
00272 }
00276 inline int bin_decode_ushort(bin_data *x,unsigned short *v)
00277 {
00278 #if BIN_DECODE_CHECKS
00279     if (x->max+2 > x->len) return 0;
00280 #endif
00281     *v =    (unsigned char)x->s[x->max  ]    |
00282             (unsigned char)x->s[x->max+1]<<8;
00283     x->max += 2;
00284 #if BIN_DEBUG   
00285     LOG(L_INFO,"INFO:"M_NAME":bin_decode_ushort: [%u] new pos %04x\n",*v,x->max);
00286 #endif
00287     return 1;
00288 }
00289 
00290 
00294 inline int bin_encode_int(bin_data *x,int k) 
00295 { 
00296     int len = sizeof(int),i;
00297     if (!bin_expand(x,len)) return 0;
00298     for(i=0;i<len;i++){
00299         x->s[x->len++]= k & 0xFF;
00300         k = k>>8;          
00301     }
00302 #if BIN_DEBUG           
00303     switch(len){
00304         case 4:
00305             LOG(L_INFO,"INFO:"M_NAME":bin_encode_int: [%d]:[%.02x %.02x %.02x %.02x] new len %04x\n",k,
00306                 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],x->len);
00307             break;
00308         case 8:
00309             LOG(L_INFO,"INFO:"M_NAME":bin_encode_int: [%d]:[%.02x %.02x %.02x %.02x%.02x %.02x %.02x %.02x] new len %04x\n",k,
00310                 x->s[x->len-8],x->s[x->len-7],x->s[x->len-6],x->s[x->len-5],
00311                 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],
00312                 x->len);
00313             break;
00314     }
00315 #endif      
00316     return 1;   
00317 }
00321 inline int bin_decode_int(bin_data *x,int *v)
00322 {
00323     int len = sizeof(int),i;
00324 #if BIN_DECODE_CHECKS
00325     if (x->max+len > x->len) return 0;
00326 #endif
00327     *v = 0;
00328     for(i=0;i<len;i++)
00329         *v =  *v | ((unsigned char)x->s[x->max++] <<(8*i));
00330 #if BIN_DEBUG   
00331     LOG(L_INFO,"INFO:"M_NAME":bin_decode_int: [%d] new pos %04x\n",*v,x->max);
00332 #endif
00333     return 1;
00334 }
00335 
00336 
00337 
00341 inline int bin_encode_uint(bin_data *x,unsigned int k) 
00342 { 
00343     int len = sizeof(unsigned int),i;
00344     if (!bin_expand(x,len)) return 0;
00345     for(i=0;i<len;i++){
00346         x->s[x->len++]= k & 0xFF;
00347         k = k>>8;          
00348     }
00349 #if BIN_DEBUG           
00350     switch(len){
00351         case 4:
00352             LOG(L_INFO,"INFO:"M_NAME":bin_encode_uint: [%u]:[%.02x %.02x %.02x %.02x] new len %04x\n",k,
00353                 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],x->len);
00354             break;
00355         case 8:
00356             LOG(L_INFO,"INFO:"M_NAME":bin_encode_uint: [%u]:[%.02x %.02x %.02x %.02x%.02x %.02x %.02x %.02x] new len %04x\n",k,
00357                 x->s[x->len-8],x->s[x->len-7],x->s[x->len-6],x->s[x->len-5],
00358                 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],
00359                 x->len);
00360             break;
00361     }
00362 #endif      
00363     return 1;   
00364 }
00368 inline int bin_decode_uint(bin_data *x,unsigned int *v)
00369 {
00370     int len = sizeof(unsigned int),i;
00371 #if BIN_DECODE_CHECKS
00372     if (x->max+len > x->len) return 0;
00373 #endif
00374     *v = 0;
00375     for(i=0;i<len;i++)
00376         *v =  *v | ((unsigned char)x->s[x->max++] <<(8*i));
00377 #if BIN_DEBUG   
00378     LOG(L_INFO,"INFO:"M_NAME":bin_decode_uint: [%u] new pos %04x\n",*v,x->max);
00379 #endif
00380     return 1;
00381 }
00382 
00386 inline int bin_encode_time_t(bin_data *x,time_t k) 
00387 { 
00388     int len = sizeof(time_t),i;
00389     if (!bin_expand(x,len)) return 0;
00390     for(i=0;i<len;i++){
00391         x->s[x->len++]= k & 0xFF;
00392         k = k>>8;          
00393     }
00394 #if BIN_DEBUG           
00395     switch(len){
00396         case 4:
00397             LOG(L_INFO,"INFO:"M_NAME":bin_encode_time_t: [%u]:[%.02x %.02x %.02x %.02x] new len %04x\n",(unsigned int)k,
00398                 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],x->len);
00399             break;
00400         case 8:
00401             LOG(L_INFO,"INFO:"M_NAME":bin_encode_time_t: [%u]:[%.02x %.02x %.02x %.02x%.02x %.02x %.02x %.02x] new len %04x\n",(unsigned int)k,
00402                 x->s[x->len-8],x->s[x->len-7],x->s[x->len-6],x->s[x->len-5],
00403                 x->s[x->len-4],x->s[x->len-3],x->s[x->len-2],x->s[x->len-1],
00404                 x->len);
00405             break;
00406     }
00407 #endif      
00408     return 1;   
00409 }
00413 inline int bin_decode_time_t(bin_data *x,time_t *v)
00414 {
00415     int len = sizeof(time_t),i;
00416 #if BIN_DECODE_CHECKS
00417     if (x->max+len > x->len) return 0;
00418 #endif
00419     *v = 0;
00420     for(i=0;i<len;i++)
00421         *v =  *v | ((unsigned char)x->s[x->max++] <<(8*i));
00422 #if BIN_DEBUG   
00423     LOG(L_INFO,"INFO:"M_NAME":bin_decode_time_t: [%u] new pos %04x\n",(unsigned int) *v,x->max);
00424 #endif
00425     return 1;
00426 }
00427 
00428 
00432 inline int bin_encode_str(bin_data *x,str *s) 
00433 { 
00434     if (!bin_expand(x,2+s->len)) return 0;
00435     if (s->len>65535) 
00436         LOG(L_ERR,"ERROR:"M_NAME":bin_encode_str: Possible loss of characters in encoding (string > 65535bytes) %d bytes \n",s->len);
00437     x->s[x->len++]=s->len & 0x000000FF;
00438     x->s[x->len++]=(s->len & 0x0000FF00)>>8;
00439     memcpy(x->s+x->len,s->s,s->len);
00440     x->len+=s->len;
00441 #if BIN_DEBUG       
00442     LOG(L_INFO,"INFO:"M_NAME":bin_encode_str : [%d]:[%.02x %.02x]:[%.*s] new len %04x\n",s->len,
00443         x->s[x->len-s->len-2],x->s[x->len-s->len-1],s->len,s->s,x->len);
00444 #endif      
00445     return 1;   
00446 }
00450 inline int bin_decode_str(bin_data *x,str *s)
00451 {
00452 #if BIN_DECODE_CHECKS
00453     if (x->max+2 > x->len) return 0;
00454 #endif
00455     s->len = (unsigned char)x->s[x->max  ]    |
00456             (unsigned char)x->s[x->max+1]<<8;
00457     x->max +=2;
00458     if (x->max+s->len>x->len) return 0;
00459     s->s = x->s + x->max;
00460     x->max += s->len;
00461 #if BIN_DEBUG   
00462     LOG(L_INFO,"INFO:"M_NAME":bin_decode_str : [%d]:[%.*s] new pos %04x\n",s->len,s->len,s->s,x->max);
00463 #endif
00464     return 1;
00465 }
00466 
00467 
00468 
00469 
00470 /* complex data types */
00471 
00472 
00473 extern dlg_func_t dialogb;                          
00482 int bin_encode_dlg_t(bin_data *x,dlg_t *d)
00483 {
00484     str s={0,0};
00485     if (d){
00486         if (dialogb.dlg2str(d,&s)!=0) goto error;
00487     }
00488     if (!bin_encode_str(x,&s)) goto error;
00489     str_free_content(&s);
00490     return 1;
00491 error:
00492     LOG(L_ERR,"ERR:"M_NAME":bin_encode_dlg_t: Error while encoding.\n");
00493     if (s.s) str_free_content(&s);
00494     return 0;       
00495 }
00496 
00503 int bin_decode_dlg_t(bin_data *x,dlg_t **d)
00504 {
00505     int len;
00506     str s;
00507     
00508     if (!bin_decode_str(x,&s)) goto error;
00509 
00510     if (!s.len) {
00511         *d = 0;
00512         return 1;
00513     }
00514     
00515     len = sizeof(dlg_t);
00516     *d = (dlg_t*) shm_malloc(len);
00517     if (!*d) {
00518         LOG(L_ERR,"ERR:"M_NAME":bin_decode_dlg_t: Error allocating %d bytes.\n",len);
00519         goto error;
00520     }
00521     memset(*d,0,len);
00522     if (dialogb.str2dlg(&s,*d)!=0) goto error;
00523     
00524     return 1;
00525 error:
00526     LOG(L_ERR,"ERR:"M_NAME":bin_decode_dlg_t: Error while decoding (at %d (%04x)).\n",x->max,x->max);
00527     if (*d) {
00528         shm_free(*d);
00529     }
00530     return 0;
00531 }
00532 
00533 
00534 
00535 
00536 
00537 /* file dumping routines */
00538 
00539 
00540 int bin_files_keep_count=3;             
00553 int bin_dump_to_file(bin_data *x,char *location,char *prepend_fname)
00554 {
00555     char c_part[256],c_time[256],c_last[256];
00556     time_t now;
00557     FILE *f;
00558     int k;
00559     
00560     now = time(0);
00561     sprintf(c_part,"%s/%s_%.10u.bin.part",location,prepend_fname,(unsigned int)now);
00562     sprintf(c_time,"%s/%s_%.10u.bin",location,prepend_fname,(unsigned int)now);
00563     sprintf(c_last,"%s/_%s.bin",location,prepend_fname);
00564 
00565     /* first dump to a partial file */  
00566     f = fopen(c_part,"w");
00567     if (!f){
00568         LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when opening file <%s> for writting [%s]\n",c_part,strerror(errno));
00569         return 0;
00570     }
00571     k = fwrite(x->s,1,x->len,f);
00572     LOG(L_INFO,"INFO:"M_NAME":bin_dump_to_file: Dumped %d bytes into %s.\n",k,c_part);
00573     fclose(f);          
00574     
00575     /* then rename it as a complete file with timestamp */
00576     if (rename(c_part,c_time)<0){
00577         LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when renaming  <%s> -> <%s> [%s]\n",c_part,c_time,strerror(errno));
00578         return 0;
00579     }
00580     
00581     /* then link the last snapshot to it */
00582     if (k==x->len) {
00583         if (remove(c_last)<0 && errno!=ENOENT){
00584             LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when removing symlink <%s> [%s]\n",c_last,strerror(errno));
00585             return 0;
00586         }
00587         if (symlink(c_time,c_last)<0){
00588             LOG(L_ERR,"ERR:"M_NAME":bin_dump_to_file: error when symlinking <%s> -> <%s> [%s]\n",c_time,c_last,strerror(errno));
00589             return 0;
00590         }
00591         /* then remove old snapshots */
00592         {
00593             struct dirent **namelist;
00594             int i,n,k=bin_files_keep_count;
00595             int len=strlen(prepend_fname);                  
00596             n = scandir(location,&namelist,0,alphasort);
00597             if (n>0){
00598                 for(i=n-1;i>=0;i--){
00599                     if (strlen(namelist[i]->d_name)>len &&
00600                         memcmp(namelist[i]->d_name,prepend_fname,len)==0) {
00601                         if (k) k--;
00602                         else {                          
00603                             sprintf(c_part,"%s/%s",location,namelist[i]->d_name);
00604                             remove(c_part);
00605                         }
00606                     }
00607                     free(namelist[i]);
00608                 }
00609                 free(namelist);
00610             }
00611         }
00612         return 1;   
00613     }
00614     else return 0;
00615 }
00616 
00617 
00624 int bin_load_from_file(bin_data *x,char *location,char *prepend_fname)
00625 {
00626     char c[256];
00627     FILE *f;
00628     int k;
00629     
00630     sprintf(c,"%s/_%s.bin",location,prepend_fname);
00631     f = fopen(c,"r");
00632     if (!f) {
00633         LOG(L_ERR,"ERR:"M_NAME":bin_load_from_file: error opening %s : %s\n",c,strerror(errno));
00634         return 0;
00635     }
00636     bin_alloc(x,1024);
00637     while(!feof(f)){
00638         bin_expand(x,1024);
00639         k = fread(x->s+x->len,1,1024,f);
00640         x->len+=k;
00641     }
00642     LOG(L_INFO,"INFO:"M_NAME":bin_load_from_file: Read %d bytes from %s.\n",x->len,c);
00643     fclose(f);  
00644     return 1;
00645 }
00646 
00647 
00655 int bin_dump(bin_data *x,int mode,char *location,char* prepend_fname)
00656 {   
00657     switch (mode){
00658         case NO_PERSISTENCY:
00659             LOG(L_ERR,"ERR:"M_NAME":bin_dump: Snapshot done but persistency was disabled...\n");
00660             return 0;
00661         case WITH_FILES:
00662             return bin_dump_to_file(x,location,prepend_fname);
00663         /*case WITH_DATABASE_BULK:
00664             return bin_dump_to_db(x, prepend_fname);
00665         case WITH_DATABASE_CACHE:
00666             LOG(L_ERR,"ERR:"M_NAME":bin_dump: Snapshot done but WITH_DATABASE_CACHE not implemented...\n");
00667             return 0;*/
00668         default:
00669             LOG(L_ERR,"ERR:"M_NAME":bin_dump: Snapshot done but no such mode %d\n",mode);
00670             return 0;
00671     }
00672 }
00673 
00680 int bin_load(bin_data *x,int mode,char *location,char* prepend_fname)
00681 {
00682     switch (mode){
00683         case NO_PERSISTENCY:
00684             LOG(L_ERR,"ERR:"M_NAME":bin_load: Persistency support was disabled\n");
00685             return 0;
00686         case WITH_FILES:
00687             return bin_load_from_file(x,location,prepend_fname);        
00688         /*case WITH_DATABASE_BULK:
00689             LOG(L_ERR,"ERR:"M_NAME":bin_load: WITH_DATABASE_BULK not implemented...\n");
00690             return 0;
00691         case WITH_DATABASE_CACHE:
00692             LOG(L_ERR,"ERR:"M_NAME":bin_load: WITH_DATABASE_CACHE not implemented...\n");
00693             return 0;*/
00694         default:
00695             LOG(L_ERR,"ERR:"M_NAME":bin_load: Can't resume because no such mode %d\n",mode);
00696             return 0;
00697     }
00698 }
00699 
00700 
00701 
00702 /* end of bin library functions */

Generated on Thu Oct 23 04:14:38 2008 for Open IMS Core CSCFs by  doxygen 1.5.2