Ejemplo n.º 1
0
bool BridgeManager::SendFile(FILE *file, int destination, int fileIdentifier) const
{
	if (destination != EndFileTransferPacket::kDestinationModem && destination != EndFileTransferPacket::kDestinationPhone)
	{
		InterfaceManager::PrintError("ERROR: Attempted to send file to unknown destination!\n");
		return (false);
	}

	if (destination == EndFileTransferPacket::kDestinationModem && fileIdentifier != -1)
	{
		InterfaceManager::PrintError("ERROR: The modem file does not have an identifier!\n");
		return (false);
	}

	FileTransferPacket flashFileTransferPacket(FileTransferPacket::kRequestFlash);
	bool success = SendPacket(&flashFileTransferPacket);

	if (!success)
	{
		InterfaceManager::PrintError("Failed to initialise transfer!\n");
		return (false);
	}

	fseek(file, 0, SEEK_END);
	long fileSize = ftell(file);
	rewind(file);

	ResponsePacket fileTransferResponse(ResponsePacket::kResponseTypeFileTransfer);
	success = ReceivePacket(&fileTransferResponse);

	if (!success)
	{
		InterfaceManager::PrintError("Failed to confirm transfer initialisation!\n");
		return (false);
	}

	int sequenceCount = fileSize / (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize);
	int lastSequenceSize = kMaxSequenceLength;
	int partialPacketLength = fileSize % SendFilePartPacket::kDefaultPacketSize;
	if  (fileSize % (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize) != 0)
	{
		sequenceCount++;

		int lastSequenceBytes = fileSize % (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize);
		lastSequenceSize = lastSequenceBytes / SendFilePartPacket::kDefaultPacketSize;
		if (partialPacketLength != 0)
			lastSequenceSize++;
	}

	long bytesTransferred = 0;
	int currentPercent;
	int previousPercent = 0;
	InterfaceManager::Print("0%%");

	for (int sequenceIndex = 0; sequenceIndex < sequenceCount; sequenceIndex++)
	{
		// Min(lastSequenceSize, 131072)
		bool isLastSequence = sequenceIndex == sequenceCount - 1;
		int sequenceSize = (isLastSequence) ? lastSequenceSize : kMaxSequenceLength;

		FlashPartFileTransferPacket *beginFileTransferPacket = new FlashPartFileTransferPacket(0, 2 * sequenceSize);
		success = SendPacket(beginFileTransferPacket);
		delete beginFileTransferPacket;

		if (!success)
		{
			InterfaceManager::PrintError("\nFailed to begin file transfer sequence!\n");
			return (false);
		}

		ResponsePacket fileTransferResponse(ResponsePacket::kResponseTypeFileTransfer);
		bool success = ReceivePacket(&fileTransferResponse);

		if (!success)
		{
			InterfaceManager::PrintError("\nFailed to confirm beginning of file transfer sequence!\n");
			return (false);
		}

		SendFilePartPacket *sendFilePartPacket;
		SendFilePartResponse *sendFilePartResponse;

		for (int filePartIndex = 0; filePartIndex < sequenceSize; filePartIndex++)
		{
			// Send
			sendFilePartPacket = new SendFilePartPacket(file);
			success = SendPacket(sendFilePartPacket);
			delete sendFilePartPacket;

			if (!success)
			{
				InterfaceManager::PrintError("\nFailed to send file part packet!\n");
				return (false);
			}

			// Response
			sendFilePartResponse = new SendFilePartResponse();
			success = ReceivePacket(sendFilePartResponse);
			int receivedPartIndex = sendFilePartResponse->GetPartIndex();

			if (verbose)
			{
				const unsigned char *data = sendFilePartResponse->GetData();
				InterfaceManager::Print("File Part #%i... Response: %X  %X  %X  %X  %X  %X  %X  %X \n", filePartIndex,
					data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
			}

			delete sendFilePartResponse;

			if (!success)
			{
				InterfaceManager::PrintError("\nFailed to receive file part response!\n");

				for (int retry = 0; retry < 4; retry++)
				{
					InterfaceManager::PrintError("\nRetrying...");

					// Send
					sendFilePartPacket = new SendFilePartPacket(file);
					success = SendPacket(sendFilePartPacket);
					delete sendFilePartPacket;

					if (!success)
					{
						InterfaceManager::PrintError("\nFailed to send file part packet!\n");
						return (false);
					}

					// Response
					sendFilePartResponse = new SendFilePartResponse();
					success = ReceivePacket(sendFilePartResponse);
					int receivedPartIndex = sendFilePartResponse->GetPartIndex();

					if (verbose)
					{
						const unsigned char *data = sendFilePartResponse->GetData();
						InterfaceManager::Print("File Part #%i... Response: %X  %X  %X  %X  %X  %X  %X  %X \n", filePartIndex,
							data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
					}

					delete sendFilePartResponse;

					if (receivedPartIndex != filePartIndex)
					{
						InterfaceManager::PrintError("\nERROR: Expected file part index: %i Received: %i\n",
							filePartIndex, receivedPartIndex);
						return (false);
					}

					if (success)
						break;
				}

				if (!success)
					return (false);
			}

			if (receivedPartIndex != filePartIndex)
			{
				InterfaceManager::PrintError("\nERROR: Expected file part index: %i Received: %i\n",
					filePartIndex, receivedPartIndex);
				return (false);
			}

			bytesTransferred += SendFilePartPacket::kDefaultPacketSize;
			if (bytesTransferred > fileSize)
				bytesTransferred = fileSize;

			currentPercent = (int)(100.0f * ((float)bytesTransferred / (float)fileSize));

			if (!verbose)
			{
				if (currentPercent != previousPercent)
				{
					if (previousPercent < 10)
						InterfaceManager::Print("\b\b%i%%", currentPercent);
					else
						InterfaceManager::Print("\b\b\b%i%%", currentPercent);
				}
			}

			previousPercent = currentPercent;
		}

		int lastFullPacketIndex = 2 * ((isLastSequence && partialPacketLength != 0) ? sequenceSize - 1 : sequenceSize);

		if (destination == EndFileTransferPacket::kDestinationPhone)
		{
			EndPhoneFileTransferPacket *endPhoneFileTransferPacket = new EndPhoneFileTransferPacket(
				(isLastSequence) ? partialPacketLength : 0, lastFullPacketIndex, 0, 0, fileIdentifier, isLastSequence);

			success = SendPacket(endPhoneFileTransferPacket, 3000);
			delete endPhoneFileTransferPacket;

			if (!success)
			{
				InterfaceManager::PrintError("\nFailed to end phone file transfer sequence!\n");
				return (false);
			}
		}
		else // destination == EndFileTransferPacket::kDestinationModem
		{
			EndModemFileTransferPacket *endModemFileTransferPacket = new EndModemFileTransferPacket(
				(isLastSequence) ? partialPacketLength : 0, lastFullPacketIndex, 0, 0, isLastSequence);

			success = SendPacket(endModemFileTransferPacket, 3000);
			delete endModemFileTransferPacket;

			if (!success)
			{
				InterfaceManager::PrintError("\nFailed to end modem file transfer sequence!\n");
				return (false);
			}
		}

		ResponsePacket fileTransferResponse2(ResponsePacket::kResponseTypeFileTransfer);
		success = ReceivePacket(&fileTransferResponse2, 30000);

		if (!success)
		{
			InterfaceManager::PrintError("\nFailed to confirm end of file transfer sequence!\n");
			return (false);
		}
	}

	if (!verbose)
		InterfaceManager::Print("\n");

	return (true);
}
Ejemplo n.º 2
0
bool BridgeManager::SendFile(FILE *file, unsigned int destination, unsigned int chipIdentifier, unsigned int fileIdentifier) const
{
    if (destination != EndFileTransferPacket::kDestinationModem && destination != EndFileTransferPacket::kDestinationPhone)
    {
        Interface::PrintError("Attempted to send file to unknown destination!\n");
        return (false);
    }

    if (destination == EndFileTransferPacket::kDestinationModem && fileIdentifier != 0xFFFFFFFF)
    {
        Interface::PrintError("The modem file does not have an identifier!\n");
        return (false);
    }

    FileTransferPacket *flashFileTransferPacket = new FileTransferPacket(FileTransferPacket::kRequestFlash);
    bool success = SendPacket(flashFileTransferPacket);
    delete flashFileTransferPacket;

    if (!success)
    {
        Interface::PrintError("Failed to initialise file transfer!\n");
        return (false);
    }

    fseek(file, 0, SEEK_END);
    long fileSize = ftell(file);
    rewind(file);

    ResponsePacket *fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
    success = ReceivePacket(fileTransferResponse);
    delete fileTransferResponse;

    if (!success)
    {
        Interface::PrintError("Failed to confirm transfer initialisation!\n");
        return (false);
    }

    // Transfer is a Double loop of Sequences (Outer) and Packets/FileParts (inner)
    unsigned int sequenceCount = fileSize / (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize);
    unsigned int lastSequenceSize = kMaxSequenceLength;
    unsigned int partialPacketByteCount = fileSize % SendFilePartPacket::kDefaultPacketSize;

    if (verbose)
        Interface::Print("fileSize: %d kMaxSequenceLength: %d kDefaultPacketSize: %d sequenceCount: %d lastSequenceSize: %d partialPacketByteCount: %d\n",
                         fileSize, kMaxSequenceLength, SendFilePartPacket::kDefaultPacketSize, sequenceCount, lastSequenceSize, partialPacketByteCount);

    if (fileSize % (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize) != 0)
    {
        sequenceCount++;

        int lastSequenceBytes = fileSize % (kMaxSequenceLength * SendFilePartPacket::kDefaultPacketSize);
        lastSequenceSize = lastSequenceBytes / SendFilePartPacket::kDefaultPacketSize;

        if (partialPacketByteCount != 0)
            lastSequenceSize++;
    }

    long bytesTransferred = 0;
    unsigned int currentPercent;
    unsigned int previousPercent = 0;
    Interface::Print("0%%");

    for (unsigned int sequenceIndex = 0; sequenceIndex < sequenceCount; sequenceIndex++)
    {
        // Min(lastSequenceSize, 131072)
        bool isLastSequence = sequenceIndex == sequenceCount - 1;
        unsigned int sequenceSize = (isLastSequence) ? lastSequenceSize : kMaxSequenceLength;

        // This is the number of data bytes transferred in this sequence, not including the zero-pad on the final packet (Just the image data)
        unsigned int sequenceByteCount =
            ((isLastSequence) ? (lastSequenceSize - 1) : kMaxSequenceLength) * SendFilePartPacket::kDefaultPacketSize +
            ((isLastSequence) ? partialPacketByteCount : 0);

        FlashPartFileTransferPacket *beginFileTransferPacket = new FlashPartFileTransferPacket(0, 2 * sequenceSize);
        success = SendPacket(beginFileTransferPacket);
        delete beginFileTransferPacket;

        if (!success)
        {
            Interface::PrintErrorSameLine("\n");
            Interface::PrintError("Failed to begin file transfer sequence!\n");
            return (false);
        }

        fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
        bool success = ReceivePacket(fileTransferResponse);
        delete fileTransferResponse;

        if (!success)
        {
            Interface::PrintErrorSameLine("\n");
            Interface::PrintError("Failed to confirm beginning of file transfer sequence!\n");
            return (false);
        }

        SendFilePartPacket *sendFilePartPacket;
        SendFilePartResponse *sendFilePartResponse;

        for (unsigned int filePartIndex = 0; filePartIndex < sequenceSize; filePartIndex++)
        {
            // Send
            // The final (short) packet data is zero-padded, so we do not need to specify the byte count,
            // even though it is an option for SendFilePartPacket
            sendFilePartPacket = new SendFilePartPacket(file);
            success = SendPacket(sendFilePartPacket);
            delete sendFilePartPacket;

            if (!success)
            {
                Interface::PrintErrorSameLine("\n");
                Interface::PrintError("Failed to send file part packet!\n");
                return (false);
            }

            // Response
            sendFilePartResponse = new SendFilePartResponse();
            success = ReceivePacket(sendFilePartResponse);
            int receivedPartIndex = sendFilePartResponse->GetPartIndex();

            if (verbose)
            {
                const unsigned char *data = sendFilePartResponse->GetData();
                Interface::Print("(%3d%%) Seq: %d/%d File Part #%d/%d... Response: %X  %X  %X  %X  %X  %X  %X  %X \n",
                                 currentPercent, sequenceIndex+1, sequenceCount, filePartIndex+1, sequenceSize,
                                 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
            }

            delete sendFilePartResponse;

            if (!success)
            {
                Interface::PrintErrorSameLine("\n");
                Interface::PrintError("Failed to receive file part response!\n");

                for (int retry = 0; retry < 4; retry++)
                {
                    Interface::PrintErrorSameLine("\n");
                    Interface::PrintError("Retrying...");

                    // Send
                    sendFilePartPacket = new SendFilePartPacket(file);
                    success = SendPacket(sendFilePartPacket);
                    delete sendFilePartPacket;

                    if (!success)
                    {
                        Interface::PrintErrorSameLine("\n");
                        Interface::PrintError("Failed to send file part packet!\n");
                        return (false);
                    }

                    // Response
                    sendFilePartResponse = new SendFilePartResponse();
                    success = ReceivePacket(sendFilePartResponse);
                    unsigned int receivedPartIndex = sendFilePartResponse->GetPartIndex();

                    if (verbose)
                    {
                        const unsigned char *data = sendFilePartResponse->GetData();
                        Interface::Print("(%3d%%) Seq: %d/%d File Part #%d/%d... Response: %X  %X  %X  %X  %X  %X  %X  %X \n",
                                         currentPercent, sequenceIndex, sequenceCount, filePartIndex, sequenceSize,
                                         data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
                    }

                    delete sendFilePartResponse;

                    if (receivedPartIndex != filePartIndex)
                    {
                        Interface::PrintErrorSameLine("\n");
                        Interface::PrintError("Expected file part index: %d Received: %d\n", filePartIndex, receivedPartIndex);
                        return (false);
                    }

                    if (success)
                        break;
                }

                if (!success)
                    return (false);
            }

            if (receivedPartIndex != filePartIndex)
            {
                Interface::PrintErrorSameLine("\n");
                Interface::PrintError("Expected file part index: %d Received: %d\n", filePartIndex, receivedPartIndex);
                return (false);
            }

            bytesTransferred += SendFilePartPacket::kDefaultPacketSize;
            if (bytesTransferred > fileSize)
                bytesTransferred = fileSize;

            currentPercent = (int)(100.0f * ((float)bytesTransferred / (float)fileSize));

            if (currentPercent != previousPercent)
            {
                if (!verbose)
                {
                    if (previousPercent < 10)
                        Interface::Print("\b\b%d%%", currentPercent);
                    else
                        Interface::Print("\b\b\b%d%%", currentPercent);
                }
            }

            previousPercent = currentPercent;
        }

        if (destination == EndFileTransferPacket::kDestinationPhone)
        {
            EndPhoneFileTransferPacket *endPhoneFileTransferPacket = new EndPhoneFileTransferPacket(sequenceByteCount, 0, chipIdentifier,
                    fileIdentifier, isLastSequence);

            success = SendPacket(endPhoneFileTransferPacket, 3000);
            delete endPhoneFileTransferPacket;

            if (!success)
            {
                Interface::PrintErrorSameLine("\n");
                Interface::PrintError("Failed to end phone file transfer sequence!\n");
                return (false);
            }
        }
        else // destination == EndFileTransferPacket::kDestinationModem
        {
            EndModemFileTransferPacket *endModemFileTransferPacket = new EndModemFileTransferPacket(sequenceByteCount, 0, chipIdentifier, isLastSequence);

            success = SendPacket(endModemFileTransferPacket, 3000);
            delete endModemFileTransferPacket;

            if (!success)
            {
                Interface::PrintErrorSameLine("\n");
                Interface::PrintError("Failed to end modem file transfer sequence!\n");
                return (false);
            }
        }

        fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
        success = ReceivePacket(fileTransferResponse, 30000);
        delete fileTransferResponse;

        if (!success)
        {
            Interface::PrintErrorSameLine("\n");
            Interface::PrintError("Failed to confirm end of file transfer sequence!\n");
            return (false);
        }
    }

    if (!verbose)
        Interface::Print("\n");

    return (true);
}
Ejemplo n.º 3
0
bool BridgeManager::SendFile(FILE *file, unsigned int destination, unsigned int deviceType, unsigned int fileIdentifier) const
{
	if (destination != EndFileTransferPacket::kDestinationModem && destination != EndFileTransferPacket::kDestinationPhone)
	{
		Interface::PrintError("Attempted to send file to unknown destination!\n");
		return (false);
	}

	if (destination == EndFileTransferPacket::kDestinationModem && fileIdentifier != 0xFFFFFFFF)
	{
		Interface::PrintError("The modem file does not have an identifier!\n");
		return (false);
	}

	FileTransferPacket *flashFileTransferPacket = new FileTransferPacket(FileTransferPacket::kRequestFlash);
	bool success = SendPacket(flashFileTransferPacket);
	delete flashFileTransferPacket;

	if (!success)
	{
		Interface::PrintError("Failed to initialise file transfer!\n");
		return (false);
	}

	fseek(file, 0, SEEK_END);
	long fileSize = ftell(file);
	rewind(file);

	ResponsePacket *fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
	success = ReceivePacket(fileTransferResponse);
	delete fileTransferResponse;

	if (!success)
	{
		Interface::PrintError("Failed to confirm transfer initialisation!\n");
		return (false);
	}

	unsigned int sequenceCount = fileSize / (fileTransferSequenceMaxLength * fileTransferPacketSize);
	unsigned int lastSequenceSize = fileTransferSequenceMaxLength;
	unsigned int partialPacketByteCount = fileSize % fileTransferPacketSize;

	if (fileSize % (fileTransferSequenceMaxLength * fileTransferPacketSize) != 0)
	{
		sequenceCount++;

		int lastSequenceBytes = fileSize % (fileTransferSequenceMaxLength * fileTransferPacketSize);
		lastSequenceSize = lastSequenceBytes / fileTransferPacketSize;

		if (partialPacketByteCount != 0)
			lastSequenceSize++;
	}

	long bytesTransferred = 0;
	unsigned int currentPercent;
	unsigned int previousPercent = 0;
	Interface::Print("0%%");

	for (unsigned int sequenceIndex = 0; sequenceIndex < sequenceCount; sequenceIndex++)
	{
		bool isLastSequence = (sequenceIndex == sequenceCount - 1);
		unsigned int sequenceSize = (isLastSequence) ? lastSequenceSize : fileTransferSequenceMaxLength;
		unsigned int sequenceByteCount;

		if (isLastSequence)
			sequenceByteCount = ((partialPacketByteCount) ? lastSequenceSize - 1 : lastSequenceSize) * fileTransferPacketSize + partialPacketByteCount;
		else
			sequenceByteCount = fileTransferSequenceMaxLength * fileTransferPacketSize;

		FlashPartFileTransferPacket *beginFileTransferPacket = new FlashPartFileTransferPacket(sequenceByteCount);
		success = SendPacket(beginFileTransferPacket);
		delete beginFileTransferPacket;

		if (!success)
		{
			Interface::PrintErrorSameLine("\n");
			Interface::PrintError("Failed to begin file transfer sequence!\n");
			return (false);
		}

		fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
		bool success = ReceivePacket(fileTransferResponse);
		delete fileTransferResponse;

		if (!success)
		{
			Interface::PrintErrorSameLine("\n");
			Interface::PrintError("Failed to confirm beginning of file transfer sequence!\n");
			return (false);
		}

		SendFilePartPacket *sendFilePartPacket;
		SendFilePartResponse *sendFilePartResponse;

		for (unsigned int filePartIndex = 0; filePartIndex < sequenceSize; filePartIndex++)
		{
			// Send
			sendFilePartPacket = new SendFilePartPacket(file, fileTransferPacketSize);
			success = SendPacket(sendFilePartPacket);
			delete sendFilePartPacket;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to send file part packet!\n");
				return (false);
			}

			// Response
			sendFilePartResponse = new SendFilePartResponse();
			success = ReceivePacket(sendFilePartResponse);
			int receivedPartIndex = sendFilePartResponse->GetPartIndex();

			delete sendFilePartResponse;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to receive file part response!\n");

				for (int retry = 0; retry < 4; retry++)
				{
					Interface::PrintErrorSameLine("\n");
					Interface::PrintError("Retrying...");

					// Send
					sendFilePartPacket = new SendFilePartPacket(file, fileTransferPacketSize);
					success = SendPacket(sendFilePartPacket);
					delete sendFilePartPacket;

					if (!success)
					{
						Interface::PrintErrorSameLine("\n");
						Interface::PrintError("Failed to send file part packet!\n");
						return (false);
					}

					// Response
					sendFilePartResponse = new SendFilePartResponse();
					success = ReceivePacket(sendFilePartResponse);
					unsigned int receivedPartIndex = sendFilePartResponse->GetPartIndex();

					delete sendFilePartResponse;

					if (receivedPartIndex != filePartIndex)
					{
						Interface::PrintErrorSameLine("\n");
						Interface::PrintError("Expected file part index: %d Received: %d\n", filePartIndex, receivedPartIndex);
						return (false);
					}

					if (success)
						break;
				}

				if (!success)
					return (false);
			}

			if (receivedPartIndex != filePartIndex)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Expected file part index: %d Received: %d\n", filePartIndex, receivedPartIndex);
				return (false);
			}

			bytesTransferred += fileTransferPacketSize;

			if (bytesTransferred > fileSize)
				bytesTransferred = fileSize;

			currentPercent = (int)(100.0f * ((float)bytesTransferred / (float)fileSize));

			if (currentPercent != previousPercent)
			{
				if (!verbose)
				{
					if (previousPercent < 10)
						Interface::Print("\b\b%d%%", currentPercent);
					else
						Interface::Print("\b\b\b%d%%", currentPercent);
				}
				else
				{
					Interface::Print("\n%d%%\n", currentPercent);
				}
			}

			previousPercent = currentPercent;
		}

		if (destination == EndFileTransferPacket::kDestinationPhone)
		{
			EndPhoneFileTransferPacket *endPhoneFileTransferPacket = new EndPhoneFileTransferPacket(sequenceByteCount, 0, deviceType, fileIdentifier, isLastSequence);

			success = SendPacket(endPhoneFileTransferPacket, 3000);
			delete endPhoneFileTransferPacket;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to end phone file transfer sequence!\n");
				return (false);
			}
		}
		else // destination == EndFileTransferPacket::kDestinationModem
		{
			EndModemFileTransferPacket *endModemFileTransferPacket = new EndModemFileTransferPacket(sequenceByteCount, 0, deviceType, isLastSequence);

			success = SendPacket(endModemFileTransferPacket, 3000);
			delete endModemFileTransferPacket;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to end modem file transfer sequence!\n");
				return (false);
			}
		}

		fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
		success = ReceivePacket(fileTransferResponse, fileTransferSequenceTimeout);
		delete fileTransferResponse;

		if (!success)
		{
			Interface::PrintErrorSameLine("\n");
			Interface::PrintError("Failed to confirm end of file transfer sequence!\n");
			return (false);
		}
	}

	if (!verbose)
		Interface::Print("\n");

	return (true);
}
Ejemplo n.º 4
0
bool BridgeManager::SendFile(FILE *file, unsigned int destination, unsigned int deviceType, unsigned int fileIdentifier) const
{
	if (destination != EndFileTransferPacket::kDestinationModem && destination != EndFileTransferPacket::kDestinationPhone)
	{
		Interface::PrintError("Attempted to send file to unknown destination!\n");
		return (false);
	}

	if (destination == EndFileTransferPacket::kDestinationModem && fileIdentifier != 0xFFFFFFFF)
	{
		Interface::PrintError("The modem file does not have an identifier!\n");
		return (false);
	}

	FileTransferPacket *flashFileTransferPacket = new FileTransferPacket(FileTransferPacket::kRequestFlash);
	bool success = SendPacket(flashFileTransferPacket);
	delete flashFileTransferPacket;

	if (!success)
	{
		Interface::PrintError("Failed to initialise file transfer!\n");
		return (false);
	}

	FileSeek(file, 0, SEEK_END);
	unsigned int fileSize = (unsigned int)FileTell(file);
	FileRewind(file);

	ResponsePacket *fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
	success = ReceivePacket(fileTransferResponse);
	delete fileTransferResponse;

	if (!success)
	{
		Interface::PrintError("Failed to confirm transfer initialisation!\n");
		return (false);
	}

	unsigned int sequenceCount = fileSize / (fileTransferSequenceMaxLength * fileTransferPacketSize);
	unsigned int lastSequenceSize = fileTransferSequenceMaxLength;
	unsigned int partialPacketByteCount = fileSize % fileTransferPacketSize;

	if (fileSize % (fileTransferSequenceMaxLength * fileTransferPacketSize) != 0)
	{
		sequenceCount++;

		int lastSequenceBytes = fileSize % (fileTransferSequenceMaxLength * fileTransferPacketSize);
		lastSequenceSize = lastSequenceBytes / fileTransferPacketSize;

		if (partialPacketByteCount != 0)
			lastSequenceSize++;
	}

	unsigned int bytesTransferred = 0;
	unsigned int currentPercent;
	unsigned int previousPercent = 0;
	Interface::Print("0%%");

	for (unsigned int sequenceIndex = 0; sequenceIndex < sequenceCount; sequenceIndex++)
	{
		bool isLastSequence = (sequenceIndex == sequenceCount - 1);
		unsigned int sequenceSize = (isLastSequence) ? lastSequenceSize : fileTransferSequenceMaxLength;
		unsigned int sequenceTotalByteCount = sequenceSize * fileTransferPacketSize;

		FlashPartFileTransferPacket *beginFileTransferPacket = new FlashPartFileTransferPacket(sequenceTotalByteCount);
		success = SendPacket(beginFileTransferPacket);
		delete beginFileTransferPacket;

		if (!success)
		{
			Interface::PrintErrorSameLine("\n");
			Interface::PrintError("Failed to begin file transfer sequence!\n");
			return (false);
		}

		fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
		bool success = ReceivePacket(fileTransferResponse);
		delete fileTransferResponse;

		if (!success)
		{
			Interface::PrintErrorSameLine("\n");
			Interface::PrintError("Failed to confirm beginning of file transfer sequence!\n");
			return (false);
		}

		for (unsigned int filePartIndex = 0; filePartIndex < sequenceSize; filePartIndex++)
		{
			// NOTE: This empty transfer thing is entirely ridiculous, but sadly it seems to be required.
			int sendEmptyTransferFlags = (filePartIndex == 0) ? kEmptyTransferNone : kEmptyTransferBefore;

			// Send
			SendFilePartPacket *sendFilePartPacket = new SendFilePartPacket(file, fileTransferPacketSize);
			success = SendPacket(sendFilePartPacket, kDefaultTimeoutSend, sendEmptyTransferFlags);
			delete sendFilePartPacket;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to send file part packet!\n");
				return (false);
			}

			// Response
			SendFilePartResponse *sendFilePartResponse = new SendFilePartResponse();
			success = ReceivePacket(sendFilePartResponse);
			int receivedPartIndex = sendFilePartResponse->GetPartIndex();
			delete sendFilePartResponse;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to receive file part response!\n");

				for (int retry = 0; retry < 4; retry++)
				{
					Interface::PrintErrorSameLine("\n");
					Interface::PrintError("Retrying...");

					// Send
					sendFilePartPacket = new SendFilePartPacket(file, fileTransferPacketSize);
					success = SendPacket(sendFilePartPacket, kDefaultTimeoutSend, sendEmptyTransferFlags);
					delete sendFilePartPacket;

					if (!success)
					{
						Interface::PrintErrorSameLine("\n");
						Interface::PrintError("Failed to send file part packet!\n");
						return (false);
					}

					// Response
					sendFilePartResponse = new SendFilePartResponse();
					success = ReceivePacket(sendFilePartResponse);
					unsigned int receivedPartIndex = sendFilePartResponse->GetPartIndex();

					delete sendFilePartResponse;

					if (receivedPartIndex != filePartIndex)
					{
						Interface::PrintErrorSameLine("\n");
						Interface::PrintError("Expected file part index: %d Received: %d\n", filePartIndex, receivedPartIndex);
						return (false);
					}

					if (success)
						break;
				}

				if (!success)
					return (false);
			}

			if (receivedPartIndex != filePartIndex)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Expected file part index: %d Received: %d\n", filePartIndex, receivedPartIndex);
				return (false);
			}

			bytesTransferred += fileTransferPacketSize;

			if (bytesTransferred > fileSize)
				bytesTransferred = fileSize;

			currentPercent = (unsigned int)(100.0 * ((double)bytesTransferred / (double)fileSize));

			if (currentPercent != previousPercent)
			{
				if (!verbose)
				{
					if (previousPercent < 10)
						Interface::Print("\b\b%d%%", currentPercent);
					else
						Interface::Print("\b\b\b%d%%", currentPercent);
				}
				else
				{
					Interface::Print("\n%d%%\n", currentPercent);
				}
			}

			previousPercent = currentPercent;
		}

		unsigned int sequenceEffectiveByteCount = (isLastSequence && partialPacketByteCount != 0) ?
			fileTransferPacketSize * (lastSequenceSize - 1) + partialPacketByteCount : sequenceTotalByteCount;

		if (destination == EndFileTransferPacket::kDestinationPhone)
		{
			EndPhoneFileTransferPacket *endPhoneFileTransferPacket = new EndPhoneFileTransferPacket(sequenceEffectiveByteCount, 0, deviceType, fileIdentifier, isLastSequence);
			//***** SEND FILE END *****
			//success = SendPacket(endPhoneFileTransferPacket, kDefaultTimeoutSend, kEmptyTransferBeforeAndAfter);
			success = SendPacket(endPhoneFileTransferPacket);//SH-G7108
			delete endPhoneFileTransferPacket;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to end phone file transfer sequence!\n");
				return (false);
			}
		}
		else // destination == EndFileTransferPacket::kDestinationModem
		{
			EndModemFileTransferPacket *endModemFileTransferPacket = new EndModemFileTransferPacket(sequenceEffectiveByteCount, 0, deviceType, isLastSequence);

			success = SendPacket(endModemFileTransferPacket, kDefaultTimeoutSend, kEmptyTransferBeforeAndAfter);
			delete endModemFileTransferPacket;

			if (!success)
			{
				Interface::PrintErrorSameLine("\n");
				Interface::PrintError("Failed to end modem file transfer sequence!\n");
				return (false);
			}
		}

		fileTransferResponse = new ResponsePacket(ResponsePacket::kResponseTypeFileTransfer);
		success = ReceivePacket(fileTransferResponse, fileTransferSequenceTimeout);
		delete fileTransferResponse;

		if (!success)
		{
			Interface::PrintErrorSameLine("\n");
			Interface::PrintError("Failed to confirm end of file transfer sequence!\n");
			return (false);
		}
	}

	if (!verbose)
		Interface::Print("\n");

	return (true);
}