protected async UniTask HandshakeAsync(int bits) { // in the very first message we must mine a hashcash token // and send that as a hello // the server won't accept connections otherwise #if NETSTANDARD string applicationName = Application.productName; HashCash token = await UniTask.RunOnThreadPool(() => HashCash.Mine(applicationName, bits)); #else // TODO - HashCash token implement a better way for both unity and .net to work. string applicationName = "Application.productName"; HashCash token = await UniTask.Run(() => HashCash.Mine(applicationName, bits)); #endif byte[] hello = new byte[1000]; int length = HashCashEncoding.Encode(hello, 0, token); var data = new ArraySegment <byte>(hello, 0, length); // send a greeting and see if the server replies await SendAsync(data); var stream = new MemoryStream(); try { await ReceiveAsync(stream); } catch (Exception e) { throw new InvalidDataException("Unable to establish connection, no Handshake message received.", e); } }
private bool Validate(byte[] data, int msgLength) { // do we have enough data in the buffer for a HashCash token? if (msgLength < Kcp.OVERHEAD + KcpConnection.RESERVED + HashCashEncoding.SIZE) { return(false); } // read the token HashCash token = HashCashEncoding.Decode(data, Kcp.OVERHEAD + KcpConnection.RESERVED); RemoveExpiredTokens(); // have this token been used? if (used.Contains(token)) { return(false); } // does the token validate? #if NETSTANDARD if (!token.Validate(Application.productName, HashCashBits)) #else // TODO - HashCash token implement a better way for both unity and .net to work. if (!token.Validate("Application.productName", HashCashBits)) #endif { return(false); } used.Add(token); expireQueue.Enqueue(token); // brand new token, and it is for this app, go on return(true); }
// calculate the hash of a hashcash token private byte[] Hash(HashAlgorithm hashAlgorithm, byte[] buffer) { int length = HashCashEncoding.Encode(buffer, 0, this); return(hashAlgorithm.ComputeHash(buffer, 0, length)); }