LOTS OF CHANGES. was hoping to get revision 5000 perfect, but really that's never going to happen. this has gone on for too long now.

vulkan, wasapi, quake injector features added.
irc, avplug, cef plugins/drivers reworked/updated/added
openal reverb, doppler effects added.
'dir' console command now attempts to view clicked files.
lots of warning fixes, should now only be deprecation warnings for most targets (depending on compiler version anyway...).
SendEntity finally reworked to use flags properly.
effectinfo improved, other smc-targetted fixes.
mapcluster stuff now has support for linux.
.basebone+.baseframe now exist in ssqc.
qcc: -Fqccx supports qccx syntax, including qccx hacks. don't expect these to work in fteqw nor dp though.
qcc: rewrote function call handling to use refs rather than defs. this makes struct passing more efficient and makes the __out keyword usable with fields etc.
qccgui: can cope a little better with non-unicode files. can now represent most quake chars.
qcc: suppressed warnings from *extensions.qc

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5000 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2016-07-12 00:40:13 +00:00
parent 5920bf05fb
commit 27a59a0cbc
271 changed files with 101001 additions and 64352 deletions

View file

@ -7,6 +7,10 @@
vfsfile_t *FS_GZ_DecompressWriteFilter(vfsfile_t *outfile, qboolean autoclosefile);
#ifndef NPFTE
static struct dl_download *activedownloads;
#endif
#if defined(WEBCLIENT)
#if defined(FTE_TARGET_WEB)
@ -422,7 +426,8 @@ struct http_dl_ctx_s {
// struct dl_download *dlctx;
#ifndef NPFTE
vfsfile_t *sock;
vfsfile_t *stream;
SOCKET sock; //so we can wait on it when multithreaded.
#else
SOCKET sock; //FIXME: support https.
#endif
@ -454,9 +459,9 @@ void HTTP_Cleanup(struct dl_download *dl)
dl->ctx = NULL;
#ifndef NPFTE
if (con->sock)
VFS_CLOSE(con->sock);
con->sock = NULL;
if (con->stream)
VFS_CLOSE(con->stream);
con->stream = NULL;
#else
if (con->sock != INVALID_SOCKET)
closesocket(con->sock);
@ -488,11 +493,32 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
char *nl;
char *msg;
int ammount;
#ifdef MULTITHREAD
//if we're running in a thread, wait for some actual activity instead of busylooping like an moron.
if (dl->threadctx)
{
struct timeval timeout;
fd_set rdset, wrset;
FD_ZERO(&wrset);
FD_ZERO(&rdset);
FD_SET(con->sock, &wrset); // network socket
FD_SET(con->sock, &rdset); // network socket
timeout.tv_sec = 0;
timeout.tv_usec = 0.1*1000*1000;
if (con->state == HC_REQUESTING)
select(con->sock+1, &rdset, &wrset, NULL, &timeout); //wake up when we can read OR write
else
select(con->sock+1, &rdset, NULL, NULL, &timeout); //wake when we can read.
//note that https should wake up more often, but we don't want to wake up because we *can* write when we're reading without any need to write.
}
#endif
switch(con->state)
{
case HC_REQUESTING:
#ifndef NPFTE
ammount = VFS_WRITE(con->sock, con->buffer, con->bufferused);
ammount = VFS_WRITE(con->stream, con->buffer, con->bufferused);
if (!ammount)
return true;
if (ammount < 0)
@ -522,7 +548,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
ExpandBuffer(con, 1530);
#ifndef NPFTE
ammount = VFS_READ(con->sock, con->buffer+con->bufferused, con->bufferlen-con->bufferused-15);
ammount = VFS_READ(con->stream, con->buffer+con->bufferused, con->bufferlen-con->bufferused-15);
if (!ammount)
return true;
if (ammount < 0)
@ -545,7 +571,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
msg = con->buffer;
con->chunking = false;
con->contentlength = -1;
con->contentlength = -1; //means unspecified
con->gzip = false;
*mimetype = 0;
*Location = 0;
@ -553,7 +579,6 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
{ //pre version 1 (lame servers). no response headers at all.
con->state = HC_GETTING;
dl->status = DL_ACTIVE;
con->contentlength = -1; //meaning end of stream.
dl->replycode = 200;
}
else
@ -715,6 +740,13 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
return false; //something went wrong.
}
if (con->contentlength != -1 && con->contentlength > dl->sizelimit)
{
dl->replycode = 413; //413 Payload Too Large
Con_Printf("HTTP: request exceeds size limit\n");
return false; //something went wrong.
}
con->bufferused -= ammount;
dl->totalsize = con->contentlength;
@ -779,7 +811,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
ExpandBuffer(con, 1530);
#ifndef NPFTE
ammount = VFS_READ(con->sock, con->buffer+con->bufferused, con->bufferlen-con->bufferused-1);
ammount = VFS_READ(con->stream, con->buffer+con->bufferused, con->bufferlen-con->bufferused-1);
if (ammount == 0)
return true; //no data yet
else if (ammount < 0)
@ -838,6 +870,12 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
}
con->totalreceived+=con->chunked;
if (con->totalreceived > dl->sizelimit)
{
dl->replycode = 413; //413 Payload Too Large
Con_Printf("HTTP: request exceeds size limit\n");
return false; //something went wrong.
}
if (con->file && con->chunked) //we've got a chunk in the buffer
{ //write it
if (VFS_WRITE(con->file, con->buffer, con->chunked) != con->chunked)
@ -854,15 +892,28 @@ static qboolean HTTP_DL_Work(struct dl_download *dl)
}
else
{
con->totalreceived+=con->bufferused;
int chunk = con->bufferused;
if (con->contentlength != -1 && chunk > con->contentlength-con->totalreceived)
chunk = con->contentlength-con->totalreceived;
con->totalreceived+=chunk;
if (con->totalreceived > dl->sizelimit)
{
dl->replycode = 413; //413 Payload Too Large
Con_Printf("HTTP: request exceeds size limit\n");
return false; //something went wrong.
}
if (con->file) //we've got a chunk in the buffer
{ //write it
if (VFS_WRITE(con->file, con->buffer, con->bufferused) != con->bufferused)
if (VFS_WRITE(con->file, con->buffer, chunk) != chunk)
{
Con_Printf("Write error whilst downloading %s\nDisk full?\n", dl->localname);
return false;
}
con->bufferused = 0;
//and move the unparsed chunk to the front.
memmove(con->buffer, con->buffer+con->bufferused, con->bufferused-chunk);
con->bufferused -= chunk;
}
if (con->totalreceived == con->contentlength)
ammount = 0;
@ -957,24 +1008,29 @@ void HTTPDL_Establish(struct dl_download *dl)
dl->status = DL_RESOLVING;
#ifndef NPFTE
con->sock = INVALID_SOCKET;
con->stream = NULL;
con->secure = false;
#ifndef HAVE_SSL
if (!https)
#endif
{
netadr_t adr = {0};
//fixme: support more than one address possibility?
//https uses a different default port
if (NET_StringToAdr2(con->server, https?443:80, &adr, 1))
con->sock = TCP_OpenStream(&adr);
con->stream = FS_OpenTCPSocket(con->sock, true, con->server);
}
#ifdef HAVE_SSL
if (https)
{
#ifdef HAVE_SSL
//https uses port 443 instead of 80 by default
con->sock = FS_OpenTCP(con->server, 443);
//and with an extra ssl/tls layer between tcp and http.
con->sock = FS_OpenSSL(con->server, con->sock, false);
#else
con->sock = NULL;
#endif
//https has an extra ssl/tls layer between tcp and http.
con->stream = FS_OpenSSL(con->server, con->stream, false, false);
con->secure = true;
}
else
{
con->sock = FS_OpenTCP(con->server, 80);
con->secure = false;
}
if (!con->sock)
#endif
if (!con->stream)
{
dl->status = DL_FAILED;
return;
@ -1299,9 +1355,12 @@ qboolean DL_Decide(struct dl_download *dl)
#endif /*!defined(NACL)*/
#ifdef MULTITHREAD
static unsigned int dlthreads = 0;
#define MAXDOWNLOADTHREADS 4
#if defined(LOADERTHREAD) && !defined(NPFTE)
static void HTTP_Wake_Think(void *ctx, void *data, size_t a, size_t b)
{
dlthreads--;
HTTP_CL_Think();
}
#endif
@ -1309,7 +1368,7 @@ static int DL_Thread_Work(void *arg)
{
struct dl_download *dl = arg;
while (!dl->threaddie)
while (dl->threadenable)
{
if (!dl->poll(dl))
{
@ -1326,6 +1385,7 @@ static int DL_Thread_Work(void *arg)
break;
}
}
dl->threadenable = false;
#if defined(LOADERTHREAD) && !defined(NPFTE)
COM_AddWork(WG_MAIN, HTTP_Wake_Think, NULL, NULL, 0, 0);
@ -1348,9 +1408,16 @@ qboolean DL_CreateThread(struct dl_download *dl, vfsfile_t *file, void (*NotifyF
if (NotifyFunction)
dl->notifycomplete = NotifyFunction;
dl->threadctx = Sys_CreateThread("download", DL_Thread_Work, dl, THREADP_NORMAL, 0);
if (!dl->threadctx)
return false;
dl->threadenable = true;
#if defined(LOADERTHREAD) && !defined(NPFTE)
if (dlthreads < 0)
#endif
{
dl->threadctx = Sys_CreateThread("download", DL_Thread_Work, dl, THREADP_NORMAL, 0);
if (!dl->threadctx)
return false;
dlthreads++;
}
return true;
}
@ -1367,6 +1434,7 @@ struct dl_download *DL_Create(const char *url)
newdl->url = (char*)(newdl+1);
strcpy(newdl->url, url);
newdl->poll = DL_Decide;
newdl->sizelimit = 0x80000000u; //some sanity limit.
if (!newdl->poll(newdl))
{
@ -1380,13 +1448,26 @@ struct dl_download *DL_Create(const char *url)
/*destroys an entire download context*/
void DL_Close(struct dl_download *dl)
{
struct dl_download **link = NULL;
#ifndef NPFTE
for (link = &activedownloads; *link; link = &(*link)->next)
{
if (*link == dl)
{
*link = dl->next;
break;
}
}
#endif
#if !defined(NPFTE) && !defined(SERVERONLY)
if (cls.download == &dl->qdownload)
cls.download = NULL;
#endif
#ifdef MULTITHREAD
dl->threaddie = true;
dl->threadenable = false;
if (dl->threadctx)
Sys_WaitOnThread(dl->threadctx);
#endif
@ -1399,11 +1480,32 @@ void DL_Close(struct dl_download *dl)
free(dl);
}
void DL_DeThread(void)
{
#ifdef MULTITHREAD
//if we're about to fork, ensure that any downloads are properly parked so that there's no workers in an unknown state.
struct dl_download *dl;
for (dl = activedownloads; dl; dl = dl->next)
{
dl->threadenable = false;
if (dl->threadctx)
Sys_WaitOnThread(dl->threadctx);
}
#endif
}
/*updates pending downloads*/
#ifndef NPFTE
unsigned int HTTP_CL_GetActiveDownloads(void)
{
struct dl_download *dl;
unsigned int count = 0;
for (dl = activedownloads; dl; dl = dl->next)
count++;
return count;
}
static struct dl_download *activedownloads;
/*create a download context and add it to the list, for lazy people. not threaded*/
struct dl_download *HTTP_CL_Get(const char *url, const char *localfile, void (*NotifyFunction)(struct dl_download *dl))
{
@ -1443,10 +1545,13 @@ struct dl_download *HTTP_CL_Put(const char *url, const char *mime, const char *d
return NULL;
dl = HTTP_CL_Get(url, NULL, NotifyFunction);
Q_strncpyz(dl->postmimetype, mime, sizeof(dl->postmimetype));
dl->postdata = BZ_Malloc(datalen);
memcpy(dl->postdata, data, datalen);
dl->postlen = datalen;
if (dl)
{
Q_strncpyz(dl->postmimetype, mime, sizeof(dl->postmimetype));
dl->postdata = BZ_Malloc(datalen);
memcpy(dl->postdata, data, datalen);
dl->postlen = datalen;
}
return dl;
}
@ -1454,6 +1559,12 @@ void HTTP_CL_Think(void)
{
struct dl_download *dl = activedownloads;
struct dl_download **link = NULL;
#ifndef SERVERONLY
float currenttime;
if (!activedownloads)
return;
currenttime = Sys_DoubleTime();
#endif
link = &activedownloads;
while (*link)
@ -1469,22 +1580,38 @@ void HTTP_CL_Think(void)
continue;
}
}
else
#endif
if (!dl->poll(dl))
else if (dl->threadenable)
{
*link = dl->next;
if (dl->file && dl->file->Seek)
VFS_SEEK(dl->file, 0);
if (dl->notifycomplete)
dl->notifycomplete(dl);
DL_Close(dl);
continue;
if (dlthreads < MAXDOWNLOADTHREADS)
{
dl->threadctx = Sys_CreateThread("download", DL_Thread_Work, dl, THREADP_NORMAL, 0);
if (dl->threadctx)
dlthreads++;
else
dl->threadenable = false;
}
}
else
#endif
{
if (!dl->poll(dl))
{
*link = dl->next;
if (dl->file && dl->file->Seek)
VFS_SEEK(dl->file, 0);
if (dl->notifycomplete)
dl->notifycomplete(dl);
DL_Close(dl);
continue;
}
}
link = &dl->next;
#ifndef SERVERONLY
if (!cls.download && !dl->isquery)
#ifdef MULTITHREAD
if (!dl->threadenable || dl->threadctx) //don't show pending downloads in preference to active ones.
#endif
{
cls.download = &dl->qdownload;
dl->qdownload.method = DL_HTTP;
@ -1509,9 +1636,9 @@ void HTTP_CL_Think(void)
dl->qdownload.percent = dl->completed*100.0f/dl->totalsize;
dl->qdownload.completedbytes = dl->completed;
if (dl->qdownload.ratetime < Sys_DoubleTime())
if (dl->qdownload.ratetime < currenttime)
{
dl->qdownload.ratetime = Sys_DoubleTime()+1;
dl->qdownload.ratetime = currenttime+1;
dl->qdownload.rate = (dl->qdownload.completedbytes - dl->qdownload.ratebytes) / 1;
dl->qdownload.ratebytes = dl->qdownload.completedbytes;
}
@ -1549,12 +1676,14 @@ typedef struct
int maxlen;
int writepos;
int readpos;
void *mutex;
} vfspipe_t;
static qboolean QDECL VFSPIPE_Close(vfsfile_t *f)
{
vfspipe_t *p = (vfspipe_t*)f;
free(p->data);
Sys_DestroyMutex(p->mutex);
free(p);
return true;
}
@ -1575,6 +1704,7 @@ static qofs_t QDECL VFSPIPE_GetLen(vfsfile_t *f)
static int QDECL VFSPIPE_ReadBytes(vfsfile_t *f, void *buffer, int len)
{
vfspipe_t *p = (vfspipe_t*)f;
Sys_LockMutex(p->mutex);
if (len > p->writepos - p->readpos)
len = p->writepos - p->readpos;
memcpy(buffer, p->data+p->readpos, len);
@ -1589,18 +1719,23 @@ static int QDECL VFSPIPE_ReadBytes(vfsfile_t *f, void *buffer, int len)
p->writepos -= p->readpos;
p->readpos = 0;
}
Sys_UnlockMutex(p->mutex);
return len;
}
static int QDECL VFSPIPE_WriteBytes(vfsfile_t *f, const void *buffer, int len)
{
vfspipe_t *p = (vfspipe_t*)f;
Sys_LockMutex(p->mutex);
if (p->writepos + len > p->maxlen)
{
p->maxlen = p->writepos + len;
if (p->maxlen < (p->writepos-p->readpos)*2) //over-allocate a little
p->maxlen = (p->writepos-p->readpos)*2;
p->data = realloc(p->data, p->maxlen);
}
memcpy(p->data+p->writepos, buffer, len);
p->writepos += len;
Sys_UnlockMutex(p->mutex);
return len;
}
@ -1608,6 +1743,7 @@ vfsfile_t *VFSPIPE_Open(void)
{
vfspipe_t *newf;
newf = malloc(sizeof(*newf));
newf->mutex = Sys_CreateMutex();
newf->data = NULL;
newf->maxlen = 0;
newf->readpos = 0;