Some more ICE polish.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6300 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2022-07-28 02:18:05 +00:00
parent 5182692590
commit 89fde9c5e4
8 changed files with 176 additions and 51 deletions

View file

@ -152,6 +152,7 @@ int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_
void NET_PrintAddresses(struct ftenet_connections_s *collection); void NET_PrintAddresses(struct ftenet_connections_s *collection);
qboolean NET_AddressSmellsFunny(netadr_t *a); qboolean NET_AddressSmellsFunny(netadr_t *a);
qboolean NET_EnsureRoute(struct ftenet_connections_s *collection, char *routename, char *host, netadr_t *adr); qboolean NET_EnsureRoute(struct ftenet_connections_s *collection, char *routename, char *host, netadr_t *adr);
void NET_TerminateRoute(struct ftenet_connections_s *collection, netadr_t *adr);
void NET_PrintConnectionsStatus(struct ftenet_connections_s *collection); void NET_PrintConnectionsStatus(struct ftenet_connections_s *collection);
enum addressscope_e enum addressscope_e
@ -204,7 +205,8 @@ void NET_DTLS_Timeouts(struct ftenet_connections_s *col);
extern cvar_t dtls_psk_hint, dtls_psk_user, dtls_psk_key; extern cvar_t dtls_psk_hint, dtls_psk_user, dtls_psk_key;
#endif #endif
#ifdef SUPPORT_ICE #ifdef SUPPORT_ICE
neterr_t ICE_SendPacket(struct ftenet_connections_s *col, size_t length, const void *data, netadr_t *to); neterr_t ICE_SendPacket(size_t length, const void *data, netadr_t *to);
void ICE_Terminate(netadr_t *to); //if we kicked the client/etc, kill their ICE too.
qboolean ICE_IsEncrypted(netadr_t *to); qboolean ICE_IsEncrypted(netadr_t *to);
void ICE_Init(void); void ICE_Init(void);
#endif #endif

View file

@ -86,7 +86,11 @@ int net_drop;
cvar_t showpackets = CVAR("showpackets", "0"); cvar_t showpackets = CVAR("showpackets", "0");
cvar_t showdrop = CVAR("showdrop", "0"); cvar_t showdrop = CVAR("showdrop", "0");
cvar_t qport = CVARF("qport_", "0", CVAR_NOSAVE); cvar_t qport = CVARF("qport_", "0", CVAR_NOSAVE);
#ifdef FTE_TARGET_WEB //with webrtc our packets will be layered over sctp(header=28,extras=20ish) over dtls(13),
cvar_t net_mtu = CVARD("net_mtu", "1384", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
#else
cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation."); cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
#endif
cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets."); cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets.");
cvar_t pext_vrinputs = CVARD("_pext_vrinputs", "0", "RENAME ME WHEN STABLE. Networks player inputs slightly differently, allowing for greater capabilities, particuarly vr controller info."); cvar_t pext_vrinputs = CVARD("_pext_vrinputs", "0", "RENAME ME WHEN STABLE. Networks player inputs slightly differently, allowing for greater capabilities, particuarly vr controller info.");

View file

@ -2068,13 +2068,29 @@ static qboolean QDECL ICE_Set(struct icestate_s *con, const char *prop, const ch
{ {
int oldstate = con->state; int oldstate = con->state;
if (!strcmp(value, STRINGIFY(ICE_CONNECTING))) if (!strcmp(value, STRINGIFY(ICE_CONNECTING)))
{
con->state = ICE_CONNECTING; con->state = ICE_CONNECTING;
if (net_ice_debug.ival >= 1)
Con_Printf(S_COLOR_GRAY"[%s]: ice state connecting\n", con->friendlyname);
}
else if (!strcmp(value, STRINGIFY(ICE_INACTIVE))) else if (!strcmp(value, STRINGIFY(ICE_INACTIVE)))
{
con->state = ICE_INACTIVE; con->state = ICE_INACTIVE;
if (net_ice_debug.ival >= 1)
Con_Printf(S_COLOR_GRAY"[%s]: ice state inactive\n", con->friendlyname);
}
else if (!strcmp(value, STRINGIFY(ICE_FAILED))) else if (!strcmp(value, STRINGIFY(ICE_FAILED)))
{
con->state = ICE_FAILED; con->state = ICE_FAILED;
if (net_ice_debug.ival >= 1)
Con_Printf(S_COLOR_GRAY"[%s]: ice state failed\n", con->friendlyname);
}
else if (!strcmp(value, STRINGIFY(ICE_CONNECTED))) else if (!strcmp(value, STRINGIFY(ICE_CONNECTED)))
{
con->state = ICE_CONNECTED; con->state = ICE_CONNECTED;
if (net_ice_debug.ival >= 1)
Con_Printf(S_COLOR_GRAY"[%s]: ice state connected\n", con->friendlyname);
}
else else
{ {
Con_Printf("ICE_Set invalid state %s\n", value); Con_Printf("ICE_Set invalid state %s\n", value);
@ -2125,12 +2141,60 @@ static qboolean QDECL ICE_Set(struct icestate_s *con, const char *prop, const ch
#endif #endif
} }
if (oldstate != con->state && con->state == ICE_INACTIVE)
{ //forget our peer
struct icecandidate_s *c;
int i;
memset(&con->chosenpeer, 0, sizeof(con->chosenpeer));
#ifdef HAVE_DTLS
if (con->sctp)
{
Z_Free(con->sctp->cookie);
Z_Free(con->sctp);
con->sctp = NULL;
}
if (con->dtlsstate)
{
con->dtlsfuncs->DestroyContext(con->dtlsstate);
con->dtlsstate = NULL;
}
#endif
while(con->rc)
{
c = con->rc;
con->rc = c->next;
Z_Free(c);
}
while(con->lc)
{
c = con->lc;
con->lc = c->next;
Z_Free(c);
}
for (i = 0; i < con->servers; i++)
{
struct iceserver_s *s = &con->server[i];
if (s->con)
{ //make sure we tell the TURN server to release our allocation.
s->state = TURN_TERMINATING;
ICE_ToStunServer(con, s);
s->con->Close(s->con);
s->con = NULL;
}
Z_Free(s->nonce);
s->nonce = NULL;
s->peers = 0;
}
}
if (oldstate != con->state && con->state == ICE_CONNECTED) if (oldstate != con->state && con->state == ICE_CONNECTED)
{ {
if (con->chosenpeer.type == NA_INVALID) if (con->chosenpeer.type == NA_INVALID)
{ {
con->state = ICE_FAILED; con->state = ICE_FAILED;
Con_Printf("ICE failed. peer not valid.\n"); Con_Printf(CON_WARNING"[%s]: ICE failed. peer not valid.\n", con->friendlyname);
} }
#ifndef CLIENTONLY #ifndef CLIENTONLY
else if (con->proto == ICEP_QWSERVER && con->mode != ICEM_WEBRTC) else if (con->proto == ICEP_QWSERVER && con->mode != ICEM_WEBRTC)
@ -2445,7 +2509,7 @@ static qboolean QDECL ICE_Get(struct icestate_s *con, const char *prop, char *va
Q_strncatz(value, "t=0 0\n", valuelen); //start+end times... Q_strncatz(value, "t=0 0\n", valuelen); //start+end times...
Q_strncatz(value, va("a=ice-options:trickle\n"), valuelen); Q_strncatz(value, va("a=ice-options:trickle\n"), valuelen);
if ((con->proto == ICEP_QWSERVER || con->proto == ICEP_QWCLIENT) && con->mode == ICEM_WEBRTC) if (con->proto == ICEP_QWSERVER || con->proto == ICEP_QWCLIENT)
{ {
#ifdef HAVE_DTLS #ifdef HAVE_DTLS
if (con->cred.local.certsize) if (con->cred.local.certsize)
@ -2457,10 +2521,20 @@ static qboolean QDECL ICE_Get(struct icestate_s *con, const char *prop, char *va
for (b = 0; b < hash_sha256.digestsize; b++) for (b = 0; b < hash_sha256.digestsize; b++)
Q_strncatz(value, va(b?":%02X":" %02X", fingerprint[b]), valuelen); Q_strncatz(value, va(b?":%02X":" %02X", fingerprint[b]), valuelen);
Q_strncatz(value, "\n", valuelen); Q_strncatz(value, "\n", valuelen);
}
if (con->mode == ICEM_WEBRTC)
{
Q_strncatz(value, "m=application 9 UDP/DTLS/SCTP webrtc-datachannel\n", valuelen); Q_strncatz(value, "m=application 9 UDP/DTLS/SCTP webrtc-datachannel\n", valuelen);
if (con->mysctpport)
Q_strncatz(value, va("a=sctp-port:%i\n", con->mysctpport), valuelen); //stupid hardcoded thing.
if (con->sctpoptional) if (con->sctpoptional)
Q_strncatz(value, "a=sctp-optional:1\n", valuelen); Q_strncatz(value, "a=sctp-optional:1\n", valuelen);
}
else
Q_strncatz(value, "m=application 9 UDP/DTLS\n", valuelen);
}
else
Q_strncatz(value, "m=application 9 UDP\n", valuelen);
#endif #endif
} }
// Q_strncatz(value, va("c=IN %s %s\n", sender.type==NA_IPV6?"IP6":"IP4", NET_BaseAdrToString(tmpstr, sizeof(tmpstr), &sender)), valuelen); // Q_strncatz(value, va("c=IN %s %s\n", sender.type==NA_IPV6?"IP6":"IP4", NET_BaseAdrToString(tmpstr, sizeof(tmpstr), &sender)), valuelen);
@ -2481,9 +2555,6 @@ static qboolean QDECL ICE_Get(struct icestate_s *con, const char *prop, char *va
else if (!strcmp(prop, "sdpoffer")) else if (!strcmp(prop, "sdpoffer"))
Q_strncatz(value, va("a=setup:actpass\n"), valuelen); //don't care if we're active or passive Q_strncatz(value, va("a=setup:actpass\n"), valuelen); //don't care if we're active or passive
} }
if (con->mysctpport)
Q_strncatz(value, va("a=sctp-port:%i\n", con->mysctpport), valuelen); //stupid hardcoded thing.
#endif #endif
/*fixme: merge the codecs into a single media line*/ /*fixme: merge the codecs into a single media line*/
@ -2752,6 +2823,8 @@ static void ICE_Destroy(struct icestate_s *con)
{ {
struct icecandidate_s *c; struct icecandidate_s *c;
ICE_Set(con, "state", STRINGIFY(ICE_INACTIVE));
#ifdef HAVE_DTLS #ifdef HAVE_DTLS
if (con->sctp) if (con->sctp)
{ {
@ -2941,8 +3014,6 @@ static void QDECL ICE_Close(struct icestate_s *con)
{ {
struct icestate_s **link; struct icestate_s **link;
ICE_Set(con, "state", STRINGIFY(ICE_INACTIVE));
for (link = &icelist; *link; ) for (link = &icelist; *link; )
{ {
if (con == *link) if (con == *link)
@ -3325,7 +3396,7 @@ struct sctp_errorcause_s
quint16_t cause; quint16_t cause;
quint16_t length; quint16_t length;
}; };
static void SCTP_ErrorChunk(const char *errortype, struct sctp_errorcause_s *s, size_t totallen) static void SCTP_ErrorChunk(struct icestate_s *peer, const char *errortype, struct sctp_errorcause_s *s, size_t totallen)
{ {
quint16_t cc, cl; quint16_t cc, cl;
while(totallen > 0) while(totallen > 0)
@ -3337,22 +3408,22 @@ static void SCTP_ErrorChunk(const char *errortype, struct sctp_errorcause_s *s,
if (totallen < cl) if (totallen < cl)
return; //err.. return; //err..
switch(cc) if (net_ice_debug.ival >= 1) switch(cc)
{ {
case 1: Con_Printf("%s: Invalid Stream Identifier\n", errortype); break; case 1: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Invalid Stream Identifier\n", peer->friendlyname, errortype); break;
case 2: Con_Printf("%s: Missing Mandatory Parameter\n", errortype); break; case 2: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Missing Mandatory Parameter\n", peer->friendlyname, errortype); break;
case 3: Con_Printf("%s: Stale Cookie Error\n", errortype); break; case 3: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Stale Cookie Error\n", peer->friendlyname, errortype); break;
case 4: Con_Printf("%s: Out of Resource\n", errortype); break; case 4: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Out of Resource\n", peer->friendlyname, errortype); break;
case 5: Con_Printf("%s: Unresolvable Address\n", errortype); break; case 5: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Unresolvable Address\n", peer->friendlyname, errortype); break;
case 6: Con_Printf("%s: Unrecognized Chunk Type\n", errortype); break; case 6: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Unrecognized Chunk Type\n", peer->friendlyname, errortype); break;
case 7: Con_Printf("%s: Invalid Mandatory Parameter\n", errortype); break; case 7: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Invalid Mandatory Parameter\n", peer->friendlyname, errortype); break;
case 8: Con_Printf("%s: Unrecognized Parameters\n", errortype); break; case 8: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Unrecognized Parameters\n", peer->friendlyname, errortype); break;
case 9: Con_Printf("%s: No User Data\n", errortype); break; case 9: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: No User Data\n", peer->friendlyname, errortype); break;
case 10: Con_Printf("%s: Cookie Received While Shutting Down\n", errortype); break; case 10: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Cookie Received While Shutting Down\n", peer->friendlyname, errortype); break;
case 11: Con_Printf("%s: Restart of an Association with New Addresses\n", errortype); break; case 11: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Restart of an Association with New Addresses\n", peer->friendlyname, errortype); break;
case 12: Con_Printf("%s: User Initiated Abort\n", errortype); break; case 12: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: User Initiated Abort\n", peer->friendlyname, errortype); break;
case 13: Con_Printf("%s: Protocol Violation [%s]\n", errortype, (char*)(s+1)); break; case 13: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Protocol Violation [%s]\n", peer->friendlyname, errortype, (char*)(s+1)); break;
default: Con_Printf("%s: Unknown Reason\n", errortype); break; default: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Unknown Reason\n", peer->friendlyname, errortype); break;
} }
totallen -= cl; totallen -= cl;
@ -3383,7 +3454,7 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection
if (net_message.cursize&3) if (net_message.cursize&3)
{ {
if (net_ice_debug.ival >= 2) if (net_ice_debug.ival >= 2)
Con_Printf("SCTP: packet not padded\n"); Con_Printf(S_COLOR_GRAY"[%s]: SCTP: packet not padded\n", peer->friendlyname);
return; //mimic chrome, despite it being pointless. return; //mimic chrome, despite it being pointless.
} }
@ -3402,11 +3473,20 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection
qint32_t adv = tsn - sctp->i.ctsn; qint32_t adv = tsn - sctp->i.ctsn;
sctp->i.ackneeded++; sctp->i.ackneeded++;
if (adv >= SCTP_RCVSIZE) if (adv >= SCTP_RCVSIZE)
Con_DPrintf("SCTP: Future Packet\n");/*too far in the future. we can't track such things*/ {
if (net_ice_debug.ival >= 1)
Con_Printf(S_COLOR_GRAY"[%s]: SCTP: Future Packet\n", peer->friendlyname);/*too far in the future. we can't track such things*/
}
else if (adv <= 0) else if (adv <= 0)
Con_DPrintf("SCTP: PreCumulative\n");/*already acked this*/ {
if (net_ice_debug.ival >= 2)
Con_Printf(S_COLOR_GRAY"[%s]: SCTP: PreCumulative\n", peer->friendlyname);/*already acked this*/
}
else if (sctp->i.received[(tsn>>3)%sizeof(sctp->i.received)] & 1<<(tsn&7)) else if (sctp->i.received[(tsn>>3)%sizeof(sctp->i.received)] & 1<<(tsn&7))
Con_DPrintf("SCTP: Dupe\n");/*already processed it. FIXME: Make a list for the next SACK*/ {
if (net_ice_debug.ival >= 2)
Con_DPrintf(S_COLOR_GRAY"[%s]: SCTP: Dupe\n", peer->friendlyname);/*already processed it. FIXME: Make a list for the next SACK*/
}
else else
{ {
qboolean err = false; qboolean err = false;
@ -3436,7 +3516,8 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection
sctp->i.r.tsn++; sctp->i.r.tsn++;
if (sctp->i.r.size + clen-sizeof(*dc) > sizeof(sctp->i.r.buf)) if (sctp->i.r.size + clen-sizeof(*dc) > sizeof(sctp->i.r.buf))
{ {
Con_DPrintf("SCTP: Oversized\n"); if (net_ice_debug.ival >= 2)
Con_Printf(S_COLOR_GRAY"[%s]: SCTP: Oversized\n", peer->friendlyname);
sctp->i.r.toobig = true; //reassembled packet was too large, just corrupt it. sctp->i.r.toobig = true; //reassembled packet was too large, just corrupt it.
} }
else else
@ -3516,7 +3597,8 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection
sctp->peerhasfwdtsn = true; sctp->peerhasfwdtsn = true;
break; break;
default: default:
Con_DPrintf("SCTP: Found unknown init parameter %i||%#x\n", ptype, ptype); if (net_ice_debug.ival >= 2)
Con_Printf(S_COLOR_GRAY"[%s]: SCTP: Found unknown init parameter %i||%#x\n", peer->friendlyname, ptype, ptype);
break; break;
} }
p = (void*)((qbyte*)p + ((plen+3)&~3)); p = (void*)((qbyte*)p + ((plen+3)&~3));
@ -3607,16 +3689,17 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection
// case SCTP_TYPE_PONG: //we don't send pings // case SCTP_TYPE_PONG: //we don't send pings
case SCTP_TYPE_ABORT: case SCTP_TYPE_ABORT:
ICE_Set(peer, "state", STRINGIFY(ICE_FAILED)); ICE_Set(peer, "state", STRINGIFY(ICE_FAILED));
SCTP_ErrorChunk("Abort", (struct sctp_errorcause_s*)(c+1), clen-sizeof(*c)); SCTP_ErrorChunk(peer, "Abort", (struct sctp_errorcause_s*)(c+1), clen-sizeof(*c));
break; break;
case SCTP_TYPE_SHUTDOWN: //FIXME. we should send an ack... case SCTP_TYPE_SHUTDOWN: //FIXME. we should send an ack...
ICE_Set(peer, "state", STRINGIFY(ICE_FAILED)); ICE_Set(peer, "state", STRINGIFY(ICE_FAILED));
Con_DPrintf(CON_ERROR"SCTP: Shutdown\n"); if (net_ice_debug.ival >= 1)
Con_Printf(S_COLOR_GRAY"[%s]: SCTP: Shutdown\n", peer->friendlyname);
break; break;
// case SCTP_TYPE_SHUTDOWNACK: //we don't send shutdowns, cos we're lame like that... // case SCTP_TYPE_SHUTDOWNACK: //we don't send shutdowns, cos we're lame like that...
case SCTP_TYPE_ERROR: case SCTP_TYPE_ERROR:
//not fatal... //not fatal...
SCTP_ErrorChunk("Error", (struct sctp_errorcause_s*)(c+1), clen-sizeof(*c)); SCTP_ErrorChunk(peer, "Error", (struct sctp_errorcause_s*)(c+1), clen-sizeof(*c));
break; break;
case SCTP_TYPE_COOKIEECHO: case SCTP_TYPE_COOKIEECHO:
if (clen >= sizeof(struct sctp_chunk_s)) if (clen >= sizeof(struct sctp_chunk_s))
@ -3666,7 +3749,8 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection
// case SCTP_TYPE_SHUTDOWNDONE: // case SCTP_TYPE_SHUTDOWNDONE:
safedefault: safedefault:
//no idea what this chunk is, just ignore it... //no idea what this chunk is, just ignore it...
Con_DPrintf("SCTP: Unsupported chunk %i\n", c->type); if (net_ice_debug.ival >= 1)
Con_Printf(S_COLOR_GRAY"[%s]: SCTP: Unsupported chunk %i\n", peer->friendlyname, c->type);
break; break;
} }
c = (struct sctp_chunk_s*)((qbyte*)c + ((clen+3)&~3)); //next chunk is 4-byte aligned. c = (struct sctp_chunk_s*)((qbyte*)c + ((clen+3)&~3)); //next chunk is 4-byte aligned.
@ -4666,7 +4750,19 @@ qboolean ICE_IsEncrypted(netadr_t *to)
#endif #endif
return false; return false;
} }
neterr_t ICE_SendPacket(ftenet_connections_t *col, size_t length, const void *data, netadr_t *to) void ICE_Terminate(netadr_t *to)
{
struct icestate_s *con;
for (con = icelist; con; con = con->next)
{
if (NET_CompareAdr(to, &con->qadr))
{
ICE_Set(con, "state", STRINGIFY(ICE_INACTIVE));
return;
}
}
}
neterr_t ICE_SendPacket(size_t length, const void *data, netadr_t *to)
{ {
struct icestate_s *con; struct icestate_s *con;
for (con = icelist; con; con = con->next) for (con = icelist; con; con = con->next)

View file

@ -545,11 +545,6 @@ static int QDECL SSL_CheckFingerprint(gnutls_session_t session)
file->peerhashfunc->process(ctx, certlist[j].data, certlist[j].size); file->peerhashfunc->process(ctx, certlist[j].data, certlist[j].size);
file->peerhashfunc->terminate(digest, ctx); file->peerhashfunc->terminate(digest, ctx);
{
vfsfile_t *f = FS_OpenVFS("/tmp/cert", "wb", FS_SYSTEM);
VFS_WRITE(f, certlist[0].data, certlist[0].size);
VFS_CLOSE(f);
}
if (!memcmp(digest, file->peerdigest, file->peerhashfunc->digestsize)) if (!memcmp(digest, file->peerdigest, file->peerhashfunc->digestsize))
return 0; return 0;
} }
@ -640,7 +635,7 @@ 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
{ {
Con_Printf("TLS Read Warning %i (bufsize %i)\n", read, bytestoread); Con_Printf("GNUTLS Read Warning %i (bufsize %i)\n", read, bytestoread);
return -1; return -1;
} }
} }
@ -667,7 +662,7 @@ static int QDECL SSL_Write(struct vfsfile_s *f, const void *buffer, int bytestow
return 0; return 0;
else else
{ {
Con_DPrintf("TLS Send Error %i (%i bytes)\n", written, bytestowrite); Con_DPrintf("GNUTLS Send Error %i (%i bytes)\n", written, bytestowrite);
return VFS_ERROR_UNSPECIFIED; return VFS_ERROR_UNSPECIFIED;
} }
} }
@ -999,7 +994,9 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred)
if (priv.size && pub.size) if (priv.size && pub.size)
{ //submit them to gnutls { //submit them to gnutls
ret = qgnutls_certificate_set_x509_key_mem(cred, &pub, &priv, GNUTLS_X509_FMT_PEM); ret = qgnutls_certificate_set_x509_key_mem(cred, &pub, &priv, GNUTLS_X509_FMT_PEM);
if (ret < 0) if (ret == GNUTLS_E_CERTIFICATE_KEY_MISMATCH)
Con_Printf(CON_ERROR"gnutls_certificate_set_x509_key_mem failed: GNUTLS_E_CERTIFICATE_KEY_MISMATCH\n");
else if (ret < 0)
Con_Printf(CON_ERROR"gnutls_certificate_set_x509_key_mem failed: %i\n", ret); Con_Printf(CON_ERROR"gnutls_certificate_set_x509_key_mem failed: %i\n", ret);
} }
else else
@ -1632,7 +1629,7 @@ static qboolean GNUDTLS_GenTempCertificate(const char *subject, struct dtlslocal
{ {
qbyte tmp[16]; qbyte tmp[16];
Sys_RandomBytes(tmp, sizeof(tmp)); Sys_RandomBytes(tmp, sizeof(tmp));
randomsub[Base16_EncodeBlock(tmp, sizeof(tmp), randomsub, sizeof(randomsub))] = 0; randomsub[Base16_EncodeBlock(tmp, sizeof(tmp), randomsub, sizeof(randomsub)-1)] = 0;
subject = randomsub; subject = randomsub;
} }
@ -1687,7 +1684,7 @@ static const dtlsfuncs_t *GNUDTLS_InitServer(void)
{ {
if (!SSL_InitGlobal(true)) if (!SSL_InitGlobal(true))
return NULL; //unable to init a server certificate. don't allow dtls to init. return NULL; //unable to init a server certificate. don't allow dtls to init.
if (servercertfail && !*dtls_psk_user.string) if (servercertfail && !*dtls_psk_user.string) //FIXME: with ICE connections we'll be using temporary certs anyway.
return NULL; return NULL;
return &dtlsfuncs_gnutls; return &dtlsfuncs_gnutls;
} }

View file

@ -8199,7 +8199,7 @@ neterr_t NET_SendPacket (ftenet_connections_t *collection, int length, const voi
#ifdef SUPPORT_ICE #ifdef SUPPORT_ICE
if (to->type == NA_ICE) if (to->type == NA_ICE)
return ICE_SendPacket(collection, length, data, to); return ICE_SendPacket(length, data, to);
#endif #endif
#ifdef HAVE_DTLS #ifdef HAVE_DTLS
if (to->prot == NP_DTLS) if (to->prot == NP_DTLS)
@ -8256,6 +8256,24 @@ qboolean NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char
} }
return true; return true;
} }
void NET_TerminateRoute(ftenet_connections_t *collection, netadr_t *adr)
{
switch(adr->prot)
{
case NP_DTLS:
#ifdef HAVE_DTLS
NET_DTLS_Disconnect(collection, adr);
#endif
break;
default:
break;
}
#ifdef SUPPORT_ICE
if (adr->type == NA_ICE)
ICE_Terminate(adr);
#endif
}
int NET_EnumerateAddresses(ftenet_connections_t *collection, struct ftenet_generic_connection_s **con, unsigned int *adrflags, netadr_t *addresses, const char **adrparams, int maxaddresses) int NET_EnumerateAddresses(ftenet_connections_t *collection, struct ftenet_generic_connection_s **con, unsigned int *adrflags, netadr_t *addresses, const char **adrparams, int maxaddresses)
{ {

View file

@ -1124,7 +1124,7 @@ qboolean GLBE_BeginShadowMap(int id, int w, int h, uploadfmt_t encoding, int *re
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); //qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
} }
tex->status = TEX_LOADED; tex->status = TEX_LOADED;
} }

View file

@ -5020,11 +5020,19 @@ void SV_CheckTimeouts (void)
SV_BroadcastTPrintf (PRINT_HIGH, "Client %s timed out\n", cl->name); SV_BroadcastTPrintf (PRINT_HIGH, "Client %s timed out\n", cl->name);
SV_DropClient (cl); SV_DropClient (cl);
cl->state = cs_free; // don't bother with zombie state for local player. cl->state = cs_free; // don't bother with zombie state for local player.
if (cl->netchan.remote_address.type != NA_INVALID)
NET_TerminateRoute(svs.sockets, &cl->netchan.remote_address);
cl->netchan.remote_address.type = NA_INVALID;
} }
} }
if (cl->state == cs_zombie && realtime - cl->connection_started > zombietime.value) if (cl->state == cs_zombie && realtime - cl->connection_started > zombietime.value)
{
cl->state = cs_free; // can now be reused cl->state = cs_free; // can now be reused
if (cl->netchan.remote_address.type != NA_INVALID)
NET_TerminateRoute(svs.sockets, &cl->netchan.remote_address);
cl->netchan.remote_address.type = NA_INVALID;
}
if (cl->state == cs_loadzombie && realtime - cl->connection_started > zombietime.value) if (cl->state == cs_loadzombie && realtime - cl->connection_started > zombietime.value)
{ {

View file

@ -770,7 +770,7 @@ static void *OSSL_CreateContext(const dtlscred_t *cred, void *cbctx, neterr_t(*p
SSL_CTX_set_session_cache_mode(n->ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_session_cache_mode(n->ctx, SSL_SESS_CACHE_OFF);
SSL_CTX_set_verify(n->ctx, SSL_VERIFY_PEER|(n->cert.hash?SSL_VERIFY_FAIL_IF_NO_PEER_CERT:0), OSSL_Verify_Peer); SSL_CTX_set_verify(n->ctx, SSL_VERIFY_PEER|(n->cert.hash?SSL_VERIFY_FAIL_IF_NO_PEER_CERT:0), OSSL_Verify_Peer);
SSL_CTX_set_verify_depth(n->ctx, 5); SSL_CTX_set_verify_depth(n->ctx, 10);
SSL_CTX_set_options(n->ctx, SSL_OP_NO_COMPRESSION| //compression allows guessing the contents of the stream somehow. SSL_CTX_set_options(n->ctx, SSL_OP_NO_COMPRESSION| //compression allows guessing the contents of the stream somehow.
SSL_OP_NO_RENEGOTIATION); SSL_OP_NO_RENEGOTIATION);