+++ /dev/null
-#include<bencode.h>
-
-ssize_t bdecode_int(const uint8_t *buf, size_t buf_len, long long int *output) {
- if(NULL==buf) { return -1; }
- if(buf_len<=0) { return -1; }
- if(NULL==output) { return -1; }
-
- const uint8_t *p = NULL;
- for(size_t i=0;i<buf_len;i++) {
- // 0 padded integers are invalid
- if((1==i)&&(buf[i]=='0')&&(buf_len>3)) { return -1; }
- if(buf[i]=='e') {
- p = &(buf[i]);
- }
- }
-
- if(NULL==p) { return -1; }
-
- ssize_t len = p - (buf+1);
- uint8_t *num_string = (uint8_t*) strndup((const char*)&(buf[1]),len);
- *output = atoll((char *)num_string);
- free(num_string);
-
- len += 2;
-
- return len;
-}
-
-ssize_t bdecode_string(const uint8_t *buf, size_t buf_len, uint8_t *output, size_t output_size) {
- if(NULL==buf) { return -1; }
- if(buf_len<=0) { return -1; }
- if(NULL==output) { return -1; }
-
- const uint8_t *p = NULL;
- for(size_t i=0;i<buf_len;i++) {
- if(buf[i]==':') {
- p = &(buf[i]);
- break;
- }
- }
-
- if(NULL==p) { return -1; }
- uint8_t *num_string = (uint8_t*) strndup((const char*)buf,p-buf);
- int str_len = atoi((char *)num_string);
- ssize_t len = str_len;
- free(num_string);
-
- if((str_len<=0)||(len>output_size)) { return -1; }
-
- p++;
- memcpy(output,p,str_len);
-
- return len;
-}
-
-enum bencode_type bdecode_type(const uint8_t *buf, size_t len) {
- switch(buf[0]) {
- case 'i':
- return BENCODE_INTEGER;
- case 'l':
- return BENCODE_LIST;
- case 'd':
- return BENCODE_DICTIONARY;
- default:
- return BENCODE_STRING;
- }
-}
+++ /dev/null
-#include<bencode.h>
-
-ssize_t bencode_dict_end(uint8_t *output, size_t output_size) {
- if(NULL==output) { return -1; }
- if(output_size<1) { return -1; }
-
- output[0] = 'e';
-
- return 1;
-}
-
-ssize_t bencode_dict_start(uint8_t *output, size_t output_size) {
- if(NULL==output) { return -1; }
- if(output_size<1) { return -1; }
-
- output[0] = 'd';
-
- return 1;
-}
-
-ssize_t bencode_int(long long int to_encode, uint8_t *output, size_t output_size) {
- size_t i;
- int ret;
-
- if(NULL==output) { return -1; }
-
- i = bencode_size_int(to_encode);
- i += 2;
-
- if((ret = snprintf((char*)output,output_size,"i%llue",to_encode))<0) { return -1; }
- if(ret!=i) { return -1; }
-
- return i;
-}
-
-ssize_t bencode_list_end(uint8_t *output, size_t output_size) {
- if(NULL==output) { return -1; }
- if(output_size<=1) { return -1; }
-
- output[0] = 'e';
-
- return 1;
-}
-
-ssize_t bencode_list_start(uint8_t *output, size_t output_size) {
- if(NULL==output) { return -1; }
- if(output_size<=1) { return -1; }
-
- output[0] = 'l';
-
- return 1;
-}
-
-ssize_t bencode_size(size_t len, uint8_t *output, size_t output_size) {
- size_t i;
-
- if(len>INTMAX_MAX) { return -1; }
-
- i = bencode_size_int(len);
- i++; // account for ':'
- if(i>output_size) { return -1; }
-
- // snprintf requires space for '\0' otherwise will truncate
- if(snprintf((char*)output,i+1,"%lu:",len)!=i) { return -1; }
-
- return i;
-}
-
-size_t bencode_size_int(intmax_t i) {
- size_t j = (i<0)?1:0;
-
- i = imaxabs(i);
- if(0==i) { return 1; }
-
- while(i>0) {
- i /= 10;
- j++;
- }
- return j;
-}
-
-ssize_t bencode_string(const uint8_t *str, size_t len, uint8_t *output, size_t output_size) {
- size_t i;
-
- if(NULL==str) { return -1; }
- if(NULL==output) { return -1; }
-
- if((i = bencode_size(len,output,output_size))<0) { return -1; }
-
- if(i+len>output_size) { return -1; }
-
- memcpy(&(output[i]),str,len);
-
- return i+len;
-}
+++ /dev/null
-#include<test_utils.h>
-
-#include<bencode.h>
-
-int main();
-static void bdecode_integer_basic_test();
-static void bdecode_string_basic_test();
-static void bdecode_type_basic_test();
-static void bencode_dict_basic_test();
-static void bencode_list_basic_test();
-static void bencode_size_basic_test();
-static void bencode_size_int_basic_test();
-static void bencode_string_basic_test();
-
-int main() {
- setup_env();
-
- bdecode_integer_basic_test();
- bdecode_string_basic_test();
- bdecode_type_basic_test();
- bencode_dict_basic_test();
- bencode_list_basic_test();
- bencode_size_basic_test();
- bencode_size_int_basic_test();
- bencode_string_basic_test();
-
- clean_env();
-
- return EXIT_SUCCESS;
-}
-
-static void bdecode_integer_basic_test() {
- uint8_t str1[] = "i10e";
- uint8_t str2[] = "i0e";
- uint8_t str3[] = "i0023423e";
- uint8_t str4[] = "i10928390128301e";
- long long int i;
-
- assert(bdecode_int(NULL,sizeof(str1)-1,&i)==-1);
- assert(bdecode_int(str1,0,&i)==-1);
- assert(bdecode_int(str1,sizeof(str1)-1,NULL)==-1);
- assert(bdecode_int(str1,sizeof(str1)-1,&i)==4);
- assert(i==10);
-
- assert(bdecode_int(str2,sizeof(str2)-1,&i)==3);
- assert(i==0);
-
- assert(bdecode_int(str3,sizeof(str3)-1,&i)==-1);
-
- assert(bdecode_int(str4,sizeof(str4)-1,&i)==16);
- assert(i==10928390128301);
-}
-
-static void bdecode_string_basic_test() {
- uint8_t buf[1024];
- uint8_t str1[] = "4:spam";
-
- assert(bdecode_string(NULL,sizeof(str1)-1,buf,1024)==-1);
- assert(bdecode_string(str1,0,buf,1024)==-1);
- assert(bdecode_string(str1,sizeof(str1)-1,NULL,1024)==-1);
- assert(bdecode_string(str1,sizeof(str1)-1,buf,0)==-1);
- assert(bdecode_string(str1,sizeof(str1)-1,buf,3)==-1);
- assert(bdecode_string(str1,sizeof(str1)-1,buf,4)==4);
- assert(bdecode_string(str1,sizeof(str1)-1,buf,1024)==4);
- assert(memcmp(buf,"spam",4)==0);
-}
-
-static void bdecode_type_basic_test() {
- uint8_t str1[] = "4:spam";
- uint8_t str2[] = "i12093e";
- uint8_t str3[] = "l4:spam4:eggse";
- uint8_t str4[] = "d3:cow3:moo4:spam4:eggse";
-
- assert(BENCODE_STRING==bdecode_type(str1,sizeof(str1)-1));
- assert(BENCODE_INTEGER==bdecode_type(str2,sizeof(str2)-1));
- assert(BENCODE_LIST==bdecode_type(str3,sizeof(str3)-1));
- assert(BENCODE_DICTIONARY==bdecode_type(str4,sizeof(str4)-1));
-}
-
-static void bencode_dict_basic_test() {
- uint8_t buf[1024];
- uint8_t *p;
-
- memset(buf,0,1024);
-
- p = buf;
- assert(bencode_dict_start(NULL,1024)==-1);
- assert(bencode_dict_start(p,0)==-1);
- assert(bencode_dict_start(p,1024)==1);
- p++;
-
- uint8_t str1[] = "cow";
- assert(bencode_string(str1,3,p,1023)==5);
- p += 5;
-
- uint8_t str2[] = "moo";
- assert(bencode_string(str2,3,p,1018)==5);
- p += 5;
-
- uint8_t str3[] = "spam";
- assert(bencode_string(str3,4,p,1013)==6);
- p += 6;
-
- uint8_t str4[] = "eggs";
- assert(bencode_string(str4,4,p,1007)==6);
- p += 6;
-
- assert(bencode_dict_end(NULL,1001)==-1);
- assert(bencode_dict_end(p,0)==-1);
- assert(bencode_dict_end(p,1001)==1);
-
- assert(memcmp(buf,"d3:cow3:moo4:spam4:eggse",24)==0);
-}
-
-static void bencode_list_basic_test() {
- uint8_t buf[1024];
- uint8_t *p;
-
- memset(buf,0,1024);
-
- p = buf;
- assert(bencode_list_start(NULL,1024)==-1);
- assert(bencode_list_start(p,0)==-1);
- assert(bencode_list_start(p,1024)==1);
- p++;
-
- uint8_t str1[] = "spam";
- assert(bencode_string(str1,4,p,1023)==6);
- p += 6;
-
- uint8_t str2[] = "eggs";
- assert(bencode_string(str2,4,p,1017)==6);
- p += 6;
-
- assert(bencode_list_end(NULL,1011)==-1);
- assert(bencode_list_end(p,0)==-1);
- assert(bencode_list_end(p,1011)==1);
-
- assert(memcmp(buf,"l4:spam4:eggse",14)==0);
-}
-
-static void bencode_size_basic_test() {
- uint8_t buf[1024];
-
- assert(bencode_size(0,buf,1)==-1);
- assert(bencode_size(0,buf,2)==2);
-
- assert(bencode_size(1234567890,buf,1024)==11);
-
- assert(bencode_size(SIZE_MAX,buf,1024)==-1);
- assert(bencode_size(INTMAX_MAX,buf,1024)>0);
-}
-
-static void bencode_size_int_basic_test() {
- assert(bencode_size_int(0)==1);
- assert(bencode_size_int(-1)==2);
- assert(bencode_size_int(109)==3);
- assert(bencode_size_int(23984723984)==11);
- assert(bencode_size_int(922337203685477580)==18);
- assert(bencode_size_int(INTMAX_MIN)>0);
- assert(bencode_size_int(INTMAX_MAX)>0);
-}
-
-static void bencode_string_basic_test() {
- uint8_t buf[1024];
-
- memset(buf,0,1024);
-
- uint8_t str1[] = "testlkajslfkdjasdfl test string";
- assert(bencode_string(NULL,31,buf,1024)==-1);
- assert(bencode_string(str1,31,NULL,1024)==-1);
- assert(bencode_string(str1,31,buf,0)==-1);
-
- assert(bencode_string(str1,0,buf,1024)==2);
- assert(memcmp("0:",buf,2)==0);
-
- assert(bencode_string(str1,31,buf,1024)==34);
- assert(memcmp("31:testlkajslfkdjasdfl test string",buf,34)==0);
-}