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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
    /**
     *
     * 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;
}