Try to fix up some ICE quirks.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6302 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
cbb18429f1
commit
a0f2ffda90
15 changed files with 227 additions and 141 deletions
|
@ -1348,7 +1348,7 @@ void CL_CheckForResend (void)
|
||||||
if (contype & 1)
|
if (contype & 1)
|
||||||
{
|
{
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
MSG_WriteString(&sb, va("%c%c%c%cgetchallenge %i %s\n", 255, 255, 255, 255, connectinfo.clchallenge, COM_QuotedString(com_protocolname.string, tmp, sizeof(tmp), false)));
|
MSG_WriteString(&sb, va("getchallenge %i %s\n", connectinfo.clchallenge, COM_QuotedString(com_protocolname.string, tmp, sizeof(tmp), false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3600,7 +3600,7 @@ void CL_ConnectionlessPacket (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
if (candtls && net_from.prot == NP_DGRAM && (connectinfo.dtlsupgrade || candtls > 1))
|
if (candtls && net_from.prot == NP_DGRAM && (connectinfo.dtlsupgrade || candtls > 1) && !NET_IsEncrypted(&net_from))
|
||||||
{
|
{
|
||||||
//c2s getchallenge
|
//c2s getchallenge
|
||||||
//s2c c%u\0DTLS=$candtls
|
//s2c c%u\0DTLS=$candtls
|
||||||
|
|
|
@ -2254,14 +2254,18 @@ void Master_CheckPollSockets(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//#ifdef Q3CLIENT
|
//q3/dpm server responses
|
||||||
if (!strcmp(s, "statusResponse"))
|
if (!strcmp(s, "statusResponse"))
|
||||||
{
|
{ //originally q3, but oh well.
|
||||||
CL_ReadServerInfo(MSG_ReadString(), MP_QUAKE3, false);
|
CL_ReadServerInfo(MSG_ReadString(), MP_DPMASTER, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//#endif
|
if (!strcmp(s, "infoResponse")) //parse a bit more...
|
||||||
|
{ //originally q3, but oh well.
|
||||||
|
CL_ReadServerInfo(MSG_ReadString(), MP_DPMASTER, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//q3/dpm master responses
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (!strncmp(s, "getserversResponse6", 19) && (s[19] == '\\' || s[19] == '/')) //parse a bit more...
|
if (!strncmp(s, "getserversResponse6", 19) && (s[19] == '\\' || s[19] == '/')) //parse a bit more...
|
||||||
{
|
{
|
||||||
|
@ -2282,11 +2286,6 @@ void Master_CheckPollSockets(void)
|
||||||
CL_MasterListParse(NA_IP, SS_GETINFO, true);
|
CL_MasterListParse(NA_IP, SS_GETINFO, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(s, "infoResponse")) //parse a bit more...
|
|
||||||
{
|
|
||||||
CL_ReadServerInfo(MSG_ReadString(), MP_DPMASTER, false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (!strncmp(s, "qw_slist6\\", 10)) //parse a bit more...
|
if (!strncmp(s, "qw_slist6\\", 10)) //parse a bit more...
|
||||||
|
@ -3294,7 +3293,7 @@ static int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolea
|
||||||
info->special |= SS_QUAKE2;
|
info->special |= SS_QUAKE2;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q3CLIENT
|
#ifdef Q3CLIENT
|
||||||
else if (prototype == MP_QUAKE3)
|
else if (prototype == MP_QUAKE3 || prototype == MP_DPMASTER/*if no protocol, assume q3 behaviours*/)
|
||||||
info->special |= SS_QUAKE3;
|
info->special |= SS_QUAKE3;
|
||||||
#endif
|
#endif
|
||||||
#ifdef NQPROT
|
#ifdef NQPROT
|
||||||
|
|
|
@ -1038,8 +1038,8 @@ void QCBUILTIN PF_cl_clipboard_set(pubprogfuncs_t *prinst, struct globalvars_s *
|
||||||
void QCBUILTIN PF_cl_localsound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
void QCBUILTIN PF_cl_localsound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{
|
{
|
||||||
const char * s = PR_GetStringOfs(prinst, OFS_PARM0);
|
const char * s = PR_GetStringOfs(prinst, OFS_PARM0);
|
||||||
float chan = (prinst->callargc>=1)?G_FLOAT(OFS_PARM1):0;
|
float chan = (prinst->callargc>1)?G_FLOAT(OFS_PARM1):0;
|
||||||
float vol = (prinst->callargc>=2)?G_FLOAT(OFS_PARM2):1;
|
float vol = (prinst->callargc>2)?G_FLOAT(OFS_PARM2):1;
|
||||||
|
|
||||||
S_LocalSound2(s, chan, vol);
|
S_LocalSound2(s, chan, vol);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5170,7 +5170,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!strcmp(gamename, "quake"))
|
if (!strcmp(gamename, "quake") || !strcmp(gamename, "afterquake") || !strcmp(gamename, "netquake") || !strcmp(gamename, "spasm") || !strcmp(gamename, "fitz") || !strcmp(gamename, "tenebrae"))
|
||||||
{
|
{
|
||||||
char *prefix[] =
|
char *prefix[] =
|
||||||
{
|
{
|
||||||
|
@ -5383,9 +5383,14 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
|
||||||
char *s;
|
char *s;
|
||||||
if (!*gamename)
|
if (!*gamename)
|
||||||
gamename = "quake"; //just a paranoia fallback, shouldn't be needed.
|
gamename = "quake"; //just a paranoia fallback, shouldn't be needed.
|
||||||
if (!strcmp(gamename, "quake"))
|
if (!strcmp(gamename, "quake_rerel"))
|
||||||
|
if (Sys_SteamHasFile(basepath, basepathlen, "Quake/rerelease", "id1/pak0.pak"))
|
||||||
|
return true;
|
||||||
|
if (!strcmp(gamename, "quake") || !strcmp(gamename, "afterquake") || !strcmp(gamename, "netquake") || !strcmp(gamename, "spasm") || !strcmp(gamename, "fitz") || !strcmp(gamename, "tenebrae"))
|
||||||
{
|
{
|
||||||
if (Sys_SteamHasFile(basepath, basepathlen, "quake", "id1/pak0.pak"))
|
if (Sys_SteamHasFile(basepath, basepathlen, "Quake", "id1/PAK0.PAK")) //dos legacies need to die.
|
||||||
|
return true;
|
||||||
|
if (Sys_SteamHasFile(basepath, basepathlen, "Quake", "id1/pak0.pak")) //people may have tried to sanitise it already.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (stat("/usr/share/quake/", &sb) == 0)
|
if (stat("/usr/share/quake/", &sb) == 0)
|
||||||
|
|
|
@ -103,6 +103,8 @@ this allows the connection to pick a new route if some router dies (like a relay
|
||||||
FIXME: the client currently disconnects from the broker. the server tracks players via ip rather than ICE.
|
FIXME: the client currently disconnects from the broker. the server tracks players via ip rather than ICE.
|
||||||
|
|
||||||
tcp rtp framing should generally be done with a 16-bit network-endian length prefix followed by the data.
|
tcp rtp framing should generally be done with a 16-bit network-endian length prefix followed by the data.
|
||||||
|
|
||||||
|
NOTE: we do NOT distinguish between media-level and session-level attributes, as such we can only handle ONE media stream per session. we also don't support rtcp.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct icecandidate_s
|
struct icecandidate_s
|
||||||
|
@ -162,7 +164,8 @@ struct icestate_s
|
||||||
} server[8];
|
} server[8];
|
||||||
unsigned int servers;
|
unsigned int servers;
|
||||||
|
|
||||||
unsigned int timeout; //time when we consider the connection dead
|
qboolean brokerless; //we lost connection to our broker... clean up on failure status.
|
||||||
|
unsigned int icetimeout; //time when we consider the connection dead
|
||||||
unsigned int keepalive; //sent periodically...
|
unsigned int keepalive; //sent periodically...
|
||||||
unsigned int retries; //bumped after each round of connectivity checks. affects future intervals.
|
unsigned int retries; //bumped after each round of connectivity checks. affects future intervals.
|
||||||
enum iceproto_e proto;
|
enum iceproto_e proto;
|
||||||
|
@ -189,7 +192,7 @@ struct icestate_s
|
||||||
unsigned int tielow;
|
unsigned int tielow;
|
||||||
int foundation;
|
int foundation;
|
||||||
|
|
||||||
qboolean blockcandidates; //don't send candidates yet.
|
qboolean blockcandidates; //don't send candidates yet. FIXME: replace with gathering.
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
void *dtlsstate;
|
void *dtlsstate;
|
||||||
struct sctp_s *sctp; //ffs! extra processing needed.
|
struct sctp_s *sctp; //ffs! extra processing needed.
|
||||||
|
@ -253,6 +256,7 @@ typedef struct sctp_s
|
||||||
unsigned short qstreamid; //in network endian.
|
unsigned short qstreamid; //in network endian.
|
||||||
} sctp_t;
|
} sctp_t;
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
|
extern cvar_t net_enable_dtls;
|
||||||
static neterr_t SCTP_Transmit(sctp_t *sctp, struct icestate_s *peer, const void *data, size_t length);
|
static neterr_t SCTP_Transmit(sctp_t *sctp, struct icestate_s *peer, const void *data, size_t length);
|
||||||
#endif
|
#endif
|
||||||
static neterr_t ICE_Transmit(void *cbctx, const qbyte *data, size_t datasize);
|
static neterr_t ICE_Transmit(void *cbctx, const qbyte *data, size_t datasize);
|
||||||
|
@ -536,17 +540,14 @@ static neterr_t TURN_Encapsulate(struct icestate_s *ice, netadr_t *to, const qby
|
||||||
struct iceserver_s *srv;
|
struct iceserver_s *srv;
|
||||||
if (to->type == NA_INVALID)
|
if (to->type == NA_INVALID)
|
||||||
return NETERR_NOROUTE;
|
return NETERR_NOROUTE;
|
||||||
if (network >= MAX_CONNECTIONS)
|
if (to->connum && network >= MAX_CONNECTIONS)
|
||||||
{ //fancy turn-related gubbins
|
{ //fancy turn-related gubbins
|
||||||
network -= MAX_CONNECTIONS;
|
network -= MAX_CONNECTIONS;
|
||||||
if (network >= countof(ice->server))
|
if (network >= countof(ice->server))
|
||||||
{ //really high, its from the raw socket, unstunned.
|
{ //really high, its from the raw socket, unstunned.
|
||||||
network -= countof(ice->server);
|
network -= countof(ice->server);
|
||||||
if (network >= countof(ice->server))
|
if (network >= countof(ice->server))
|
||||||
{
|
|
||||||
Con_Printf("TURN_Encapsulate: %i\n", to->connum);
|
|
||||||
return NETERR_NOROUTE;
|
return NETERR_NOROUTE;
|
||||||
}
|
|
||||||
srv = &ice->server[network];
|
srv = &ice->server[network];
|
||||||
|
|
||||||
if (!srv->con || net_ice_relayonly.ival)
|
if (!srv->con || net_ice_relayonly.ival)
|
||||||
|
@ -990,7 +991,7 @@ static qboolean ICE_SendSpam(struct icestate_s *con)
|
||||||
}
|
}
|
||||||
|
|
||||||
extern ftenet_generic_connection_t *FTENET_Datagram_EstablishConnection(ftenet_connections_t *col, const char *address, netadr_t adr);
|
extern ftenet_generic_connection_t *FTENET_Datagram_EstablishConnection(ftenet_connections_t *col, const char *address, netadr_t adr);
|
||||||
#ifdef TCPCONNECT
|
#ifdef HAVE_TCP
|
||||||
struct turntcp_connection_s
|
struct turntcp_connection_s
|
||||||
{ //this sends packets only to the relay, and accepts them only from there too. all packets must be stun packets (for byte-count framing)
|
{ //this sends packets only to the relay, and accepts them only from there too. all packets must be stun packets (for byte-count framing)
|
||||||
ftenet_generic_connection_t pub;
|
ftenet_generic_connection_t pub;
|
||||||
|
@ -1178,7 +1179,13 @@ static void ICE_ToStunServer(struct icestate_s *con, struct iceserver_s *srv)
|
||||||
if (srv->addr.type == NA_INVALID)
|
if (srv->addr.type == NA_INVALID)
|
||||||
return; //nope...
|
return; //nope...
|
||||||
if (srv->addr.prot != NP_DGRAM)
|
if (srv->addr.prot != NP_DGRAM)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_TCP
|
||||||
srv->con = TURN_TCP_EstablishConnection(collection, srv->realm, srv->addr);
|
srv->con = TURN_TCP_EstablishConnection(collection, srv->realm, srv->addr);
|
||||||
|
#else
|
||||||
|
srv->con = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
netadr_t localadr;
|
netadr_t localadr;
|
||||||
|
@ -2096,7 +2103,7 @@ static qboolean QDECL ICE_Set(struct icestate_s *con, const char *prop, const ch
|
||||||
Con_Printf("ICE_Set invalid state %s\n", value);
|
Con_Printf("ICE_Set invalid state %s\n", value);
|
||||||
con->state = ICE_INACTIVE;
|
con->state = ICE_INACTIVE;
|
||||||
}
|
}
|
||||||
con->timeout = Sys_Milliseconds() + 30;
|
con->icetimeout = Sys_Milliseconds() + 30*1000;
|
||||||
|
|
||||||
con->retries = 0;
|
con->retries = 0;
|
||||||
|
|
||||||
|
@ -2117,15 +2124,14 @@ static qboolean QDECL ICE_Set(struct icestate_s *con, const char *prop, const ch
|
||||||
{
|
{
|
||||||
if (!con->dtlsstate && con->dtlsfuncs)
|
if (!con->dtlsstate && con->dtlsfuncs)
|
||||||
{
|
{
|
||||||
extern cvar_t net_enable_dtls;
|
|
||||||
if (con->cred.peer.hash)
|
if (con->cred.peer.hash)
|
||||||
con->dtlsstate = con->dtlsfuncs->CreateContext(&con->cred, con, ICE_Transmit, con->dtlspassive);
|
con->dtlsstate = con->dtlsfuncs->CreateContext(&con->cred, con, ICE_Transmit, con->dtlspassive);
|
||||||
else if (net_enable_dtls.ival)
|
else if (net_enable_dtls.ival >= 3)
|
||||||
{ //peer doesn't seem to support dtls.
|
{ //peer doesn't seem to support dtls.
|
||||||
con->state = ICE_FAILED;
|
con->state = ICE_FAILED;
|
||||||
Con_Printf(CON_WARNING"WARNING: peer does not support dtls. Set net_enable_dtls to 0 to make optional.\n");
|
Con_Printf(CON_WARNING"WARNING: peer does not support dtls. Set net_enable_dtls to 0 to make optional.\n");
|
||||||
}
|
}
|
||||||
else if (con->state == ICE_CONNECTING)
|
else if (con->state == ICE_CONNECTING && net_enable_dtls.ival>=2)
|
||||||
Con_Printf(CON_WARNING"WARNING: peer does not support dtls.\n");
|
Con_Printf(CON_WARNING"WARNING: peer does not support dtls.\n");
|
||||||
}
|
}
|
||||||
if (!con->sctp && (!con->sctpoptional || !con->peersctpoptional) && con->mysctpport && con->peersctpport)
|
if (!con->sctp && (!con->sctpoptional || !con->peersctpoptional) && con->mysctpport && con->peersctpport)
|
||||||
|
@ -2408,6 +2414,9 @@ static qboolean QDECL ICE_Get(struct icestate_s *con, const char *prop, char *va
|
||||||
case ICE_FAILED:
|
case ICE_FAILED:
|
||||||
Q_strncpyz(value, STRINGIFY(ICE_FAILED), valuelen);
|
Q_strncpyz(value, STRINGIFY(ICE_FAILED), valuelen);
|
||||||
break;
|
break;
|
||||||
|
case ICE_GATHERING:
|
||||||
|
Q_strncpyz(value, STRINGIFY(ICE_GATHERING), valuelen);
|
||||||
|
break;
|
||||||
case ICE_CONNECTING:
|
case ICE_CONNECTING:
|
||||||
Q_strncpyz(value, STRINGIFY(ICE_CONNECTING), valuelen);
|
Q_strncpyz(value, STRINGIFY(ICE_CONNECTING), valuelen);
|
||||||
break;
|
break;
|
||||||
|
@ -2512,6 +2521,13 @@ static qboolean QDECL ICE_Get(struct icestate_s *con, const char *prop, char *va
|
||||||
if (con->proto == ICEP_QWSERVER || con->proto == ICEP_QWCLIENT)
|
if (con->proto == ICEP_QWSERVER || con->proto == ICEP_QWCLIENT)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
|
if (net_enable_dtls.ival >= 3)
|
||||||
|
{ //this is a preliminary check to avoid wasting time
|
||||||
|
if (!con->cred.local.certsize)
|
||||||
|
return false; //fail if we cannot do dtls when its required.
|
||||||
|
if (!strcmp(prop, "sdpanswer") || !con->cred.peer.hash)
|
||||||
|
return false; //don't answer if they failed to provide a cert
|
||||||
|
}
|
||||||
if (con->cred.local.certsize)
|
if (con->cred.local.certsize)
|
||||||
{
|
{
|
||||||
qbyte fingerprint[DIGEST_MAXSIZE];
|
qbyte fingerprint[DIGEST_MAXSIZE];
|
||||||
|
@ -2607,12 +2623,17 @@ static void ICE_PrintSummary(struct icestate_s *con, qboolean islisten)
|
||||||
{
|
{
|
||||||
case ICE_INACTIVE: Con_Printf(S_COLOR_RED "inactive"); break;
|
case ICE_INACTIVE: Con_Printf(S_COLOR_RED "inactive"); break;
|
||||||
case ICE_FAILED: Con_Printf(S_COLOR_RED "failed"); break;
|
case ICE_FAILED: Con_Printf(S_COLOR_RED "failed"); break;
|
||||||
|
case ICE_GATHERING: Con_Printf(S_COLOR_YELLOW "gathering"); break;
|
||||||
case ICE_CONNECTING: Con_Printf(S_COLOR_YELLOW "connecting"); break;
|
case ICE_CONNECTING: Con_Printf(S_COLOR_YELLOW "connecting"); break;
|
||||||
case ICE_CONNECTED: Con_Printf(S_COLOR_GRAY"%s via %s", NET_AdrToString(msg,sizeof(msg), &con->chosenpeer), ICE_NetworkToName(con, con->chosenpeer.connum)); break;
|
case ICE_CONNECTED: Con_Printf(S_COLOR_GRAY"%s via %s", NET_AdrToString(msg,sizeof(msg), &con->chosenpeer), ICE_NetworkToName(con, con->chosenpeer.connum)); break;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_DTLS
|
||||||
if (con->dtlsstate)
|
if (con->dtlsstate)
|
||||||
Con_Printf(S_COLOR_GREEN " (encrypted)");
|
Con_Printf(S_COLOR_GREEN " (encrypted%s)", con->sctp?", sctp":"");
|
||||||
|
else if (con->sctp)
|
||||||
|
Con_Printf(S_COLOR_RED " (plain-text, sctp)"); //weeeeeeird and pointless...
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
Con_Printf(S_COLOR_RED " (plain-text)");
|
Con_Printf(S_COLOR_RED " (plain-text)");
|
||||||
Con_Printf("\n");
|
Con_Printf("\n");
|
||||||
}
|
}
|
||||||
|
@ -2622,6 +2643,14 @@ static void ICE_Debug(struct icestate_s *con)
|
||||||
char buf[65536];
|
char buf[65536];
|
||||||
ICE_Get(con, "state", buf, sizeof(buf));
|
ICE_Get(con, "state", buf, sizeof(buf));
|
||||||
Con_Printf("ICE [%s] (%s):\n", con->friendlyname, buf);
|
Con_Printf("ICE [%s] (%s):\n", con->friendlyname, buf);
|
||||||
|
if (con->brokerless)
|
||||||
|
Con_Printf(" timeout: %g\n", (int)(con->icetimeout-Sys_Milliseconds())/1000.0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int idle = (Sys_Milliseconds()+30*1000 - con->icetimeout);
|
||||||
|
if (idle > 500)
|
||||||
|
Con_Printf(" idle: %g\n", idle/1000.0);
|
||||||
|
}
|
||||||
if (net_ice_debug.ival >= 2)
|
if (net_ice_debug.ival >= 2)
|
||||||
{ //rather uninteresting really...
|
{ //rather uninteresting really...
|
||||||
if (con->initiator)
|
if (con->initiator)
|
||||||
|
@ -2880,7 +2909,7 @@ static void ICE_Destroy(struct icestate_s *con)
|
||||||
//send pings to establish/keep the connection alive
|
//send pings to establish/keep the connection alive
|
||||||
void ICE_Tick(void)
|
void ICE_Tick(void)
|
||||||
{
|
{
|
||||||
struct icestate_s *con;
|
struct icestate_s **link, *con;
|
||||||
unsigned int curtime;
|
unsigned int curtime;
|
||||||
|
|
||||||
if (!icelist)
|
if (!icelist)
|
||||||
|
@ -2889,8 +2918,20 @@ void ICE_Tick(void)
|
||||||
|
|
||||||
MDNS_SendQueries();
|
MDNS_SendQueries();
|
||||||
|
|
||||||
for (con = icelist; con; con = con->next)
|
for (link = &icelist; (con=*link);)
|
||||||
{
|
{
|
||||||
|
if (con->brokerless)
|
||||||
|
{
|
||||||
|
if (con->state <= ICE_GATHERING)
|
||||||
|
{
|
||||||
|
*link = con->next;
|
||||||
|
ICE_Destroy(con);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ((signed int)(curtime-con->icetimeout) > 0)
|
||||||
|
ICE_Set(con, "state", STRINGIFY(ICE_FAILED)); //with no broker context, if we're not trying to send anything then kill the link.
|
||||||
|
}
|
||||||
|
|
||||||
switch(con->mode)
|
switch(con->mode)
|
||||||
{
|
{
|
||||||
case ICEM_RAW:
|
case ICEM_RAW:
|
||||||
|
@ -3008,18 +3049,25 @@ void ICE_Tick(void)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
link = &con->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void QDECL ICE_Close(struct icestate_s *con)
|
static void QDECL ICE_Close(struct icestate_s *con, qboolean force)
|
||||||
{
|
{
|
||||||
struct icestate_s **link;
|
struct icestate_s **link;
|
||||||
|
|
||||||
for (link = &icelist; *link; )
|
for (link = &icelist; *link; )
|
||||||
{
|
{
|
||||||
if (con == *link)
|
if (con == *link)
|
||||||
|
{
|
||||||
|
if (!force)
|
||||||
|
con->brokerless = true;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
*link = con->next;
|
*link = con->next;
|
||||||
ICE_Destroy(con);
|
ICE_Destroy(con);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3938,7 +3986,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
|
||||||
{
|
{
|
||||||
char str[256];
|
char str[256];
|
||||||
if (net_ice_debug.ival >= 1)
|
if (net_ice_debug.ival >= 1)
|
||||||
Con_Printf(S_COLOR_GRAY"[%s]: We can reach %s (%s)\n", con->friendlyname, NET_AdrToString(str, sizeof(str), &net_from), ICE_GetCandidateType(&rc->info));
|
Con_Printf(S_COLOR_GRAY"[%s]: We can reach %s (%s) via %s\n", con->friendlyname, NET_AdrToString(str, sizeof(str), &net_from), ICE_GetCandidateType(&rc->info), ICE_NetworkToName(con, net_from.connum));
|
||||||
}
|
}
|
||||||
rc->reachable |= 1u<<(net_from.connum-1);
|
rc->reachable |= 1u<<(net_from.connum-1);
|
||||||
rc->reached = Sys_Milliseconds();
|
rc->reached = Sys_Milliseconds();
|
||||||
|
@ -4698,8 +4746,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
|
||||||
{
|
{
|
||||||
// if (rc->reachable)
|
// if (rc->reachable)
|
||||||
{ //found it. fix up its source address to our ICE connection (so we don't have path-switching issues) and keep chugging along.
|
{ //found it. fix up its source address to our ICE connection (so we don't have path-switching issues) and keep chugging along.
|
||||||
|
con->icetimeout = Sys_Milliseconds() + 1000*30; //not dead yet...
|
||||||
con->timeout = Sys_Milliseconds() + 32; //not dead yet...
|
|
||||||
|
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
if (con->dtlsstate)
|
if (con->dtlsstate)
|
||||||
|
@ -4711,7 +4758,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
|
||||||
case NETERR_NOROUTE:
|
case NETERR_NOROUTE:
|
||||||
return false; //not a dtls packet at all. don't de-ICE it when we're meant to be using ICE.
|
return false; //not a dtls packet at all. don't de-ICE it when we're meant to be using ICE.
|
||||||
case NETERR_DISCONNECTED: //dtls failure. ICE failed.
|
case NETERR_DISCONNECTED: //dtls failure. ICE failed.
|
||||||
iceapi.ICE_Set(con, "state", STRINGIFY(ICE_FAILED));
|
iceapi.Set(con, "state", STRINGIFY(ICE_FAILED));
|
||||||
return true;
|
return true;
|
||||||
default: //some kind of failure decoding the dtls packet. drop it.
|
default: //some kind of failure decoding the dtls packet. drop it.
|
||||||
return true;
|
return true;
|
||||||
|
@ -4722,6 +4769,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
if (con->sctp)
|
if (con->sctp)
|
||||||
SCTP_Decode(con->sctp, con, col);
|
SCTP_Decode(con->sctp, con, col);
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
if (net_message.cursize)
|
if (net_message.cursize)
|
||||||
col->ReadGamePacket();
|
col->ReadGamePacket();
|
||||||
|
@ -4769,6 +4817,12 @@ neterr_t ICE_SendPacket(size_t length, const void *data, netadr_t *to)
|
||||||
{
|
{
|
||||||
if (NET_CompareAdr(to, &con->qadr))
|
if (NET_CompareAdr(to, &con->qadr))
|
||||||
{
|
{
|
||||||
|
con->icetimeout = Sys_Milliseconds()+30*1000; //keep it alive a little longer.
|
||||||
|
|
||||||
|
if (con->state == ICE_CONNECTING)
|
||||||
|
return NETERR_CLOGGED;
|
||||||
|
else if (con->state != ICE_CONNECTED)
|
||||||
|
return NETERR_DISCONNECTED;
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
if (con->sctp)
|
if (con->sctp)
|
||||||
return SCTP_Transmit(con->sctp, con, data, length);
|
return SCTP_Transmit(con->sctp, con, data, length);
|
||||||
|
@ -4777,8 +4831,6 @@ neterr_t ICE_SendPacket(size_t length, const void *data, netadr_t *to)
|
||||||
#endif
|
#endif
|
||||||
if (con->chosenpeer.type != NA_INVALID)
|
if (con->chosenpeer.type != NA_INVALID)
|
||||||
return ICE_Transmit(con, data, length);
|
return ICE_Transmit(con, data, length);
|
||||||
if (con->state < ICE_CONNECTING)
|
|
||||||
return NETERR_DISCONNECTED;
|
|
||||||
return NETERR_CLOGGED; //still pending
|
return NETERR_CLOGGED; //still pending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4835,10 +4887,10 @@ static void FTENET_ICE_Close(ftenet_generic_connection_t *gcon)
|
||||||
|
|
||||||
for (cl = 0; cl < b->numclients; cl++)
|
for (cl = 0; cl < b->numclients; cl++)
|
||||||
if (b->clients[cl].ice)
|
if (b->clients[cl].ice)
|
||||||
iceapi.ICE_Close(b->clients[cl].ice);
|
iceapi.Close(b->clients[cl].ice, true);
|
||||||
Z_Free(b->clients);
|
Z_Free(b->clients);
|
||||||
if (b->ice)
|
if (b->ice)
|
||||||
iceapi.ICE_Close(b->ice);
|
iceapi.Close(b->ice, true);
|
||||||
|
|
||||||
Z_Free(b);
|
Z_Free(b);
|
||||||
}
|
}
|
||||||
|
@ -4940,9 +4992,11 @@ static void FTENET_ICE_SendOffer(ftenet_ice_connection_t *b, int cl, struct ices
|
||||||
{
|
{
|
||||||
char buf[8192];
|
char buf[8192];
|
||||||
//okay, now send the sdp to our peer.
|
//okay, now send the sdp to our peer.
|
||||||
if (iceapi.ICE_Get(ice, type, buf, sizeof(buf)))
|
if (iceapi.Get(ice, type, buf, sizeof(buf)))
|
||||||
{
|
{
|
||||||
char json[8192+256];
|
char json[8192+256];
|
||||||
|
if (ice->state == ICE_GATHERING)
|
||||||
|
ice->state = ICE_CONNECTING;
|
||||||
if (ice->mode == ICEM_WEBRTC)
|
if (ice->mode == ICEM_WEBRTC)
|
||||||
{
|
{
|
||||||
Q_strncpyz(json, va("{\"type\":\"%s\",\"sdp\":\"", type+3), sizeof(json));
|
Q_strncpyz(json, va("{\"type\":\"%s\",\"sdp\":\"", type+3), sizeof(json));
|
||||||
|
@ -4962,24 +5016,24 @@ static void FTENET_ICE_Establish(ftenet_ice_connection_t *b, int cl, struct ices
|
||||||
qboolean usewebrtc;
|
qboolean usewebrtc;
|
||||||
char *s;
|
char *s;
|
||||||
if (*ret)
|
if (*ret)
|
||||||
iceapi.ICE_Close(*ret);
|
iceapi.Close(*ret, false);
|
||||||
#ifndef HAVE_DTLS
|
#ifndef HAVE_DTLS
|
||||||
usewebrtc = false;
|
usewebrtc = false;
|
||||||
#else
|
#else
|
||||||
if (!*net_ice_usewebrtc.string)
|
if (!*net_ice_usewebrtc.string && net_enable_dtls.ival)
|
||||||
usewebrtc = true; //let the peer decide. this means we use dtls, but not sctp.
|
usewebrtc = true; //let the peer decide. this means we can use dtls, but not sctp.
|
||||||
else
|
else
|
||||||
usewebrtc = net_ice_usewebrtc.ival;
|
usewebrtc = net_ice_usewebrtc.ival;
|
||||||
#endif
|
#endif
|
||||||
ice = *ret = iceapi.ICE_Create(b, NULL, b->generic.islisten?NULL:va("/%s", b->gamename), usewebrtc?ICEM_WEBRTC:ICEM_ICE, b->generic.islisten?ICEP_QWSERVER:ICEP_QWCLIENT, !b->generic.islisten);
|
ice = *ret = iceapi.Create(b, NULL, b->generic.islisten?NULL:va("/%s", b->gamename), usewebrtc?ICEM_WEBRTC:ICEM_ICE, b->generic.islisten?ICEP_QWSERVER:ICEP_QWCLIENT, !b->generic.islisten);
|
||||||
if (!*ret)
|
if (!*ret)
|
||||||
return; //some kind of error?!?
|
return; //some kind of error?!?
|
||||||
|
|
||||||
iceapi.ICE_Set(ice, "server", va("stun:%s:%i", b->brokername, BigShort(b->brokeradr.port)));
|
iceapi.Set(ice, "server", va("stun:%s:%i", b->brokername, BigShort(b->brokeradr.port)));
|
||||||
|
|
||||||
s = net_ice_servers.string;
|
s = net_ice_servers.string;
|
||||||
while((s=COM_Parse(s)))
|
while((s=COM_Parse(s)))
|
||||||
iceapi.ICE_Set(ice, "server", com_token);
|
iceapi.Set(ice, "server", com_token);
|
||||||
|
|
||||||
if (!b->generic.islisten)
|
if (!b->generic.islisten)
|
||||||
FTENET_ICE_SendOffer(b, cl, ice, "sdpoffer");
|
FTENET_ICE_SendOffer(b, cl, ice, "sdpoffer");
|
||||||
|
@ -4989,7 +5043,7 @@ static void FTENET_ICE_Refresh(ftenet_ice_connection_t *b, int cl, struct icesta
|
||||||
char buf[8192];
|
char buf[8192];
|
||||||
if (ice->blockcandidates)
|
if (ice->blockcandidates)
|
||||||
return; //don't send candidates before the offers...
|
return; //don't send candidates before the offers...
|
||||||
while (ice && iceapi.ICE_GetLCandidateSDP(ice, buf, sizeof(buf)))
|
while (ice && iceapi.GetLCandidateSDP(ice, buf, sizeof(buf)))
|
||||||
{
|
{
|
||||||
char json[8192+256];
|
char json[8192+256];
|
||||||
if (ice->mode == ICEM_WEBRTC)
|
if (ice->mode == ICEM_WEBRTC)
|
||||||
|
@ -5058,11 +5112,11 @@ handleerror:
|
||||||
for (cl = 0; cl < b->numclients; cl++)
|
for (cl = 0; cl < b->numclients; cl++)
|
||||||
{
|
{
|
||||||
if (b->clients[cl].ice)
|
if (b->clients[cl].ice)
|
||||||
iceapi.ICE_Close(b->clients[cl].ice);
|
iceapi.Close(b->clients[cl].ice, false);
|
||||||
b->clients[cl].ice = NULL;
|
b->clients[cl].ice = NULL;
|
||||||
}
|
}
|
||||||
if (b->ice)
|
if (b->ice)
|
||||||
iceapi.ICE_Close(b->ice);
|
iceapi.Close(b->ice, false);
|
||||||
b->ice = NULL;
|
b->ice = NULL;
|
||||||
if (b->error != 1 || !b->generic.islisten)
|
if (b->error != 1 || !b->generic.islisten)
|
||||||
return false; //permanant error...
|
return false; //permanant error...
|
||||||
|
@ -5163,7 +5217,7 @@ handleerror:
|
||||||
|
|
||||||
switch(cmd)
|
switch(cmd)
|
||||||
{
|
{
|
||||||
case ICEMSG_PEERDROP: //connection closing...
|
case ICEMSG_PEERLOST: //the broker lost its connection to our peer...
|
||||||
if (cl == -1)
|
if (cl == -1)
|
||||||
{
|
{
|
||||||
b->error = true;
|
b->error = true;
|
||||||
|
@ -5172,7 +5226,7 @@ handleerror:
|
||||||
else if (cl >= 0 && cl < b->numclients)
|
else if (cl >= 0 && cl < b->numclients)
|
||||||
{
|
{
|
||||||
if (b->clients[cl].ice)
|
if (b->clients[cl].ice)
|
||||||
iceapi.ICE_Close(b->clients[cl].ice);
|
iceapi.Close(b->clients[cl].ice, false);
|
||||||
b->clients[cl].ice = NULL;
|
b->clients[cl].ice = NULL;
|
||||||
// Con_Printf("Broker closing connection: %s\n", data);
|
// Con_Printf("Broker closing connection: %s\n", data);
|
||||||
}
|
}
|
||||||
|
@ -5223,8 +5277,8 @@ handleerror:
|
||||||
{
|
{
|
||||||
if (cl >= 0 && cl < b->numclients && b->clients[cl].ice)
|
if (cl >= 0 && cl < b->numclients && b->clients[cl].ice)
|
||||||
{
|
{
|
||||||
iceapi.ICE_Set(b->clients[cl].ice, "sdpoffer", data);
|
iceapi.Set(b->clients[cl].ice, "sdpoffer", data);
|
||||||
iceapi.ICE_Set(b->clients[cl].ice, "state", STRINGIFY(ICE_CONNECTING));
|
iceapi.Set(b->clients[cl].ice, "state", STRINGIFY(ICE_CONNECTING));
|
||||||
|
|
||||||
FTENET_ICE_SendOffer(b, cl, b->clients[cl].ice, "sdpanswer");
|
FTENET_ICE_SendOffer(b, cl, b->clients[cl].ice, "sdpanswer");
|
||||||
}
|
}
|
||||||
|
@ -5233,8 +5287,8 @@ handleerror:
|
||||||
{
|
{
|
||||||
if (b->ice)
|
if (b->ice)
|
||||||
{
|
{
|
||||||
iceapi.ICE_Set(b->ice, "sdpanswer", data);
|
iceapi.Set(b->ice, "sdpanswer", data);
|
||||||
iceapi.ICE_Set(b->ice, "state", STRINGIFY(ICE_CONNECTING));
|
iceapi.Set(b->ice, "state", STRINGIFY(ICE_CONNECTING));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -5251,12 +5305,12 @@ handleerror:
|
||||||
if (b->generic.islisten)
|
if (b->generic.islisten)
|
||||||
{
|
{
|
||||||
if (cl >= 0 && cl < b->numclients && b->clients[cl].ice)
|
if (cl >= 0 && cl < b->numclients && b->clients[cl].ice)
|
||||||
iceapi.ICE_Set(b->clients[cl].ice, "sdp", data);
|
iceapi.Set(b->clients[cl].ice, "sdp", data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (b->ice)
|
if (b->ice)
|
||||||
iceapi.ICE_Set(b->ice, "sdp", data);
|
iceapi.Set(b->ice, "sdp", data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -635,6 +635,9 @@ static int QDECL SSL_Read(struct vfsfile_s *f, void *buffer, int bytestoread)
|
||||||
return 0; //caller is expected to try again later, no real need to loop here, just in case it repeats (eg E_AGAIN)
|
return 0; //caller is expected to try again later, no real need to loop here, just in case it repeats (eg E_AGAIN)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (read == GNUTLS_E_PULL_ERROR)
|
||||||
|
Con_Printf("GNUTLS_E_PULL_ERROR (%s)\n", file->certname);
|
||||||
|
else
|
||||||
Con_Printf("GNUTLS Read Warning %i (bufsize %i)\n", read, bytestoread);
|
Con_Printf("GNUTLS Read Warning %i (bufsize %i)\n", read, bytestoread);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -752,6 +755,7 @@ static ssize_t DTLS_Push(gnutls_transport_ptr_t p, const void *data, size_t size
|
||||||
switch(ne)
|
switch(ne)
|
||||||
{
|
{
|
||||||
case NETERR_CLOGGED:
|
case NETERR_CLOGGED:
|
||||||
|
case NETERR_NOROUTE:
|
||||||
qgnutls_transport_set_errno(file->session, EAGAIN);
|
qgnutls_transport_set_errno(file->session, EAGAIN);
|
||||||
return -1;
|
return -1;
|
||||||
case NETERR_MTU:
|
case NETERR_MTU:
|
||||||
|
|
|
@ -3151,6 +3151,8 @@ qboolean NET_DTLS_CheckInbound(ftenet_connections_t *col)
|
||||||
netadr_t *from = &net_from;
|
netadr_t *from = &net_from;
|
||||||
if (from->prot != NP_DGRAM || !net_enable_dtls.ival || !col->dtlsfuncs)
|
if (from->prot != NP_DGRAM || !net_enable_dtls.ival || !col->dtlsfuncs)
|
||||||
return false;
|
return false;
|
||||||
|
if (!net_message.cursize || !(20 <= net_message.data[0] && net_message.data[0] <= 63))
|
||||||
|
return false; //lead byte must be between 20 and 63 to be valid dtls.
|
||||||
for (peer = col->dtls; peer; peer = peer->next)
|
for (peer = col->dtls; peer; peer = peer->next)
|
||||||
{
|
{
|
||||||
if (NET_CompareAdr(&peer->addr, from))
|
if (NET_CompareAdr(&peer->addr, from))
|
||||||
|
@ -5385,7 +5387,7 @@ static qboolean FTENET_TCP_KillStream(ftenet_tcp_connection_t *con, ftenet_tcp_s
|
||||||
if (o->clienttype == TCPC_WEBRTC_HOST && !strcmp(o->webrtc.resource, st->webrtc.resource))
|
if (o->clienttype == TCPC_WEBRTC_HOST && !strcmp(o->webrtc.resource, st->webrtc.resource))
|
||||||
{
|
{
|
||||||
qbyte msg[3];
|
qbyte msg[3];
|
||||||
msg[0] = ICEMSG_PEERDROP;
|
msg[0] = ICEMSG_PEERLOST;
|
||||||
msg[1] = (st->webrtc.clientnum>>0)&0xff;
|
msg[1] = (st->webrtc.clientnum>>0)&0xff;
|
||||||
msg[2] = (st->webrtc.clientnum>>8)&0xff;
|
msg[2] = (st->webrtc.clientnum>>8)&0xff;
|
||||||
|
|
||||||
|
@ -5402,7 +5404,7 @@ static qboolean FTENET_TCP_KillStream(ftenet_tcp_connection_t *con, ftenet_tcp_s
|
||||||
if (o->clienttype == TCPC_WEBRTC_CLIENT && !strcmp(o->webrtc.resource, st->webrtc.resource))
|
if (o->clienttype == TCPC_WEBRTC_CLIENT && !strcmp(o->webrtc.resource, st->webrtc.resource))
|
||||||
{
|
{
|
||||||
qbyte msg[3];
|
qbyte msg[3];
|
||||||
msg[0] = ICEMSG_PEERDROP;
|
msg[0] = ICEMSG_PEERLOST;
|
||||||
msg[1] = (st->webrtc.clientnum>>0)&0xff;
|
msg[1] = (st->webrtc.clientnum>>0)&0xff;
|
||||||
msg[2] = (st->webrtc.clientnum>>8)&0xff;
|
msg[2] = (st->webrtc.clientnum>>8)&0xff;
|
||||||
|
|
||||||
|
@ -7356,11 +7358,11 @@ static qboolean FTENET_WebRTC_GetPacket(ftenet_generic_connection_t *gcon)
|
||||||
|
|
||||||
switch(cmd)
|
switch(cmd)
|
||||||
{
|
{
|
||||||
case ICEMSG_PEERDROP: //connection closing...
|
case ICEMSG_PEERLOST: //connection closing...
|
||||||
if (cl == -1)
|
if (cl == -1)
|
||||||
{
|
{
|
||||||
wsc->failed = true;
|
wsc->failed = true;
|
||||||
Con_Printf("Broker closing connection: %s\n", MSG_ReadString());
|
// Con_Printf("Broker closing connection: %s\n", MSG_ReadString());
|
||||||
}
|
}
|
||||||
else if (cl >= 0 && cl < wsc->numclients)
|
else if (cl >= 0 && cl < wsc->numclients)
|
||||||
{
|
{
|
||||||
|
@ -7368,7 +7370,7 @@ static qboolean FTENET_WebRTC_GetPacket(ftenet_generic_connection_t *gcon)
|
||||||
if (wsc->clients[cl].datasock != INVALID_SOCKET)
|
if (wsc->clients[cl].datasock != INVALID_SOCKET)
|
||||||
emscriptenfte_ws_close(wsc->clients[cl].datasock);
|
emscriptenfte_ws_close(wsc->clients[cl].datasock);
|
||||||
wsc->clients[cl].datasock = INVALID_SOCKET;
|
wsc->clients[cl].datasock = INVALID_SOCKET;
|
||||||
Con_Printf("Broker closing connection: %s\n", MSG_ReadString());
|
// Con_Printf("Broker closing connection: %s\n", MSG_ReadString());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ICEMSG_GREETING: //reports the trailing url we're 'listening' on. anyone else using that url will connect to us.
|
case ICEMSG_GREETING: //reports the trailing url we're 'listening' on. anyone else using that url will connect to us.
|
||||||
|
|
|
@ -274,6 +274,7 @@ enum icestate_e
|
||||||
{
|
{
|
||||||
ICE_INACTIVE, //idle.
|
ICE_INACTIVE, //idle.
|
||||||
ICE_FAILED,
|
ICE_FAILED,
|
||||||
|
ICE_GATHERING,
|
||||||
ICE_CONNECTING, //exchanging pings.
|
ICE_CONNECTING, //exchanging pings.
|
||||||
ICE_CONNECTED //media is flowing, supposedly. sending keepalives.
|
ICE_CONNECTED //media is flowing, supposedly. sending keepalives.
|
||||||
};
|
};
|
||||||
|
@ -281,15 +282,15 @@ struct icestate_s;
|
||||||
#define ICE_API_CURRENT "Internet Connectivity Establishment 0.0"
|
#define ICE_API_CURRENT "Internet Connectivity Establishment 0.0"
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
struct icestate_s *(QDECL *ICE_Create)(void *module, const char *conname, const char *peername, enum icemode_e mode, enum iceproto_e proto, qboolean initiator); //doesn't start pinging anything.
|
struct icestate_s *(QDECL *Create)(void *module, const char *conname, const char *peername, enum icemode_e mode, enum iceproto_e proto, qboolean initiator); //doesn't start pinging anything.
|
||||||
qboolean (QDECL *ICE_Set)(struct icestate_s *con, const char *prop, const char *value);
|
qboolean (QDECL *Set)(struct icestate_s *con, const char *prop, const char *value);
|
||||||
qboolean (QDECL *ICE_Get)(struct icestate_s *con, const char *prop, char *value, size_t valuesize);
|
qboolean (QDECL *Get)(struct icestate_s *con, const char *prop, char *value, size_t valuesize);
|
||||||
struct icecandinfo_s *(QDECL *ICE_GetLCandidateInfo)(struct icestate_s *con); //retrieves candidates that need reporting to the peer.
|
struct icecandinfo_s *(QDECL *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 *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 *Close)(struct icestate_s *con, qboolean force); //bye then.
|
||||||
void (QDECL *ICE_CloseModule)(void *module); //closes all unclosed connections, with warning.
|
void (QDECL *CloseModule)(void *module); //closes all unclosed connections, with warning.
|
||||||
// struct icestate_s *(QDECL *ICE_Find)(void *module, const char *conname);
|
// struct icestate_s *(QDECL *Find)(void *module, const char *conname);
|
||||||
qboolean (QDECL *ICE_GetLCandidateSDP)(struct icestate_s *con, char *out, size_t valuesize); //retrieves candidates that need reporting to the peer.
|
qboolean (QDECL *GetLCandidateSDP)(struct icestate_s *con, char *out, size_t valuesize); //retrieves candidates that need reporting to the peer.
|
||||||
} icefuncs_t;
|
} icefuncs_t;
|
||||||
extern icefuncs_t iceapi;
|
extern icefuncs_t iceapi;
|
||||||
#endif
|
#endif
|
||||||
|
@ -439,7 +440,7 @@ void QDECL ICE_AddLCandidateInfo(struct icestate_s *con, netadr_t *adr, int adrn
|
||||||
ftenet_generic_connection_t *FTENET_ICE_EstablishConnection(ftenet_connections_t *col, const char *address, netadr_t adr);
|
ftenet_generic_connection_t *FTENET_ICE_EstablishConnection(ftenet_connections_t *col, const char *address, netadr_t adr);
|
||||||
enum icemsgtype_s
|
enum icemsgtype_s
|
||||||
{ //shared by rtcpeers+broker
|
{ //shared by rtcpeers+broker
|
||||||
ICEMSG_PEERDROP=0, //other side dropped connection
|
ICEMSG_PEERLOST=0, //other side dropped connection
|
||||||
ICEMSG_GREETING=1, //master telling us our unique game name
|
ICEMSG_GREETING=1, //master telling us our unique game name
|
||||||
ICEMSG_NEWPEER=2, //relay established, send an offer now.
|
ICEMSG_NEWPEER=2, //relay established, send an offer now.
|
||||||
ICEMSG_OFFER=3, //peer's initial details
|
ICEMSG_OFFER=3, //peer's initial details
|
||||||
|
|
|
@ -1567,7 +1567,7 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
|
||||||
//MORE HUGE HACKS! WHEN WILL THEY CEASE!
|
//MORE HUGE HACKS! WHEN WILL THEY CEASE!
|
||||||
// clamp lighting so it doesn't overbright as much
|
// clamp lighting so it doesn't overbright as much
|
||||||
// ZOID: never allow players to go totally black
|
// ZOID: never allow players to go totally black
|
||||||
if (e->playerindex >= 0)
|
if (e->playerindex >= 0 && !(e->flags & (RF_WEAPONMODEL|RF_WEAPONMODELNOBOB|RF_DEPTHHACK)))
|
||||||
{
|
{
|
||||||
float fb = r_fullbrightSkins.value;
|
float fb = r_fullbrightSkins.value;
|
||||||
if (fb > cls.allow_fbskins)
|
if (fb > cls.allow_fbskins)
|
||||||
|
|
|
@ -10845,6 +10845,12 @@ static void QCBUILTIN PF_CheckPlayerEXFlags_qex(pubprogfuncs_t *prinst, struct g
|
||||||
|
|
||||||
G_FLOAT(OFS_RETURN) = flags;
|
G_FLOAT(OFS_RETURN) = flags;
|
||||||
}
|
}
|
||||||
|
static void QCBUILTIN PF_walkpathtogoal_qex(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
|
{ //this builtin is supposed to provide more advanced routing.
|
||||||
|
//the possible return values include an 'inprogress' which is kinda vague and implies persistent state.
|
||||||
|
//we can get away with returning false as a failure here, equivelent to if the map has no waypoints defined. the gamecode is expected to then fall back on the really lame movetogoal builtin.
|
||||||
|
G_FLOAT(OFS_RETURN) = false;
|
||||||
|
}
|
||||||
static void QCBUILTIN PF_centerprint_qex(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
static void QCBUILTIN PF_centerprint_qex(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||||
{ //TODO: send the strings to the client for localisation+reordering
|
{ //TODO: send the strings to the client for localisation+reordering
|
||||||
const char *arg[8];
|
const char *arg[8];
|
||||||
|
@ -11208,7 +11214,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
||||||
{"ex_bot_movetopoint",PF_Fixme, 0, 0, 0,0, D("float(entity bot, vector point)", "Behaviour is undocumented.")},
|
{"ex_bot_movetopoint",PF_Fixme, 0, 0, 0,0, D("float(entity bot, vector point)", "Behaviour is undocumented.")},
|
||||||
{"ex_bot_followentity",PF_Fixme, 0, 0, 0,0, D("float(entity bot, entity goal)", "Behaviour is undocumented.")},
|
{"ex_bot_followentity",PF_Fixme, 0, 0, 0,0, D("float(entity bot, entity goal)", "Behaviour is undocumented.")},
|
||||||
{"ex_CheckPlayerEXFlags",PF_CheckPlayerEXFlags_qex,0,0, 0,0, D("float(entity playerEnt)", "Behaviour is undocumented.")},
|
{"ex_CheckPlayerEXFlags",PF_CheckPlayerEXFlags_qex,0,0, 0,0, D("float(entity playerEnt)", "Behaviour is undocumented.")},
|
||||||
{"ex_walkpathtogoal",PF_Fixme, 0, 0, 0,0, D("float(float movedist, vector goal)", "Behaviour is undocumented.")},
|
{"ex_walkpathtogoal",PF_walkpathtogoal_qex,0, 0, 0,0, D("float(float movedist, vector goal)", "Behaviour is undocumented.")},
|
||||||
//End QuakeEx, for now. :(
|
//End QuakeEx, for now. :(
|
||||||
|
|
||||||
// Tomaz - QuakeC String Manipulation Begin
|
// Tomaz - QuakeC String Manipulation Begin
|
||||||
|
|
|
@ -2211,8 +2211,8 @@ static void SV_Status_f (void)
|
||||||
Con_Printf(" Qizmo");
|
Con_Printf(" Qizmo");
|
||||||
if (net_enable_qtv.ival)
|
if (net_enable_qtv.ival)
|
||||||
Con_Printf(" QTV");
|
Con_Printf(" QTV");
|
||||||
#endif
|
|
||||||
Con_Printf("\n");
|
Con_Printf("\n");
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef SUBSERVERS
|
#ifdef SUBSERVERS
|
||||||
|
@ -2354,7 +2354,7 @@ static void SV_Status_f (void)
|
||||||
columns |= 1<<5;
|
columns |= 1<<5;
|
||||||
if (cl->protocol != SCP_BAD && (cl->protocol >= SCP_NETQUAKE || cl->spectator || (cl->protocol == SCP_QUAKEWORLD && !(cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))))
|
if (cl->protocol != SCP_BAD && (cl->protocol >= SCP_NETQUAKE || cl->spectator || (cl->protocol == SCP_QUAKEWORLD && !(cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS))))
|
||||||
columns |= 1<<9;
|
columns |= 1<<9;
|
||||||
if (cl->netchan.remote_address.type == NA_IPV6||cl->reversedns)
|
if ((cl->netchan.remote_address.type == NA_IPV6 && memcmp(cl->netchan.remote_address.address.ip6, "\0\0\0\0""\0\0\0\0""\0\0\xff\xff", 12))||cl->reversedns)
|
||||||
columns |= (1<<10);
|
columns |= (1<<10);
|
||||||
}
|
}
|
||||||
if (columns&(1<<10)) //if address2, remove the limited length addresses.
|
if (columns&(1<<10)) //if address2, remove the limited length addresses.
|
||||||
|
|
|
@ -3517,7 +3517,7 @@ void SVC_DirectConnect(int expectedreliablesequence)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DTLS
|
#ifdef HAVE_DTLS
|
||||||
if (net_enable_dtls.ival > 2 && (net_from.prot == NP_DGRAM || net_from.prot == NP_STREAM || net_from.prot == NP_WS) && net_from.type != NA_LOOPBACK)
|
if (net_enable_dtls.ival > 2 && (net_from.prot == NP_DGRAM || net_from.prot == NP_STREAM || net_from.prot == NP_WS) && net_from.type != NA_LOOPBACK && !NET_IsEncrypted(&net_from))
|
||||||
{
|
{
|
||||||
SV_RejectMessage (info.protocol, "This server requires the use of DTLS/TLS/WSS.\n");
|
SV_RejectMessage (info.protocol, "This server requires the use of DTLS/TLS/WSS.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -4432,7 +4432,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
MSG_WriteString(&sb, "Incorrect game\n");
|
MSG_WriteString(&sb, "Incorrect game\n");
|
||||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||||
return false; //not our game.
|
return true; //not our game.
|
||||||
}
|
}
|
||||||
if (protver != NQ_NETCHAN_VERSION && protver != NQ_NETCHAN_VERSION_QEX)
|
if (protver != NQ_NETCHAN_VERSION && protver != NQ_NETCHAN_VERSION_QEX)
|
||||||
{
|
{
|
||||||
|
@ -4442,7 +4442,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
MSG_WriteString(&sb, "Incorrect version\n");
|
MSG_WriteString(&sb, "Incorrect version\n");
|
||||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||||
return false; //not our version...
|
return true; //not our version...
|
||||||
}
|
}
|
||||||
|
|
||||||
banreason = SV_BannedReason (&net_from);
|
banreason = SV_BannedReason (&net_from);
|
||||||
|
@ -4454,7 +4454,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
MSG_WriteString(&sb, *banreason?va("You are banned: %s\n", banreason):"You are banned\n");
|
MSG_WriteString(&sb, *banreason?va("You are banned: %s\n", banreason):"You are banned\n");
|
||||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||||
return false; //not our version...
|
return true; //not our version...
|
||||||
}
|
}
|
||||||
|
|
||||||
//proquake's extensions
|
//proquake's extensions
|
||||||
|
@ -4462,6 +4462,8 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
modver = MSG_ReadByte();
|
modver = MSG_ReadByte();
|
||||||
flags = MSG_ReadByte();
|
flags = MSG_ReadByte();
|
||||||
passwd = MSG_ReadLong();
|
passwd = MSG_ReadLong();
|
||||||
|
if (msg_badread)
|
||||||
|
passwd = 0;
|
||||||
|
|
||||||
if (SV_ChallengeRecent())
|
if (SV_ChallengeRecent())
|
||||||
return true;
|
return true;
|
||||||
|
@ -4482,10 +4484,21 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
||||||
MSG_WriteString(&sb, "NQ clients are not supported with hexen2 gamecode\n");
|
MSG_WriteString(&sb, "NQ clients are not supported with hexen2 gamecode\n");
|
||||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||||
return false; //not our version...
|
return true; //not our version...
|
||||||
}
|
}
|
||||||
if (sv_listen_nq.ival == 2 && net_from.prot == NP_DGRAM)
|
if (NET_WasSpecialPacket(svs.sockets))
|
||||||
|
return true;
|
||||||
|
if (sv_listen_nq.ival == 2 && net_from.prot == NP_DGRAM && net_from.type != NA_ICE)
|
||||||
{
|
{
|
||||||
|
if (password.string[0] &&
|
||||||
|
stricmp(password.string, "none") &&
|
||||||
|
strcmp(password.string, va("%i", passwd)) )
|
||||||
|
{ //make sure we don't get crippled because of being unable to specify the actual password with proquake's stuff.
|
||||||
|
Con_TPrintf ("%s:password failed (nq)\n", NET_AdrToString (buffer2, sizeof(buffer2), &net_from));
|
||||||
|
SV_RejectMessage (SCP_NETQUAKE, "server requires a password\n\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SZ_Clear(&sb);
|
SZ_Clear(&sb);
|
||||||
MSG_WriteLong(&sb, 0);
|
MSG_WriteLong(&sb, 0);
|
||||||
MSG_WriteByte(&sb, CCREP_ACCEPT);
|
MSG_WriteByte(&sb, CCREP_ACCEPT);
|
||||||
|
@ -4714,6 +4727,8 @@ void SV_ReadPacket(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NET_WasSpecialPacket(svs.sockets)) //fixes up IP->ICE addresses (so we don't break when routes change).
|
||||||
|
return;
|
||||||
SV_ConnectionlessPacket();
|
SV_ConnectionlessPacket();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1312,37 +1312,37 @@ static struct ircice_s *IRC_ICE_Create(ircclient_t *irc, const char *sender, enu
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!creator && type == ICEP_QWSERVER)
|
if (!creator && type == ICEP_QWSERVER)
|
||||||
ice = piceapi->ICE_Create(NULL, NULL, sender, ICEM_ICE, ICEP_QWCLIENT, creator);
|
ice = piceapi->Create(NULL, NULL, sender, ICEM_ICE, ICEP_QWCLIENT, creator);
|
||||||
else if (!creator && type == ICEP_QWCLIENT)
|
else if (!creator && type == ICEP_QWCLIENT)
|
||||||
ice = piceapi->ICE_Create(NULL, NULL, sender, ICEM_ICE, ICEP_QWSERVER, creator);
|
ice = piceapi->Create(NULL, NULL, sender, ICEM_ICE, ICEP_QWSERVER, creator);
|
||||||
else
|
else
|
||||||
ice = piceapi->ICE_Create(NULL, NULL, sender, ICEM_ICE, type, creator);
|
ice = piceapi->Create(NULL, NULL, sender, ICEM_ICE, type, creator);
|
||||||
|
|
||||||
if (!ice)
|
if (!ice)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
piceapi->ICE_Set(ice, "controller", creator?"1":"0");
|
piceapi->Set(ice, "controller", creator?"1":"0");
|
||||||
if (creator && type == ICEP_VOICE)
|
if (creator && type == ICEP_VOICE)
|
||||||
{
|
{
|
||||||
//note: the engine will ignore codecs it does not support.
|
//note: the engine will ignore codecs it does not support.
|
||||||
piceapi->ICE_Set(ice, "codec96", "opus@48000");
|
piceapi->Set(ice, "codec96", "opus@48000");
|
||||||
piceapi->ICE_Set(ice, "codec97", "speex@16000"); //wide
|
piceapi->Set(ice, "codec97", "speex@16000"); //wide
|
||||||
piceapi->ICE_Set(ice, "codec98", "speex@8000"); //narrow
|
piceapi->Set(ice, "codec98", "speex@8000"); //narrow
|
||||||
piceapi->ICE_Set(ice, "codec99", "speex@32000"); //ultrawide
|
piceapi->Set(ice, "codec99", "speex@32000"); //ultrawide
|
||||||
piceapi->ICE_Set(ice, "codec8", "pcma@8000");
|
piceapi->Set(ice, "codec8", "pcma@8000");
|
||||||
piceapi->ICE_Set(ice, "codec0", "pcmu@8000");
|
piceapi->Set(ice, "codec0", "pcmu@8000");
|
||||||
}
|
}
|
||||||
|
|
||||||
//query dns to see if there's a stunserver hosted by the same domain
|
//query dns to see if there's a stunserver hosted by the same domain
|
||||||
//nslookup -querytype=SRV _stun._udp.example.com
|
//nslookup -querytype=SRV _stun._udp.example.com
|
||||||
// Q_snprintf(stunhost, sizeof(stunhost), "_stun._udp.%s", ice->server);
|
// Q_snprintf(stunhost, sizeof(stunhost), "_stun._udp.%s", ice->server);
|
||||||
// if (NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost)))
|
// if (NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost)))
|
||||||
// piceapi->ICE_Set(ice, "stunip", stunhost);
|
// piceapi->Set(ice, "stunip", stunhost);
|
||||||
// else
|
// else
|
||||||
{
|
{
|
||||||
//irc services tend to not provide any stun info, so steal someone's... hopefully they won't mind too much. :(
|
//irc services tend to not provide any stun info, so steal someone's... hopefully they won't mind too much. :(
|
||||||
piceapi->ICE_Set(ice, "stunport", "19302");
|
piceapi->Set(ice, "stunport", "19302");
|
||||||
piceapi->ICE_Set(ice, "stunip", "stun.l.google.com");
|
piceapi->Set(ice, "stunip", "stun.l.google.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
ircice = malloc(sizeof(*ircice));
|
ircice = malloc(sizeof(*ircice));
|
||||||
|
@ -1395,8 +1395,8 @@ static void IRC_ICE_Update(ircclient_t *irc, struct ircice_s *ice, char updatety
|
||||||
char ufrag[256];
|
char ufrag[256];
|
||||||
char pwd[256];
|
char pwd[256];
|
||||||
|
|
||||||
piceapi->ICE_Get(ice->ice, "lufrag", ufrag, sizeof(ufrag));
|
piceapi->Get(ice->ice, "lufrag", ufrag, sizeof(ufrag));
|
||||||
piceapi->ICE_Get(ice->ice, "lpwd", pwd, sizeof(pwd));
|
piceapi->Get(ice->ice, "lpwd", pwd, sizeof(pwd));
|
||||||
|
|
||||||
Q_snprintf(message, sizeof(message), " ufrag/%s pwd/%s", ufrag, pwd);
|
Q_snprintf(message, sizeof(message), " ufrag/%s pwd/%s", ufrag, pwd);
|
||||||
}
|
}
|
||||||
|
@ -1410,7 +1410,7 @@ static void IRC_ICE_Update(ircclient_t *irc, struct ircice_s *ice, char updatety
|
||||||
char codecname[64];
|
char codecname[64];
|
||||||
char argn[64];
|
char argn[64];
|
||||||
Q_snprintf(argn, sizeof(argn), "codec%i", i);
|
Q_snprintf(argn, sizeof(argn), "codec%i", i);
|
||||||
if (!piceapi->ICE_Get(ice->ice, argn, codecname, sizeof(codecname)))
|
if (!piceapi->Get(ice->ice, argn, codecname, sizeof(codecname)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!strcmp(codecname, "speex@8000")) //speex narrowband
|
if (!strcmp(codecname, "speex@8000")) //speex narrowband
|
||||||
|
@ -1448,7 +1448,7 @@ static void IRC_ICE_Update(ircclient_t *irc, struct ircice_s *ice, char updatety
|
||||||
*/
|
*/
|
||||||
if (updatetype != '+' && updatetype != '-')
|
if (updatetype != '+' && updatetype != '-')
|
||||||
{
|
{
|
||||||
while ((c = piceapi->ICE_GetLCandidateInfo(ice->ice)))
|
while ((c = piceapi->GetLCandidateInfo(ice->ice)))
|
||||||
{
|
{
|
||||||
char type[] = "hspr";
|
char type[] = "hspr";
|
||||||
char cand[256];
|
char cand[256];
|
||||||
|
@ -1503,7 +1503,7 @@ static void IRC_ICE_ParseCandidate(struct icestate_s *ice, char *cand)
|
||||||
Q_strlcpy(info.candidateid, cand+1, sizeof(info.candidateid));
|
Q_strlcpy(info.candidateid, cand+1, sizeof(info.candidateid));
|
||||||
Q_strlcpy(info.addr, addr, sizeof(info.candidateid));
|
Q_strlcpy(info.addr, addr, sizeof(info.candidateid));
|
||||||
|
|
||||||
piceapi->ICE_AddRCandidateInfo(ice, &info);
|
piceapi->AddRCandidateInfo(ice, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRC_ICE_ParseCodec(struct icestate_s *ice, char *codec)
|
static void IRC_ICE_ParseCodec(struct icestate_s *ice, char *codec)
|
||||||
|
@ -1518,7 +1518,7 @@ static void IRC_ICE_ParseCodec(struct icestate_s *ice, char *codec)
|
||||||
|
|
||||||
Q_strlcat(name, va("@%u", rate), sizeof(name));
|
Q_strlcat(name, va("@%u", rate), sizeof(name));
|
||||||
|
|
||||||
piceapi->ICE_Set(ice, va("codec%i", num), name);
|
piceapi->Set(ice, va("codec%i", num), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IRC_ICE_Parse(ircclient_t *irc, const char *sender, char *message)
|
static void IRC_ICE_Parse(ircclient_t *irc, const char *sender, char *message)
|
||||||
|
@ -1559,16 +1559,16 @@ static void IRC_ICE_Parse(ircclient_t *irc, const char *sender, char *message)
|
||||||
else if (!strncmp(token, "codec/", 6))
|
else if (!strncmp(token, "codec/", 6))
|
||||||
IRC_ICE_ParseCodec(ice->ice, token);
|
IRC_ICE_ParseCodec(ice->ice, token);
|
||||||
else if (!strncmp(token, "ufrag/", 6))
|
else if (!strncmp(token, "ufrag/", 6))
|
||||||
piceapi->ICE_Set(ice->ice, "rufrag", token+6);
|
piceapi->Set(ice->ice, "rufrag", token+6);
|
||||||
else if (!strncmp(token, "pwd/", 4))
|
else if (!strncmp(token, "pwd/", 4))
|
||||||
piceapi->ICE_Set(ice->ice, "rpwd", token+4);
|
piceapi->Set(ice->ice, "rpwd", token+4);
|
||||||
else if (*token)
|
else if (*token)
|
||||||
IRC_Printf(irc, sender, "unknown ice token %s\n", token);
|
IRC_Printf(irc, sender, "unknown ice token %s\n", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((icetype == '=' || icetype == '*') && !ice->accepted && ice->allowed)
|
if ((icetype == '=' || icetype == '*') && !ice->accepted && ice->allowed)
|
||||||
{
|
{
|
||||||
piceapi->ICE_Set(ice->ice, "state", STRINGIFY(ICE_CONNECTING));
|
piceapi->Set(ice->ice, "state", STRINGIFY(ICE_CONNECTING));
|
||||||
ice->accepted = true;
|
ice->accepted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1642,7 +1642,7 @@ static void IRC_ICE_Frame(ircclient_t *irc)
|
||||||
if (!ice->accepted || !ice->allowed)
|
if (!ice->accepted || !ice->allowed)
|
||||||
continue;
|
continue;
|
||||||
//ice needs some maintainence. if things change then we need to be prepared to send updated candidate info
|
//ice needs some maintainence. if things change then we need to be prepared to send updated candidate info
|
||||||
piceapi->ICE_Get(ice->ice, "newlc", bah, sizeof(bah));
|
piceapi->Get(ice->ice, "newlc", bah, sizeof(bah));
|
||||||
if (atoi(bah))
|
if (atoi(bah))
|
||||||
{
|
{
|
||||||
IRC_Printf(irc, ice->peer, "Sending updated peer info\n");
|
IRC_Printf(irc, ice->peer, "Sending updated peer info\n");
|
||||||
|
@ -1687,7 +1687,7 @@ static void IRC_ICE_Authorise(ircclient_t *irc, const char *with, enum iceproto_
|
||||||
IRC_ICE_Update(irc, ice, '-');
|
IRC_ICE_Update(irc, ice, '-');
|
||||||
*link = ice->next;
|
*link = ice->next;
|
||||||
if (ice->ice)
|
if (ice->ice)
|
||||||
piceapi->ICE_Close(ice->ice);
|
piceapi->Close(ice->ice, true);
|
||||||
IRC_Free(ice);
|
IRC_Free(ice);
|
||||||
|
|
||||||
IRC_Printf(irc, announce, "Connection terminated\n");
|
IRC_Printf(irc, announce, "Connection terminated\n");
|
||||||
|
|
|
@ -22,24 +22,24 @@ static struct c2c_s *JCL_JingleAddContentToSession(jclient_t *jcl, struct c2c_s
|
||||||
}
|
}
|
||||||
|
|
||||||
if (piceapi)
|
if (piceapi)
|
||||||
ice = piceapi->ICE_Create(NULL, sid, with, method, mediatype, creator);
|
ice = piceapi->Create(NULL, sid, with, method, mediatype, creator);
|
||||||
if (ice)
|
if (ice)
|
||||||
{
|
{
|
||||||
piceapi->ICE_Get(ice, "sid", generatedname, sizeof(generatedname));
|
piceapi->Get(ice, "sid", generatedname, sizeof(generatedname));
|
||||||
sid = generatedname;
|
sid = generatedname;
|
||||||
|
|
||||||
//the controlling role MUST be assumed by the initiator and the controlled role MUST be assumed by the responder
|
//the controlling role MUST be assumed by the initiator and the controlled role MUST be assumed by the responder
|
||||||
piceapi->ICE_Set(ice, "controller", creator?"1":"0");
|
piceapi->Set(ice, "controller", creator?"1":"0");
|
||||||
|
|
||||||
if (creator && mediatype == ICEP_VOICE)
|
if (creator && mediatype == ICEP_VOICE)
|
||||||
{
|
{
|
||||||
//note: the engine will ignore codecs it does not support.
|
//note: the engine will ignore codecs it does not support.
|
||||||
piceapi->ICE_Set(ice, "codec96", "opus@48000");
|
piceapi->Set(ice, "codec96", "opus@48000");
|
||||||
piceapi->ICE_Set(ice, "codec97", "speex@16000"); //wide
|
piceapi->Set(ice, "codec97", "speex@16000"); //wide
|
||||||
piceapi->ICE_Set(ice, "codec98", "speex@8000"); //narrow
|
piceapi->Set(ice, "codec98", "speex@8000"); //narrow
|
||||||
piceapi->ICE_Set(ice, "codec99", "speex@32000"); //ultrawide
|
piceapi->Set(ice, "codec99", "speex@32000"); //ultrawide
|
||||||
piceapi->ICE_Set(ice, "codec0", "pcmu@8000");
|
piceapi->Set(ice, "codec0", "pcmu@8000");
|
||||||
piceapi->ICE_Set(ice, "codec8", "pcma@8000");
|
piceapi->Set(ice, "codec8", "pcma@8000");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -73,7 +73,7 @@ static struct c2c_s *JCL_JingleAddContentToSession(jclient_t *jcl, struct c2c_s
|
||||||
//google doesn't provide a stun srv entry
|
//google doesn't provide a stun srv entry
|
||||||
//facebook doesn't provide a stun srv entry
|
//facebook doesn't provide a stun srv entry
|
||||||
if (!Q_snprintfz(stunhost, sizeof(stunhost), "_stun._udp.%s", jcl->domain) && NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost)))
|
if (!Q_snprintfz(stunhost, sizeof(stunhost), "_stun._udp.%s", jcl->domain) && NET_DNSLookup_SRV(stunhost, stunhost, sizeof(stunhost)))
|
||||||
piceapi->ICE_Set(ice, "stunip", stunhost);
|
piceapi->Set(ice, "stunip", stunhost);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//there is no real way to query stun servers from the xmpp server.
|
//there is no real way to query stun servers from the xmpp server.
|
||||||
|
@ -83,8 +83,8 @@ static struct c2c_s *JCL_JingleAddContentToSession(jclient_t *jcl, struct c2c_s
|
||||||
//so we're basically screwed if we want to work with the googletalk xmpp service long term.
|
//so we're basically screwed if we want to work with the googletalk xmpp service long term.
|
||||||
//more methods are best, I suppose, but I'm lazy.
|
//more methods are best, I suppose, but I'm lazy.
|
||||||
//yes, hardcoding means that other services might 'borrow' googles' stun servers.
|
//yes, hardcoding means that other services might 'borrow' googles' stun servers.
|
||||||
piceapi->ICE_Set(ice, "stunport", "19302");
|
piceapi->Set(ice, "stunport", "19302");
|
||||||
piceapi->ICE_Set(ice, "stunip", "stun.l.google.com");
|
piceapi->Set(ice, "stunip", "stun.l.google.com");
|
||||||
}
|
}
|
||||||
return c2c;
|
return c2c;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ static qboolean JCL_JingleAcceptAck(jclient_t *jcl, xmltree_t *tree, struct iq_s
|
||||||
for (i = 0; i < c2c->contents; i++)
|
for (i = 0; i < c2c->contents; i++)
|
||||||
{
|
{
|
||||||
if (c2c->content[i].ice)
|
if (c2c->content[i].ice)
|
||||||
piceapi->ICE_Set(c2c->content[i].ice, "state", STRINGIFY(ICE_CONNECTING));
|
piceapi->Set(c2c->content[i].ice, "state", STRINGIFY(ICE_CONNECTING));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ static void JCL_PopulateAudioDescription(xmltree_t *description, struct icestate
|
||||||
char codecname[64];
|
char codecname[64];
|
||||||
char argn[64];
|
char argn[64];
|
||||||
Q_snprintf(argn, sizeof(argn), "codec%i", i);
|
Q_snprintf(argn, sizeof(argn), "codec%i", i);
|
||||||
if (piceapi->ICE_Get(ice, argn, codecname, sizeof(codecname)))
|
if (piceapi->Get(ice, argn, codecname, sizeof(codecname)))
|
||||||
{
|
{
|
||||||
if (!strcasecmp(codecname, "speex@8000") || !strcasecmp(codecname, "speex@16000") || !strcasecmp(codecname, "speex@32000"))
|
if (!strcasecmp(codecname, "speex@8000") || !strcasecmp(codecname, "speex@16000") || !strcasecmp(codecname, "speex@32000"))
|
||||||
{ //speex narrowband
|
{ //speex narrowband
|
||||||
|
@ -373,7 +373,7 @@ static qboolean JCL_JingleSend(jclient_t *jcl, struct c2c_s *c2c, char *action)
|
||||||
for (c = 0; c < c2c->contents; c++)
|
for (c = 0; c < c2c->contents; c++)
|
||||||
{
|
{
|
||||||
if (c2c->content[c].ice)
|
if (c2c->content[c].ice)
|
||||||
piceapi->ICE_Close(c2c->content[c].ice);
|
piceapi->Close(c2c->content[c].ice, true);
|
||||||
c2c->content[c].ice = NULL;
|
c2c->content[c].ice = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ static qboolean JCL_JingleSend(jclient_t *jcl, struct c2c_s *c2c, char *action)
|
||||||
xmltree_t *candidate;
|
xmltree_t *candidate;
|
||||||
struct icecandinfo_s *b = NULL;
|
struct icecandinfo_s *b = NULL;
|
||||||
struct icecandinfo_s *c;
|
struct icecandinfo_s *c;
|
||||||
while ((c = piceapi->ICE_GetLCandidateInfo(ice)))
|
while ((c = piceapi->GetLCandidateInfo(ice)))
|
||||||
{
|
{
|
||||||
if (!b || b->priority < c->priority)
|
if (!b || b->priority < c->priority)
|
||||||
b = c;
|
b = c;
|
||||||
|
@ -426,13 +426,13 @@ static qboolean JCL_JingleSend(jclient_t *jcl, struct c2c_s *c2c, char *action)
|
||||||
{
|
{
|
||||||
char val[64];
|
char val[64];
|
||||||
transport = XML_CreateNode(content, "transport", "urn:xmpp:jingle:transports:ice-udp:1", "");
|
transport = XML_CreateNode(content, "transport", "urn:xmpp:jingle:transports:ice-udp:1", "");
|
||||||
piceapi->ICE_Get(ice, "lufrag", val, sizeof(val));
|
piceapi->Get(ice, "lufrag", val, sizeof(val));
|
||||||
XML_AddParameter(transport, "ufrag", val);
|
XML_AddParameter(transport, "ufrag", val);
|
||||||
piceapi->ICE_Get(ice, "lpwd", val, sizeof(val));
|
piceapi->Get(ice, "lpwd", val, sizeof(val));
|
||||||
XML_AddParameter(transport, "pwd", val);
|
XML_AddParameter(transport, "pwd", val);
|
||||||
{
|
{
|
||||||
struct icecandinfo_s *c;
|
struct icecandinfo_s *c;
|
||||||
while ((c = piceapi->ICE_GetLCandidateInfo(ice)))
|
while ((c = piceapi->GetLCandidateInfo(ice)))
|
||||||
{
|
{
|
||||||
char *ctypename[]={"host", "srflx", "prflx", "relay"};
|
char *ctypename[]={"host", "srflx", "prflx", "relay"};
|
||||||
xmltree_t *candidate = XML_CreateNode(transport, "candidate", "", "");
|
xmltree_t *candidate = XML_CreateNode(transport, "candidate", "", "");
|
||||||
|
@ -509,7 +509,7 @@ void JCL_JingleTimeouts(jclient_t *jcl, qboolean killall)
|
||||||
if (c2c->content[c].method == ICEM_ICE)
|
if (c2c->content[c].method == ICEM_ICE)
|
||||||
{
|
{
|
||||||
char bah[2];
|
char bah[2];
|
||||||
piceapi->ICE_Get(c2c->content[c].ice, "newlc", bah, sizeof(bah));
|
piceapi->Get(c2c->content[c].ice, "newlc", bah, sizeof(bah));
|
||||||
if (atoi(bah))
|
if (atoi(bah))
|
||||||
{
|
{
|
||||||
Con_DPrintf("Sending updated local addresses\n");
|
Con_DPrintf("Sending updated local addresses\n");
|
||||||
|
@ -659,8 +659,8 @@ static void JCL_JingleParsePeerPorts(jclient_t *jcl, struct c2c_s *c2c, xmltree_
|
||||||
if (!intransport)
|
if (!intransport)
|
||||||
continue; //err, I guess it wasn't a transport update then (or related).
|
continue; //err, I guess it wasn't a transport update then (or related).
|
||||||
|
|
||||||
piceapi->ICE_Set(ice, "rufrag", XML_GetParameter(intransport, "ufrag", ""));
|
piceapi->Set(ice, "rufrag", XML_GetParameter(intransport, "ufrag", ""));
|
||||||
piceapi->ICE_Set(ice, "rpwd", XML_GetParameter(intransport, "pwd", ""));
|
piceapi->Set(ice, "rpwd", XML_GetParameter(intransport, "pwd", ""));
|
||||||
|
|
||||||
for (i = 0; (incandidate = XML_ChildOfTree(intransport, "candidate", i)); i++)
|
for (i = 0; (incandidate = XML_ChildOfTree(intransport, "candidate", i)); i++)
|
||||||
{
|
{
|
||||||
|
@ -689,7 +689,7 @@ static void JCL_JingleParsePeerPorts(jclient_t *jcl, struct c2c_s *c2c, xmltree_
|
||||||
rem.transport = 0;
|
rem.transport = 0;
|
||||||
else
|
else
|
||||||
rem.transport = 0;
|
rem.transport = 0;
|
||||||
piceapi->ICE_AddRCandidateInfo(ice, &rem);
|
piceapi->AddRCandidateInfo(ice, &rem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -946,12 +946,12 @@ static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, co
|
||||||
{
|
{
|
||||||
Q_snprintf(parm, sizeof(parm), "codec%i", atoi(id));
|
Q_snprintf(parm, sizeof(parm), "codec%i", atoi(id));
|
||||||
Q_snprintf(val, sizeof(val), "%s@%i", name, atoi(clock));
|
Q_snprintf(val, sizeof(val), "%s@%i", name, atoi(clock));
|
||||||
okay |= piceapi->ICE_Set(c2c->content[c].ice, parm, val);
|
okay |= piceapi->Set(c2c->content[c].ice, parm, val);
|
||||||
}
|
}
|
||||||
else if (!strcasecmp(name, "opus"))
|
else if (!strcasecmp(name, "opus"))
|
||||||
{
|
{
|
||||||
Q_snprintf(parm, sizeof(parm), "codec%i", atoi(id));
|
Q_snprintf(parm, sizeof(parm), "codec%i", atoi(id));
|
||||||
okay |= piceapi->ICE_Set(c2c->content[c].ice, parm, "opus@48000");
|
okay |= piceapi->Set(c2c->content[c].ice, parm, "opus@48000");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -966,7 +966,7 @@ static struct c2c_s *JCL_JingleHandleInitiate(jclient_t *jcl, xmltree_t *inj, co
|
||||||
XMPP_ConversationPrintf(b->accountdomain, b->name, false, "%s does not support any compatible codecs, and is unable to call you.\n", convolink);
|
XMPP_ConversationPrintf(b->accountdomain, b->name, false, "%s does not support any compatible codecs, and is unable to call you.\n", convolink);
|
||||||
|
|
||||||
if (c2c->content[c].ice)
|
if (c2c->content[c].ice)
|
||||||
piceapi->ICE_Close(c2c->content[c].ice);
|
piceapi->Close(c2c->content[c].ice, true);
|
||||||
c2c->content[c].ice = NULL;
|
c2c->content[c].ice = NULL;
|
||||||
c2c->contents--;
|
c2c->contents--;
|
||||||
}
|
}
|
||||||
|
@ -1022,7 +1022,7 @@ static qboolean JCL_JingleHandleSessionTerminate(jclient_t *jcl, xmltree_t *tree
|
||||||
|
|
||||||
for (c = 0; c < c2c->contents; c++)
|
for (c = 0; c < c2c->contents; c++)
|
||||||
if (c2c->content[c].ice)
|
if (c2c->content[c].ice)
|
||||||
piceapi->ICE_Close(c2c->content[c].ice);
|
piceapi->Close(c2c->content[c].ice, true);
|
||||||
free(c2c);
|
free(c2c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1066,7 +1066,7 @@ static qboolean JCL_JingleHandleSessionAccept(jclient_t *jcl, xmltree_t *tree, c
|
||||||
//if we didn't error out, the ICE stuff is meant to start sending handshakes/media as soon as the connection is accepted
|
//if we didn't error out, the ICE stuff is meant to start sending handshakes/media as soon as the connection is accepted
|
||||||
for (c = 0; c < c2c->contents; c++)
|
for (c = 0; c < c2c->contents; c++)
|
||||||
if (c2c->content[c].ice)
|
if (c2c->content[c].ice)
|
||||||
piceapi->ICE_Set(c2c->content[c].ice, "state", STRINGIFY(ICE_CONNECTING));
|
piceapi->Set(c2c->content[c].ice, "state", STRINGIFY(ICE_CONNECTING));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -930,7 +930,7 @@ static neterr_t OSSL_Transmit(void *ctx, const qbyte *data, size_t datasize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (BIO_should_retry(o->bio))
|
if (BIO_should_retry(o->bio))
|
||||||
return 0;
|
return NETERR_CLOGGED;
|
||||||
return NETERR_DISCONNECTED; //eof or something
|
return NETERR_DISCONNECTED; //eof or something
|
||||||
}
|
}
|
||||||
return NETERR_SENT;
|
return NETERR_SENT;
|
||||||
|
|
Loading…
Reference in a new issue