Support for reverse qtv connections. (server can now connect to qtv to stream the game, rather than the qtv having to know about the server)

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2511 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2007-05-28 02:25:32 +00:00
parent a696882cb4
commit e7f6c231e7

View file

@ -40,7 +40,8 @@ typedef struct mvdpendingdest_s {
char outbuffer[2048]; char outbuffer[2048];
char challenge[64]; char challenge[64];
int hasauthed; qboolean hasauthed;
qboolean isreverse;
int insize; int insize;
int outsize; int outsize;
@ -50,6 +51,7 @@ typedef struct mvdpendingdest_s {
typedef struct mvddest_s { typedef struct mvddest_s {
qboolean error; //disables writers, quit ASAP. qboolean error; //disables writers, quit ASAP.
qboolean droponmapchange;
enum {DEST_NONE, DEST_FILE, DEST_BUFFEREDFILE, DEST_STREAM} desttype; enum {DEST_NONE, DEST_FILE, DEST_BUFFEREDFILE, DEST_STREAM} desttype;
@ -254,6 +256,7 @@ void SV_MVD_RunPendingConnections(void)
} }
if (end) if (end)
{ //we found the end of the header { //we found the end of the header
qboolean server = false, reverse = false;
char *start, *lineend; char *start, *lineend;
int versiontouse = 0; int versiontouse = 0;
int raw = 0; int raw = 0;
@ -283,10 +286,21 @@ void SV_MVD_RunPendingConnections(void)
start = lineend+1; start = lineend+1;
if (strcmp(com_token, "QTV")) if (strcmp(com_token, "QTV"))
{ //it's an error if it's not qtv. { //it's an error if it's not qtv.
if (!strcmp(com_token, "QTVSV"))
server = true;
else
{
p->error = true; p->error = true;
lineend = strchr(start, '\n'); lineend = strchr(start, '\n');
continue; continue;
} }
}
if (server != p->isreverse)
{ //just a small check
p->error = true;
return;
}
for(;;) for(;;)
{ {
@ -375,6 +389,8 @@ void SV_MVD_RunPendingConnections(void)
if (p->hasauthed) if (p->hasauthed)
{ {
} }
else if (p->isreverse)
p->hasauthed = true; //reverse connections do not need to auth.
else if (!*qtv_password.string) else if (!*qtv_password.string)
p->hasauthed = true; //no password, no need to auth. p->hasauthed = true; //no password, no need to auth.
else if (*password) else if (*password)
@ -496,12 +512,15 @@ void SV_MVD_RunPendingConnections(void)
{ {
if (p->hasauthed == true) if (p->hasauthed == true)
{ {
mvddest_t *dst;
e = ("QTVSV 1\n" e = ("QTVSV 1\n"
"BEGIN\n" "BEGIN\n"
"\n"); "\n");
send(p->socket, e, strlen(e), 0); send(p->socket, e, strlen(e), 0);
e = NULL; e = NULL;
SV_MVD_Record(SV_InitStream(p->socket)); dst = SV_InitStream(p->socket);
dst->droponmapchange = p->isreverse;
SV_MVD_Record(dst);
p->socket = -1; //so it's not cleared wrongly. p->socket = -1; //so it's not cleared wrongly.
} }
else else
@ -543,7 +562,7 @@ int DestCloseAllFlush(qboolean destroyfiles, qboolean mvdonly)
while(d) while(d)
{ {
next = d->nextdest; next = d->nextdest;
if (!mvdonly || d->desttype != DEST_STREAM) if (!mvdonly || d->droponmapchange)
{ {
*prev = d->nextdest; *prev = d->nextdest;
DestClose(d, destroyfiles); DestClose(d, destroyfiles);
@ -1437,6 +1456,7 @@ mvddest_t *SV_InitRecordFile (char *name)
dst->maxcachesize = 0x81000; dst->maxcachesize = 0x81000;
dst->cache = BZ_Malloc(dst->maxcachesize); dst->cache = BZ_Malloc(dst->maxcachesize);
} }
dst->droponmapchange = true;
Check_DemoDir(); Check_DemoDir();
@ -1489,13 +1509,14 @@ mvddest_t *SV_InitStream(int socket)
dst->socket = socket; dst->socket = socket;
dst->maxcachesize = 0x8000; //is this too small? dst->maxcachesize = 0x8000; //is this too small?
dst->cache = BZ_Malloc(dst->maxcachesize); dst->cache = BZ_Malloc(dst->maxcachesize);
dst->droponmapchange = false;
SV_BroadcastPrintf (PRINT_CHAT, "Smile, you're on QTV!\n"); SV_BroadcastPrintf (PRINT_CHAT, "Smile, you're on QTV!\n");
return dst; return dst;
} }
void SV_MVD_InitPendingStream(int socket, char *ip) mvdpendingdest_t *SV_MVD_InitPendingStream(int socket, char *ip)
{ {
mvdpendingdest_t *dst; mvdpendingdest_t *dst;
int i; int i;
@ -1508,6 +1529,8 @@ void SV_MVD_InitPendingStream(int socket, char *ip)
dst->nextdest = demo.pendingdest; dst->nextdest = demo.pendingdest;
demo.pendingdest = dst; demo.pendingdest = dst;
return dst;
} }
/* /*
@ -2058,6 +2081,91 @@ void SV_MVD_Record_f (void)
SV_MVD_Record (SV_InitRecordFile(name)); SV_MVD_Record (SV_InitRecordFile(name));
} }
void SV_MVD_QTVReverse_f (void)
{
char *ip;
if (sv.state != ss_active)
{
Con_Printf ("Server is not running\n");
return;
}
if (Cmd_Argc() != 2)
{
Con_Printf ("%s ip:port\n", Cmd_Argv(0));
return;
}
ip = Cmd_Argv(1);
{
char *data;
int sock;
struct sockaddr_in local;
struct sockaddr_qstorage remote;
// int fromlen;
unsigned int nonblocking = true;
if (!NET_StringToSockaddr(ip, &remote))
{
Con_Printf ("qtvreverse: failed to resolve address\n");
return;
}
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = 0;
if ((sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
Con_Printf ("qtvreverse: socket: %s\n", strerror(qerrno));
return;
}
if( bind (sock, (void *)&local, sizeof(local)) == -1)
{
closesocket(sock);
Con_Printf ("qtvreverse: bind: %s\n", strerror(qerrno));
return;
}
if (connect(sock, (void*)&remote, sizeof(remote)) == -1)
{
closesocket(sock);
Con_Printf ("qtvreverse: connect: %s\n", strerror(qerrno));
return;
}
if (ioctlsocket (sock, FIONBIO, &nonblocking) == -1)
{
closesocket(sock);
Con_Printf ("qtvreverse: ioctl FIONBIO: %s\n", strerror(qerrno));
return;
}
data = "QTV\n"
"REVERSE\n"
"\n";
if (send(sock, data, strlen(data), 0) == -1)
{
closesocket(sock);
Con_Printf ("qtvreverse: send: %s\n", strerror(qerrno));
return;
}
SV_MVD_InitPendingStream(sock, ip)->isreverse = true;
}
//SV_MVD_Record (dest);
}
/* /*
==================== ====================
SV_EasyRecord_f SV_EasyRecord_f
@ -2786,6 +2894,7 @@ void SV_MVDInit(void)
Cmd_AddCommand ("stop", SV_MVDStop_f); Cmd_AddCommand ("stop", SV_MVDStop_f);
Cmd_AddCommand ("cancel", SV_MVD_Cancel_f); Cmd_AddCommand ("cancel", SV_MVD_Cancel_f);
#endif #endif
Cmd_AddCommand ("qtvreverse", SV_MVD_QTVReverse_f);
Cmd_AddCommand ("mvdrecord", SV_MVD_Record_f); Cmd_AddCommand ("mvdrecord", SV_MVD_Record_f);
Cmd_AddCommand ("easyrecord", SV_MVDEasyRecord_f); Cmd_AddCommand ("easyrecord", SV_MVDEasyRecord_f);
Cmd_AddCommand ("mvdstop", SV_MVDStop_f); Cmd_AddCommand ("mvdstop", SV_MVDStop_f);