bool NetworkMessage::send(int sd) { fseek(payload, 0, SEEK_SET); uint32_t payload_left = get_payload_size(); uint32_t msg_size = htonl(payload_left); if (::send(sd, &header, sizeof(uint8_t), 0) < 0) return false; if (::send(sd, &msg_size, sizeof(uint32_t), 0) < 0) return false; if (payload != NULL) { off_t offset = 0; int send_len = 0; int fd = fileno(payload); while (payload_left > 0) { send_len = sendfile(sd, fd, &offset, 65535); if (send_len < 0) return false; payload_left -= send_len; } } return true; }
static int test_02_incorrect_payload_type(uint32_t data) { bool failed = false; bass_return_code result = BASS_RC_ERROR_UNKNOWN; bass_payload_type_t correct_payload_type = BASS_PL_TYPE_X_LOADER; bass_payload_type_t payload_type = BASS_PL_TYPE_TAPP; bass_hash_type_t hashtype = BASS_APP_SHA256_HASH; size_t i = 0; size_t ehash_size = SHA256_HASH_SIZE; uint8_t ehash[SHA256_HASH_SIZE]; uint32_t payload_size = 0; uint32_t payload_offset = 0; (void)data; dprintf(INFO, "Starting test\n"); memset(&ehash, 0, sizeof(ehash)); /* * We use the correct payload_type when getting the expected hash from * verify signed header, since the purpose of this test case is to test if * bass_app_test_check_payload_hash is working as it should. */ result = get_ehash(signed_payload, signed_payload_size, correct_payload_type, ehash); if (result != BASS_RC_SUCCESS) { dprintf(ERROR, "failed to getting ehash\n"); return result; } payload_offset = get_header_size(signed_payload); payload_size = get_payload_size(signed_payload); for (i = payload_type; (i <= BASS_PL_TYPE_FRAC) && (i != correct_payload_type); ++i) { result = bass_check_payload_hash(&hashtype, &payload_type, (void *)(signed_payload + payload_offset), payload_size, ehash, ehash_size); if (result == BASS_RC_SUCCESS) { dprintf(ERROR, "incorrectly got a successfull result when " "checking payload hash using payload_type: %d\n", i); failed = true; } } return failed ? BASS_RC_FAILURE : BASS_RC_SUCCESS; }
static int test_01_normal_payload_check(uint32_t data) { bass_return_code result = BASS_RC_ERROR_UNKNOWN; bass_payload_type_t payload_type = BASS_PL_TYPE_X_LOADER; bass_hash_type_t hashtype = BASS_APP_SHA256_HASH; size_t ehash_size = SHA256_HASH_SIZE; uint8_t ehash[SHA256_HASH_SIZE]; uint32_t payload_size = 0; uint32_t payload_offset = 0; (void)data; dprintf(INFO, "Starting test\n"); memset(&ehash, 0, sizeof(ehash)); result = get_ehash(signed_payload, signed_payload_size, payload_type, ehash); if (result != BASS_RC_SUCCESS) { dprintf(ERROR, "failed to getting ehash\n"); return result; } payload_offset = get_header_size(signed_payload); payload_size = get_payload_size(signed_payload); result = bass_check_payload_hash(&hashtype, &payload_type, (void *)(signed_payload + payload_offset), payload_size, ehash, ehash_size); if (result != BASS_RC_SUCCESS) { dprintf(ERROR, "failed checking payload hash\n"); return result; } return result; }
int rtp_connection_kick(struct rtp_connection *connection) { int n, err = 0, retval = 0, i = 0, bytes_available = 0, sk = 0; struct hostent *hp; char buffer[1000]; struct rtp_packet *packet; fd_set rfds; int readchars = 0; struct timeval tv; packet = create_rtp_packet(get_payload_size(connection)); if(packet == NULL) { err = RTP_PACKET_ALLOC_ERROR; goto exit_no_packet; } /* Initialize rtp packet */ init_rtp_packet(packet, connection->seq_no, connection->timestamp, connection->ssrc); while(1) { /* TODO Here we should take into account the * processing time taken to send the packets, * so that we don't introduce extra latency * between samples */ tv.tv_sec = connection->send_interval.tv_sec; tv.tv_usec = connection->send_interval.tv_usec; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(0, &rfds); retval = select(fileno(stdin)+1, &rfds, NULL, NULL, &tv); if (retval < 0) { perror("Error in select: "); goto exit; } // Check amount of data in pipe err = ioctl(connection->data_input, FIONREAD, &bytes_available); if(err != 0) { perror("Error while checking size of pipe: "); goto exit; } if (FD_ISSET(fileno(stdin), &rfds)) { // stdin read(fileno(stdin), buffer, 1); if(buffer[0] == 'e' || buffer[0] == 'E') { goto exit; } else if(buffer[0] == 'f' || buffer[0] == 'F') { // Flush flush_file(connection->data_input); continue; } } if (bytes_available >= packet->payload_size) { // audio stream readchars = read(connection->data_input, packet->payload, packet->payload_size); for(i = 0; i < connection->howmany; i++) { sk = (connection->destinations[i].addr.ss_family == AF_INET) ? connection->bind_sk4 : connection->bind_sk6; n = sendto(sk, packet->start, packet->packet_size, 0, (const struct sockaddr *) &connection->destinations[i].addr, connection->destinations[i].length); if (n < 0) { err = UDP_SEND_ERROR; goto exit; } } // printf("."); // fflush(stdout); connection->seq_no++; connection->timestamp += get_timestamp_per_packet_inc(connection); /* TODO packet no as seq no might wrap */ init_rtp_packet(packet, htons(connection->seq_no), htonl(connection->timestamp), connection->ssrc); } } exit: free(packet); exit_no_packet: return err; }
/** * * Hybi 13 data streams represent a series of variable length frames. Each * frame is made up of a series of fixed length fields. The lengths of later * fields are contained in earlier fields. The first field length is fixed * by the spec. * * This processor represents a state machine that keeps track of what field * is presently being read and how many more bytes are needed to complete it * * * * * Read two header bytes * Extract full frame length. * Read extra header bytes * Validate frame header (including extension validate) * Read extension data into extension message state object * Read payload data into payload * * @param buf Input buffer * * @param len Length of input buffer * * @return Number of bytes processed or zero on error */ size_t consume(uint8_t * buf, size_t len, lib::error_code & ec) { size_t p = 0; ec = lib::error_code(); //std::cout << "consume: " << utility::to_hex(buf,len) << std::endl; // Loop while we don't have a message ready and we still have bytes // left to process. while (m_state != READY && m_state != FATAL_ERROR && (p < len || m_bytes_needed == 0)) { if (m_state == HEADER_BASIC) { p += this->copy_basic_header_bytes(buf+p,len-p); if (m_bytes_needed > 0) { continue; } ec = this->validate_incoming_basic_header( m_basic_header, base::m_server, !m_data_msg.msg_ptr ); if (ec) {break;} // extract full header size and adjust consume state accordingly m_state = HEADER_EXTENDED; m_cursor = 0; m_bytes_needed = frame::get_header_len(m_basic_header) - frame::BASIC_HEADER_LENGTH; } else if (m_state == HEADER_EXTENDED) { p += this->copy_extended_header_bytes(buf+p,len-p); if (m_bytes_needed > 0) { continue; } ec = validate_incoming_extended_header(m_basic_header,m_extended_header); if (ec){break;} m_state = APPLICATION; m_bytes_needed = static_cast<size_t>(get_payload_size(m_basic_header,m_extended_header)); // check if this frame is the start of a new message and set up // the appropriate message metadata. frame::opcode::value op = frame::get_opcode(m_basic_header); // TODO: get_message failure conditions if (frame::opcode::is_control(op)) { m_control_msg = msg_metadata( m_msg_manager->get_message(op,m_bytes_needed), frame::get_masking_key(m_basic_header,m_extended_header) ); m_current_msg = &m_control_msg; } else { if (!m_data_msg.msg_ptr) { if (m_bytes_needed > base::m_max_message_size) { ec = make_error_code(error::message_too_big); break; } m_data_msg = msg_metadata( m_msg_manager->get_message(op,m_bytes_needed), frame::get_masking_key(m_basic_header,m_extended_header) ); } else { // Fetch the underlying payload buffer from the data message we // are writing into. std::string & out = m_data_msg.msg_ptr->get_raw_payload(); if (out.size() + m_bytes_needed > base::m_max_message_size) { ec = make_error_code(error::message_too_big); break; } // Each frame starts a new masking key. All other state // remains between frames. m_data_msg.prepared_key = prepare_masking_key( frame::get_masking_key( m_basic_header, m_extended_header ) ); out.reserve(out.size() + m_bytes_needed); } m_current_msg = &m_data_msg; } } else if (m_state == EXTENSION) { m_state = APPLICATION; } else if (m_state == APPLICATION) { size_t bytes_to_process = (std::min)(m_bytes_needed,len-p); if (bytes_to_process > 0) { p += this->process_payload_bytes(buf+p,bytes_to_process,ec); if (ec) {break;} } if (m_bytes_needed > 0) { continue; } // If this was the last frame in the message set the ready flag. // Otherwise, reset processor state to read additional frames. if (frame::get_fin(m_basic_header)) { // ensure that text messages end on a valid UTF8 code point if (frame::get_opcode(m_basic_header) == frame::opcode::TEXT) { if (!m_current_msg->validator.complete()) { ec = make_error_code(error::invalid_utf8); break; } } m_state = READY; } else { this->reset_headers(); } } else { // shouldn't be here ec = make_error_code(error::general); return 0; } } return p; }
static int test_03_modified_payload(uint32_t data) { bool failed = false; bass_return_code result = BASS_RC_ERROR_UNKNOWN; bass_payload_type_t payload_type = BASS_PL_TYPE_X_LOADER; bass_hash_type_t hashtype = BASS_APP_SHA256_HASH; size_t ehash_size = SHA256_HASH_SIZE; uint8_t ehash[SHA256_HASH_SIZE]; uint8_t *modified_payload = NULL; uint32_t payload_size = 0; uint32_t payload_offset = 0; (void)data; dprintf(INFO, "Starting test\n"); memset(&ehash, 0, sizeof(ehash)); result = get_ehash(signed_payload, signed_payload_size, payload_type, ehash); if (result != BASS_RC_SUCCESS) { dprintf(ERROR, "failed to getting ehash\n"); return result; } payload_offset = get_header_size(signed_payload); payload_size = get_payload_size(signed_payload); modified_payload = malloc(sizeof(uint8_t) * payload_size); if (!modified_payload) { return BASS_RC_FAILURE; } memcpy(modified_payload, signed_payload + payload_offset, payload_size); /* * Set the first 48 bytes to 0xFF (which is ok in in the payloads used in * this file, any number is good as long as it isn't greater than payload * size). * */ memset(modified_payload, 0xFF, 48); result = bass_check_payload_hash(&hashtype, &payload_type, (void *)(modified_payload), payload_size, ehash, ehash_size); if (result == BASS_RC_SUCCESS) { dump_buffer("Expected hash", ehash, ehash_size); dump_buffer("Correct payload", signed_payload + payload_offset, payload_size); dump_buffer("modified_payload", modified_payload, payload_size); dprintf(ERROR, "incorrectly got a successfull result when checking " "payload hash using modified payload\n"); failed = true; } free(modified_payload); /* * Not that we expect this to fail internally, but to the function calling * this function it should be BASS_RC_SUCCESS test case went as expected. */ return failed ? BASS_RC_FAILURE : BASS_RC_SUCCESS; }