/**RFC3320-Setction_8.4. Byte copying From UDVM to UDVM */ int tcomp_udvm_bytecopy_self(tcomp_udvm_t *udvm, uint32_t *destination, uint32_t source, uint32_t tsk_size_tocopy) { uint32_t byte_copy_left, byte_copy_right; //if (*destination == TCOMP_UDVM_GET_SIZE() || source == TCOMP_UDVM_GET_SIZE()) if (*destination >= TCOMP_UDVM_GET_SIZE() || source >= TCOMP_UDVM_GET_SIZE()) { /* SEGFAULT */ tcomp_udvm_createNackInfo2(udvm, NACK_SEGFAULT); return 0; } /* * The string of bytes is copied in ascending order of memory address, * respecting the bounds set by byte_copy_left and byte_copy_right. */ byte_copy_left = TCOMP_UDVM_GET_2BYTES_VAL(TCOMP_UDVM_HEADER_BYTE_COPY_LEFT_INDEX); byte_copy_right = TCOMP_UDVM_GET_2BYTES_VAL(TCOMP_UDVM_HEADER_BYTE_COPY_RIGHT_INDEX); // string of bytes is copied one byte at a time while((tsk_size_tocopy--)) { *TCOMP_UDVM_GET_BUFFER_AT((*destination)++) = *TCOMP_UDVM_GET_BUFFER_AT(source++); *destination = (*destination == byte_copy_right)? byte_copy_left : *destination; source = (source == byte_copy_right)? byte_copy_left : source; } return 1; }
//======================================================== // UDVM machine definition // static tsk_object_t* tcomp_udvm_ctor(tsk_object_t * self, va_list * app) { tcomp_udvm_t *udvm = self; if(udvm){ /* RFC 3320 - 7. SigComp Message Format */ udvm->sigCompMessage = va_arg(*app, tcomp_message_t *); udvm->stateHandler = va_arg(*app, tcomp_statehandler_t *); udvm->lpResult = va_arg(*app, tcomp_result_t *); udvm->isOK = tsk_true; udvm->maximum_UDVM_cycles = 0; /* RFC 3320 subclause 8.6 */ udvm->consumed_cycles = 0; udvm->memory = tcomp_buffer_create_null(); /* Alloc UDVM memory */ if(udvm->sigCompMessage->stream_based){ /* * If the transport is stream-based however, then a fixed-size input buffer is required to accommodate the stream, independently of the * size of each SigComp message. So, for simplicity, the UDVM memory size is set to (decompression_memory_size / 2). */ tcomp_buffer_allocBuff(udvm->memory, udvm->stateHandler->sigcomp_parameters->dmsValue/2); } else{ /* * If the transport is message-based then sufficient memory must be available * to buffer the entire SigComp message before it is passed to the UDVM. So if the message is n bytes long, then the UDVM memory size is set * to (decompression_memory_size - n), up to a maximum of 65536 bytes. */ tcomp_buffer_allocBuff(udvm->memory, (udvm->stateHandler->sigcomp_parameters->dmsValue-udvm->sigCompMessage->totalSize)); } /* * Has feedback with my state id? */ if(tcomp_buffer_getSize(udvm->sigCompMessage->ret_feedback_buffer)){ tsk_size_t size = tcomp_buffer_getSize(udvm->sigCompMessage->ret_feedback_buffer); tcomp_buffer_allocBuff(udvm->lpResult->ret_feedback, size); memcpy(tcomp_buffer_getBuffer(udvm->lpResult->ret_feedback), tcomp_buffer_getBuffer(udvm->sigCompMessage->ret_feedback_buffer), size); } /* * Has state? */ if(tcomp_buffer_getSize(udvm->sigCompMessage->stateId)){ /* Find the provided state */ tcomp_state_t* lpState = NULL; uint16_t match_count = tcomp_statehandler_findState(udvm->stateHandler, udvm->sigCompMessage->stateId, &lpState); if( (!match_count || match_count>1 || !lpState) || (lpState->minimum_access_length > tcomp_buffer_getSize(udvm->sigCompMessage->stateId)) || ((tsk_size_t)(lpState->address + lpState->length) > TCOMP_UDVM_GET_SIZE()) ) { tcomp_udvm_createNackInfo(udvm, NACK_STATE_NOT_FOUND, udvm->sigCompMessage->stateId, 0); udvm->isOK = tsk_false; return self; } //this->sigCompMessage->stateId.print();//FIXME /* * Copy bytecodes to UDVM memory */ if( (tsk_size_t)(lpState->address + lpState->length) >= TCOMP_UDVM_GET_SIZE() ){ tcomp_udvm_createNackInfo2(udvm, NACK_SEGFAULT); udvm->isOK = tsk_false; return self; } memcpy( TCOMP_UDVM_GET_BUFFER_AT(lpState->address), tcomp_buffer_getBuffer(lpState->value), tcomp_buffer_getSize(lpState->value) ); //RFC 3320 - 7.2. Accessing Stored State (Useful values) TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_PARTIAL_STATE_ID_LENGTH_INDEX, tcomp_buffer_getSize(udvm->sigCompMessage->stateId)); TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_STATE_LENGTH_INDEX, tcomp_buffer_getSize(lpState->value)); udvm->executionPointer = lpState->instruction; } else // DON'T HAVE STATE { /* * Copy bytecodes to UDVM memory */ tsk_size_t bytecodes_destination = udvm->sigCompMessage->bytecodes_destination; if( (bytecodes_destination + tcomp_buffer_getSize(udvm->sigCompMessage->uploaded_UDVM_buffer)) >= TCOMP_UDVM_GET_SIZE() ){ tcomp_udvm_createNackInfo2(udvm, NACK_BYTECODES_TOO_LARGE); udvm->isOK = tsk_false; return self; } memcpy( TCOMP_UDVM_GET_BUFFER_AT(bytecodes_destination), tcomp_buffer_getBuffer(udvm->sigCompMessage->uploaded_UDVM_buffer), tcomp_buffer_getSize(udvm->sigCompMessage->uploaded_UDVM_buffer)); // Set pointer indicating execution index udvm->executionPointer = bytecodes_destination; } /* RFC 3320-Section_8.6. UDVM Cycles /* * To ensure that a SigComp message cannot consume excessive processing * resources, SigComp limits the number of "UDVM cycles" allocated to * each message. The number of available UDVM cycles is initialized to * 1000 plus the number of bits in the SigComp header (as described in * Section 7); this sum is then multiplied by cycles_per_bit. */ /*maximum_UDVM_cycles = (8 * n + 1000) * cycles_per_bit*///FIXME:header_size udvm->maximum_UDVM_cycles = ( (8 * udvm->sigCompMessage->header_size + 1000)* udvm->stateHandler->sigcomp_parameters->cpbValue ); // // RFC 3320 - 7.2. Useful values // TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_UDVM_MEMORY_SIZE_INDEX, TCOMP_UDVM_GET_SIZE()); TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_CYCLES_PER_BIT_INDEX, udvm->stateHandler->sigcomp_parameters->cpbValue); TCOMP_UDVM_SET_2BYTES_VAL(TCOMP_UDVM_HEADER_SIGCOMP_VERSION_INDEX, udvm->stateHandler->sigcomp_parameters->SigComp_version); memset(TCOMP_UDVM_GET_BUFFER_AT(TCOMP_UDVM_HEADER_RESERVED_INDEX), 0, TCOMP_UDVM_HEADER_RESERVED_SIZE); } else{