mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-21 19:41:14 +00:00
Allow browser port's FS_OpenTCP function to open a 'faketcp' websocket connection. This is so qtvplay can work without first needing to use the 'udp' protocol.
This commit is contained in:
parent
353f5b7ff9
commit
0923cda873
2 changed files with 114 additions and 2 deletions
|
@ -11149,6 +11149,114 @@ vfsfile_t *FS_OpenTCP(const char *name, int defaultport, qboolean assumetls)
|
|||
else
|
||||
return NULL;
|
||||
}
|
||||
#elif defined(FTE_TARGET_WEB)
|
||||
typedef struct {
|
||||
vfsfile_t funcs;
|
||||
|
||||
int id;
|
||||
int readbuffered;
|
||||
char readbuffer[65536];
|
||||
} wsfile_t;
|
||||
int QDECL VFSWS_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
|
||||
{
|
||||
wsfile_t *f = (wsfile_t*)file;
|
||||
int len;
|
||||
int trying;
|
||||
|
||||
//websockets are pseudo-packetised. tcp isn't.
|
||||
while (f->readbuffered < bytestoread)
|
||||
{
|
||||
trying = sizeof(f->readbuffer) - f->readbuffered;
|
||||
if (trying < sizeof(f->readbuffer)/2)
|
||||
break; //don't try to fill the entire buffer, if we grab too much we'll truncate a message.
|
||||
len = emscriptenfte_ws_recv(f->id, f->readbuffer + f->readbuffered, trying);
|
||||
if (len == 0)
|
||||
break; //no more left to read
|
||||
else if (len < 0)
|
||||
{
|
||||
if (!f->readbuffered)
|
||||
return VFS_ERROR_EOF; //not gonna give any more.
|
||||
break; //will find it next time.
|
||||
}
|
||||
else f->readbuffered += len;
|
||||
}
|
||||
|
||||
len = min(bytestoread, f->readbuffered);
|
||||
memcpy(buffer, f->readbuffer, len);
|
||||
f->readbuffered -= len;
|
||||
memmove(f->readbuffer, f->readbuffer+len, f->readbuffered);
|
||||
return len;
|
||||
}
|
||||
int QDECL VFSWS_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite)
|
||||
{
|
||||
wsfile_t *f = (wsfile_t*)file;
|
||||
int len;
|
||||
|
||||
len = emscriptenfte_ws_send(f->id, buffer, bytestowrite);
|
||||
if (len < 0)
|
||||
return VFS_ERROR_EOF; //its dead jim.
|
||||
//if len == 0 //couldn't write yet
|
||||
return len; //would have been the full packet.
|
||||
}
|
||||
qboolean QDECL VFSWS_Seek (struct vfsfile_s *file, qofs_t pos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static qofs_t QDECL VFSWS_Tell (struct vfsfile_s *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static qofs_t QDECL VFSWS_GetLen (struct vfsfile_s *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static qboolean QDECL VFSWS_Close (struct vfsfile_s *file)
|
||||
{
|
||||
wsfile_t *f = (wsfile_t *)file;
|
||||
emscriptenfte_ws_close(f->id);
|
||||
f->id = -1;
|
||||
Z_Free(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
vfsfile_t *FS_OpenTCP(const char *name, int defaultport, qboolean assumetls)
|
||||
{
|
||||
wsfile_t *newf;
|
||||
int id;
|
||||
if (!strncmp(name, "./", 2) || //relative-to-page
|
||||
!strncmp(name, "/", 1) || //relative-to-host
|
||||
!strncmp(name, "wss://", 6) || //what we'd rather be using...
|
||||
!strncmp(name, "ws://", 5)) //what we're probably going to be able to use
|
||||
;
|
||||
else
|
||||
{
|
||||
//bad prefix... probably just a real hostname. don't get confused with relative-to-page uris.
|
||||
//FIXME: we should probably be trying to handle the defaultport. oh well.
|
||||
if (assumetls)
|
||||
name = va("wss://%s", name);
|
||||
else
|
||||
{
|
||||
Con_Printf(CON_WARNING"FS_OpenTCP(%s): Assuming insecure\n", name);
|
||||
name = va("ws://%s", name); //urgh. will probably fail when browsers block it on https pages.
|
||||
}
|
||||
}
|
||||
id = emscriptenfte_ws_connect(name, "faketcp");
|
||||
if (id < 0)
|
||||
return NULL;
|
||||
|
||||
newf = Z_Malloc(sizeof(*newf));
|
||||
newf->id = id;
|
||||
newf->funcs.Close = VFSWS_Close;
|
||||
newf->funcs.Flush = NULL;
|
||||
newf->funcs.GetLen = VFSWS_GetLen;
|
||||
newf->funcs.ReadBytes = VFSWS_ReadBytes;
|
||||
newf->funcs.Seek = VFSWS_Seek;
|
||||
newf->funcs.Tell = VFSWS_Tell;
|
||||
newf->funcs.WriteBytes = VFSWS_WriteBytes;
|
||||
newf->funcs.seekstyle = SS_UNSEEKABLE;
|
||||
|
||||
return &newf->funcs;
|
||||
}
|
||||
#else
|
||||
vfsfile_t *FS_OpenTCP(const char *name, int defaultport, qboolean assumetls)
|
||||
{
|
||||
|
|
|
@ -1186,7 +1186,8 @@ char *HTTPSV_GetMethod(cluster_t *cluster, oproxy_t *pend)
|
|||
for (ctx = NULL; HTTPSV_GetHeaderCommaField((char*)pend->inbuffer, &ctx, "Sec-WebSocket-Protocol", wsprot, sizeof(wsprot)); )
|
||||
{
|
||||
//if (!strcmp(wsprot, "quake")) //webquake. we don't support this! (no OOB and missing header flags and some screwy sequence numbers)
|
||||
if (!strcmp(wsprot, "fteqw"))
|
||||
if (!strcmp(wsprot, "fteqw") || //as a client
|
||||
(!strcmp(wsprot, "faketcp") && !urilen)) //as a qtv proxy (eztv style, but websocked). we are NOT proxying tcp. require a qtv handshake over the resulting websocket connection.
|
||||
break; //break out on the first one we know. this is the recommended way...
|
||||
}
|
||||
|
||||
|
@ -1233,7 +1234,10 @@ char *HTTPSV_GetMethod(cluster_t *cluster, oproxy_t *pend)
|
|||
pend->drop = false;
|
||||
|
||||
uri[urilen] = 0; //make sure its null terminated
|
||||
return strdup(uri+1);
|
||||
if (!strcmp(wsprot, "faketcp"))
|
||||
return NULL; //we're using websockets, don't treat it as a client
|
||||
else
|
||||
return strdup(uri+1); //its a client, track the url as the initial stream.
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue