diff --git a/engine/common/net.h b/engine/common/net.h index 371471b26..3994fc337 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -152,6 +152,7 @@ int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_ void NET_PrintAddresses(struct ftenet_connections_s *collection); qboolean NET_AddressSmellsFunny(netadr_t *a); 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); 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; #endif #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); void ICE_Init(void); #endif diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index ee082f841..b68224700 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -86,7 +86,11 @@ int net_drop; cvar_t showpackets = CVAR("showpackets", "0"); cvar_t showdrop = CVAR("showdrop", "0"); 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."); +#endif 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."); diff --git a/engine/common/net_ice.c b/engine/common/net_ice.c index 873af08e8..bfb3bac88 100644 --- a/engine/common/net_ice.c +++ b/engine/common/net_ice.c @@ -2068,13 +2068,29 @@ static qboolean QDECL ICE_Set(struct icestate_s *con, const char *prop, const ch { int oldstate = con->state; if (!strcmp(value, STRINGIFY(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))) + { 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))) + { 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))) + { con->state = ICE_CONNECTED; + if (net_ice_debug.ival >= 1) + Con_Printf(S_COLOR_GRAY"[%s]: ice state connected\n", con->friendlyname); + } else { 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 } + 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 (con->chosenpeer.type == NA_INVALID) { 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 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, 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 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++) Q_strncatz(value, va(b?":%02X":" %02X", fingerprint[b]), valuelen); Q_strncatz(value, "\n", valuelen); + + if (con->mode == ICEM_WEBRTC) + { + 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) + Q_strncatz(value, "a=sctp-optional:1\n", valuelen); + } + else + Q_strncatz(value, "m=application 9 UDP/DTLS\n", valuelen); } - Q_strncatz(value, "m=application 9 UDP/DTLS/SCTP webrtc-datachannel\n", valuelen); - if (con->sctpoptional) - Q_strncatz(value, "a=sctp-optional:1\n", valuelen); + else + Q_strncatz(value, "m=application 9 UDP\n", valuelen); #endif } // 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")) 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 /*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; + ICE_Set(con, "state", STRINGIFY(ICE_INACTIVE)); + #ifdef HAVE_DTLS if (con->sctp) { @@ -2941,8 +3014,6 @@ static void QDECL ICE_Close(struct icestate_s *con) { struct icestate_s **link; - ICE_Set(con, "state", STRINGIFY(ICE_INACTIVE)); - for (link = &icelist; *link; ) { if (con == *link) @@ -3325,7 +3396,7 @@ struct sctp_errorcause_s quint16_t cause; 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; while(totallen > 0) @@ -3337,22 +3408,22 @@ static void SCTP_ErrorChunk(const char *errortype, struct sctp_errorcause_s *s, if (totallen < cl) return; //err.. - switch(cc) + if (net_ice_debug.ival >= 1) switch(cc) { - case 1: Con_Printf("%s: Invalid Stream Identifier\n", errortype); break; - case 2: Con_Printf("%s: Missing Mandatory Parameter\n", errortype); break; - case 3: Con_Printf("%s: Stale Cookie Error\n", errortype); break; - case 4: Con_Printf("%s: Out of Resource\n", errortype); break; - case 5: Con_Printf("%s: Unresolvable Address\n", errortype); break; - case 6: Con_Printf("%s: Unrecognized Chunk Type\n", errortype); break; - case 7: Con_Printf("%s: Invalid Mandatory Parameter\n", errortype); break; - case 8: Con_Printf("%s: Unrecognized Parameters\n", errortype); break; - case 9: Con_Printf("%s: No User Data\n", errortype); break; - case 10: Con_Printf("%s: Cookie Received While Shutting Down\n", errortype); break; - case 11: Con_Printf("%s: Restart of an Association with New Addresses\n", errortype); break; - case 12: Con_Printf("%s: User Initiated Abort\n", errortype); break; - case 13: Con_Printf("%s: Protocol Violation [%s]\n", errortype, (char*)(s+1)); break; - default: Con_Printf("%s: Unknown Reason\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_COLOR_GRAY"[%s]: SCTP %s: Missing Mandatory Parameter\n", peer->friendlyname, 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_COLOR_GRAY"[%s]: SCTP %s: Out of Resource\n", peer->friendlyname, errortype); break; + case 5: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Unresolvable Address\n", peer->friendlyname, 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_COLOR_GRAY"[%s]: SCTP %s: Invalid Mandatory Parameter\n", peer->friendlyname, errortype); break; + case 8: Con_Printf(S_COLOR_GRAY"[%s]: SCTP %s: Unrecognized Parameters\n", peer->friendlyname, 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_COLOR_GRAY"[%s]: SCTP %s: Cookie Received While Shutting Down\n", peer->friendlyname, 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_COLOR_GRAY"[%s]: SCTP %s: User Initiated Abort\n", peer->friendlyname, errortype); 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_COLOR_GRAY"[%s]: SCTP %s: Unknown Reason\n", peer->friendlyname, errortype); break; } 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_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. } @@ -3402,11 +3473,20 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection qint32_t adv = tsn - sctp->i.ctsn; sctp->i.ackneeded++; 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) - 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)) - 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 { qboolean err = false; @@ -3436,7 +3516,8 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection sctp->i.r.tsn++; 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. } else @@ -3516,7 +3597,8 @@ static void SCTP_Decode(sctp_t *sctp, struct icestate_s *peer, ftenet_connection sctp->peerhasfwdtsn = true; break; 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; } 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_ABORT: 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; case SCTP_TYPE_SHUTDOWN: //FIXME. we should send an ack... 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; // case SCTP_TYPE_SHUTDOWNACK: //we don't send shutdowns, cos we're lame like that... case SCTP_TYPE_ERROR: //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; case SCTP_TYPE_COOKIEECHO: 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: safedefault: //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; } 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 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; for (con = icelist; con; con = con->next) diff --git a/engine/common/net_ssl_gnutls.c b/engine/common/net_ssl_gnutls.c index 4b51db1fe..f154535ae 100644 --- a/engine/common/net_ssl_gnutls.c +++ b/engine/common/net_ssl_gnutls.c @@ -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->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)) 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) 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; } } @@ -667,7 +662,7 @@ static int QDECL SSL_Write(struct vfsfile_s *f, const void *buffer, int bytestow return 0; 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; } } @@ -999,7 +994,9 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred) if (priv.size && pub.size) { //submit them to gnutls 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); } else @@ -1632,7 +1629,7 @@ static qboolean GNUDTLS_GenTempCertificate(const char *subject, struct dtlslocal { qbyte tmp[16]; 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; } @@ -1687,7 +1684,7 @@ static const dtlsfuncs_t *GNUDTLS_InitServer(void) { if (!SSL_InitGlobal(true)) 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 &dtlsfuncs_gnutls; } diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 4c1ffaaaa..c6e3085a8 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -8199,7 +8199,7 @@ neterr_t NET_SendPacket (ftenet_connections_t *collection, int length, const voi #ifdef SUPPORT_ICE if (to->type == NA_ICE) - return ICE_SendPacket(collection, length, data, to); + return ICE_SendPacket(length, data, to); #endif #ifdef HAVE_DTLS if (to->prot == NP_DTLS) @@ -8256,6 +8256,24 @@ qboolean NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char } 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) { diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 96e296225..804722820 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -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_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; } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index c2ca594b2..5015f2388 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -5020,11 +5020,19 @@ void SV_CheckTimeouts (void) SV_BroadcastTPrintf (PRINT_HIGH, "Client %s timed out\n", cl->name); SV_DropClient (cl); 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) + { 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) { diff --git a/plugins/net_ssl_openssl.c b/plugins/net_ssl_openssl.c index 511144a6d..6e0fe2836 100644 --- a/plugins/net_ssl_openssl.c +++ b/plugins/net_ssl_openssl.c @@ -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_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_OP_NO_RENEGOTIATION);