예제 #1
0
void CToxProto::OnFileRequest(Tox*, uint32_t friendNumber, uint32_t fileNumber, TOX_FILE_CONTROL control, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	MCONTACT hContact = proto->GetContact(friendNumber);
	if (hContact)
	{
		FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber);
		if (transfer == NULL)
		{
			proto->logger->Log(__FUNCTION__": failed to find transfer (%d)", fileNumber);
			return;
		}

		switch (control)
		{
		case TOX_FILE_CONTROL_PAUSE:
			break;

		case TOX_FILE_CONTROL_RESUME:
			break;

		case TOX_FILE_CONTROL_CANCEL:
			proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0);
			proto->transfers.Remove(transfer);
			break;
		}
	}
}
예제 #2
0
void CToxProto::OnGotFriendAvatarData(Tox *tox, int32_t number, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t length, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	MCONTACT hContact = proto->FindContact(number);
	if (hContact)
	{
		db_set_blob(hContact, proto->m_szModuleName, TOX_SETTINGS_AVATAR_HASH, hash, TOX_HASH_LENGTH);

		std::tstring path = proto->GetAvatarFilePath(hContact);
		FILE *hFile = _tfopen(path.c_str(), L"wb");
		if (hFile)
		{
			if (fwrite(data, sizeof(uint8_t), length, hFile) == length)
			{
				PROTO_AVATAR_INFORMATIONW pai = { sizeof(pai) };
				pai.format = PA_FORMAT_PNG;
				pai.hContact = hContact;
				_tcscpy(pai.filename, path.c_str());

				proto->ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0);
			}
			fclose(hFile);
		}
	}
}
예제 #3
0
void CToxProto::OnGotFriendAvatarInfo(Tox *tox, int32_t number, uint8_t format, uint8_t *hash, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	MCONTACT hContact = proto->FindContact(number);
	if (hContact)
	{
		std::tstring path = proto->GetAvatarFilePath(hContact);
		if (format == TOX_AVATAR_FORMAT_NONE)
		{
			proto->delSetting(hContact, TOX_SETTINGS_AVATAR_HASH);
			proto->ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, 0, 0);
			if (IsFileExists(path))
			{
				DeleteFile(path.c_str());
			}
		}
		else
		{
			DBVARIANT dbv;
			if (!db_get(hContact, proto->m_szModuleName, TOX_SETTINGS_AVATAR_HASH, &dbv))
			{
				if (memcmp(hash, dbv.pbVal, TOX_HASH_LENGTH) != 0)
				{
					tox_request_avatar_data(proto->tox, number);
				}
				db_free(&dbv);
			}
			else
			{
				tox_request_avatar_data(proto->tox, number);
			}
		}
	}
}
예제 #4
0
void CToxProto::OnFileSendData(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, size_t length, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber);
	if (transfer == NULL)
	{
		proto->logger->Log(__FUNCTION__": failed to find transfer (%d) to (%d)", fileNumber, friendNumber);
		return;
	}

	if (length == 0)
	{
		// file sending is finished
		proto->logger->Log(__FUNCTION__": finised the transfer of file (%d) to (%d)", fileNumber, friendNumber);
		bool isFileFullyTransfered = transfer->pfts.currentFileProgress == transfer->pfts.currentFileSize;
		if (!isFileFullyTransfered)
			proto->logger->Log(__FUNCTION__": file (%d) is not completely transferred to (%d)", fileNumber, friendNumber);
		proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, isFileFullyTransfered ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)transfer, 0);
		proto->transfers.Remove(transfer);
		return;
	}

	uint64_t sentBytes = _ftelli64(transfer->hFile);
	if (sentBytes != position)
		_fseeki64(transfer->hFile, position, SEEK_SET);

	uint8_t *data = (uint8_t*)mir_alloc(length);
	if (fread(data, sizeof(uint8_t), length, transfer->hFile) != length)
	{
		proto->logger->Log(__FUNCTION__": failed to read from file (%d) to (%d)", fileNumber, friendNumber);
		proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0);
		tox_file_control(proto->toxThread->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
		mir_free(data);
		return;
	}

	TOX_ERR_FILE_SEND_CHUNK error;
	if (!tox_file_send_chunk(proto->toxThread->tox, friendNumber, fileNumber, position, data, length, &error))
	{
		if (error == TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED)
		{
			mir_free(data);
			return;
		}
		proto->logger->Log(__FUNCTION__": failed to send file chunk (%d) to (%d) cause (%d)", fileNumber, friendNumber, error);
		proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0);
		tox_file_control(proto->toxThread->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
		mir_free(data);
		return;
	}

	transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += length;
	proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts);

	mir_free(data);
}
예제 #5
0
// getting the file data
void CToxProto::OnDataReceiving(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, const uint8_t *data, size_t length, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber);
	if (transfer == NULL)
	{
		proto->logger->Log(__FUNCTION__": failed to find transfer (%d) from (%d)", fileNumber, friendNumber);
		return;
	}

	//receiving is finished
	if (length == 0 || position == UINT64_MAX)
	{
		proto->OnTransferCompleted(transfer);
		return;
	}

	MCONTACT hContact = proto->GetContact(friendNumber);
	if (hContact == NULL)
	{
		proto->logger->Log(__FUNCTION__": cannot find contact by number (%d)", friendNumber);
		tox_file_control(proto->toxThread->tox, friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
		return;
	}

	uint64_t filePos = _ftelli64(transfer->hFile);
	if (filePos != position)
		_fseeki64(transfer->hFile, position, SEEK_SET);

	if (fwrite(data, sizeof(uint8_t), length, transfer->hFile) != length)
	{
		proto->logger->Log(__FUNCTION__": failed write to file (%d)", fileNumber);
		proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0);
		tox_file_control(proto->toxThread->tox, friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL);
		return;
	}

	transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += length;
	proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts);
}
예제 #6
0
void CToxProto::OnGroupChatInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	if (type == TOX_GROUPCHAT_TYPE_AV)
	{
		Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": audio chat is not supported yet");
		return;
	}

	int groupNumber = tox_join_groupchat(tox, friendNumber, data, length);
	if (groupNumber == TOX_ERROR)
	{
		Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": failed to join to group chat");
		return;
	}

	MCONTACT hContact = proto->AddChatRoom(groupNumber);
	if (!hContact)
	{
		Netlib_Logf(proto->m_hNetlibUser, __FUNCTION__": failed to create group chat");
	}
}
예제 #7
0
// incoming transfer flow
void CToxProto::OnFriendFile(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint32_t kind, uint64_t fileSize, const uint8_t *fileName, size_t filenameLength, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	MCONTACT hContact = proto->GetContact(friendNumber);
	if (hContact)
	{
		switch (kind)
		{
		case TOX_FILE_KIND_AVATAR:
			{
				proto->logger->Log(__FUNCTION__": incoming avatar (%d) from (%d)", fileNumber, friendNumber);

				ptrT address(proto->getTStringA(hContact, TOX_SETTINGS_ID));
				TCHAR avatarName[MAX_PATH];
				mir_sntprintf(avatarName, MAX_PATH, _T("%s.png"), address);

				AvatarTransferParam *transfer = new AvatarTransferParam(friendNumber, fileNumber, avatarName, fileSize);
				transfer->pfts.flags |= PFTS_RECEIVING;
				transfer->pfts.hContact = hContact;
				proto->transfers.Add(transfer);

				TOX_ERR_FILE_GET error;
				tox_file_get_file_id(proto->toxThread->tox, friendNumber, fileNumber, transfer->hash, &error);
				if (error != TOX_ERR_FILE_GET_OK)
				{
					proto->logger->Log(__FUNCTION__": unable to get avatar hash (%d) from (%d) cause (%d)", fileNumber, friendNumber, error);
					memset(transfer->hash, 0, TOX_HASH_LENGTH);
				}
				proto->OnGotFriendAvatarInfo(transfer);
			}
			break;

		case TOX_FILE_KIND_DATA:
			{
				proto->logger->Log(__FUNCTION__": incoming file (%d) from (%d)", fileNumber, friendNumber);

				ptrA rawName((char*)mir_alloc(filenameLength + 1));
				memcpy(rawName, fileName, filenameLength);
				rawName[filenameLength] = 0;
				TCHAR *name = mir_utf8decodeT(rawName);

				FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, name, fileSize);
				transfer->pfts.flags |= PFTS_RECEIVING;
				transfer->pfts.hContact = hContact;
				proto->transfers.Add(transfer);

				PROTORECVFILET pre = { 0 };
				pre.dwFlags = PRFF_TCHAR;
				pre.fileCount = 1;
				pre.timestamp = time(NULL);
				pre.descr.t = _T("");
				pre.files.t = &name;
				pre.lParam = (LPARAM)transfer;
				ProtoChainRecvFile(hContact, &pre);
			}
			break;

		default:
			proto->logger->Log(__FUNCTION__": unsupported transfer (%d) from (%d) with type (%d)", fileNumber, friendNumber, kind);
			return;
		}
	}
}