int binrpc_parse_error_response( struct binrpc_response_handle *resp_handle, int *err_no, char **err) { struct binrpc_val val; unsigned char *p, *end; int ret; resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0; p = resp_handle->reply_buf; end = p+resp_handle->in_pkt.tlen; val.type=BINRPC_T_INT; val.name.s=0; val.name.len=0; p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret); if (ret < 0) { snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "parse_error_response: error when parsing reply (code): %s", binrpc_error(ret) ); return FATAL_ERROR; } *err_no = val.u.intval; val.type=BINRPC_T_STR; p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret); if (ret < 0) { snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "parse_error_response: error when parsing reply (str): %s", binrpc_error(ret) ); return FATAL_ERROR; } *err = val.u.strval.s; /* it's null terminated */ return 0; }
static int print_body(struct binrpc_parse_ctx* in_pkt, unsigned char* body, int size, char* fmt) { unsigned char* p; unsigned char* end; struct binrpc_val val; int ret; int rec; char *f; char* s; int f_size; int fmt_has_values; p=body; end=p+size; rec=0; f=fmt; fmt_has_values=0; /* read body */ while(p<end){ if (f){ do{ if (*f==0) f=fmt; /* reset */ s=f; f=parse_fmt(f, &val.type, &f_size); printf("%.*s", f_size, s); if (val.type!=-1){ fmt_has_values=1; goto read_value; } }while(*f || fmt_has_values); val.type=BINRPC_T_ALL; }else{ val.type=BINRPC_T_ALL; } read_value: val.name.s=0; val.name.len=0; p=binrpc_read_record(in_pkt, p, end, &val, 1, &ret); if (ret<0){ if (fmt) putchar('\n'); /*if (ret==E_BINRPC_MORE_DATA) goto error_read_again;*/ if (ret==E_BINRPC_EOP){ printf("end of message detected\n"); break; } fprintf(stderr, "ERROR:: while parsing the record %d," " @%d: %02x : %s\n", rec, in_pkt->offset, *p, binrpc_error(ret)); goto error; } rec++; if (fmt){ print_binrpc_val(&val, 0); }else{ print_binrpc_val(&val, in_pkt->in_struct+in_pkt->in_array); putchar('\n'); } } if (fmt && *f){ /* print the rest, with empty values */ while(*f){ s=f; f=parse_fmt(f, &val.type, &f_size); printf("%.*s", f_size, s); } } return 0; error: return -1; /*error_read_again: fprintf(stderr, "ERROR: more data needed\n"); return -2; */ }
/* parse the body into a malloc allocated, binrpc_val array */ static struct binrpc_val* parse_reply_body(int* records, struct binrpc_parse_ctx* in_pkt, unsigned char* body, int size) { struct binrpc_val* a; struct binrpc_val* t; unsigned char* p; unsigned char* end; struct binrpc_val val; int ret; int rec; rec=0; if (*records==0){ *records=100; /* start with a reasonable size */ }; a=malloc(*records*sizeof(struct binrpc_val)); if (a==0) goto error_mem; p=body; end=p+size; /* read body */ while(p<end){ val.type=BINRPC_T_ALL; val.name.s=0; val.name.len=0; p=binrpc_read_record(in_pkt, p, end, &val, 1, &ret); if (ret<0){ if (ret==E_BINRPC_EOP){ printf("end of message detected\n"); break; } fprintf(stderr, "ERROR: while parsing the record %d," " @%d: %02x : %s\n", rec, in_pkt->offset, *p, binrpc_error(ret)); goto error; } if (rec>=*records){ t=realloc(a, *records*sizeof(struct binrpc_val)*2); if (t==0) goto error_mem; a=t; *records*=2; } a[rec]=val; if (val.name.s){ if ((a[rec].name.s=malloc(val.name.len+1))==0) goto error_mem; memcpy(a[rec].name.s, val.name.s, val.name.len); a[rec].name.s[val.name.len+1]=0; /* 0-term */ } if (val.u.strval.s){ if (val.type==BINRPC_T_STR){ if ((a[rec].u.strval.s=malloc(val.u.strval.len+1))==0) goto error_mem; memcpy(a[rec].u.strval.s, val.u.strval.s, val.u.strval.len); a[rec].u.strval.s[val.u.strval.len]=0; /* 0-term */ }else if (val.type==BINRPC_T_BYTES){ if ((a[rec].u.strval.s=malloc(val.u.strval.len))==0) goto error_mem; memcpy(a[rec].u.strval.s, val.u.strval.s, val.u.strval.len); } } rec++; } if (rec && (rec<*records)){ a=realloc(a, rec*sizeof(struct binrpc_val)); } *records=rec; return a; error_mem: fprintf(stderr, "ERROR: parse_reply_body: out of memory\n"); error: if (a){ free_rpc_array(a, rec); } *records=0; return 0; }
int binrpc_parse_response(struct binrpc_val** vals, int* val_count, struct binrpc_response_handle *resp_handle) { struct binrpc_val val; unsigned char *p, *end; int ret, i; resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0; if (*val_count==0){ *val_count=VAL_ARRAY_CHUNK; /* start with a reasonable size */ } *vals = (struct binrpc_val*) binrpc_malloc(*val_count*sizeof(**vals)); if (*vals == 0) goto error_mem; p = resp_handle->reply_buf; end = p + resp_handle->in_pkt.tlen; i=0; /* read body */ while(p < end){ val.type = BINRPC_T_ALL; val.name.s = 0; val.name.len = 0; p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret); if (ret<0){ if (ret==E_BINRPC_EOP){ break; } snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "ERROR while parsing the record %d," " @%d: %02x : %s", i, resp_handle->in_pkt.offset, *p, binrpc_error(ret)); goto error; } if (i >= *val_count){ struct binrpc_val *t; t= (struct binrpc_val*) binrpc_realloc(*vals, (VAL_ARRAY_CHUNK+(*val_count))*sizeof(**vals)); if (t==0) goto error_mem; *vals = t; *val_count += VAL_ARRAY_CHUNK; } (*vals)[i] = val; i++; } if (i == 0) { binrpc_free(*vals); *vals = NULL; } else if (i<*val_count){ /* do not try to save memory because it causes fragmentation when used ser mem utils and "regualar" memory leak struct binrpc_val *t; t = (struct binrpc_val*) binrpc_realloc(*vals, i*sizeof(**vals)); if (t) *vals = t; */ } *val_count = i; return 0; error_mem: snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "parse_response: out of memory"); error: if (*vals){ binrpc_free(*vals); *vals = NULL; } *val_count=0; return FATAL_ERROR; }
int binrpc_print_response(struct binrpc_response_handle *resp_handle, char* fmt) { unsigned char* p; unsigned char* end; struct binrpc_val val; int ret; int rec; char *f; char* s; int f_size; int fmt_has_values; if (!resp_handle) { goto error; } resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0; p=resp_handle->reply_buf; end=p+resp_handle->in_pkt.tlen; rec=0; f=fmt; fmt_has_values=0; /* read body */ while(p<end){ if (f){ do{ if (*f==0) f=fmt; /* reset */ s=f; f=parse_fmt(f, &val.type, &f_size); printf("%.*s", f_size, s); if (val.type!=-1){ fmt_has_values=1; goto read_value; } }while(*f || fmt_has_values); val.type=BINRPC_T_ALL; }else{ val.type=BINRPC_T_ALL; } read_value: val.name.s=0; val.name.len=0; p=binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret); if (ret<0){ if (fmt) putchar('\n'); /*if (ret==E_BINRPC_MORE_DATA) goto error_read_again;*/ if (ret==E_BINRPC_EOP){ printf("end of message detected\n"); break; } snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "error while parsing the record %d," " @%d: %02x : %s", rec, resp_handle->in_pkt.offset, *p, binrpc_error(ret)); goto error; } rec++; if (fmt){ print_binrpc_val(&val, 0); }else{ print_binrpc_val(&val, resp_handle->in_pkt.in_struct+resp_handle->in_pkt.in_array); putchar('\n'); } } if (fmt && *f){ /* print the rest, with empty values */ while(*f){ s=f; f=parse_fmt(f, &val.type, &f_size); printf("%.*s", f_size, s); } } return 0; error: return FATAL_ERROR; /*error_read_again: snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "ERROR: more data needed"); return -2; */ }
int binrpc_response_to_text( struct binrpc_response_handle *resp_handle, unsigned char** txt_rsp, int* txt_rsp_len, char delimiter) { unsigned char* p; unsigned char* end; struct binrpc_val val; int ret; int rec; int pos; pos = 0; if (!resp_handle) { goto error; } resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0; p=resp_handle->reply_buf; end=p+resp_handle->in_pkt.tlen; rec=0; if (*txt_rsp == NULL) { *txt_rsp_len = 0; if (realloc_buf(txt_rsp, txt_rsp_len, 0) != 0) { goto error; } } /* read body */ while(p<end){ val.type=BINRPC_T_ALL; val.name.s=0; val.name.len=0; p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret); if (ret < 0) { if (ret == E_BINRPC_EOP) { printf("end of message detected\n"); break; } snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1, "ERROR while parsing the record %d," " @%d: %02x : %s", rec, resp_handle->in_pkt.offset, *p, binrpc_error(ret)); goto error; } rec++; if (val2buffer(&val, txt_rsp, txt_rsp_len, &pos) != 0) { goto error; } if(char2buffer(txt_rsp, txt_rsp_len, &pos, delimiter) != 0) { goto error; } } /* rewrite last char - we don't need delimiter there */ (*txt_rsp)[pos-1] = '\0'; /* if(char2buffer(txt_rsp, txt_rsp_len, &pos, '\0') != 0) { goto error; } */ return 0; error: return FATAL_ERROR; }