xmpp NAT holepunching (ICE) is now implemented. it doesn't know how to do relays.

xmpp voip support (speex only). just because.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4413 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-06-29 16:01:07 +00:00
parent 601373a1c3
commit 0823eb0968
21 changed files with 2875 additions and 1060 deletions

View File

@ -3698,8 +3698,6 @@ void Host_DoRunFile(hrf_t *f)
VFS_SEEK(f->srcfile, 0); VFS_SEEK(f->srcfile, 0);
COM_StripExtension(COM_SkipPath(f->fname), qname, sizeof(qname));
f->dstfile = FS_OpenVFS(qname, "rb", FS_GAME); f->dstfile = FS_OpenVFS(qname, "rb", FS_GAME);
if (f->dstfile) if (f->dstfile)
{ {
@ -3987,6 +3985,7 @@ double Host_Frame (double time)
#ifdef PLUGINS #ifdef PLUGINS
Plug_Tick(); Plug_Tick();
#endif #endif
NET_Tick();
if (cl.paused) if (cl.paused)
cl.gametimemark += time; cl.gametimemark += time;

View File

@ -375,6 +375,8 @@ void CL_PredictUsercmd (int pnum, int entnum, player_state_t *from, player_state
CL_PredictUsercmd (pnum, entnum, &temp, to, &split); CL_PredictUsercmd (pnum, entnum, &temp, to, &split);
return; return;
} }
if (!cl.worldmodel || cl.worldmodel->needload)
return;
VectorCopy (from->origin, pmove.origin); VectorCopy (from->origin, pmove.origin);
VectorCopy (u->angles, pmove.angles); VectorCopy (u->angles, pmove.angles);

View File

@ -138,6 +138,8 @@ void Con_Destroy (console_t *con)
console_t *Con_FindConsole(char *name) console_t *Con_FindConsole(char *name)
{ {
console_t *con; console_t *con;
if (!strcmp(name, "current") && con_current)
return con_current;
for (con = &con_main; con; con = con->next) for (con = &con_main; con; con = con->next)
{ {
if (!strcmp(con->name, name)) if (!strcmp(con->name, name))
@ -149,6 +151,10 @@ console_t *Con_FindConsole(char *name)
console_t *Con_Create(char *name, unsigned int flags) console_t *Con_Create(char *name, unsigned int flags)
{ {
console_t *con; console_t *con;
if (!strcmp(name, "current"))
return NULL;
if (!strcmp(name, "MAIN"))
return NULL;
con = Z_Malloc(sizeof(console_t)); con = Z_Malloc(sizeof(console_t));
Q_strncpyz(con->name, name, sizeof(con->name)); Q_strncpyz(con->name, name, sizeof(con->name));

View File

@ -10,6 +10,7 @@ cvar_t menualias = SCVAR("menualias", "");
void M_Script_Remove (menu_t *menu) void M_Script_Remove (menu_t *menu)
{ {
menu_script = NULL; menu_script = NULL;
Cbuf_AddText(va("set option cancel\n%s\n", menualias.string), RESTRICT_LOCAL);
Cvar_Set(&menualias, ""); Cvar_Set(&menualias, "");
} }
qboolean M_Script_Key (int key, menu_t *menu) qboolean M_Script_Key (int key, menu_t *menu)
@ -29,12 +30,11 @@ qboolean M_Script_Key (int key, menu_t *menu)
void M_MenuS_Clear_f (void) void M_MenuS_Clear_f (void)
{ {
Cvar_Set(&menualias, "");
if (menu_script) if (menu_script)
{ {
M_RemoveMenu(menu_script); M_RemoveMenu(menu_script);
} }
// Cvar_Set(menualias.name, "");
} }
void M_MenuS_Script_f (void) //create a menu. void M_MenuS_Script_f (void) //create a menu.

View File

@ -617,15 +617,35 @@ static void M_Menu_Prompt_Cancel (struct menu_s *gm)
void M_Menu_Prompt (void (*callback)(void *, int), void *ctx, char *m1, char *m2, char *m3, char *optionyes, char *optionno, char *optioncancel) void M_Menu_Prompt (void (*callback)(void *, int), void *ctx, char *m1, char *m2, char *m3, char *optionyes, char *optionno, char *optioncancel)
{ {
promptmenu_t *m; promptmenu_t *m;
char *t;
key_dest = key_menu; key_dest = key_menu;
m_state = m_complex; m_state = m_complex;
m = (promptmenu_t*)M_CreateMenuInfront(sizeof(*m) - sizeof(m->m)); m = (promptmenu_t*)M_CreateMenuInfront(sizeof(*m) - sizeof(m->m) + strlen(m1)+strlen(m2)+strlen(m3)+strlen(optionyes)+strlen(optionyes)+strlen(optioncancel)+6);
m->callback = callback; m->callback = callback;
m->ctx = ctx; m->ctx = ctx;
m->m.remove = M_Menu_Prompt_Cancel; m->m.remove = M_Menu_Prompt_Cancel;
t = (char*)(m+1);
strcpy(t, m1);
m1 = t;
t += strlen(t)+1;
strcpy(t, m2);
m2 = t;
t += strlen(t)+1;
strcpy(t, m3);
m3 = t;
t += strlen(t)+1;
strcpy(t, optionyes);
optionyes = t;
t += strlen(t)+1;
strcpy(t, optionno);
optionno = t;
t += strlen(t)+1;
strcpy(t, optioncancel);
optioncancel = t;
MC_AddWhiteText(&m->m, 64, 84, m1, false); MC_AddWhiteText(&m->m, 64, 84, m1, false);
MC_AddWhiteText(&m->m, 64, 92, m2, false); MC_AddWhiteText(&m->m, 64, 92, m2, false);
MC_AddWhiteText(&m->m, 64, 100, m3, false); MC_AddWhiteText(&m->m, 64, 100, m3, false);

View File

@ -341,9 +341,6 @@ static void PClassic_DrawParticles(void)
static float oldtime; static float oldtime;
RSpeedMark(); RSpeedMark();
//make sure all ents are pushed through first
RQ_RenderBatchClear();
if (!active_particles) if (!active_particles)
{ {
oldtime = cl.time; oldtime = cl.time;

View File

@ -1534,12 +1534,23 @@ static void P_ParticleEffect_f(void)
if (!settype) if (!settype)
{ {
if (ptype->looks.type == PT_NORMAL && !*ptype->texname) if (ptype->looks.type == PT_NORMAL && !*ptype->texname)
ptype->looks.type = PT_SPARK; {
if (ptype->looks.type == PT_SPARK) if (ptype->scale)
{
ptype->looks.type = PT_SPARKFAN;
Con_DPrintf("effect %s lacks a texture. assuming type sparkfan.\n", ptype->name);
}
else
{
ptype->looks.type = PT_SPARK;
Con_DPrintf("effect %s lacks a texture. assuming type spark.\n", ptype->name);
}
}
else if (ptype->looks.type == PT_SPARK)
{ {
if (*ptype->texname) if (*ptype->texname)
ptype->looks.type = PT_TEXTUREDSPARK; ptype->looks.type = PT_TEXTUREDSPARK;
if (ptype->scale) else if (ptype->scale)
ptype->looks.type = PT_SPARKFAN; ptype->looks.type = PT_SPARKFAN;
} }
} }
@ -4836,8 +4847,8 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type)
continue; continue;
p = b->p; p = b->p;
q->rgba[3] = 1; // q->rgba[3] = 1;
p->rgba[3] = 1; // p->rgba[3] = 1;
VectorSubtract(r_refdef.vieworg, q->org, v); VectorSubtract(r_refdef.vieworg, q->org, v);
VectorNormalize(v); VectorNormalize(v);

View File

@ -225,9 +225,11 @@ void S_SoundInfo_f(void)
enum enum
{ {
VOIP_SPEEX = 0, //original supported codec VOIP_SPEEX_OLD = 0, //original supported codec (with needless padding and at the wrong rate to keep quake implementations easy)
VOIP_RAW = 1, //support is not recommended. VOIP_RAW = 1, //support is not recommended.
VOIP_OPUS = 2, //supposed to be better than speex. VOIP_OPUS = 2, //supposed to be better than speex.
VOIP_SPEEX_NARROW = 3, //narrowband speex. packed data.
VOIP_SPEEX_WIDE = 4, //wideband speex. packed data.
VOIP_INVALID = 16 //not currently generating audio. VOIP_INVALID = 16 //not currently generating audio.
}; };
@ -242,7 +244,8 @@ static struct
SpeexBits encbits; SpeexBits encbits;
SpeexBits decbits[MAX_CLIENTS]; SpeexBits decbits[MAX_CLIENTS];
const SpeexMode *mode; const SpeexMode *modenb;
const SpeexMode *modewb;
} speex; } speex;
struct struct
@ -280,6 +283,7 @@ static struct
unsigned char capturebuf[32768]; /*pending data*/ unsigned char capturebuf[32768]; /*pending data*/
unsigned int capturepos;/*amount of pending data*/ unsigned int capturepos;/*amount of pending data*/
unsigned int encsequence;/*the outgoing sequence count*/ unsigned int encsequence;/*the outgoing sequence count*/
unsigned int enctimestamp;/*for rtp streaming*/
unsigned int generation;/*incremented whenever capture is restarted*/ unsigned int generation;/*incremented whenever capture is restarted*/
qboolean wantsend; /*set if we're capturing data to send*/ qboolean wantsend; /*set if we're capturing data to send*/
float voiplevel; /*your own voice level*/ float voiplevel; /*your own voice level*/
@ -439,7 +443,8 @@ static qboolean S_Speex_Init(void)
} }
#endif #endif
s_voip.speex.mode = qspeex_lib_get_mode(SPEEX_MODEID_NB); s_voip.speex.modenb = qspeex_lib_get_mode(SPEEX_MODEID_NB);
s_voip.speex.modewb = qspeex_lib_get_mode(SPEEX_MODEID_WB);
s_voip.speex.loaded = true; s_voip.speex.loaded = true;
return s_voip.speex.loaded; return s_voip.speex.loaded;
@ -498,7 +503,9 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
//make sure old state is closed properly. //make sure old state is closed properly.
switch(s_voip.deccodec[sender]) switch(s_voip.deccodec[sender])
{ {
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
qspeex_decoder_destroy(s_voip.decoder[sender]); qspeex_decoder_destroy(s_voip.decoder[sender]);
break; break;
case VOIP_OPUS: case VOIP_OPUS:
@ -513,17 +520,23 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
{ {
default: //codec not supported. default: //codec not supported.
return; return;
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
if (!S_Speex_Init()) if (!S_Speex_Init())
return; //speex not usable. return; //speex not usable.
if (codec == VOIP_SPEEX_NARROW)
s_voip.decsamplerate[sender] = 11025; s_voip.decsamplerate[sender] = 8000;
else if (codec == VOIP_SPEEX_WIDE)
s_voip.decsamplerate[sender] = 16000;
else
s_voip.decsamplerate[sender] = 11025;
s_voip.decframesize[sender] = 160; s_voip.decframesize[sender] = 160;
if (!s_voip.decoder[sender]) if (!s_voip.decoder[sender])
{ {
qspeex_bits_init(&s_voip.speex.decbits[sender]); qspeex_bits_init(&s_voip.speex.decbits[sender]);
qspeex_bits_reset(&s_voip.speex.decbits[sender]); qspeex_bits_reset(&s_voip.speex.decbits[sender]);
s_voip.decoder[sender] = qspeex_decoder_init(s_voip.speex.mode); s_voip.decoder[sender] = qspeex_decoder_init(codec==VOIP_SPEEX_WIDE?s_voip.speex.modewb:s_voip.speex.modenb);
if (!s_voip.decoder[sender]) if (!s_voip.decoder[sender])
return; return;
} }
@ -576,7 +589,9 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
} }
switch(codec) switch(codec)
{ {
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
qspeex_decode_int(s_voip.decoder[sender], NULL, decodebuf + decodesamps); qspeex_decode_int(s_voip.decoder[sender], NULL, decodebuf + decodesamps);
decodesamps += s_voip.decframesize[sender]; decodesamps += s_voip.decframesize[sender];
break; break;
@ -601,25 +616,46 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
default: default:
bytes = 0; bytes = 0;
break; break;
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
bytes--; case VOIP_SPEEX_NARROW:
len = *start++; case VOIP_SPEEX_WIDE:
if (bytes < len) if (codec == VOIP_SPEEX_OLD)
break; { //older versions support only this, and require this extra bit.
bytes--;
len = *start++;
if (bytes < len)
break;
}
else
len = bytes;
qspeex_bits_read_from(&s_voip.speex.decbits[sender], start, len); qspeex_bits_read_from(&s_voip.speex.decbits[sender], start, len);
bytes -= len; bytes -= len;
start += len; start += len;
qspeex_decode_int(s_voip.decoder[sender], &s_voip.speex.decbits[sender], decodebuf + decodesamps); while (qspeex_decode_int(s_voip.decoder[sender], &s_voip.speex.decbits[sender], decodebuf + decodesamps) == 0)
decodesamps += s_voip.decframesize[sender]; {
decodesamps += s_voip.decframesize[sender];
s_voip.decseq[sender]++;
seq++;
if (decodesamps + s_voip.decframesize[sender] > sizeof(decodebuf)/sizeof(decodebuf[0]))
{
S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value);
decodesamps = 0;
}
}
break; break;
case VOIP_OPUS: case VOIP_OPUS:
//FIXME: we shouldn't need this crap
bytes--; bytes--;
len = *start++; len = *start++;
if (bytes < len) if (bytes < len)
break; break;
r = qopus_decode(s_voip.decoder[sender], start, len, decodebuf + decodesamps, sizeof(decodebuf)/sizeof(decodebuf[0]) - decodesamps, false); r = qopus_decode(s_voip.decoder[sender], start, len, decodebuf + decodesamps, sizeof(decodebuf)/sizeof(decodebuf[0]) - decodesamps, false);
if (r > 0) if (r > 0)
{
decodesamps += r; decodesamps += r;
s_voip.decseq[sender]++;
seq++;
}
else if (r < 0) else if (r < 0)
Con_Printf("Opus decoding error %i\n", r); Con_Printf("Opus decoding error %i\n", r);
@ -627,8 +663,6 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
start += len; start += len;
break; break;
} }
s_voip.decseq[sender]++;
seq++;
} }
if (drops) if (drops)
@ -638,6 +672,22 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value); S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value);
} }
#ifdef SUPPORT_ICE
void S_Voip_RTP_Parse(unsigned short sequence, char *codec, unsigned char *data, unsigned int datalen)
{
if (!strcmp(codec, "speex@8000"))
S_Voip_Decode(MAX_CLIENTS-1, VOIP_SPEEX_NARROW, 0, sequence, datalen, data);
if (!strcmp(codec, "speex@11025"))
S_Voip_Decode(MAX_CLIENTS-1, VOIP_SPEEX_OLD, 0, sequence, datalen, data); //very much non-standard rtp
if (!strcmp(codec, "speex@16000"))
S_Voip_Decode(MAX_CLIENTS-1, VOIP_SPEEX_WIDE, 0, sequence, datalen, data);
}
qboolean NET_RTP_Transmit(unsigned int sequence, unsigned int timestamp, char *codec, char *cdata, int clength);
qboolean NET_RTP_Active(void);
#else
#define NET_RTP_Active() false
#endif
void S_Voip_Parse(void) void S_Voip_Parse(void)
{ {
unsigned int sender; unsigned int sender;
@ -674,7 +724,8 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
unsigned int outpos;//in bytes unsigned int outpos;//in bytes
unsigned int encpos;//in bytes unsigned int encpos;//in bytes
short *start; short *start;
unsigned char initseq;//in frames unsigned int initseq;//in frames
unsigned int inittimestamp;//in samples
unsigned int i; unsigned int i;
unsigned int samps; unsigned int samps;
float level, f; float level, f;
@ -682,6 +733,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
float micamp = cl_voip_micamp.value; float micamp = cl_voip_micamp.value;
qboolean voipsendenable = true; qboolean voipsendenable = true;
int voipcodec = cl_voip_codec.ival; int voipcodec = cl_voip_codec.ival;
qboolean rtpstream = NET_RTP_Active();
if (buf) if (buf)
{ {
@ -693,6 +745,14 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
} }
else else
voipsendenable = cl_voip_test.ival; voipsendenable = cl_voip_test.ival;
if (rtpstream)
{
voipsendenable = true;
//if rtp streaming is enabled, hack the codec to something better supported
if (voipcodec == VOIP_SPEEX_OLD)
voipcodec = VOIP_SPEEX_NARROW;
}
voicevolumemod = s_voip.lastspoke_any > realtime?cl_voip_ducking.value:1; voicevolumemod = s_voip.lastspoke_any > realtime?cl_voip_ducking.value:1;
@ -714,7 +774,9 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
} }
switch(s_voip.enccodec) switch(s_voip.enccodec)
{ {
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
break; break;
case VOIP_OPUS: case VOIP_OPUS:
qopus_encoder_destroy(s_voip.encoder); qopus_encoder_destroy(s_voip.encoder);
@ -749,7 +811,9 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
/*see if we can init our encoding codec...*/ /*see if we can init our encoding codec...*/
switch(voipcodec) switch(voipcodec)
{ {
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
if (!S_Speex_Init()) if (!S_Speex_Init())
{ {
Con_Printf("Unable to use speex codec - not installed\n"); Con_Printf("Unable to use speex codec - not installed\n");
@ -758,12 +822,17 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
qspeex_bits_init(&s_voip.speex.encbits); qspeex_bits_init(&s_voip.speex.encbits);
qspeex_bits_reset(&s_voip.speex.encbits); qspeex_bits_reset(&s_voip.speex.encbits);
s_voip.encoder = qspeex_encoder_init(s_voip.speex.mode); s_voip.encoder = qspeex_encoder_init(voipcodec == VOIP_SPEEX_WIDE?s_voip.speex.modewb:s_voip.speex.modenb);
if (!s_voip.encoder) if (!s_voip.encoder)
return; return;
qspeex_encoder_ctl(s_voip.encoder, SPEEX_GET_FRAME_SIZE, &s_voip.encframesize); qspeex_encoder_ctl(s_voip.encoder, SPEEX_GET_FRAME_SIZE, &s_voip.encframesize);
qspeex_encoder_ctl(s_voip.encoder, SPEEX_GET_SAMPLING_RATE, &s_voip.encsamplerate); qspeex_encoder_ctl(s_voip.encoder, SPEEX_GET_SAMPLING_RATE, &s_voip.encsamplerate);
s_voip.encsamplerate = 11025; if (voipcodec == VOIP_SPEEX_NARROW)
s_voip.encsamplerate = 8000;
else if (voipcodec == VOIP_SPEEX_WIDE)
s_voip.encsamplerate = 16000;
else
s_voip.encsamplerate = 11025;
qspeex_encoder_ctl(s_voip.encoder, SPEEX_SET_SAMPLING_RATE, &s_voip.encsamplerate); qspeex_encoder_ctl(s_voip.encoder, SPEEX_SET_SAMPLING_RATE, &s_voip.encsamplerate);
break; break;
case VOIP_OPUS: case VOIP_OPUS:
@ -833,7 +902,9 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
//reset codecs so they start with a clean slate when new audio blocks are generated. //reset codecs so they start with a clean slate when new audio blocks are generated.
switch(s_voip.enccodec) switch(s_voip.enccodec)
{ {
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
qspeex_bits_reset(&s_voip.speex.encbits); qspeex_bits_reset(&s_voip.speex.encbits);
break; break;
case VOIP_OPUS: case VOIP_OPUS:
@ -861,10 +932,11 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
} }
initseq = s_voip.encsequence; initseq = s_voip.encsequence;
inittimestamp = s_voip.enctimestamp;
level = 0; level = 0;
samps=0; samps=0;
//*2 for 16bit audio input. //*2 for 16bit audio input.
for (encpos = 0, outpos = 0; s_voip.capturepos-encpos >= s_voip.encframesize*2 && sizeof(outbuf)-outpos > 64; s_voip.encsequence++) for (encpos = 0, outpos = 0; s_voip.capturepos-encpos >= s_voip.encframesize*2 && sizeof(outbuf)-outpos > 64; )
{ {
start = (short*)(s_voip.capturebuf + encpos); start = (short*)(s_voip.capturebuf + encpos);
@ -902,7 +974,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
switch(s_voip.enccodec) switch(s_voip.enccodec)
{ {
case VOIP_SPEEX: case VOIP_SPEEX_OLD:
qspeex_bits_reset(&s_voip.speex.encbits); qspeex_bits_reset(&s_voip.speex.encbits);
qspeex_encode_int(s_voip.encoder, start, &s_voip.speex.encbits); qspeex_encode_int(s_voip.encoder, start, &s_voip.speex.encbits);
len = qspeex_bits_write(&s_voip.speex.encbits, outbuf+(outpos+1), sizeof(outbuf) - (outpos+1)); len = qspeex_bits_write(&s_voip.speex.encbits, outbuf+(outpos+1), sizeof(outbuf) - (outpos+1));
@ -910,6 +982,28 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
len = 0; len = 0;
outbuf[outpos] = len; outbuf[outpos] = len;
outpos += 1+len; outpos += 1+len;
s_voip.encsequence++;
s_voip.enctimestamp += s_voip.encframesize;
samps+=s_voip.encframesize;
encpos += s_voip.encframesize*2;
break;
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
qspeex_bits_reset(&s_voip.speex.encbits);
for (; s_voip.capturepos-encpos >= s_voip.encframesize*2 && sizeof(outbuf)-outpos > 64; )
{
start = (short*)(s_voip.capturebuf + encpos);
qspeex_encode_int(s_voip.encoder, start, &s_voip.speex.encbits);
s_voip.encsequence++;
samps+=s_voip.encframesize;
s_voip.enctimestamp += s_voip.encframesize;
encpos += s_voip.encframesize*2;
if (rtpstream)
break;
}
len = qspeex_bits_write(&s_voip.speex.encbits, outbuf+outpos, sizeof(outbuf) - outpos);
outpos += len;
break; break;
case VOIP_OPUS: case VOIP_OPUS:
len = qopus_encode(s_voip.encoder, start, s_voip.encframesize, outbuf+(outpos+1), max(255, sizeof(outbuf) - (outpos+1))); len = qopus_encode(s_voip.encoder, start, s_voip.encframesize, outbuf+(outpos+1), max(255, sizeof(outbuf) - (outpos+1)));
@ -925,20 +1019,25 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
//error! //error!
Con_Printf("Opus encoding error: %i\n", len); Con_Printf("Opus encoding error: %i\n", len);
} }
s_voip.encsequence++;
samps+=s_voip.encframesize;
s_voip.enctimestamp += s_voip.encframesize;
encpos += s_voip.encframesize*2;
break; break;
default: default:
outbuf[outpos] = 0; outbuf[outpos] = 0;
break; break;
} }
samps+=s_voip.encframesize;
encpos += s_voip.encframesize*2; if (rtpstream)
break;
} }
if (samps) if (samps)
{ {
float nl; float nl;
nl = (3000*level) / (32767.0f*32767*samps); nl = (3000*level) / (32767.0f*32767*samps);
s_voip.voiplevel = (s_voip.voiplevel*7 + nl)/8; s_voip.voiplevel = (s_voip.voiplevel*7 + nl)/8;
if (s_voip.voiplevel < cl_voip_vad_threshhold.ival && !(cl_voip_send.ival & 2)) if (s_voip.voiplevel < cl_voip_vad_threshhold.ival && !(cl_voip_send.ival & 6))
{ {
/*try and dump it, it was too quiet, and they're not pressing +voip*/ /*try and dump it, it was too quiet, and they're not pressing +voip*/
if (s_voip.keeps > samps) if (s_voip.keeps > samps)
@ -965,7 +1064,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
if (outpos && (!buf || buf->maxsize - buf->cursize >= outpos+4)) if (outpos && (!buf || buf->maxsize - buf->cursize >= outpos+4))
{ {
if (buf) if (buf && (cl_voip_send.ival & ~4))
{ {
MSG_WriteByte(buf, clc); MSG_WriteByte(buf, clc);
MSG_WriteByte(buf, (s_voip.enccodec<<4) | (s_voip.generation & 0x0f)); /*gonna leave that nibble clear here... in this version, the client will ignore packets with those bits set. can use them for codec or something*/ MSG_WriteByte(buf, (s_voip.enccodec<<4) | (s_voip.generation & 0x0f)); /*gonna leave that nibble clear here... in this version, the client will ignore packets with those bits set. can use them for codec or something*/
@ -974,6 +1073,18 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
SZ_Write(buf, outbuf, outpos); SZ_Write(buf, outbuf, outpos);
} }
switch(s_voip.enccodec)
{
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
case VOIP_SPEEX_OLD:
NET_RTP_Transmit(initseq, inittimestamp, va("speex@%i", s_voip.encsamplerate), outbuf, outpos);
break;
case VOIP_OPUS:
NET_RTP_Transmit(initseq, inittimestamp, "opus", outbuf, outpos);
break;
}
if (cl_voip_test.ival) if (cl_voip_test.ival)
S_Voip_Decode(cl.playerview[0].playernum, s_voip.enccodec, s_voip.generation & 0x0f, initseq, outpos, outbuf); S_Voip_Decode(cl.playerview[0].playernum, s_voip.enccodec, s_voip.generation & 0x0f, initseq, outpos, outbuf);

View File

@ -246,7 +246,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define IRCCONNECT //an ircconnect command, that allows the player to connect to irc-encapsulated qw protocols... yeah, really. #define IRCCONNECT //an ircconnect command, that allows the player to connect to irc-encapsulated qw protocols... yeah, really.
#define PLUGINS //qvm/dll plugins. #define PLUGINS //qvm/dll plugins.
#define SUPPORT_ICE //Internet Connection Establishment protocol, for peer-to-peer connections #define SUPPORT_ICE //Interactive Connectivity Establishment protocol, for peer-to-peer connections
#ifdef _DEBUG #ifdef _DEBUG
// #define OFFSCREENGECKO //FIXME: move to plugin and remove from engine // #define OFFSCREENGECKO //FIXME: move to plugin and remove from engine

View File

@ -510,6 +510,9 @@ qbyte COM_BlockSequenceCheckByte (qbyte *base, int length, int sequence, unsigne
qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence); qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence); qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
int SHA1(char *digest, int maxdigestsize, char *string, int stringlen);
int SHA1_HMAC(unsigned char *digest, int maxdigestsize, unsigned char *key, int keylen, unsigned char *data, int datalen);
int version_number(void); int version_number(void);
char *version_string(void); char *version_string(void);

View File

@ -106,8 +106,8 @@ typedef struct conline_s {
float time; float time;
} conline_t; } conline_t;
#define CONF_HIDDEN 1 #define CONF_HIDDEN 1 /*do not show in the console list (unless active)*/
#define CONF_NOTIFY 2 #define CONF_NOTIFY 2 /*text printed to console also appears as notify lines*/
#define CONF_NOTIFY_BOTTOM 4 /*align the bottom*/ #define CONF_NOTIFY_BOTTOM 4 /*align the bottom*/
#define CONF_NOTIMES 8 #define CONF_NOTIMES 8
typedef struct console_s typedef struct console_s

View File

@ -83,6 +83,7 @@ int TCP_OpenStream (netadr_t *remoteaddr); //makes things easier
struct ftenet_connections_s; struct ftenet_connections_s;
void NET_Init (void); void NET_Init (void);
void NET_Tick (void);
void SVNET_RegisterCvars(void); void SVNET_RegisterCvars(void);
void NET_InitClient (void); void NET_InitClient (void);
void NET_InitServer (void); void NET_InitServer (void);

File diff suppressed because it is too large Load Diff

View File

@ -130,10 +130,12 @@
#endif #endif
#define EWOULDBLOCK WSAEWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#define EMSGSIZE WSAEMSGSIZE #define EMSGSIZE WSAEMSGSIZE
#define ECONNRESET WSAECONNRESET #define ECONNRESET WSAECONNRESET
#define ECONNABORTED WSAECONNABORTED #define ECONNABORTED WSAECONNABORTED
#define ECONNREFUSED WSAECONNREFUSED #define ECONNREFUSED WSAECONNREFUSED
#define ENOTCONN WSAENOTCONN
#define EACCES WSAEACCES #define EACCES WSAEACCES
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL #define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define EAFNOSUPPORT WSAEAFNOSUPPORT #define EAFNOSUPPORT WSAEAFNOSUPPORT
@ -196,11 +198,10 @@
#endif #endif
#if 1//def SUPPORT_ICE #if 1//def SUPPORT_ICE
struct icecandidate_s struct icecandinfo_s
{ {
struct icecandidate_s *next; char candidateid[64];
char *candidateid; char addr[64]; //v4/v6/fqdn. fqdn should prefer ipv6
char *addr; //v4/v6/fqdn. fqdn should prefer ipv6
int port; int port;
int transport; //0=udp. other values not supported int transport; //0=udp. other values not supported
int foundation; //to figure out... int foundation; //to figure out...
@ -213,42 +214,41 @@ struct icecandidate_s
ICE_PRFLX=2, ICE_PRFLX=2,
ICE_RELAY=3, ICE_RELAY=3,
} type; //says what sort of proxy is used. } type; //says what sort of proxy is used.
char *reladdr; //when proxied, this is our local info char reladdr[64]; //when proxied, this is our local info
int relport; int relport;
int generation; //for ice restarts. starts at 0. int generation; //for ice restarts. starts at 0.
int network; //which network device this comes from. int network; //which network device this comes from.
qboolean dirty;
}; };
struct icestate_s enum iceproto_e
{ {
struct icestate_s *next; ICEP_INVALID, //not allowed..
void *module; ICEP_QWSERVER, //we're server side
ICEP_QWCLIENT, //we're client side
int netsrc; ICEP_VOICE //speex. requires client.
enum icemode_e
{
ICE_RAW, //not actually interactive beyond a simple handshake.
ICE_ICE //rfc5245. meant to be able to holepunch, but not implemented properly yet.
} mode;
char *conname; //internal id.
char *friendlyname; //who you're talking to.
char *stunserver;//where to get our public ip from.
int stunport;
struct icecandidate_s *lc;
char *lpwd;
char *lfrag;
struct icecandidate_s *rc;
char *rpwd;
char *rfrag;
}; };
struct icestate_s *QDECL ICE_Create(void *module, char *conname, char *peername, enum icemode_e mode); //doesn't start pinging anything. enum icemode_e
struct icestate_s *QDECL ICE_Find(void *module, char *conname); {
void QDECL ICE_Begin(struct icestate_s *con, char *stunip, int stunport); //begins sending stun packets and stuff as required. data flows automagically. caller should poll ICE_GetLCandidateInfo periodically to pick up new candidates that need to be reported to the peer. ICEM_RAW, //not actually interactive beyond a simple handshake.
struct icecandidate_s *QDECL ICE_GetLCandidateInfo(struct icestate_s *con); //retrieves candidates that need reporting to the peer. ICEM_ICE //rfc5245. meant to be able to holepunch, but not implemented properly yet.
void QDECL ICE_AddRCandidateInfo(struct icestate_s *con, struct icecandidate_s *cand); //stuff that came from the peer. };
void QDECL ICE_Close(struct icestate_s *con); //bye then. enum icestate_e
void QDECL ICE_CloseModule(void *module); //closes all unclosed connections, with warning. {
ICE_INACTIVE, //idle.
ICE_FAILED,
ICE_CONNECTING, //exchanging pings.
ICE_CONNECTED //media is flowing, supposedly. sending keepalives.
};
struct icestate_s;
#define ICE_API_CURRENT "Internet Connectivity Establishment 0.0"
typedef struct
{
struct icestate_s *(QDECL *ICE_Create)(void *module, char *conname, char *peername, enum icemode_e mode, enum iceproto_e proto); //doesn't start pinging anything.
qboolean (QDECL *ICE_Set)(struct icestate_s *con, char *prop, char *value);
qboolean (QDECL *ICE_Get)(struct icestate_s *con, char *prop, char *value, int valuesize);
struct icecandinfo_s *(QDECL *ICE_GetLCandidateInfo)(struct icestate_s *con); //retrieves candidates that need reporting to the peer.
void (QDECL *ICE_AddRCandidateInfo)(struct icestate_s *con, struct icecandinfo_s *cand); //stuff that came from the peer.
void (QDECL *ICE_Close)(struct icestate_s *con); //bye then.
void (QDECL *ICE_CloseModule)(void *module); //closes all unclosed connections, with warning.
} icefuncs_t;
extern icefuncs_t iceapi;
#endif #endif

View File

@ -120,18 +120,8 @@ static qintptr_t VARGS Plug_GetNativePointer(void *offset, quintptr_t mask, cons
{ {
char *p = (char *)VM_POINTER(args[0]); char *p = (char *)VM_POINTER(args[0]);
#ifdef SUPPORT_ICE #ifdef SUPPORT_ICE
if (!strcmp(p, "ICE_Create")) if (!strcmp(p, ICE_API_CURRENT))
return (qintptr_t)ICE_Create; return (qintptr_t)&iceapi;
if (!strcmp(p, "ICE_Find"))
return (qintptr_t)ICE_Find;
if (!strcmp(p, "ICE_Begin"))
return (qintptr_t)ICE_Begin;
if (!strcmp(p, "ICE_GetLCandidateInfo"))
return (qintptr_t)ICE_GetLCandidateInfo;
if (!strcmp(p, "ICE_AddRCandidateInfo"))
return (qintptr_t)ICE_AddRCandidateInfo;
if (!strcmp(p, "ICE_Close"))
return (qintptr_t)ICE_Close;
#endif #endif
return (qintptr_t)NULL; return (qintptr_t)NULL;

View File

@ -191,3 +191,90 @@ int SHA1(char *digest, int maxdigestsize, char *string, int stringlen)
return DIGEST_SIZE; return DIGEST_SIZE;
} }
/* hmac-sha1.c -- hashed message authentication codes
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Simon Josefsson.
hacked up a bit by someone else...
*/
#define IPAD 0x36
#define OPAD 0x5c
static void memxor(char *dest, char *src, size_t length)
{
size_t i;
for (i = 0; i < length; i++)
{
dest[i] ^= src[i];
}
}
int SHA1_HMAC(unsigned char *digest, int maxdigestsize,
unsigned char *key, int keylen,
unsigned char *data, int datalen)
{
SHA1_CTX inner;
SHA1_CTX outer;
char optkeybuf[20];
char block[64];
char innerhash[20];
if (maxdigestsize < DIGEST_SIZE)
return 0;
/* Reduce the key's size, so that it becomes <= 64 bytes large. */
if (keylen > 64)
{
SHA1_CTX keyhash;
SHA1Init (&keyhash);
SHA1Update (&keyhash, key, keylen);
SHA1Final (optkeybuf, &keyhash);
key = optkeybuf;
keylen = 20;
}
/* Compute INNERHASH from KEY and IN. */
SHA1Init (&inner);
memset (block, IPAD, sizeof (block));
memxor (block, key, keylen);
SHA1Update (&inner, block, 64);
SHA1Update (&inner, data, datalen);
SHA1Final (innerhash, &inner);
/* Compute result from KEY and INNERHASH. */
SHA1Init (&outer);
memset (block, OPAD, sizeof (block));
memxor (block, key, keylen);
SHA1Update (&outer, block, 64);
SHA1Update (&outer, innerhash, 20);
SHA1Final (digest, &outer);
return DIGEST_SIZE;
}

View File

@ -4120,6 +4120,7 @@ void SV_MVDStream_Poll(void);
#ifdef PLUGINS #ifdef PLUGINS
Plug_Tick(); Plug_Tick();
#endif #endif
NET_Tick();
SV_GetConsoleCommands (); SV_GetConsoleCommands ();

View File

@ -309,7 +309,7 @@ qboolean Sys_Rename (char *oldfname, char *newfname)
return !rename(oldfname, newfname); return !rename(oldfname, newfname);
} }
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *fname, int fsize, void *parm, void *spath), void *parm, void *spath) int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *fname, int fsize, void *parm, searchpathfuncs_t *spath), void *parm, searchpathfuncs_t *spath)
{ {
HANDLE r; HANDLE r;
WIN32_FIND_DATA fd; WIN32_FIND_DATA fd;

File diff suppressed because it is too large Load Diff

View File

@ -103,11 +103,13 @@ char *XML_Markup(char *s, char *d, int dlen)
d+=xmlchars[i].namelen; d+=xmlchars[i].namelen;
*d++ = ';'; *d++ = ';';
s++; s++;
dlen -= xmlchars[i].namelen+2;
} }
else else
{ {
if (!dlen) if (!dlen)
break; break;
dlen--;
*d++ = *s++; *d++ = *s++;
} }
} }

View File

@ -20,7 +20,7 @@ int Q_vsnprintf(char *buffer, size_t maxlen, const char *format, va_list vargs)
float _float; float _float;
int i; int i;
int use0s; int use0s;
int precision, useprepad; int precision, useprepad, plus;
if (!maxlen) if (!maxlen)
return 0; return 0;
@ -31,6 +31,7 @@ maxlen--;
switch(*format) switch(*format)
{ {
case '%': case '%':
plus = 0;
precision= 0; precision= 0;
useprepad=0; useprepad=0;
use0s=0; use0s=0;
@ -40,6 +41,9 @@ retry:
case '-': case '-':
useprepad=true; useprepad=true;
goto retry; goto retry;
case '+':
plus = true;
goto retry;
case '0': case '0':
if (!precision) if (!precision)
{ {
@ -177,6 +181,12 @@ Con_Printf("%i bytes left\n", maxlen);
*buffer++ = '-'; *buffer++ = '-';
_int *= -1; _int *= -1;
} }
else if (plus)
{
if (maxlen-- == 0)
{*buffer++='\0';return tokens;}
*buffer++ = '+';
}
i = sizeof(tempbuffer)-2; i = sizeof(tempbuffer)-2;
tempbuffer[sizeof(tempbuffer)-1] = '\0'; tempbuffer[sizeof(tempbuffer)-1] = '\0';
while(_int) while(_int)