00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 #ifndef _binrpc_h
00105 #define _binrpc_h
00106
00107
00108 #include "../../str.h"
00109 #include <string.h>
00110
00111 #define BINRPC_MAGIC 0xA
00112 #define BINRPC_VERS 1
00113
00114
00115 #define BINRPC_FIXED_HDR_SIZE 2
00116 #define BINRPC_TLEN_OFFSET BINRPC_FIXED_HDR_SIZE
00117 #define BINRPC_MIN_HDR_SIZE (BINRPC_FIXED_HDR_SIZE+2)
00118 #define BINRPC_MAX_HDR_SIZE (BINRPC_FIXED_HDR_SIZE+4+4)
00119 #define BINRPC_MIN_RECORD_SIZE 1
00120
00121 #define BINRPC_MIN_PKT_SIZE BINRPC_MIN_HDR_SIZE
00122
00123
00124 #define BINRPC_REQ 0
00125 #define BINRPC_REPL 1
00126 #define BINRPC_FAULT 3
00127
00128
00129 #define BINRPC_T_INT 0
00130 #define BINRPC_T_STR 1
00131 #define BINRPC_T_DOUBLE 2
00132 #define BINRPC_T_STRUCT 3
00133 #define BINRPC_T_ARRAY 4
00134 #define BINRPC_T_AVP 5
00135 #define BINRPC_T_BYTES 6
00136
00137 #define BINRPC_T_ALL 0xf
00138
00139
00140
00141 #define E_BINRPC_INVAL -1
00142 #define E_BINRPC_OVERFLOW -2
00143 #define E_BINRPC_BADPKT -3
00144
00145 #define E_BINRPC_MORE_DATA -4
00146
00147
00148 #define E_BINRPC_EOP -5
00149 #define E_BINRPC_NOTINIT -6
00150 #define E_BINRPC_TYPE -7
00151
00152 #define E_BINRPC_RECORD -8
00153 #define E_BINRPC_BUG -9
00154 #define E_BINRPC_LAST -10
00155
00156
00157
00158 #define BINRPC_F_INIT 1
00159
00160 struct binrpc_pkt{
00161 unsigned char* body;
00162 unsigned char* end;
00163 unsigned char* crt;
00164 };
00165
00166
00167 struct binrpc_parse_ctx{
00168
00169 unsigned int tlen;
00170 unsigned int cookie;
00171 int type;
00172
00173
00174 unsigned int flags;
00175 unsigned int offset;
00176 unsigned int in_struct;
00177 unsigned int in_array;
00178 };
00179
00180
00181
00182 struct binrpc_val{
00183 str name;
00184 int type;
00185 union{
00186 str strval;
00187 double fval;
00188 int intval;
00189 int end;
00190 }u;
00191 };
00192
00193
00194
00195
00196
00197
00198
00199 inline static int binrpc_get_int_len(int i)
00200 {
00201 int size;
00202 for (size=4; size && ((i & (0xff<<24))==0); i<<=8, size--);
00203 return size;
00204 }
00205
00206
00207
00208
00209 inline static int binrpc_add_tag(struct binrpc_pkt* pkt, int type, int end)
00210 {
00211 if (pkt->crt>=pkt->end) return E_BINRPC_OVERFLOW;
00212 *pkt->crt=(end<<7)|type;
00213 pkt->crt++;
00214 return 0;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224 inline static unsigned char* binrpc_write_int( unsigned char* p,
00225 unsigned char* end,
00226 int i, int *len)
00227 {
00228 int size;
00229
00230 for (size=4; size && ((i & (0xff<<24))==0); i<<=8, size--);
00231 *len=size;
00232 for(; (p<end) && (size); p++, size--){
00233 *p=(unsigned char)(i>>24);
00234 i<<=8;
00235 }
00236 return p;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 inline static int binrpc_init_pkt(struct binrpc_pkt *pkt,
00256 unsigned char* buf, int b_len)
00257 {
00258 if (b_len<BINRPC_MIN_RECORD_SIZE)
00259 return E_BINRPC_OVERFLOW;
00260 pkt->body=buf;
00261 pkt->end=buf+b_len;
00262 pkt->crt=pkt->body;
00263 return 0;
00264 };
00265
00266
00267
00268
00269
00270 inline static int binrpc_pkt_update_buf(struct binrpc_pkt *pkt,
00271 unsigned char* new_buf,
00272 int new_len)
00273 {
00274 if ((int)(pkt->crt-pkt->body)>new_len){
00275 return E_BINRPC_OVERFLOW;
00276 }
00277 pkt->crt=new_buf+(pkt->crt-pkt->body);
00278 pkt->body=new_buf;
00279 pkt->end=new_buf+new_len;
00280 return 0;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 inline static int binrpc_build_hdr( int type, int body_len,
00293 unsigned int cookie,
00294 unsigned char* buf, int b_len)
00295 {
00296 unsigned char* p;
00297 int len_len;
00298 int c_len;
00299
00300 len_len=binrpc_get_int_len(body_len);
00301 c_len=binrpc_get_int_len(cookie);
00302 if (len_len==0) len_len=1;
00303 if (c_len==0) c_len=1;
00304
00305 if (b_len<(BINRPC_FIXED_HDR_SIZE+len_len+c_len)){
00306 goto error_len;
00307 }
00308 p=buf;
00309 *p=(BINRPC_MAGIC << 4) | BINRPC_VERS;
00310 p++;
00311 *p=(type<<4)|((len_len-1)<<2)|(c_len-1);
00312 p++;
00313 for(;len_len>0; len_len--,p++){
00314 *p=(unsigned char)(body_len>>((len_len-1)*8));
00315 }
00316 for(;c_len>0; c_len--,p++){
00317 *p=(unsigned char)(cookie>>((c_len-1)*8));
00318 }
00319 return (int)(p-buf);
00320 error_len:
00321 return E_BINRPC_OVERFLOW;
00322 }
00323
00324
00325
00326 #define binrpc_pkt_len(pkt) ((int)((pkt)->crt-(pkt)->body))
00327
00328
00329
00330
00331 inline static int binrpc_hdr_change_len(unsigned char* hdr, int hdr_len,
00332 int new_len)
00333 {
00334 int len_len;
00335
00336 binrpc_write_int(&hdr[BINRPC_TLEN_OFFSET], hdr+hdr_len, new_len, &len_len);
00337 return 0;
00338 }
00339
00340
00341
00342
00343 inline static int binrpc_add_int_type(struct binrpc_pkt* pkt, int i, int type)
00344 {
00345
00346 unsigned char* p;
00347 int size;
00348
00349 p=binrpc_write_int(pkt->crt+1, pkt->end, i, &size);
00350 if ((pkt->crt>=pkt->end) || ((int)(p-pkt->crt-1)!=size))
00351 goto error_len;
00352 *(pkt->crt)=(size<<4) | type;
00353 pkt->crt=p;
00354 return 0;
00355 error_len:
00356 return E_BINRPC_OVERFLOW;
00357 }
00358
00359
00360
00361
00362
00363 #define binrpc_add_double_type(pkt, f, type)\
00364 binrpc_add_int_type((pkt), (int)((f)*1000), (type))
00365
00366
00367
00368
00369
00370
00371 inline static int binrpc_add_skip(struct binrpc_pkt* pkt, int bytes)
00372 {
00373
00374 if ((pkt->crt+bytes)>=pkt->end)
00375 return E_BINRPC_OVERFLOW;
00376 pkt->crt+=bytes;
00377 return 0;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 inline static int binrpc_add_str_mark(struct binrpc_pkt* pkt, int type,
00393 int l)
00394 {
00395 int size;
00396 unsigned char* p;
00397
00398 if (pkt->crt>=pkt->end) goto error_len;
00399 if (l<8){
00400 size=l;
00401 p=pkt->crt+1;
00402 }else{
00403 p=binrpc_write_int(pkt->crt+1, pkt->end, l, &size);
00404 if (((int)(p-pkt->crt-1)!=size))
00405 goto error_len;
00406 size|=8;
00407 }
00408 *(pkt->crt)=(size)<<4|type;
00409 pkt->crt=p;
00410 return 0;
00411 error_len:
00412 return E_BINRPC_OVERFLOW;
00413 }
00414
00415
00416
00417 inline static int binrpc_add_str_type(struct binrpc_pkt* pkt, char* s, int len,
00418 int type)
00419 {
00420 int size;
00421 int l;
00422 int zero_term;
00423 unsigned char* p;
00424
00425 zero_term=((type==BINRPC_T_STR)||(type==BINRPC_T_AVP));
00426 l=len+zero_term;
00427 if (l<8){
00428 size=l;
00429 p=pkt->crt+1;
00430 }else{
00431 p=binrpc_write_int(pkt->crt+1, pkt->end, l, &size);
00432
00433
00434 size|=8;
00435 }
00436 if ((p+l)>pkt->end) goto error_len;
00437 *(pkt->crt)=(size)<<4|type;
00438 memcpy(p, s, len);
00439 if (zero_term) p[len]=0;
00440 pkt->crt=p+l;
00441 return 0;
00442 error_len:
00443 return E_BINRPC_OVERFLOW;
00444 }
00445
00446
00447
00448
00449 inline static int binrpc_addavp(struct binrpc_pkt* pkt, struct binrpc_val* avp)
00450 {
00451 int ret;
00452 unsigned char* bak;
00453
00454 bak=pkt->crt;
00455 ret=binrpc_add_str_type(pkt, avp->name.s, avp->name.len, BINRPC_T_AVP);
00456 if (ret<0) return ret;
00457 switch (avp->type){
00458 case BINRPC_T_INT:
00459 ret=binrpc_add_int_type(pkt, avp->u.intval, avp->type);
00460 break;
00461 case BINRPC_T_STR:
00462 case BINRPC_T_BYTES:
00463 ret=binrpc_add_str_type(pkt, avp->u.strval.s,
00464 avp->u.strval.len,
00465 avp->type);
00466 break;
00467 case BINRPC_T_STRUCT:
00468 case BINRPC_T_ARRAY:
00469 ret=binrpc_add_tag(pkt, avp->type, 0);
00470 break;
00471 case BINRPC_T_DOUBLE:
00472 ret=binrpc_add_double_type(pkt, avp->u.fval, avp->type);
00473 break;
00474 default:
00475 ret=E_BINRPC_BUG;
00476 }
00477 if (ret<0)
00478 pkt->crt=bak;
00479 return ret;
00480 }
00481
00482
00483
00484 #define binrpc_addint(pkt, i) binrpc_add_int_type((pkt), (i), BINRPC_T_INT)
00485
00486 #define binrpc_adddouble(pkt, f) \
00487 binrpc_add_double_type((pkt), (f), BINRPC_T_DOUBLE)
00488
00489 #define binrpc_addstr(pkt, s, len) \
00490 binrpc_add_str_type((pkt), (s), (len), BINRPC_T_STR)
00491
00492 #define binrpc_addbytes(pkt, s, len) \
00493 binrpc_add_str_type((pkt), (s), (len), BINRPC_T_BYTES)
00494
00495
00496
00497
00498
00499 #define binrpc_start_struct(pkt) binrpc_add_tag((pkt), BINRPC_T_STRUCT, 0)
00500
00501 #define binrpc_end_struct(pkt) binrpc_add_tag((pkt), BINRPC_T_STRUCT, 1)
00502
00503 #define binrpc_start_array(pkt) binrpc_add_tag((pkt), BINRPC_T_ARRAY, 0)
00504
00505 #define binrpc_end_array(pkt) binrpc_add_tag((pkt), BINRPC_T_ARRAY, 1)
00506
00507
00508 static inline int binrpc_addfault( struct binrpc_pkt* pkt,
00509 int code,
00510 char* s, int len)
00511 {
00512 int ret;
00513 unsigned char* bak;
00514
00515 bak=pkt->crt;
00516 if ((ret=binrpc_addint(pkt, code))<0)
00517 return ret;
00518 ret=binrpc_addstr(pkt, s, len);
00519 if (ret<0)
00520 pkt->crt=bak;
00521 return ret;
00522 }
00523
00524
00525
00526
00527 static inline unsigned char* binrpc_read_int( int* i,
00528 int len,
00529 unsigned char* s,
00530 unsigned char* end,
00531 int *err
00532 )
00533 {
00534 unsigned char* start;
00535
00536 start=s;
00537 *i=0;
00538 *err=0;
00539 for(;len>0; len--, s++){
00540 if (s>=end){
00541 *err=E_BINRPC_MORE_DATA;
00542 return start;
00543 }
00544 *i<<=8;
00545 *i|=*s;
00546 };
00547 return s;
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 static inline unsigned char* binrpc_parse_init( struct binrpc_parse_ctx* ctx,
00560 unsigned char* buf,
00561 int len,
00562 int *err
00563 )
00564 {
00565 int len_len, c_len;
00566 unsigned char *p;
00567
00568 *err=0;
00569 ctx->tlen=0;
00570 ctx->cookie=0;
00571 if (len<BINRPC_MIN_PKT_SIZE){
00572 *err=E_BINRPC_MORE_DATA;
00573 goto error;
00574 }
00575 if (buf[0]!=((BINRPC_MAGIC<<4)|BINRPC_VERS)){
00576 *err=E_BINRPC_BADPKT;
00577 goto error;
00578 }
00579 ctx->type=buf[1]>>4;
00580
00581 switch(ctx->type){
00582 case BINRPC_REQ:
00583 case BINRPC_REPL:
00584 case BINRPC_FAULT:
00585 break;
00586 default:
00587 *err=E_BINRPC_BADPKT;
00588 goto error;
00589 }
00590 len_len=((buf[1]>>2) & 3) + 1;
00591 c_len=(buf[1]&3) + 1;
00592 if ((BINRPC_TLEN_OFFSET+len_len+c_len)>len){
00593 *err=E_BINRPC_MORE_DATA;
00594 goto error;
00595 }
00596 p=binrpc_read_int((int*)&ctx->tlen, len_len, &buf[BINRPC_TLEN_OFFSET],
00597 &buf[len], err);
00598
00599
00600
00601
00602
00603 p=binrpc_read_int((int*)&ctx->cookie, c_len, p, &buf[len], err);
00604 ctx->offset=0;
00605 ctx->flags|=BINRPC_F_INIT;
00606 return p;
00607 error:
00608 return buf;
00609 }
00610
00611
00612
00613
00614
00615
00616 inline static int binrpc_bytes_needed(struct binrpc_parse_ctx *ctx)
00617 {
00618 if (ctx->flags & BINRPC_F_INIT)
00619 return ctx->tlen-ctx->offset;
00620 return E_BINRPC_NOTINIT;
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630 inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
00631 unsigned char* buf,
00632 unsigned char* end,
00633 struct binrpc_val* v,
00634 int* err
00635 )
00636 {
00637 int type;
00638 int len;
00639 int end_tag;
00640 int tmp;
00641 unsigned char* p;
00642 int i;
00643
00644 p=buf;
00645 end_tag=0;
00646 *err=0;
00647 if (!(ctx->flags & BINRPC_F_INIT)){
00648 *err=E_BINRPC_NOTINIT;
00649 goto error;
00650 }
00651 if (ctx->offset>=ctx->tlen){
00652 *err=E_BINRPC_EOP;
00653 goto error;
00654 }
00655 if (p>=end){
00656 *err=E_BINRPC_MORE_DATA;
00657 goto error;
00658 }
00659
00660 type=*p & 0xf;
00661 len=*p>>4;
00662 p++;
00663 if (len & 8){
00664 end_tag=1;
00665
00666 p=binrpc_read_int(&len, len&7, p, end, err);
00667 if (*err<0)
00668 goto error;
00669 }
00670 if ((p+len)>end){
00671 *err=E_BINRPC_MORE_DATA;
00672 goto error;
00673 }
00674 if ((v->type!=type) && (v->type !=BINRPC_T_ALL)){
00675 goto error_type;
00676 }
00677 v->type=type;
00678 if (ctx->in_struct){
00679 switch(type){
00680 case BINRPC_T_STRUCT:
00681 if (end_tag){
00682 ctx->in_struct--;
00683 v->u.end=1;
00684 }else{
00685 goto error_record;
00686 }
00687 break;
00688 case BINRPC_T_AVP:
00689
00690 v->name.s=(char*)p;
00691 v->name.len=(len-1);
00692 p+=len;
00693 if (p>=end){
00694 *err=E_BINRPC_MORE_DATA;
00695 goto error;
00696 }
00697
00698 type=*p & 0xf;
00699 if ((type!=BINRPC_T_AVP) && (type!=BINRPC_T_ARRAY)){
00700 tmp=ctx->in_struct;
00701 ctx->in_struct=0;
00702 v->type=type;
00703 p=binrpc_read_record(ctx, p, end, v, err);
00704 if (err<0){
00705 ctx->in_struct=tmp;
00706 goto error;
00707 }else{
00708 ctx->in_struct+=tmp;
00709
00710 goto no_offs_update;
00711 }
00712 }else{
00713 goto error_record;
00714 }
00715 break;
00716 default:
00717 goto error_record;
00718 }
00719 }else{
00720 switch(type){
00721 case BINRPC_T_INT:
00722 p=binrpc_read_int(&v->u.intval, len, p, end, err);
00723 break;
00724 case BINRPC_T_STR:
00725 v->u.strval.s=(char*)p;
00726 v->u.strval.len=(len-1);
00727 p+=len;
00728 break;
00729 case BINRPC_T_BYTES:
00730 v->u.strval.s=(char*)p;
00731 v->u.strval.len=len;
00732 p+=len;
00733 case BINRPC_T_STRUCT:
00734 if (end_tag)
00735 goto error_record;
00736 v->u.end=0;
00737 ctx->in_struct++;
00738 break;
00739 case BINRPC_T_ARRAY:
00740 if (end_tag){
00741 if (ctx->in_array>0){
00742 ctx->in_array--;
00743 v->u.end=1;
00744 }else
00745 goto error_record;
00746 }else{
00747 ctx->in_array++;
00748 v->u.end=0;
00749 }
00750 break;
00751 case BINRPC_T_DOUBLE:
00752
00753 p=binrpc_read_int(&i, len, p, end, err);
00754 v->u.fval=((double)i)/1000;
00755 break;
00756 default:
00757 goto error_type;
00758 }
00759 }
00760 ctx->offset+=(int)(p-buf);
00761 no_offs_update:
00762 return p;
00763 error_type:
00764 *err=E_BINRPC_TYPE;
00765 return buf;
00766 error_record:
00767 *err=E_BINRPC_RECORD;
00768 error:
00769 return buf;
00770 }
00771
00772
00773
00774
00775
00776
00777
00778 inline static unsigned char* binrpc_read_struct(struct binrpc_parse_ctx* ctx,
00779 unsigned char* buf,
00780 unsigned char* end,
00781 struct binrpc_val* v,
00782 int* err
00783 )
00784 {
00785
00786 int type;
00787 int len;
00788 int end_tag;
00789 unsigned char* p;
00790 int in_struct;
00791
00792 *err=0;
00793 p=buf;
00794 end_tag=0;
00795 if (!(ctx->flags & BINRPC_F_INIT)){
00796 *err=E_BINRPC_NOTINIT;
00797 goto error;
00798 }
00799 if (ctx->offset>=ctx->tlen){
00800 *err=E_BINRPC_EOP;
00801 goto error;
00802 }
00803 if (p>=end){
00804 *err=E_BINRPC_MORE_DATA;
00805 goto error;
00806 }
00807
00808 type=*p & 0xf;
00809 len=*p>>4;
00810 p++;
00811 if (len & 8){
00812 end_tag=1;
00813
00814 p=binrpc_read_int(&len, len&7, p, end, err);
00815 if (*err<0)
00816 goto error;
00817 }
00818 if ((p+len)>=end){
00819 *err=E_BINRPC_MORE_DATA;
00820 goto error;
00821 }
00822 if (type!=BINRPC_T_STRUCT){
00823 goto error_type;
00824 }
00825 if (end_tag){
00826 goto error_record;
00827 }
00828 p+=len;
00829 in_struct=1;
00830 v->type=type;
00831 v->u.strval.s=(char*)p;
00832 while(in_struct){
00833
00834 type=*p & 0xf;
00835 len=*p>>4;
00836 p++;
00837 if (len & 8){
00838 end_tag=1;
00839
00840 p=binrpc_read_int(&len, len&7, p, end, err);
00841 if (*err<0)
00842 goto error;
00843 }
00844 if ((type==BINRPC_T_STRUCT) && end_tag){
00845 in_struct--;
00846 if (in_struct<0)
00847 goto error_record;
00848 continue;
00849 }else if (type!=BINRPC_T_AVP){
00850 goto error_record;
00851 }
00852
00853 p+=len;
00854 if (p>=end){
00855 *err=E_BINRPC_MORE_DATA;
00856 goto error;
00857 }
00858
00859 type=*p & 0xf;
00860 len=*p>>4;
00861 p++;
00862 if (len & 8){
00863 end_tag=1;
00864
00865 p=binrpc_read_int(&len, len&7, p, end, err);
00866 if (*err<0)
00867 goto error;
00868 }
00869 if (type==BINRPC_T_STRUCT){
00870 if (end_tag)
00871 goto error_record;
00872 in_struct++;
00873 };
00874 p+=len;
00875 if (p>=end){
00876 *err=E_BINRPC_MORE_DATA;
00877 goto error;
00878 }
00879 }
00880 ;
00881 v->u.strval.len=(int)(p-(unsigned char*)v->u.strval.s)-1;
00882 return p;
00883
00884 error_type:
00885 *err=E_BINRPC_RECORD;
00886 return buf;
00887 error_record:
00888 *err=E_BINRPC_TYPE;
00889 error:
00890 return buf;
00891 }
00892
00893
00894
00895
00896 const char* binrpc_error(int err);
00897 #endif