@@ -22,15 +22,11 @@ public abstract class KcpPeer
2222 // => cookie can be a random number, but it needs to be cryptographically
2323 // secure random that can't be easily predicted.
2424 // => cookie can be hash(ip, port) BUT only if salted to be not predictable
25- readonly uint cookie ;
26-
27- // this is the cookie that the other end received during handshake.
28- // store byte[] representation to avoid runtime int->byte[] conversions.
29- internal readonly byte [ ] receivedCookie = new byte [ 4 ] ;
25+ internal uint cookie ;
3026
3127 // state: connected as soon as we create the peer.
3228 // leftover from KcpConnection. remove it after refactoring later.
33- KcpState state = KcpState . Connected ;
29+ protected KcpState state = KcpState . Connected ;
3430
3531 // If we don't receive anything these many milliseconds
3632 // then consider us disconnected
@@ -133,7 +129,7 @@ protected KcpPeer(KcpConfig config, uint cookie)
133129 protected void Reset ( KcpConfig config )
134130 {
135131 // reset state
136- Array . Clear ( receivedCookie ) ;
132+ cookie = 0 ;
137133 state = KcpState . Connected ;
138134 lastReceiveTime = 0 ;
139135 lastPingTime = 0 ;
@@ -295,26 +291,13 @@ void TickIncoming_Connected(uint time)
295291 // message type FSM. no default so we never miss a case.
296292 switch ( header )
297293 {
298- case KcpHeader . Handshake :
294+ case KcpHeader . Hello :
299295 {
300- // we were waiting for a handshake .
296+ // we were waiting for a Hello message .
301297 // it proves that the other end speaks our protocol.
302298
303- // parse the cookie
304- if ( message . Count != 4 )
305- {
306- // pass error to user callback. no need to log it manually.
307- OnError ( ErrorCode . InvalidReceive , $ "{ GetType ( ) } : received invalid handshake message with size { message . Count } != 4. Disconnecting the connection.") ;
308- Disconnect ( ) ;
309- return ;
310- }
311-
312- // store the cookie bytes to avoid int->byte[] conversions when sending.
313- // still convert to uint once, just for prettier logging.
314- Buffer . BlockCopy ( message . Array , message . Offset , receivedCookie , 0 , 4 ) ;
315- uint prettyCookie = BitConverter . ToUInt32 ( message . Array , message . Offset ) ;
316-
317- Log . Info ( $ "{ GetType ( ) } : received handshake with cookie={ prettyCookie } ") ;
299+ // log with previously parsed cookie
300+ Log . Info ( $ "{ GetType ( ) } : received hello with cookie={ cookie } ") ;
318301 state = KcpState . Authenticated ;
319302 OnAuthenticated ( ) ;
320303 break ;
@@ -352,9 +335,9 @@ void TickIncoming_Authenticated(uint time)
352335 // message type FSM. no default so we never miss a case.
353336 switch ( header )
354337 {
355- case KcpHeader . Handshake :
338+ case KcpHeader . Hello :
356339 {
357- // should never receive another handshake after auth
340+ // should never receive another hello after auth
358341 // GetType() shows Server/ClientConn instead of just Connection.
359342 Log . Warning ( $ "{ GetType ( ) } : received invalid header { header } while Authenticated. Disconnecting the connection.") ;
360343 Disconnect ( ) ;
@@ -496,7 +479,7 @@ public virtual void TickOutgoing()
496479 }
497480 }
498481
499- void OnRawInputReliable ( ArraySegment < byte > message )
482+ protected void OnRawInputReliable ( ArraySegment < byte > message )
500483 {
501484 // input into kcp, but skip channel byte
502485 int input = kcp . Input ( message . Array , message . Offset , message . Count ) ;
@@ -507,7 +490,7 @@ void OnRawInputReliable(ArraySegment<byte> message)
507490 }
508491 }
509492
510- void OnRawInputUnreliable ( ArraySegment < byte > message )
493+ protected void OnRawInputUnreliable ( ArraySegment < byte > message )
511494 {
512495 // ideally we would queue all unreliable messages and
513496 // then process them in ReceiveNext() together with the
@@ -558,57 +541,6 @@ void OnRawInputUnreliable(ArraySegment<byte> message)
558541 }
559542 }
560543
561- // insert raw IO. usually from socket.Receive.
562- // offset is useful for relays, where we may parse a header and then
563- // feed the rest to kcp.
564- public void RawInput ( ArraySegment < byte > segment )
565- {
566- // ensure valid size: at least 1 byte for channel + 4 bytes for cookie
567- if ( segment . Count <= 5 ) return ;
568-
569- // parse channel
570- // byte channel = segment[0]; ArraySegment[i] isn't supported in some older Unity Mono versions
571- byte channel = segment . Array [ segment . Offset + 0 ] ;
572-
573- // parse cookie
574- uint messageCookie = BitConverter . ToUInt32 ( segment . Array , segment . Offset + 1 ) ;
575-
576- // compare cookie to protect against UDP spoofing.
577- // messages won't have a cookie until after handshake.
578- // so only compare if we are authenticated.
579- // simply drop the message if the cookie doesn't match.
580- if ( state == KcpState . Authenticated && messageCookie != cookie )
581- {
582- Log . Warning ( $ "{ GetType ( ) } : dropped message with invalid cookie: { messageCookie } expected: { cookie } .") ;
583- return ;
584- }
585-
586- // parse message
587- ArraySegment < byte > message = new ArraySegment < byte > ( segment . Array , segment . Offset + 1 + 4 , segment . Count - 1 - 4 ) ;
588-
589- switch ( channel )
590- {
591- case ( byte ) KcpChannel . Reliable :
592- {
593- OnRawInputReliable ( message ) ;
594- break ;
595- }
596- case ( byte ) KcpChannel . Unreliable :
597- {
598- OnRawInputUnreliable ( message ) ;
599- break ;
600- }
601- default :
602- {
603- // invalid channel indicates random internet noise.
604- // servers may receive random UDP data.
605- // just ignore it, but log for easier debugging.
606- Log . Warning ( $ "{ GetType ( ) } : invalid channel header: { channel } , likely internet noise") ;
607- break ;
608- }
609- }
610- }
611-
612544 // raw send called by kcp
613545 void RawSendReliable ( byte [ ] data , int length )
614546 {
@@ -618,7 +550,7 @@ void RawSendReliable(byte[] data, int length)
618550
619551 // write handshake cookie to protect against UDP spoofing.
620552 // from 1, with 4 bytes
621- Buffer . BlockCopy ( receivedCookie , 0 , rawSendBuffer , 1 , 4 ) ;
553+ Utils . Encode32U ( rawSendBuffer , 1 , cookie ) ; // allocation free
622554
623555 // write data
624556 // from 5, with N bytes
@@ -673,7 +605,7 @@ void SendUnreliable(ArraySegment<byte> message)
673605
674606 // write handshake cookie to protect against UDP spoofing.
675607 // from 1, with 4 bytes
676- Buffer . BlockCopy ( receivedCookie , 0 , rawSendBuffer , 1 , 4 ) ;
608+ Utils . Encode32U ( rawSendBuffer , 1 , cookie ) ; // allocation free
677609
678610 // write data
679611 // from 5, with N bytes
@@ -690,20 +622,14 @@ void SendUnreliable(ArraySegment<byte> message)
690622 // * server should send it as reply to client's handshake, not before
691623 // (server should not reply to random internet messages with handshake)
692624 // => handshake info needs to be delivered, so it goes over reliable.
693- public void SendHandshake ( )
625+ public void SendHello ( )
694626 {
695- // server includes a random cookie in handshake.
696- // client is expected to include in every message.
697- // this avoid UDP spoofing.
698- // KcpPeer simply always sends a cookie.
699- // in case client -> server cookies are ever implemented, etc.
700-
701- // TODO nonalloc
702- byte [ ] cookieBytes = BitConverter . GetBytes ( cookie ) ;
627+ // send an empty message with 'Hello' header.
628+ // cookie is automatically included in all messages.
703629
704630 // GetType() shows Server/ClientConn instead of just Connection.
705631 Log . Info ( $ "{ GetType ( ) } : sending handshake to other end with cookie={ cookie } ") ;
706- SendReliable ( KcpHeader . Handshake , new ArraySegment < byte > ( cookieBytes ) ) ;
632+ SendReliable ( KcpHeader . Hello , ArraySegment < byte > . Empty ) ;
707633 }
708634
709635 public void SendData ( ArraySegment < byte > data , KcpChannel channel )
0 commit comments