示例#1
0
/**
Set up as a fresh packet with the given opcode.
@param aOpcode a opcode
*/
EXPORT_C void CObexPacket::Init (TObexOpcode aOpcode)
	{
	LOG_LINE
	LOG_FUNC

	SetOpcode (aOpcode);
	SetPacketSize (KObexPacketHeaderSize);
	iInsertPoint = Payload ();
	iExtractPoint = Payload ();
	iNotificationEvents = 0;
	}
示例#2
0
文件: merge_test.cpp 项目: lalo/bond
void AllMerging()
{
    // default value
    Merging<Reader, Writer>(Payload(), T());
    Merging<Reader, Writer>(Payload(), T(), Reader::version);
    Merging<Reader, Writer>(InitRandom<Payload>(), T());
    Merging<Reader, Writer>(InitRandom<Payload>(), T(), Reader::version);
    Merging<Reader, Writer>(Payload(), InitRandom<T>());
    Merging<Reader, Writer>(Payload(), InitRandom<T>(), Reader::version);
    
    // random values
    MergingRandom<Reader, Writer, Payload, T>();
}
bool FStreamingNetworkPlatformFile::SendReadMessage(uint64 HandleId, uint8* Destination, int64 BytesToRead)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	// Send the filename over.
	FStreamingNetworkFileArchive Payload(NFS_Messages::Read);
	Payload << HandleId;
	Payload << BytesToRead;

	// Send the filename over
	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == false)
	{
		return false;
	}

	// Get the server number of bytes read.
	int64 ServerBytesRead = 0;
	Response << ServerBytesRead;

	bool bSuccess = (ServerBytesRead == BytesToRead);

	if (bSuccess)
	{
		// Get the data.
		Response.Serialize(Destination, BytesToRead);
	}

	return bSuccess;
}
bool FStreamingNetworkPlatformFile::MoveFile(const TCHAR* To, const TCHAR* From)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	FString RelativeFrom = From; 
	MakeStandardNetworkFilename(RelativeFrom);
	FString RelativeTo = To; 
	MakeStandardNetworkFilename(RelativeTo);

	FStreamingNetworkFileArchive Payload(NFS_Messages::MoveFile);
	Payload << RelativeFrom;
	Payload << RelativeTo;

	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == false)
	{
		return false;
	}

	uint32 Success = 0;
	Response << Success;

	return !!Success;
}
void FNetworkPlatformFile::PerformHeartbeat()
{
	// send the filename over (cast away const here because we know this << will not modify the string)
	FNetworkFileArchive Payload(NFS_Messages::Heartbeat);

	// send the filename over
	FArrayReader Response;
	if (!SendPayloadAndReceiveResponse(Payload, Response))
	{
		return;
	}

	// get any files that have been modified on the server - 
	TArray<FString> UpdatedFiles;
	Response << UpdatedFiles;

	// delete any outdated files from the client
	// @todo: This may need a critical section around all calls to LowLevel in the other functions
	// because we don't want to delete files while other threads are using them!
	for (int32 FileIndex = 0; FileIndex < UpdatedFiles.Num(); FileIndex++)
	{
		UE_LOG(LogNetworkPlatformFile, Log, TEXT("Server updated file '%s', deleting local copy"), *UpdatedFiles[FileIndex]);
		if (InnerPlatformFile->DeleteFile(*UpdatedFiles[FileIndex]) == false)
		{
			UE_LOG(LogNetworkPlatformFile, Error, TEXT("Failed to delete %s, someone is probably accessing without FNetworkPlatformFile, or we need better thread protection"), *UpdatedFiles[FileIndex]);
		}
	}
}
bool FStreamingNetworkPlatformFile::InitializeInternal(IPlatformFile* Inner, const TCHAR* HostIP)
{
	// look for the commandline that will read files from over the network
	if (HostIP == nullptr)
	{
		UE_LOG(LogStreamingPlatformFile, Error, TEXT("No Host IP specified in the commandline."));
		bIsUsable = false;

		return false;
	}

	// optionally get the port from the command line
	int32 OverridePort;
	if (FParse::Value(FCommandLine::Get(), TEXT("fileserverport="), OverridePort))
	{
		UE_LOG(LogStreamingPlatformFile, Display, TEXT("Overriding file server port: %d"), OverridePort);
		FileServerPort = OverridePort;
	}

	// Send the filenames and timestamps to the server.
	FNetworkFileArchive Payload(NFS_Messages::GetFileList);
	FillGetFileList(Payload, true);

	// Send the directories over, and wait for a response.
	FArrayReader Response;

	if(SendPayloadAndReceiveResponse(Payload,Response))
	{
		// Receive the cooked version information.
		int32 ServerPackageVersion = 0;
		int32 ServerPackageLicenseeVersion = 0;
		ProcessServerInitialResponse(Response, ServerPackageVersion, ServerPackageLicenseeVersion);

		// Make sure we can sync a file.
		FString TestSyncFile = FPaths::Combine(*(FPaths::EngineDir()), TEXT("Config/BaseEngine.ini"));
		IFileHandle* TestFileHandle = OpenRead(*TestSyncFile);
		if (TestFileHandle != nullptr)
		{
			uint8* FileContents = (uint8*)FMemory::Malloc(TestFileHandle->Size());
			if (!TestFileHandle->Read(FileContents, TestFileHandle->Size()))
			{
				UE_LOG(LogStreamingPlatformFile, Fatal, TEXT("Could not read test file %s."), *TestSyncFile);
			}
			FMemory::Free(FileContents);
			delete TestFileHandle;
		}
		else
		{
			UE_LOG(LogStreamingPlatformFile, Fatal, TEXT("Could not open test file %s."), *TestSyncFile);
		}

		FCommandLine::AddToSubprocessCommandline( *FString::Printf( TEXT("-StreamingHostIP=%s"), HostIP ) );

		return true; 
	}

	return false; 
}
bool FStreamingNetworkPlatformFile::SendCloseMessage(uint64 HandleId)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	// Send the filename over (cast away const here because we know this << will not modify the string)
	FStreamingNetworkFileArchive Payload(NFS_Messages::Close);
	Payload << HandleId;

	FArrayReader Response;

	return SendPayloadAndReceiveResponse(Payload, Response);
}
void FStreamingNetworkPlatformFile::PerformHeartbeat()
{
	FNetworkFileArchive Payload(NFS_Messages::Heartbeat);

	// send the filename over
	FArrayReader Response;

	if(SendPayloadAndReceiveResponse(Payload,Response))
	{
		return;
	}
  
    check(0);
}
FString FStreamingNetworkPlatformFile::ConvertToAbsolutePathForExternalAppForWrite( const TCHAR* Filename )
{
	FScopeLock ScopeLock(&SynchronizationObject);

	FStreamingNetworkFileArchive Payload(NFS_Messages::ToAbsolutePathForWrite);
	FString RelativeFilename = Filename; 
	MakeStandardNetworkFilename(RelativeFilename);
	Payload << RelativeFilename;

	// perform a local operation
	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == true)
	{
		Response << RelativeFilename;
	}

	return RelativeFilename;
}
FStreamingNetworkFileHandle* FStreamingNetworkPlatformFile::SendOpenMessage(const FString& Filename, bool bIsWriting, bool bAppend, bool bAllowRead)
{
	FScopeLock ScopeLock(&SynchronizationObject);
	
	FStreamingNetworkFileArchive Payload(bIsWriting ? NFS_Messages::OpenWrite : NFS_Messages::OpenRead);
	Payload << const_cast<FString&>(Filename);

	if (bIsWriting)
	{
		Payload << bAppend;
		Payload << bAllowRead;
	}

	// Send the filename over
	FArrayReader Response;
	if (SendPayloadAndReceiveResponse(Payload, Response) == false)
	{
		return nullptr;
	}

	// This server handle ID which will be used to perform operations on this file.
	uint64 HandleId = 0;
	Response << HandleId;

	// Get the server file timestamp
	FDateTime ServerTimeStamp;
	Response << ServerTimeStamp;

	// Get the server file size
	int64 ServerFileSize = 0;
	Response << ServerFileSize;

	if (bIsWriting || ServerFileSize > 0)
	{
		FStreamingNetworkFileHandle* FileHandle = new FStreamingNetworkFileHandle(*this, *Filename, HandleId, ServerFileSize, bIsWriting);
		return FileHandle;
	}
	else
	{
		return nullptr;
	}
}
void FStreamingNetworkPlatformFile::SetTimeStamp(const TCHAR* Filename, FDateTime DateTime)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	FStreamingNetworkFileArchive Payload(NFS_Messages::SetTimeStamp);
	FString RelativeFilename = Filename;
	MakeStandardNetworkFilename(RelativeFilename);
	Payload << RelativeFilename;
	Payload << DateTime;

	// perform a local operation
	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == false)
	{
		return;
	}

	bool bSuccess = 0;
	Response << bSuccess;
}
bool FStreamingNetworkPlatformFile::SendSeekMessage(uint64 HandleId, int64 NewPosition)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	// Send the filename over.
	FStreamingNetworkFileArchive Payload(NFS_Messages::Seek);
	Payload << HandleId;
	Payload << NewPosition;

	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == false)
	{
		return false;
	}

	int64 ServerNewPosition = -1;
	Response << ServerNewPosition;

	return (ServerNewPosition == NewPosition);
}
bool FNetworkPlatformFile::SendMessageToServer(const TCHAR* Message, IPlatformFile::IFileServerMessageHandler* Handler)
{
	// handle the recompile shaders message
	// @todo: Maybe we should just send the string message to the server, but then we'd have to 
	// handle the return from the server in a generic way
	if (FCString::Stricmp(Message, TEXT("RecompileShaders")) == 0)
	{
		FNetworkFileArchive Payload(NFS_Messages::RecompileShaders);

		// let the handler fill out the object
		Handler->FillPayload(Payload);

		FArrayReader Response;
		if (!SendPayloadAndReceiveResponse(Payload, Response))
		{
			return false;
		}

		// locally delete any files that were modified on the server, so that any read will recache the file
		// this has to be done in this class, not in the Handler (which can't access these members)
		TArray<FString> ModifiedFiles;
		Response << ModifiedFiles;

		if( InnerPlatformFile != NULL )
		{
			for (int32 Index = 0; Index < ModifiedFiles.Num(); Index++)
			{
				InnerPlatformFile->DeleteFile(*ModifiedFiles[Index]);
				CachedLocalFiles.Remove(ModifiedFiles[Index]);
				ServerFiles.AddFileOrDirectory(ModifiedFiles[Index], FDateTime::UtcNow());
			}
		}


		// let the handler process the response directly
		Handler->ProcessResponse(Response);
	}

	return true;
}
bool FStreamingNetworkPlatformFile::DeleteDirectoryRecursively(const TCHAR* Directory)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	FStreamingNetworkFileArchive Payload(NFS_Messages::DeleteDirectoryRecursively);
	FString RelativeDirectory = Directory;
	MakeStandardNetworkFilename(RelativeDirectory);
	Payload << RelativeDirectory;

	// perform a local operation
	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == false)
	{
		return false;
	}

	bool bSuccess = 0;
	Response << bSuccess;

	return bSuccess;
}
void FStreamingNetworkPlatformFile::GetFileInfo(const TCHAR* Filename, FFileInfo& Info)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	FString RelativeFilename = Filename;
	MakeStandardNetworkFilename(RelativeFilename);

	if (!CachedFileInfo.Contains(RelativeFilename))
	{
		FStreamingNetworkFileArchive Payload(NFS_Messages::GetFileInfo);
		Payload << const_cast<FString&>(RelativeFilename);

//		if (RelativeFilename == TEXT("../../../UDKGame/Content/Maps/GDC12_Ice/GDC_2012_Throne_Cave.uasset"))
//		{
//			Info.ReadOnly = true;
//		}

		// Send the filename over
		FArrayReader Response;
		if (SendPayloadAndReceiveResponse(Payload, Response) == false)
		{
			return;
		}

		// Get info from the response
		Response << Info.FileExists;
		Response << Info.ReadOnly;
		Response << Info.Size;
		Response << Info.TimeStamp;
		Response << Info.AccessTimeStamp;

		CachedFileInfo.Add(RelativeFilename, Info);
	}
	else
	{
		Info = *(CachedFileInfo.Find(RelativeFilename));
	}
}
示例#16
0
bool FNetworkPlatformFile::InitializeInternal(IPlatformFile* Inner, const TCHAR* HostIP)
{
	// This platform file requires an inner.
	check(Inner != NULL);
	InnerPlatformFile = Inner;
	if (HostIP == NULL)
	{
		UE_LOG(LogNetworkPlatformFile, Error, TEXT("No Host IP specified in the commandline."));
		bIsUsable = false;
		return false;
	}

	// Save and Intermediate directories are always local
	LocalDirectories.Add(FPaths::EngineDir() / TEXT("Binaries"));
	LocalDirectories.Add(FPaths::EngineIntermediateDir());
	LocalDirectories.Add(FPaths::GameDir() / TEXT("Binaries"));
	LocalDirectories.Add(FPaths::GameIntermediateDir());
	LocalDirectories.Add(FPaths::GameSavedDir() / TEXT("Backup"));
	LocalDirectories.Add(FPaths::GameSavedDir() / TEXT("Config"));
	LocalDirectories.Add(FPaths::GameSavedDir() / TEXT("Logs"));
	LocalDirectories.Add(FPaths::GameSavedDir() / TEXT("Sandboxes"));

	InnerPlatformFile->GetLowerLevel()->AddLocalDirectories(LocalDirectories);

	FNetworkFileArchive Payload(NFS_Messages::Heartbeat); 
	FArrayReader Out;
	if (!SendPayloadAndReceiveResponse(Payload,Out))
		bIsUsable = true; 


	// lets see we can test whether the server is up. 
	if (Out.Num())
	{
		FCommandLine::AddToSubprocessCommandline( *FString::Printf( TEXT("-FileHostIP=%s"), HostIP ) );
		bIsUsable = true; 
	}
	return bIsUsable;
}
bool FStreamingNetworkPlatformFile::CopyFile(const TCHAR* To, const TCHAR* From, EPlatformFileRead ReadFlags, EPlatformFileWrite WriteFlags)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	FStreamingNetworkFileArchive Payload(NFS_Messages::CopyFile);
	FString RelativeTo = To; MakeStandardNetworkFilename(RelativeTo);
	FString RelativeFrom = From; MakeStandardNetworkFilename(RelativeFrom);
	Payload << RelativeTo;
	Payload << RelativeFrom;

	// perform a local operation
	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == false)
	{
		return false;
	}

	bool bSuccess = 0;
	Response << bSuccess;

	return bSuccess;
}
bool FStreamingNetworkPlatformFile::SendWriteMessage(uint64 HandleId, const uint8* Source, int64 BytesToWrite)
{
	FScopeLock ScopeLock(&SynchronizationObject);

	// Send the filename over.
	FStreamingNetworkFileArchive Payload(NFS_Messages::Write);
	Payload << HandleId;
	// Send the data over
	Payload << BytesToWrite;
	Payload.Serialize(const_cast<uint8*>(Source), BytesToWrite);

	FArrayReader Response;

	if (SendPayloadAndReceiveResponse(Payload, Response) == false) 
	{
		return false;
	}

	// Get the number of bytes the server wrote.
	int64 ServerBytesWritten = 0;
	Response << ServerBytesWritten;

	return (ServerBytesWritten == BytesToWrite);
}
示例#19
0
bool CHexarcSession::Connect (CString *retsError)

//	Connect
//
//	Connect to the server (if not already connected)

	{
	//	Already connected?

	if (m_Session.IsConnected())
		return true;

	//	Need host and root URL

	if (m_sHost.IsBlank() || m_sRootURL.IsBlank())
		{
		*retsError = ERR_NO_SERVER_DEFINED;
		return false;
		}

	//	Connect to host

	EInetsErrors iError = m_Session.Connect(m_sHost, m_sPort);
	if (iError != inetsOK)
		{
		switch (iError)
			{
			case inetsDNSError:
				*retsError = strPatternSubst(ERR_DNS_ERROR, GetHostspec());
				kernelDebugLogMessage(*retsError);
				return false;

			case inetsCannotConnect:
				*retsError = strPatternSubst(ERR_CONNECT_ERROR, GetHostspec());
				kernelDebugLogMessage(*retsError);
				return false;

			default:
				*retsError = strPatternSubst(ERR_INTERNAL, GetHostspec());
				kernelDebugLogMessage(*retsError);
				return false;
			}
		}

	//	Compose a connect payload

	CJSONValue Payload(CJSONValue::typeObject);
	Payload.InsertHandoff(FIELD_CLIENT_ID, CJSONValue(m_sClientID));
	Payload.InsertHandoff(FIELD_CLIENT_VERSION, CJSONValue(GetClientVersion()));
	Payload.InsertHandoff(FIELD_PROTOCOL_VERSION, CJSONValue(TRANS_SERVICE_VERSION));
	if (!m_sUsername.IsBlank())
		Payload.InsertHandoff(FIELD_USERNAME, CJSONValue(m_sUsername));

	//	Now issue the connect command

	CHTTPMessage Request;
	InitRequest(METHOD_POST, FUNC_CONNECT_CLIENT, &Request);
	Request.SetBody(new CJSONMessage(Payload));

	//	Send the request and wait for response

	CHTTPMessage Response;
	if (iError = m_Session.Send(Request, &Response))
		{
		m_Session.Disconnect();
		*retsError = strPatternSubst(ERR_REQUEST_FAILED, GetHostspec());
		kernelDebugLogMessage(*retsError);
		return false;
		}

	//	If we got a 301 redirect then we try the whole thing again

	if (Response.GetStatusCode() == 301)
		{
		m_Session.Disconnect();

		//	LATER: Set up the new host and recurse
		//	LATER: Keep track of recursion count, in case of ping-pong redirects
		*retsError = CONSTLIT("LATER: Redirect");
		kernelDebugLogMessage(*retsError);
		return false;
		}

	//	If we get an error, return

	else if (Response.GetStatusCode() != 200)
		{
		m_Session.Disconnect();
		*retsError = strPatternSubst(ERR_FROM_SERVER, GetHostspec(), Response.GetStatusMsg());
		kernelDebugLogMessage(*retsError);
		return false;
		}

	//	Get the JSON response

	CJSONValue ResponseData;
	if (!GetJSONResponse(Response, &ResponseData, retsError))
		{
		m_Session.Disconnect();
		*retsError = strPatternSubst(ERR_INVALID_JSON, GetHostspec(), *retsError);
		return false;
		}

	//	If this is an error, then return it

	if (CHexarc::IsError(ResponseData, NULL, retsError))
		{
		m_Session.Disconnect();
		kernelDebugLogMessage(*retsError);
		return false;
		}

	//	LATER: Process return value (challenge)

	//	Done

	return true;
	}
示例#20
0
bool Connect (const CString &sHostspec, CHTTPClientSession &Session)
	{
	CString sHost;
	CString sPort;
	urlParseHostspec(sHostspec, &sHost, &sPort);

	EInetsErrors iError = Session.Connect(sHost, sPort);
	if (iError != inetsOK)
		{
		switch (iError)
			{
			case inetsDNSError:
				printf("Unable to resolve IP address for: %s\n", sHost.GetASCIIZPointer());
				return false;

			case inetsCannotConnect:
				printf("Unable to connect to: %s\n", sHostspec.GetASCIIZPointer());
				return false;

			default:
				printf("Unknown error connecting to: %s\n", sHostspec.GetASCIIZPointer());
				return false;
			}
		}

	//	Use a constant clientID (representing TransData)

	BYTE ClientIDBytes[4] = { 0, 1, 0, 1 };
	CIntegerIP ClientID(4, ClientIDBytes);
	CString sClientID = ClientID.AsBase64();

	//	Compose a connect payload

	CJSONValue Payload(CJSONValue::typeObject);
	Payload.InsertHandoff(FIELD_CLIENT_ID, CJSONValue(sClientID));
	Payload.InsertHandoff(FIELD_CLIENT_VERSION, CJSONValue(CLIENT_TYPE));
	Payload.InsertHandoff(FIELD_PROTOCOL_VERSION, CJSONValue(TRANS_SERVICE_VERSION));

	//	Now issue the connect command

	CHTTPMessage Request;
	InitRequest(sHost, METHOD_POST, FUNC_CONNECT, &Request);
	Request.SetBody(new CJSONMessage(Payload));

	//	Send the request and wait for response

	CHTTPMessage Response;
	if (iError = Session.Send(Request, &Response))
		{
		Session.Disconnect();
		printf("Unable to send to: %s\n", sHostspec.GetASCIIZPointer());
		return false;
		}

	//	If we got a 301 redirect then we try the whole thing again

	if (Response.GetStatusCode() == 301)
		{
		Session.Disconnect();

		//	LATER: Set up the new host and recurse
		//	LATER: Keep track of recursion count, in case of ping-pong redirects
		printf("REDIRECT\n");
		return false;
		}

	//	If we get an error, return

	else if (Response.GetStatusCode() != 200)
		{
		Session.Disconnect();
		printf("[%d] %s\n", Response.GetStatusCode(), Response.GetStatusMsg().GetASCIIZPointer());
		return false;
		}

	//	Get the JSON response

	CString sError;
	CJSONValue ResponseData;
	if (!GetJSONResponse(Response, &ResponseData, &sError))
		{
		Session.Disconnect();
		printf("Unable to parse JSON reply: %s\n", sError.GetASCIIZPointer());
		return false;
		}

	//	Done

	printf("Connected to %s\n", sHostspec.GetASCIIZPointer());
	return true;
	}
void FNetworkPlatformFile::InitializeAfterSetActive()
{
	double NetworkFileStartupTime = 0.0;
	{
		SCOPE_SECONDS_COUNTER(NetworkFileStartupTime);

		// send the filenames and timestamps to the server
		FNetworkFileArchive Payload(NFS_Messages::GetFileList);
		FillGetFileList(Payload, false);

		// send the directories over, and wait for a response
		FArrayReader Response;
		if (!SendPayloadAndReceiveResponse(Payload, Response))
		{
			delete Transport; 
			return; 
		}
		else
		{
			// receive the cooked version information
			int32 ServerPackageVersion = 0;
			int32 ServerPackageLicenseeVersion = 0;
			ProcessServerInitialResponse(Response, ServerPackageVersion, ServerPackageLicenseeVersion);

			// receive a list of the cache files and their timestamps
			TMap<FString, FDateTime> ServerCachedFiles;
			Response << ServerCachedFiles;

			bool bDeleteAllFiles = true;
			// Check the stored cooked version
			FString CookedVersionFile = FPaths::GeneratedConfigDir() / TEXT("CookedVersion.txt");

			if (InnerPlatformFile->FileExists(*CookedVersionFile) == true)
			{
				IFileHandle* FileHandle = InnerPlatformFile->OpenRead(*CookedVersionFile);
				if (FileHandle != NULL)
				{
					int32 StoredPackageCookedVersion;
					int32 StoredPackageCookedLicenseeVersion;
					if (FileHandle->Read((uint8*)&StoredPackageCookedVersion, sizeof(int32)) == true)
					{
						if (FileHandle->Read((uint8*)&StoredPackageCookedLicenseeVersion, sizeof(int32)) == true)
						{
							if ((ServerPackageVersion == StoredPackageCookedVersion) &&
								(ServerPackageLicenseeVersion == StoredPackageCookedLicenseeVersion))
							{
								bDeleteAllFiles = false;
							}
							else
							{
								UE_LOG(LogNetworkPlatformFile, Display, 
									TEXT("Engine version mismatch: Server %d.%d, Stored %d.%d\n"), 
									ServerPackageVersion, ServerPackageLicenseeVersion,
									StoredPackageCookedVersion, StoredPackageCookedLicenseeVersion);
							}
						}
					}

					delete FileHandle;
				}
			}
			else
			{
				UE_LOG(LogNetworkPlatformFile, Display, TEXT("Cooked version file missing: %s\n"), *CookedVersionFile);
			}

			if (bDeleteAllFiles == true)
			{
				// Make sure the config file exists...
				InnerPlatformFile->CreateDirectoryTree(*(FPaths::GeneratedConfigDir()));
				// Update the cooked version file
				IFileHandle* FileHandle = InnerPlatformFile->OpenWrite(*CookedVersionFile);
				if (FileHandle != NULL)
				{
					FileHandle->Write((const uint8*)&ServerPackageVersion, sizeof(int32));
					FileHandle->Write((const uint8*)&ServerPackageLicenseeVersion, sizeof(int32));
					delete FileHandle;
				}
			}

			// list of directories to skip
			TArray<FString> DirectoriesToSkip;
			TArray<FString> DirectoriesToNotRecurse;
			// use the timestamp grabbing visitor to get all the content times
			FLocalTimestampDirectoryVisitor Visitor(*InnerPlatformFile, DirectoriesToSkip, DirectoriesToNotRecurse, false);

			TArray<FString> RootContentPaths;
			FPackageName::QueryRootContentPaths( RootContentPaths );
			for( TArray<FString>::TConstIterator RootPathIt( RootContentPaths ); RootPathIt; ++RootPathIt )
			{
				const FString& RootPath = *RootPathIt;
				const FString& ContentFolder = FPackageName::LongPackageNameToFilename(RootPath);

				InnerPlatformFile->IterateDirectory( *ContentFolder, Visitor);
			}

			// delete out of date files using the server cached files
			for (TMap<FString, FDateTime>::TIterator It(ServerCachedFiles); It; ++It)
			{
				bool bDeleteFile = bDeleteAllFiles;
				FString ServerFile = It.Key();

				// Convert the filename to the client version
				ConvertServerFilenameToClientFilename(ServerFile);

				// Set it in the visitor file times list
				Visitor.FileTimes.Add(ServerFile, FDateTime::MinValue());

				if (bDeleteFile == false)
				{
					// Check the time stamps...
					// get local time
					FDateTime LocalTime = InnerPlatformFile->GetTimeStamp(*ServerFile);
					// If local time == MinValue than the file does not exist in the cache.
					if (LocalTime != FDateTime::MinValue())
					{
						FDateTime ServerTime = It.Value();
						// delete if out of date
						// We will use 1.0 second as the tolerance to cover any platform differences in resolution
						FTimespan TimeDiff = LocalTime - ServerTime;
						double TimeDiffInSeconds = TimeDiff.GetTotalSeconds();
						bDeleteFile = (TimeDiffInSeconds > 1.0) || (TimeDiffInSeconds < -1.0);
						if (bDeleteFile == true)
						{
							if (InnerPlatformFile->FileExists(*ServerFile) == true)
							{
								UE_LOG(LogNetworkPlatformFile, Display, TEXT("Deleting cached file: TimeDiff %5.3f, %s"), TimeDiffInSeconds, *It.Key());
							}
							else
							{
								// It's a directory
								bDeleteFile = false;
							}
						}
					}
				}
				if (bDeleteFile == true)
				{
					InnerPlatformFile->DeleteFile(*ServerFile);
				}
			}

			// Any content files we have locally that were not cached, delete them
			for (TMap<FString, FDateTime>::TIterator It(Visitor.FileTimes); It; ++It)
			{
				if (It.Value() != FDateTime::MinValue())
				{
					// This was *not* found in the server file list... delete it
					UE_LOG(LogNetworkPlatformFile, Display, TEXT("Deleting cached file: %s"), *It.Key());
					InnerPlatformFile->DeleteFile(*It.Key());
				}
			}

			// make sure we can sync a file
			FString TestSyncFile = FPaths::Combine(*(FPaths::EngineDir()), TEXT("Config/BaseEngine.ini"));

			InnerPlatformFile->SetReadOnly(*TestSyncFile, false);
			InnerPlatformFile->DeleteFile(*TestSyncFile);
			if (InnerPlatformFile->FileExists(*TestSyncFile))
			{
				UE_LOG(LogNetworkPlatformFile, Fatal, TEXT("Could not delete file sync test file %s."), *TestSyncFile);
			}

			EnsureFileIsLocal(TestSyncFile);

			if (!InnerPlatformFile->FileExists(*TestSyncFile) || InnerPlatformFile->FileSize(*TestSyncFile) < 1)
			{
				UE_LOG(LogNetworkPlatformFile, Fatal, TEXT("Could not sync test file %s."), *TestSyncFile);
			}
		}
	}

	FPlatformMisc::LowLevelOutputDebugStringf(TEXT("Network file startup time: %5.3f seconds\n"), NetworkFileStartupTime);

}
void FNetworkPlatformFile::EnsureFileIsLocal(const FString& Filename)
{
	double StartTime;
	float ThisTime;
	StartTime = FPlatformTime::Seconds();

	{
		FScopeLock ScopeLock(&SynchronizationObject);
		// have we already cached this file? 
		if (CachedLocalFiles.Find(Filename) != NULL)
		{
			return;
		}
	}

	if ( FinishedAsyncNetworkReadUnsolicitedFiles )
	{
		delete FinishedAsyncNetworkReadUnsolicitedFiles; // wait here for any async unsolicited files to finish reading being read from the network 
		FinishedAsyncNetworkReadUnsolicitedFiles = NULL;
	}
	if( FinishedAsyncWriteUnsolicitedFiles)
	{
		delete FinishedAsyncWriteUnsolicitedFiles; // wait here for any async unsolicited files to finish writing to disk
		FinishedAsyncWriteUnsolicitedFiles = NULL;
	}
	



	FScopeLock ScopeLock(&SynchronizationObject);

	ThisTime = 1000.0f * float(FPlatformTime::Seconds() - StartTime);
	//UE_LOG(LogNetworkPlatformFile, Display, TEXT("Lock and wait for old async writes %6.2fms"), ThisTime);

	// have we already cached this file? (test again, since some other thread might have done this between waits)
	if (CachedLocalFiles.Find(Filename) != NULL)
	{
		return;
	}
	// even if an error occurs later, we still want to remember not to try again
	CachedLocalFiles.Add(Filename);

	StartTime = FPlatformTime::Seconds();

	// no need to read it if it already exists 
	// @todo: Handshake with server to delete files that are out of date
	if (InnerPlatformFile->FileExists(*Filename))
	{
		return;
	}

	ThisTime = 1000.0f * float(FPlatformTime::Seconds() - StartTime);
	//UE_LOG(LogNetworkPlatformFile, Display, TEXT("Check for local file %6.2fms - %s"), ThisTime, *Filename);

	// this is a bit of a waste if we aren't doing cook on the fly, but we assume missing asset files are relatively rare
	bool bIsCookable = GConfig && GConfig->IsReadyForUse() && FPackageName::IsPackageExtension(*FPaths::GetExtension(Filename, true));

	// we only copy files that actually exist on the server, can greatly reduce network traffic for, say,
	// the INT file each package tries to load
	if (!bIsCookable && ServerFiles.FindFile(Filename) == NULL)
	{
		// Uncomment this to have the server file list dumped
		// the first time a file requested is not found.
#if 0
		static bool sb_DumpedServer = false;
		if (sb_DumpedServer == false)
		{
			FPlatformMisc::LowLevelOutputDebugStringf(TEXT("Dumping server files... %s not found\n"), *Filename);
			for (TMap<FString, FServerTOC::FDirectory*>::TIterator ServerDumpIt(ServerFiles.Directories); ServerDumpIt; ++ServerDumpIt)
			{
				FServerTOC::FDirectory& Directory = *ServerDumpIt.Value();
				for (FServerTOC::FDirectory::TIterator DirDumpIt(Directory); DirDumpIt; ++DirDumpIt)
				{
					FPlatformMisc::LowLevelOutputDebugStringf(TEXT("%10s - %s\n"), *(DirDumpIt.Value().ToString()), *(DirDumpIt.Key()));
				}
			}
			sb_DumpedServer = true;
		}
#endif
		return;
	}

	// send the filename over (cast away const here because we know this << will not modify the string)
	FNetworkFileArchive Payload(NFS_Messages::SyncFile);
	Payload << (FString&)Filename;

	StartTime = FPlatformTime::Seconds();

	// allocate array reader on the heap, because the SyncWriteFile function will delete it
	FArrayReader Response;
	if (!SendPayloadAndReceiveResponse(Payload, Response))
	{
		UE_LOG(LogNetworkPlatformFile, Fatal, TEXT("Receive failure!"));
		return;
	}
	ThisTime = 1000.0f * float(FPlatformTime::Seconds() - StartTime);
	//UE_LOG(LogNetworkPlatformFile, Display, TEXT("Send and receive %6.2fms"), ThisTime);

	StartTime = FPlatformTime::Seconds();

	FString ReplyFile;
	Response << ReplyFile;
	ConvertServerFilenameToClientFilename(ReplyFile);
	check(ReplyFile == Filename);

	// get the server file timestamp
	FDateTime ServerTimeStamp;
	Response << ServerTimeStamp;

	// write the file in chunks, synchronously
	SyncWriteFile(&Response, ReplyFile, ServerTimeStamp, *InnerPlatformFile);

	int32 NumUnsolictedFiles;
	Response << NumUnsolictedFiles;

	if (NumUnsolictedFiles)
	{
		check( FinishedAsyncNetworkReadUnsolicitedFiles == NULL );
		check( FinishedAsyncWriteUnsolicitedFiles == NULL );
		FinishedAsyncNetworkReadUnsolicitedFiles = new FScopedEvent;
		FinishedAsyncWriteUnsolicitedFiles = new FScopedEvent;
		AsyncReadUnsolicitedFiles(NumUnsolictedFiles, *this, *InnerPlatformFile, ServerEngineDir, ServerGameDir, FinishedAsyncNetworkReadUnsolicitedFiles, FinishedAsyncWriteUnsolicitedFiles);
	}
	
	ThisTime = 1000.0f * float(FPlatformTime::Seconds() - StartTime);
	//UE_LOG(LogNetworkPlatformFile, Display, TEXT("Write file to local %6.2fms"), ThisTime);
}
	/************************************************************************
	  CMinPack minimzation:
	*************************************************************************/
	void SkeletonFitting::updateCMP(Joint* joint)
	{
		// TODO: use same minimization method also with MT_CMINPACK_CCD, just exchange the function

		if (!joint) {
			WARN << "joint invalid" << ENDL;	// should never happen
			return;
		}
		
		// TODO: implement simple steepest descent method using the same functions
		const int i = 0;
		
		// if this is the root joint, also update the position
		if (!joint->getPrevJoint()) {
			const double tol = 0.000001;
			const double factor = 0.01;
			const double eps = 0.00001;
			const int iterFac = 50;

			cv::Point3d addPos(0, 0, 0);
			double addSize = 0;
			
			if (i == 0) {
				minimize(&Payload(joint, 0), funcPos, 1, 1, &addPos.x, tol, iterFac, factor, eps);
				minimize(&Payload(joint, 1), funcPos, 1, 1, &addPos.y, tol, iterFac, factor, eps);
				minimize(&Payload(joint, 2), funcPos, 1, 1, &addPos.z, tol, iterFac, factor, eps);

				if (m_minimizeSize)
					minimize(&Payload(joint, 2), funcSize, 1, 1, &addSize, tol, iterFac, factor, eps);
			}
			else {
				/*minimizeSteepestDesc(&Payload(joint, 0), funcPos, 1, 1, &addPos.x);
				minimizeSteepestDesc(&Payload(joint, 1), funcPos, 1, 1, &addPos.y);
				minimizeSteepestDesc(&Payload(joint, 2), funcPos, 1, 1, &addPos.z);
				
				if (m_minimizeSize)
					minimizeSteepestDesc(&Payload(joint, 2), funcSize, 1, 1, &addSize);*/
			}
		
			joint->addPos3d(addPos);
			joint->addBoneSize(addSize);
			joint->updateForward(false);	// changing position doesn't need constraint checking
		}
		
		// update joint angles
		const double tol = 0.001;
		const int iterFac = 50;
		double factor = 100;
		double eps = 0.001;

		switch (joint->getClass()) {
		case JC_BALLANDSOCKET:
			{
				// update ball and socket joints
				JointBallAndSocket* jointBAS = (JointBallAndSocket*)joint;

				// update angles
				cv::Point3d addRot(0, 0, 0);
			
				if (i == 0) {
					minimize(&Payload(joint, 0), funcBAS, 1, 1, &addRot.x, tol, iterFac, factor, eps);
					minimize(&Payload(joint, 1), funcBAS, 1, 1, &addRot.y, tol, iterFac, factor, eps);
					minimize(&Payload(joint, 2), funcBAS, 1, 1, &addRot.z, tol, iterFac, factor, eps);
				}
				else {
					//minimizeSteepestDesc(&Payload(joint, 0), funcBAS, 1, 1, &addRot.x);
					//minimizeSteepestDesc(&Payload(joint, 1), funcBAS, 1, 1, &addRot.y);
					//minimizeSteepestDesc(&Payload(joint, 2), funcBAS, 1, 1, &addRot.z);
				}


				jointBAS->addOrientation(addRot);
				jointBAS->updateForward(true);

				break;
			}
		case JC_HINGE:
			{
				// update hinge joints
				JointHinge* jointHinge = (JointHinge*)joint;
				
				// update angles
				double addAngle = 0;
				
				if (i == 0) {
					minimize(&Payload(joint, 0), funcHinge, 1, 1, &addAngle, tol, iterFac, factor, eps);
				}
				else {
					//minimizeSteepestDesc(&Payload(joint, 0), funcHinge, 1, 1, &addAngle);
				}

				jointHinge->addAngle(addAngle);
				jointHinge->updateForward(true);

				break;
			}
		case JC_ENDCONNECTOR:
			// no need to update end connector joints, their position is only
			// affected by their subordinate joints
			break;
		case JC_CONNECTOR:
			// does also not need to be updated
			break;
		default:
			WARN << "unknown joint type: " << (int)joint->getClass() << ENDL;
			break;
		}
		
		// if this is not the root joint, update the next previous joint
		if (joint->getPrevJoint())
			updateCMP(joint->getPrevJoint());
	}