Ejemplo n.º 1
0
/**
* @brief After receiving a valid game state, we validate the cgame and
* local zip files here and determine if we need to download them
*/
void Com_InitDownloads(void)
{
	char missingfiles[1024];

	// init some of the www dl data
	dld.bWWWDl             = qfalse;
	dld.bWWWDlAborting     = qfalse;
	dld.bWWWDlDisconnected = qfalse;
	Com_ClearStaticDownload();

	if (!Com_InitUpdateDownloads())
	{
		// whatever auto download configuration, store missing files in a cvar, use later in the ui maybe
		if (FS_ComparePaks(missingfiles, sizeof(missingfiles), qfalse))
		{
			Cvar_Set("com_missingFiles", missingfiles);
		}
		else
		{
			Cvar_Set("com_missingFiles", "");
		}

		// reset the redirect checksum tracking
		dld.redirectedList[0] = '\0';

#ifdef DEDICATED
		Com_NextDownload();
#else
		if (cl_allowDownload->integer && FS_ComparePaks(dld.downloadList, sizeof(dld.downloadList), qtrue))
		{
			// this gets printed to UI, i18n
			Com_Printf(CL_TranslateStringBuf("Need paks: %s\n"), dld.downloadList);

			if (*dld.downloadList)
			{
				// if autodownloading is not enabled on the server
				cls.state = CA_CONNECTED;
				Com_NextDownload();
				return;
			}
		}
#endif
	}
	else
	{
		return;
	}

	Com_DownloadsComplete();
}
Ejemplo n.º 2
0
/*
==================
Com_WWWDownload
==================
*/
void Com_WWWDownload(void)
{
	char            *to_ospath;
	dlStatus_t      ret;
	static qboolean bAbort = qfalse;

	if (dld.bWWWDlAborting)
	{
		if (!bAbort)
		{
			Com_DPrintf("Com_WWWDownload: WWWDlAborting\n");
			bAbort = qtrue;
		}
		return;
	}
	if (bAbort)
	{
		Com_DPrintf("Com_WWWDownload: WWWDlAborting done\n");
		bAbort = qfalse;
	}

	ret = DL_DownloadLoop();

	if (ret == DL_CONTINUE)
	{
		return;
	}

	if (ret == DL_DONE)
	{
		// taken from CL_ParseDownload
		// we work with OS paths
		dld.download                     = 0;
		to_ospath                        = FS_BuildOSPath(Cvar_VariableString("fs_homepath"), dld.originalDownloadName, "");
		to_ospath[strlen(to_ospath) - 1] = '\0';
		if (rename(dld.downloadTempName, to_ospath))
		{
			FS_CopyFile(dld.downloadTempName, to_ospath);
			remove(dld.downloadTempName);
		}
		*dld.downloadTempName = *dld.downloadName = 0;
		Cvar_Set("cl_downloadName", "");
		if (dld.bWWWDlDisconnected)
		{
			// for an auto-update in disconnected mode, we'll be spawning the setup in CL_DownloadsComplete
			if (!autoupdate.updateStarted && !dld.noReconnect)
			{
				// reconnect to the server, which might send us to a new disconnected download
				Cbuf_ExecuteText(EXEC_APPEND, "reconnect\n");
			}
		}
		else
		{
			Com_AddReliableCommand("wwwdl done");
			// tracking potential web redirects leading us to wrong checksum - only works in connected mode
			if (strlen(dld.redirectedList) + strlen(dld.originalDownloadName) + 1 >= sizeof(dld.redirectedList))
			{
				// just to be safe
				Com_Printf("ERROR: redirectedList overflow (%s)\n", dld.redirectedList);
			}
			else
			{
				strcat(dld.redirectedList, "@");
				strcat(dld.redirectedList, dld.originalDownloadName);
			}
		}
	}
	else
	{
		if (dld.bWWWDlDisconnected)
		{
			// in a connected download, we'd tell the server about failure and wait for a reply
			// but in this case we can't get anything from server
			// if we just reconnect it's likely we'll get the same disconnected download message, and error out again
			// this may happen for a regular dl or an auto update
			const char *error = va("Download failure while getting '%s'\n", dld.downloadName);    // get the msg before clearing structs

			dld.bWWWDlDisconnected = qfalse; // need clearing structs before ERR_DROP, or it goes into endless reload
			Com_ClearStaticDownload();
			Com_Error(ERR_DROP, "%s", error);
		}
		else
		{
			// see CL_ParseDownload, same abort strategy
			Com_Printf("Download failure while getting '%s'\n", dld.downloadName);
			Com_AddReliableCommand("wwwdl fail");
			dld.bWWWDlAborting = qtrue;
		}
		return;
	}

	dld.bWWWDl = qfalse;
	Com_NextDownload();
}
Ejemplo n.º 3
0
/**
 * @brief A download message has been received from the server
 */
void CL_ParseDownload(msg_t *msg)
{
	int           size;
	unsigned char data[MAX_MSGLEN];
	int           block;

	if (!*cls.download.downloadTempName)
	{
		Com_Printf("Server sending download, but no download was requested\n");
		CL_AddReliableCommand("stopdl");
		return;
	}

	// read the data
	block = MSG_ReadShort(msg);

	// unfortunately DLTYPE_WWW is -1 FIXME: change this someday!
	//if (block < 0)
	//{
	//Com_Error(ERR_DROP, "CL_ParseDownload: Server sending invalid download data");
	//}

	// www dl, if we haven't acknowledged the download redirect yet
	if (block == DLTYPE_WWW)
	{
		if (!cls.download.bWWWDl)
		{
			// server is sending us a www download
			Q_strncpyz(cls.download.originalDownloadName, cls.download.downloadName, sizeof(cls.download.originalDownloadName));
			Q_strncpyz(cls.download.downloadName, MSG_ReadString(msg), sizeof(cls.download.downloadName));
			cls.download.downloadSize  = MSG_ReadLong(msg);
			cls.download.downloadFlags = MSG_ReadLong(msg);
			if (cls.download.downloadFlags & (1 << DL_FLAG_URL))
			{
				Sys_OpenURL(cls.download.downloadName, qtrue);
				Cbuf_ExecuteText(EXEC_APPEND, "quit\n");
				CL_AddReliableCommand("wwwdl bbl8r");   // not sure if that's the right msg
				cls.download.bWWWDlAborting = qtrue;
				return;
			}
			Cvar_SetValue("cl_downloadSize", cls.download.downloadSize);
			Com_DPrintf("Server redirected download: %s\n", cls.download.downloadName);
			cls.download.bWWWDl = qtrue; // activate wwwdl client loop
			CL_AddReliableCommand("wwwdl ack");
			// make sure the server is not trying to redirect us again on a bad checksum
			if (strstr(cls.download.badChecksumList, va("@%s", cls.download.originalDownloadName)))
			{
				Com_Printf("refusing redirect to %s by server (bad checksum)\n", cls.download.downloadName);
				CL_AddReliableCommand("wwwdl fail");
				cls.download.bWWWDlAborting = qtrue;
				return;
			}
			// make downloadTempName an OS path
			Q_strncpyz(cls.download.downloadTempName, FS_BuildOSPath(Cvar_VariableString("fs_homepath"), cls.download.downloadTempName, ""), sizeof(cls.download.downloadTempName));
			cls.download.downloadTempName[strlen(cls.download.downloadTempName) - 1] = '\0';
			if (!DL_BeginDownload(cls.download.downloadTempName, cls.download.downloadName))
			{
				// setting bWWWDl to false after sending the wwwdl fail doesn't work
				// not sure why, but I suspect we have to eat all remaining block -1 that the server has sent us
				// still leave a flag so that CL_WWWDownload is inactive
				// we count on server sending us a gamestate to start up clean again
				CL_AddReliableCommand("wwwdl fail");
				cls.download.bWWWDlAborting = qtrue;
				Com_Printf("Failed to initialize download for '%s'\n", cls.download.downloadName);
			}
			// Check for a disconnected download
			// we'll let the server disconnect us when it gets the bbl8r message
			if (cls.download.downloadFlags & (1 << DL_FLAG_DISCON))
			{
				CL_AddReliableCommand("wwwdl bbl8r");
				cls.download.bWWWDlDisconnected = qtrue;
			}
			return;
		}
		else
		{
			// server keeps sending that message till we acknowledge it, eat and ignore
			//MSG_ReadLong( msg );
			MSG_ReadString(msg);
			MSG_ReadLong(msg);
			MSG_ReadLong(msg);
			return;
		}
	}

	if (!block)
	{
		// block zero is special, contains file size
		cls.download.downloadSize = MSG_ReadLong(msg);

		Cvar_SetValue("cl_downloadSize", cls.download.downloadSize);

		if (cls.download.downloadSize < 0)
		{
			Com_Error(ERR_DROP, "%s", MSG_ReadString(msg));
			return;
		}
	}

	size = MSG_ReadShort(msg);
	if (size < 0 || size > sizeof(data))
	{
		Com_Error(ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk.", size);
		return;
	}

	MSG_ReadData(msg, data, size);

	if (cls.download.downloadBlock != block)
	{
		Com_DPrintf("CL_ParseDownload: Expected block %d, got %d\n", cls.download.downloadBlock, block);
		return;
	}

	// open the file if not opened yet
	if (!cls.download.download)
	{
		cls.download.download = FS_SV_FOpenFileWrite(cls.download.downloadTempName);

		if (!cls.download.download)
		{
			Com_Printf("Could not create %s\n", cls.download.downloadTempName);
			CL_AddReliableCommand("stopdl");
			Com_NextDownload();
			return;
		}
	}

	if (size)
	{
		FS_Write(data, size, cls.download.download);
	}

	CL_AddReliableCommand(va("nextdl %d", cls.download.downloadBlock));
	cls.download.downloadBlock++;

	cls.download.downloadCount += size;

	// So UI gets access to it
	Cvar_SetValue("cl_downloadCount", cls.download.downloadCount);

	if (!size)     // A zero length block means EOF
	{
		if (cls.download.download)
		{
			FS_FCloseFile(cls.download.download);
			cls.download.download = 0;

			// rename the file
			FS_SV_Rename(cls.download.downloadTempName, cls.download.downloadName);
		}
		*cls.download.downloadTempName = *cls.download.downloadName = 0;
		Cvar_Set("cl_downloadName", "");

		// send intentions now
		// We need this because without it, we would hold the last nextdl and then start
		// loading right away.  If we take a while to load, the server is happily trying
		// to send us that last block over and over.
		// Write it twice to help make sure we acknowledge the download
		CL_WritePacket();
		CL_WritePacket();

		// get another file if needed
		Com_NextDownload();
	}
}