/* Serval Mesh Copyright (C) 2013 Alexandra Sclapari Copyright (C) 2013 Paul Gardner-Stephen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "serval.h" #include "rhizome.h" void hex_dump(unsigned char *data, int size) { int i; // index in data... int j; // index in line... char temp[8]; char buffer[128]; char *ascii; memset(buffer, 0, 128); printf("---------> Dump <--------- (%d bytes from %p)\n", size, data); // Printing the ruler... printf(" +0 +4 +8 +c 0 4 8 c \n"); // Hex portion of the line is 8 (the padding) + 3 * 16 = 52 chars long // We add another four bytes padding and place the ASCII version... ascii = buffer + 58; memset(buffer, ' ', 58 + 16); buffer[58 + 16] = '\n'; buffer[58 + 17] = '\0'; buffer[0] = '+'; buffer[1] = '0'; buffer[2] = '0'; buffer[3] = '0'; buffer[4] = '0'; for (i = 0, j = 0; i < size; i++, j++) { if (j == 16) { printf("%s", buffer); memset(buffer, ' ', 58 + 16); sprintf(temp, "+%04x", i); memcpy(buffer, temp, 5); j = 0; } sprintf(temp, "%02x", 0xff & data[i]); memcpy(buffer + 8 + (j * 3), temp, 2); if ((data[i] > 31) && (data[i] < 127)) ascii[j] = data[i]; else ascii[j] = '.'; } if (j != 0) printf("%s", buffer); } int encode_length_forwards(unsigned char *buffer,int *offset, unsigned int length) { if (length<0xff) { buffer[(*offset)++]=length; return 0; } buffer[(*offset)++]=0xff; int i; for(i=0;i<16;i+=8) buffer[(*offset)++]=(length>>i)&0xff; return 0; } int encode_length_backwards(unsigned char *buffer,int *offset, unsigned int length) { if (length<0xff) { buffer[(*offset)++]=length; return 0; } int i; for(i=0;i<16;i+=8) buffer[(*offset)++]=(length>>i)&0xff; buffer[(*offset)++]=0xff; return 0; } int decode_length_forwards(unsigned char *buffer,int *offset, unsigned int buffer_length, unsigned int *length) { *length=0; if (*offset>=buffer_length) return -1; switch(buffer[*offset]) { case 0xff: (*offset)++; if (*offset>=buffer_length) return -1; int i; for(i=0;i<16;i+=8) { (*length)|=buffer[(*offset)++]<=buffer_length) return -1; } return 0; default: *length=buffer[(*offset)++]; if (*offset>=buffer_length) return -1; return 0; } } int decode_length_backwards(unsigned char *buffer,int offset, unsigned int *length) { // it is assumed that offset points to the first byte after the end // of the length field. if (offset<=0) return -1; offset--; *length=0; switch(buffer[offset]) { case 0xff: offset-=2; int i; for(i=0;i<16;i+=8) (*length)|=buffer[offset++]<>i)&0xff; } return 0; } int unpack_int(unsigned char *buffer,int *offset,int32_t *v) { int i; *v=0; for(i=0;i<32;i+=8) (*v)|=(((uint32_t)buffer[(*offset)++])<>i)&0xff; } return 0; } int unpack_time(unsigned char *buffer,int *offset,uint64_t *time) { int i; *time=0; for(i=0;i<64;i+=8) (*time)|=(((uint64_t)buffer[(*offset)++])<>4; else n=n&0xf; if (n!=15) did_out[i]=did_chars[n]; else { did_out[i]=0; (*offset)+=((i+1)/2); if (!(i&1)) (*offset)++; return 0; } } return 0; } int pack_did(unsigned char *buffer,int *offset,const char *did) { int i; int highlow=0; for(i=0;i<64;i++) { int j; for(j=0;j<16;j++) if (did_chars[j]==tolower(did[i])) break; if (!did[i]) j=15; if (j>=16) return -1; // illegal character if (highlow) { buffer[(*offset)++]|=j<<4; } else buffer[*offset]=j; highlow^=1; if (j==15) { if (highlow) (*offset)++; return 0; } } return -1; // number too long } int serialize_ack(unsigned char *buffer,int *offset, int buffer_size, int ack_address) { if ((*offset)+1+1+4+1>=buffer_size) return -1; encode_length_forwards(buffer,offset,1+1+4+1); buffer[(*offset)++]=RHIZOME_MESHMS_BLOCK_TYPE_ACK; pack_int(buffer,offset,ack_address); encode_length_backwards(buffer,offset,1+1+4+1); return 0; } int serialize_meshms(unsigned char *buffer,int *offset,unsigned int length,const char *sender_did,const char *recipient_did, unsigned long long time, const char *payload, int payload_length) { int ret = 0; encode_length_forwards(buffer,offset,length); buffer[(*offset)++]=RHIZOME_MESHMS_BLOCK_TYPE_MESSAGE; pack_did(buffer,offset,sender_did); pack_did(buffer,offset,recipient_did); pack_time(buffer,offset,time); int i=0; for(i;i=blength) return -1; decode_length_forwards(buffer,&offset,blength,&length); if (offset>=blength) return -1; unsigned char block_type=buffer[offset]; return block_type; } int deserialize_ack(unsigned char *buffer,int *offset, int buffer_size, int *ack_address) { unsigned int length=0; int length_length=*offset; decode_length_forwards(buffer,offset,buffer_size,&length); length_length=(*offset)-length_length; unsigned char block_type=buffer[(*offset)++]; if (block_type!=RHIZOME_MESHMS_BLOCK_TYPE_ACK) return -1; unpack_int(buffer,offset,ack_address); (*offset)+=length_length; return 0; } int deserialize_meshms(int message_number, unsigned char *buffer,int *offset, int buffer_size, char *delivery_status) { int ret = 0; int i=0; unsigned int length =0; unsigned int start_offset=*offset; cli_printf("%d",message_number); cli_delim(":"); cli_printf("%d",*offset); cli_delim(":"); int length_length=*offset; decode_length_forwards(buffer,offset,buffer_size,&length); length_length=(*offset)-length_length; cli_printf("%d",length); cli_delim(":"); unsigned char block_type=buffer[(*offset)++]; if (block_type!=RHIZOME_MESHMS_BLOCK_TYPE_MESSAGE) { WHYF("Corrupt meshms message block: type=0x%02x instead of 0x%02x", block_type,RHIZOME_MESHMS_BLOCK_TYPE_MESSAGE); return -1; } char sender_did_out[64]; unpack_did(buffer,offset,sender_did_out); cli_printf("%s",sender_did_out); cli_delim(":"); char recipient_did_out[64]; unpack_did(buffer,offset,recipient_did_out); cli_printf("%s",recipient_did_out); cli_delim(":"); unsigned long long time = 0; unpack_time(buffer,offset,&time); cli_printf("%lld",time); cli_delim(":"); cli_printf("%s",delivery_status); cli_delim(":"); cli_printf("%s","meshms"); cli_delim(":"); int j=0; int payload_end=start_offset+length-length_length; for(j=*offset;j