diff --git a/fteqtv/parse.c b/fteqtv/parse.c index 2bca61f67..93837d095 100644 --- a/fteqtv/parse.c +++ b/fteqtv/parse.c @@ -207,7 +207,7 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma { int protocol; viewer_t *v; - + protocol = ReadLong(m); if (protocol != PROTOCOL_VERSION) { @@ -306,14 +306,14 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask) { //the fromproxy check is because it's fairly common to find a qw server with brackets after it's name. char *s; s = strchr(value, '('); //so strip the parent proxy's hostname, and put our hostname first, leaving the origional server's hostname within the brackets - _snprintf(text, sizeof(text), "%s %s", tv->hostname, s); + snprintf(text, sizeof(text), "%s %s", tv->hostname, s); } else { if (tv->file) - _snprintf(text, sizeof(text), "%s (recorded from: %s)", tv->hostname, value); + snprintf(text, sizeof(text), "%s (recorded from: %s)", tv->hostname, value); else - _snprintf(text, sizeof(text), "%s (live: %s)", tv->hostname, value); + snprintf(text, sizeof(text), "%s (live: %s)", tv->hostname, value); } Info_SetValueForStarKey(tv->serverinfo, "hostname", text, sizeof(tv->serverinfo)); @@ -366,6 +366,8 @@ static void ParsePrint(sv_t *tv, netmsg_t *m, int to, unsigned int mask) *t = '['; if (*t == 17) *t = ']'; + if (*t == '\a') //doh. :D + *t = ' '; } printf("%s", text); } @@ -519,7 +521,7 @@ static void ParsePlayerInfo(sv_t *tv, netmsg_t *m) tv->players[num].active = true; - tv->players[num].leafcount = BSP_SphereLeafNums(tv->bsp, MAX_ENTITY_LEAFS, tv->players[num].leafs, + tv->players[num].leafcount = BSP_SphereLeafNums(tv->bsp, MAX_ENTITY_LEAFS, tv->players[num].leafs, tv->players[num].current.origin[0]/8.0f, tv->players[num].current.origin[1]/8.0f, tv->players[num].current.origin[2]/8.0f, 32); @@ -755,23 +757,23 @@ static void ParseSound(sv_t *tv, netmsg_t *m, int to, unsigned int mask) unsigned char sound_num; short org[3]; - chan = ReadShort(m); + chan = ReadShort(m); if (chan & SND_VOLUME) vol = ReadByte (m); else vol = DEFAULT_SOUND_PACKET_VOLUME; - + if (chan & SND_ATTENUATION) atten = ReadByte (m) / 64.0; else atten = DEFAULT_SOUND_PACKET_ATTENUATION; - + sound_num = ReadByte (m); for (i=0 ; i<3 ; i++) org[i] = ReadShort (m); - + Multicast(tv, m->data+m->startpos, m->readpos - m->startpos, to, mask); } @@ -983,7 +985,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask) case svc_damage: ParseDamage(tv, &buf, to, mask); break; - + case svc_spawnstatic: ParseSpawnStatic(tv, &buf, to, mask); break; @@ -992,7 +994,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask) case svc_spawnbaseline: ParseBaseline(tv, &buf, to, mask); break; - + case svc_temp_entity: ParseTempEntity(tv, &buf, to, mask); break; @@ -1054,7 +1056,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask) case svc_playerinfo: ParsePlayerInfo(tv, &buf); break; -//#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8 +//#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8 case svc_chokecount: ReadByte(&buf); break; @@ -1100,7 +1102,7 @@ void ParseMessage(sv_t *tv, char *buffer, int length, int to, int mask) ParsePacketloss(tv, &buf, to, mask); break; -//#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 +//#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 default: buf.readpos = buf.startpos; diff --git a/fteqtv/qtv.h b/fteqtv/qtv.h index 4581e955c..ce1b70017 100644 --- a/fteqtv/qtv.h +++ b/fteqtv/qtv.h @@ -41,6 +41,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #pragma warning(disable: 4018) //signed/unsigned mismatch #endif + #define snprintf _snprintf + #elif defined(__CYGWIN__) #include @@ -324,7 +326,9 @@ typedef struct sv_s { SOCKET qwdsocket; //udp + quakeworld protocols viewer_t *viewers; + int numviewers; oproxy_t *proxies; + int numproxies; qboolean parsingconnectiondata; //so reject any new connects for now @@ -354,6 +358,8 @@ typedef struct sv_s { char server[MAX_QPATH]; char master[MAX_QPATH]; qboolean nobsp; + int maxviewers; + int maxproxies; } sv_t; typedef struct { @@ -412,11 +418,11 @@ void ReadString(netmsg_t *b, char *string, int maxlen); //#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte] //#define svc_particle 18 // [vec3] #define svc_damage 19 - + #define svc_spawnstatic 20 //#define svc_spawnstatic2 21 #define svc_spawnbaseline 22 - + #define svc_temp_entity 23 // variable //#define svc_setpause 24 // [qbyte] on / off //#define svc_signonnum 25 // [qbyte] used for the signon sequence @@ -451,7 +457,7 @@ void ReadString(netmsg_t *b, char *string, int maxlen); #define svc_download 41 // [short] size [size bytes] #define svc_playerinfo 42 // variable -//#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8 +//#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8 #define svc_chokecount 44 // [qbyte] packets choked #define svc_modellist 45 // [strings] #define svc_soundlist 46 // [strings] @@ -463,7 +469,7 @@ void ReadString(netmsg_t *b, char *string, int maxlen); #define svc_serverinfo 52 // serverinfo #define svc_updatepl 53 // [qbyte] [qbyte] -//#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 +//#define svc_nails2 54 //qwe - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 diff --git a/fteqtv/qw.c b/fteqtv/qw.c index 9a057eb67..a5260a3a2 100644 --- a/fteqtv/qw.c +++ b/fteqtv/qw.c @@ -45,7 +45,7 @@ void ReadDeltaUsercmd (netmsg_t *m, const usercmd_t *from, usercmd_t *move) memcpy (move, from, sizeof(*move)); bits = ReadByte (m); - + // read current angles if (bits & CM_ANGLE1) move->angles[0] = ReadShort (m); @@ -53,7 +53,7 @@ void ReadDeltaUsercmd (netmsg_t *m, const usercmd_t *from, usercmd_t *move) move->angles[1] = ReadShort (m); if (bits & CM_ANGLE3) move->angles[2] = ReadShort (m); - + // read movement if (bits & CM_FORWARD) move->forwardmove = ReadShort(m); @@ -61,7 +61,7 @@ void ReadDeltaUsercmd (netmsg_t *m, const usercmd_t *from, usercmd_t *move) move->sidemove = ReadShort(m); if (bits & CM_UP) move->upmove = ReadShort(m); - + // read buttons if (bits & CM_BUTTONS) move->buttons = ReadByte (m); @@ -106,7 +106,7 @@ void WriteDeltaUsercmd (netmsg_t *m, const usercmd_t *from, usercmd_t *move) WriteShort (m, move->angles[1]); if (bits & CM_ANGLE3) WriteShort (m, move->angles[2]); - + // read movement if (bits & CM_FORWARD) WriteShort(m, move->forwardmove); @@ -114,7 +114,7 @@ void WriteDeltaUsercmd (netmsg_t *m, const usercmd_t *from, usercmd_t *move) WriteShort(m, move->sidemove); if (bits & CM_UP) WriteShort(m, move->upmove); - + // read buttons if (bits & CM_BUTTONS) WriteByte (m, move->buttons); @@ -208,7 +208,7 @@ void SendServerData(sv_t *tv, viewer_t *viewer) netmsg_t msg; char buffer[1024]; InitNetMsg(&msg, buffer, sizeof(buffer)); - + BuildServerData(tv, &msg, false); SendBufferToViewer(viewer, msg.data, msg.cursize, true); @@ -413,6 +413,8 @@ void NewQWClient(sv_t *qtv, netadr_t *addr, char *connectmessage) qtv->viewers = viewer; viewer->delta_frame = -1; + qtv->numviewers++; + Info_ValueForKey(infostring, "name", viewer->name, sizeof(viewer->name)); Netchan_OutOfBandPrint(qtv->qwdsocket, *addr, "j"); @@ -433,7 +435,7 @@ void QTV_Rcon(sv_t *qtv, char *message, netadr_t *from) while(*message > '\0' && *message <= ' ') message++; - + command = strchr(message, ' '); passlen = command-message; if (passlen != strlen(qtv->password) || strncmp(message, qtv->password, passlen)) @@ -524,7 +526,7 @@ void ConnectionlessPacket(sv_t *qtv, netadr_t *from, netmsg_t *m) ReadLong(m); ReadString(m, buffer, sizeof(buffer)); - + if (!strncmp(buffer, "rcon ", 5)) { QTV_Rcon(qtv, buffer+5, from); @@ -552,6 +554,8 @@ void ConnectionlessPacket(sv_t *qtv, netadr_t *from, netmsg_t *m) Netchan_OutOfBandPrint(qtv->qwdsocket, *from, "n" "Proxy is not connected to a server\n"); else if (qtv->parsingconnectiondata) //connecting at this time is a bit silly. Netchan_OutOfBandPrint(qtv->qwdsocket, *from, "n" "Buffering demo, please try again\n"); + else if (qtv->numviewers >= qtv->maxviewers && qtv->maxviewers) + Netchan_OutOfBandPrint(qtv->qwdsocket, *from, "n" "Sorry, proxy is full.\n"); else NewQWClient(qtv, from, buffer); return; @@ -688,7 +692,7 @@ void SV_EmitPacketEntities (const sv_t *qtv, const viewer_t *v, const packet_ent { // this is a new entity, send it from the baseline baseline = &qtv->entity[newnum].baseline; //Con_Printf ("baseline %i\n", newnum); - SV_WriteDelta (newnum, baseline, &to->ents[newindex], msg, true); + SV_WriteDelta (newnum, baseline, &to->ents[newindex], msg, true); newindex++; continue; @@ -762,7 +766,7 @@ void SendPlayerStates(sv_t *tv, viewer_t *v, netmsg_t *msg) { BSP_SetupForPosition(tv->bsp, v->origin[0], v->origin[1], v->origin[2]); } - + lerp = ((tv->curtime - tv->oldpackettime)/1000.0f) / ((tv->nextpackettime - tv->oldpackettime)/1000.0f); if (lerp < 0) lerp = 0; @@ -944,7 +948,7 @@ void AngleVectors (short angles[3], float *forward, float *right, float *up) { float angle; float sr, sp, sy, cr, cp, cy; - + angle = angles[1] * (M_PI*2 / 65535); sy = sin(angle); cy = cos(angle); @@ -1045,7 +1049,7 @@ void ParseQWC(sv_t *qtv, viewer_t *v, netmsg_t *m) case clc_delta: v->delta_frame = ReadByte(m); break; - case clc_stringcmd: + case clc_stringcmd: ReadString (m, buf, sizeof(buf)); // printf("stringcmd: %s\n", buf); @@ -1206,7 +1210,7 @@ void ParseQWC(sv_t *qtv, viewer_t *v, netmsg_t *m) { printf("Client sent unknown string command: %s\n", buf); } - + break; case clc_move: @@ -1235,7 +1239,7 @@ void ParseQWC(sv_t *qtv, viewer_t *v, netmsg_t *m) } static const char dropcmd[] = {svc_stufftext, 'd', 'i', 's', 'c', 'o', 'n', 'n', 'e', 'c', 't', '\n', '\0'}; -void QW_FreeViewer(viewer_t *viewer) +void QW_FreeViewer(sv_t *qtv, viewer_t *viewer) { int i; //note: unlink them yourself. @@ -1254,6 +1258,8 @@ void QW_FreeViewer(viewer_t *viewer) } free(viewer); + + qtv->numviewers--; } void QW_UpdateUDPStuff(sv_t *qtv) @@ -1340,7 +1346,7 @@ void QW_UpdateUDPStuff(sv_t *qtv) f = qtv->viewers; qtv->viewers = f->next; - QW_FreeViewer(f); + QW_FreeViewer(qtv, f); } for (v = qtv->viewers; v; v = v->next) @@ -1351,7 +1357,7 @@ void QW_UpdateUDPStuff(sv_t *qtv) f = v->next; v->next = f->next; - QW_FreeViewer(f); + QW_FreeViewer(qtv, f); } if (v->maysend && !qtv->parsingconnectiondata) //don't send incompleate connection data. diff --git a/fteqtv/rcon.c b/fteqtv/rcon.c index a57e32b66..5b5daf5df 100644 --- a/fteqtv/rcon.c +++ b/fteqtv/rcon.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -26,7 +26,7 @@ char *Info_ValueForKey (char *s, const char *key, char *buffer, int buffersize) { char pkey[1024]; char *o; - + if (*s == '\\') s++; while (1) @@ -59,7 +59,7 @@ char *Info_ValueForKey (char *s, const char *key, char *buffer, int buffersize) return buffer; } *o++ = *s++; - + if (o+2 >= buffer+buffersize) //hrm. hackers at work.. { *buffer='\0'; @@ -172,7 +172,7 @@ void Info_SetValueForStarKey (char *s, const char *key, const char *value, int m if (!value || !strlen(value)) return; - _snprintf (newv, sizeof(newv)-1, "\\%s\\%s", key, value); + snprintf (newv, sizeof(newv)-1, "\\%s\\%s", key, value); newv[sizeof(newv)-1] = '\0'; if ((int)(strlen(newv) + strlen(s) + 1) > maxsize) @@ -209,13 +209,13 @@ char *COM_ParseToken (char *data, char *out, int outsize, const char *punctuatio if (!punctuation) punctuation = DEFAULT_PUNCTUATION; - + len = 0; out[0] = 0; - + if (!data) return NULL; - + // skip whitespace skipwhite: while ( (c = *data) <= ' ') @@ -224,7 +224,7 @@ skipwhite: return NULL; // end of file; data++; } - + // skip // comments if (c=='/') { @@ -243,7 +243,7 @@ skipwhite: goto skipwhite; } } - + // handle quoted strings specially if (c == '\"') @@ -288,7 +288,7 @@ skipwhite: if (strchr(punctuation, c)) break; } while (c>32); - + out[len] = 0; return data; } @@ -355,7 +355,7 @@ char *Rcon_Command(sv_t *qtv, char *command, char *buffer, int sizeofbuffer, qbo else if (!strcmp(arg[0], "option")) { if (!*arg[1]) - return "option X Y\nWhere X is choke/late/talking/hostname/nobsp and Y is (mostly) 0/1\n"; + return "option X Y\nWhere X is choke/late/talking/hostname/nobsp/master/maxviewers/maxproxies and Y is (mostly) 0/1\n"; if (!strcmp(arg[1], "choke")) qtv->chokeonnotupdated = !!atoi(arg[2]); @@ -383,6 +383,10 @@ char *Rcon_Command(sv_t *qtv, char *command, char *buffer, int sizeofbuffer, qbo if (NET_StringToAddr(arg[1], &addr)) NET_SendPacket (qtv->qwdsocket, 1, "k", addr); } + else if (!strcmp(arg[1], "maxviewers")) + qtv->maxviewers = atoi(arg[2]); + else if (!strcmp(arg[1], "maxproxies")) + qtv->maxproxies = atoi(arg[2]); else return "Option not recognised\n"; return "Set\n"; @@ -436,7 +440,7 @@ char *Rcon_Command(sv_t *qtv, char *command, char *buffer, int sizeofbuffer, qbo } else if (!strcmp(arg[0], "help")) { - return "FTEQTV proxy\nValid commands: connect, file, status, option\n"; + return "FTEQTV proxy version "VERSION"\nValid commands: connect, file, status, option, mvdport, port, reconnect\n"; } else if (!strcmp(arg[0], "reconnect")) { @@ -450,17 +454,33 @@ char *Rcon_Command(sv_t *qtv, char *command, char *buffer, int sizeofbuffer, qbo { int news; int newp = atoi(arg[1]); - news = Net_MVDListen(newp); - if (news != INVALID_SOCKET) + if (!newp) { - closesocket(qtv->listenmvd); - qtv->listenmvd = news; - qtv->tcplistenportnum = newp; - return "Opened tcp port\n"; + if (qtv->listenmvd != INVALID_SOCKET) + { + closesocket(qtv->listenmvd); + qtv->listenmvd = INVALID_SOCKET; + qtv->tcplistenportnum = 0; + + return "mvd port is now closed\n"; + } + return "Already closed\n"; } else - return "Failed to open tcp port\n"; + { + news = Net_MVDListen(newp); + + if (news != INVALID_SOCKET) + { + closesocket(qtv->listenmvd); + qtv->listenmvd = news; + qtv->tcplistenportnum = newp; + return "Opened tcp port\n"; + } + else + return "Failed to open tcp port\n"; + } } else if (!strcmp(arg[0], "ping")) @@ -474,22 +494,41 @@ char *Rcon_Command(sv_t *qtv, char *command, char *buffer, int sizeofbuffer, qbo return "couldn't resolve\n"; } - else if (!strcmp(arg[0], "port")) + else if (!strcmp(arg[0], "port") || !strcmp(arg[0], "udpport")) { int news; int newp = atoi(arg[1]); - news = QW_InitUDPSocket(newp); - if (news != INVALID_SOCKET) + if (!localcommand) + return "Changing udp port is not allowed via rcon\n"; + + if (!newp) { - qtv->mastersendtime = qtv->curtime; - closesocket(qtv->qwdsocket); - qtv->qwdsocket = news; - qtv->qwlistenportnum = newp; - return "Opened udp port\n"; + if (qtv->listenmvd != INVALID_SOCKET) + { + closesocket(qtv->listenmvd); + qtv->listenmvd = INVALID_SOCKET; + qtv->tcplistenportnum = 0; + + return "Closed udp port\n"; + } + return "udp port was already closed\n"; } else - return "Failed to open udp port\n"; + { + news = QW_InitUDPSocket(newp); + + if (news != INVALID_SOCKET) + { + qtv->mastersendtime = qtv->curtime; + closesocket(qtv->qwdsocket); + qtv->qwdsocket = news; + qtv->qwlistenportnum = newp; + return "Opened udp port\n"; + } + else + return "Failed to open udp port\n"; + } } else if (!strcmp(arg[0], "password")) diff --git a/fteqtv/source.c b/fteqtv/source.c index a08dc3023..179ad5e38 100644 --- a/fteqtv/source.c +++ b/fteqtv/source.c @@ -264,6 +264,14 @@ void Net_FindProxies(sv_t *qtv) if (sock == INVALID_SOCKET) return; + if (qtv->numproxies >= qtv->maxproxies && qtv->maxproxies) + { + const char buffer[] = {dem_all, 1, 'P','r','o','x','y',' ','i','s',' ','f','u','l','l','.'}; + send(sock, buffer, strlen(buffer), 0); + closesocket(sock); + return; + } + prox = malloc(sizeof(*prox)); memset(prox, 0, sizeof(*prox)); prox->flushing = true; //allow the buffer overflow resumption code to send the connection info. @@ -272,6 +280,8 @@ void Net_FindProxies(sv_t *qtv) prox->next = qtv->proxies; qtv->proxies = prox; + + qtv->numproxies++; } qboolean Net_FileProxy(sv_t *qtv, char *filename) @@ -283,6 +293,8 @@ qboolean Net_FileProxy(sv_t *qtv, char *filename) if (!f) return false; + //no full proxy check, this is going to be used by proxy admins, who won't want to have to raise the limit to start recording. + prox = malloc(sizeof(*prox)); memset(prox, 0, sizeof(*prox)); prox->flushing = true; //allow the buffer overflow resumption code to send the connection info. @@ -292,6 +304,8 @@ qboolean Net_FileProxy(sv_t *qtv, char *filename) prox->next = qtv->proxies; qtv->proxies = prox; + qtv->numproxies++; + return true; } @@ -498,7 +512,7 @@ void Net_SendConnectionMVD(sv_t *qtv, oproxy_t *prox) Prox_SendMessage(prox, msg.data, msg.cursize, dem_read, (unsigned)-1); msg.cursize = 0; } - + for (prespawn = 0;prespawn >= 0;) { prespawn = SendList(qtv, prespawn, qtv->modellist, svc_modellist, &msg); @@ -562,6 +576,7 @@ void Net_ForwardStream(sv_t *qtv, char *buffer, int length) else closesocket(fre->sock); free(fre); + qtv->numproxies--; qtv->proxies = next; } @@ -576,6 +591,7 @@ void Net_ForwardStream(sv_t *qtv, char *buffer, int length) else closesocket(fre->sock); free(fre); + qtv->numproxies--; prox->next = next; } @@ -595,7 +611,7 @@ void Net_ForwardStream(sv_t *qtv, char *buffer, int length) if (prox->drop) continue; - + //add the new data Net_ProxySend(prox, buffer, length); @@ -710,22 +726,14 @@ void NetSleep(sv_t *tv) #ifdef _WIN32 for (;;) -#else - if (FD_ISSET(STDIN, &socketset)) -#endif { char buffer[8192]; char *result; char c; -#ifdef _WIN32 if (!kbhit()) break; - else - c = getch(); -#else - c = recv(STDIN, &c, 1, 0); -#endif + c = getch(); if (c == '\n' || c == '\r') { @@ -754,10 +762,30 @@ void NetSleep(sv_t *tv) tv->commandinput[tv->inputlength++] = c; tv->commandinput[tv->inputlength] = '\0'; } - } - + }if (FD_ISSET(STDIN, &socketset)) printf("\r%s \b", tv->commandinput); } +#else + if (FD_ISSET(STDIN, &socketset)) + { + char buffer[8192]; + char *result; + tv->inputlength = read (0, tv->commandinput, sizeof(tv->commandinput)); + if (tv->inputlength >= 1) + { + tv->commandinput[tv->inputlength-1] = 0; // rip off the /n and terminate + + if (tv->inputlength) + { + tv->commandinput[tv->inputlength] = '\0'; + result = Rcon_Command(tv, tv->commandinput, buffer, sizeof(buffer), true); + printf("%s", result); + tv->inputlength = 0; + tv->commandinput[0] = '\0'; + } + } + } +#endif } void Trim(char *s) @@ -1029,6 +1057,9 @@ int main(int argc, char **argv) qtv.listenmvd = INVALID_SOCKET; qtv.sourcesock = INVALID_SOCKET; + qtv.maxviewers = 100; + qtv.maxproxies = 100; + line[sizeof(line)-1] = '\0'; if (argc < 2)