public NodeContact(Stream s) { byte[] nodeID = new byte[20]; OffsetStream.StreamRead(s, nodeID, 0, 20); _nodeID = new BinaryID(nodeID); byte[] address; byte[] port; switch (s.ReadByte()) { case 0: address = new byte[4]; port = new byte[2]; OffsetStream.StreamRead(s, address, 0, 4); OffsetStream.StreamRead(s, port, 0, 2); break; case 1: address = new byte[16]; port = new byte[2]; OffsetStream.StreamRead(s, address, 0, 16); OffsetStream.StreamRead(s, port, 0, 2); break; default: throw new Exception("AddressFamily not supported."); } _nodeEP = new IPEndPoint(new IPAddress(address), BitConverter.ToUInt16(port, 0)); }
public bool RequestStartTcpRelay(BinaryID[] networkIDs, Uri[] trackerURIs, int timeout) { BinaryID channelName = BinaryID.GenerateRandomID160(); object lockObject = new object(); lock (_tcpRelayRequestLockList) { _tcpRelayRequestLockList.Add(channelName, lockObject); } try { lock (lockObject) { using (MemoryStream mS = new MemoryStream(1024)) { byte[] XORnetworkID = new byte[20]; byte[] randomChannelID = channelName.ID; //write networkid list mS.WriteByte(Convert.ToByte(networkIDs.Length)); foreach (BinaryID networkID in networkIDs) { byte[] network = networkID.ID; for (int i = 0; i < 20; i++) { XORnetworkID[i] = (byte)(randomChannelID[i] ^ network[i]); } mS.Write(XORnetworkID, 0, 20); } //write tracker uri list mS.WriteByte(Convert.ToByte(trackerURIs.Length)); foreach (Uri trackerURI in trackerURIs) { byte[] buffer = Encoding.UTF8.GetBytes(trackerURI.AbsoluteUri); mS.WriteByte(Convert.ToByte(buffer.Length)); mS.Write(buffer, 0, buffer.Length); } byte[] data = mS.ToArray(); WriteFrame(SignalType.StartTcpRelay, channelName, data, 0, data.Length); } return(Monitor.Wait(lockObject, timeout)); } } finally { lock (_tcpRelayRequestLockList) { _tcpRelayRequestLockList.Remove(channelName); } } }
private void CreateInvitationPrivateChat(BinaryID hashedPeerEmailAddress, BinaryID networkID, IPEndPoint peerEP, string message) { BitChatNetwork network = new BitChatNetwork(_connectionManager, _trustedRootCertificates, _supportedCryptoOptions, hashedPeerEmailAddress, networkID, null, BitChatNetworkStatus.Offline, peerEP.ToString(), message); BitChat chat = CreateBitChat(network, BinaryID.GenerateRandomID160().ToString(), BinaryID.GenerateRandomID256().ID, 0, null, new BitChatProfile.SharedFileInfo[] { }, _profile.TrackerURIs, true, false, false); RaiseEventBitChatInvitationReceived(chat); }
public ConnectionManager(IPEndPoint localEP, ChannelRequest requestHandler) { try { _tcpListener = new TcpListener(localEP); _tcpListener.Start(10); } catch { _tcpListener = new TcpListener(new IPEndPoint(localEP.Address, 0)); _tcpListener.Start(10); } _externalSelfEP = (IPEndPoint)_tcpListener.LocalEndpoint; _requestHandler = requestHandler; _localPeerID = BinaryID.GenerateRandomID160(); //start accepting connections _tcpListenerThread = new Thread(AcceptTcpConnectionAsync); _tcpListenerThread.IsBackground = true; _tcpListenerThread.Start(); //start upnp process _upnpTimer = new Timer(UPnPTimerCallback, null, 1000, Timeout.Infinite); }
private IPEndPoint ConvertChannelNameToEp(BinaryID channelName) { byte[] address; byte[] port; switch (channelName.ID[0]) { case 0: address = new byte[4]; port = new byte[2]; Buffer.BlockCopy(channelName.ID, 1, address, 0, 4); Buffer.BlockCopy(channelName.ID, 1 + 4, port, 0, 2); break; case 1: address = new byte[16]; port = new byte[2]; Buffer.BlockCopy(channelName.ID, 1, address, 0, 16); Buffer.BlockCopy(channelName.ID, 1 + 16, port, 0, 2); break; default: throw new Exception("AddressFamily not supported."); } return(new IPEndPoint(new IPAddress(address), BitConverter.ToUInt16(port, 0))); }
public bool BitChatNetworkChannelExists(BinaryID channelName) { lock (_bitChatNetworkChannels) { return(_bitChatNetworkChannels.ContainsKey(channelName)); } }
public Connection(Stream baseStream, BinaryID remotePeerID, IPEndPoint remotePeerEP, ConnectionManager connectionManager) { _baseStream = baseStream; _remotePeerID = remotePeerID; _remotePeerEP = remotePeerEP; _connectionManager = connectionManager; }
public bool RequestPeerStatus(IPEndPoint remotePeerEP) { BinaryID channelName = ConvertEpToChannelName(remotePeerEP); object lockObject = new object(); lock (_peerStatusLockList) { _peerStatusLockList.Add(channelName, lockObject); } try { lock (lockObject) { WriteFrame(SignalType.PeerStatusQuery, channelName, null, 0, 0); return(Monitor.Wait(lockObject, 10000)); } } finally { lock (_peerStatusLockList) { _peerStatusLockList.Remove(channelName); } } }
public FileBlockRequest(BinaryID fileID, int blockNumber, int blockOffset, ushort length) { _fileID = fileID; _blockNumber = blockNumber; _blockOffset = blockOffset; _length = length; }
public SharedFileMetaData(Stream s) { BinaryReader bR = new BinaryReader(s); switch (bR.ReadByte()) //version { case 1: _fileName = Encoding.UTF8.GetString(bR.ReadBytes(bR.ReadByte())); _contentType = new ContentType(Encoding.UTF8.GetString(bR.ReadBytes(bR.ReadByte()))); _lastModified = _epoch.AddSeconds(bR.ReadInt64()); _fileSize = bR.ReadInt64(); _blockSize = bR.ReadInt32(); _hashAlgo = Encoding.ASCII.GetString(bR.ReadBytes(bR.ReadByte())); int totalBlocks = Convert.ToInt32(Math.Ceiling(Convert.ToDouble((double)_fileSize / _blockSize))); _blockHash = new byte[totalBlocks][]; int hashLength = bR.ReadByte(); for (int i = 0; i < totalBlocks; i++) { _blockHash[i] = bR.ReadBytes(hashLength); } _fileID = ComputeFileID(); break; default: throw new BitChatException("FileMetaData format version not supported."); } }
public FileBlockWanted(Stream s) { BinaryReader bR = new BinaryReader(s); _fileID = new BinaryID(bR.ReadBytes(bR.ReadByte())); _blockNumber = bR.ReadInt32(); }
private void WriteDataFrame(byte[] buffer, int offset, int count, BinaryID channelName, ChannelType type) { //Debug.Write("Connection.WriteDataFrame", _remotePeerEP.ToString() + "; channel:" + channelName.ToString() + "; dataSize:" + count); if (count < 1) { return; } lock (_baseStream) { //write frame signal _writeBufferData[0] = SIGNAL_DATA; //write channel name Buffer.BlockCopy(channelName.ID, 0, _writeBufferData, 1, 20); //write channel type _writeBufferData[21] = (byte)type; //write data byte[] bufferCount = BitConverter.GetBytes(Convert.ToUInt16(count - 1)); _writeBufferData[22] = bufferCount[0]; _writeBufferData[23] = bufferCount[1]; Buffer.BlockCopy(buffer, offset, _writeBufferData, 24, count); //output to base stream _baseStream.Write(_writeBufferData, 0, 24 + count); _baseStream.Flush(); } }
public BitChatNetwork(MailAddress peerEmailAddress, string sharedSecret, BinaryID networkID, Certificate[] knownPeerCerts, IBitChatNetworkManager networkManager, ISecureChannelSecurityManager securityManager) { _type = BitChatNetworkType.PrivateChat; _peerEmailAddress = peerEmailAddress; _sharedSecret = sharedSecret; _networkManager = networkManager; _securityManager = securityManager; LoadPeers(knownPeerCerts); if (knownPeerCerts.Length > 0) _peerName = knownPeerCerts[0].IssuedTo.Name; if (networkID == null) { //compute network id HashAlgorithm hash = HashAlgorithm.Create("SHA1"); byte[] peerEmailAddressHash = hash.ComputeHash(Encoding.UTF8.GetBytes(_peerEmailAddress.Address.ToLower())); byte[] selfEmailAddressHash = hash.ComputeHash(Encoding.UTF8.GetBytes(networkManager.GetLocalCredentials().Certificate.IssuedTo.EmailAddress.Address.ToLower())); byte[] salt = new byte[20]; for (int i = 0; i < 20; i++) { salt[i] = (byte)(peerEmailAddressHash[i] ^ selfEmailAddressHash[i]); } _networkID = new BinaryID(PBKDF2.CreateHMACSHA1(_sharedSecret, salt, 200000).GetBytes(20)); } else { _networkID = networkID; } }
private Connection MakeConnectionInitiateProtocol(Stream networkStream, IPEndPoint remotePeerEP) { try { //send request { byte[] buffer = new byte[23]; //request buffer buffer[0] = 1; //version Buffer.BlockCopy(_localPeerID.ID, 0, buffer, 1, 20); //peer id Buffer.BlockCopy(BitConverter.GetBytes(Convert.ToUInt16(_localPort)), 0, buffer, 21, 2); //service port networkStream.Write(buffer, 0, 23); } //read response int response = networkStream.ReadByte(); if (response == 0) { byte[] buffer = new byte[20]; networkStream.Read(buffer, 0, 20); BinaryID remotePeerID = new BinaryID(buffer); Connection connection = AddConnection(networkStream, remotePeerID, remotePeerEP); if (connection == null) { //check for existing connection again! Connection existingConnection = GetExistingConnection(remotePeerEP); if (existingConnection != null) { networkStream.Dispose(); return(existingConnection); } throw new IOException("Cannot connect to remote peer: connection already exists."); } return(connection); } else { Thread.Sleep(500); //wait so that other thread gets time to add his connection in list so that this thread can pick same connection to proceed //check for existing connection again! Connection existingConnection = GetExistingConnection(remotePeerEP); if (existingConnection != null) { networkStream.Dispose(); return(existingConnection); } throw new IOException("Cannot connect to remote peer: request rejected."); } } catch { networkStream.Dispose(); throw; } }
public PeerInfo(IPEndPoint peerEP, BinaryID networkID) { _peerEP = peerEP; _networkID = networkID; _dateAdded = DateTime.UtcNow; }
public KBucket FindClosestBucket(BinaryID nodeID) { KBucket currentBucket = this; ReaderWriterLockSlim currentLock = this._lock; while (true) { currentLock.TryEnterReadLock(LOCK_TIMEOUT); try { if (currentBucket._contacts != null) { break; } if ((currentBucket._leftBucket._bucketID & nodeID) == currentBucket._leftBucket._bucketID) { currentBucket = currentBucket._leftBucket; } else { currentBucket = currentBucket._rightBucket; } } finally { currentLock.ExitReadLock(); } currentLock = currentBucket._lock; } currentBucket._lastChanged = DateTime.UtcNow; return(currentBucket); }
private void SendAnnouncementBlockWanted(BinaryID fileID, int blockNumber) { byte[] packetData = BitChatMessage.CreateFileBlockWanted(fileID, blockNumber); //announce to all peers _peersLock.EnterReadLock(); try { foreach (BitChatNetwork.VirtualPeer.VirtualSession peer in _peers) { peer.WriteMessage(packetData, 0, packetData.Length); } } finally { _peersLock.ExitReadLock(); } //announce to all seeds _seedersLock.EnterReadLock(); try { foreach (BitChatNetwork.VirtualPeer.VirtualSession seeder in _seeders) { seeder.WriteMessage(packetData, 0, packetData.Length); } } finally { _seedersLock.ExitReadLock(); } }
public void StorePeer(BinaryID networkID, PeerEndPoint peerEP) { lock (_data) { List <PeerEndPoint> peerList; if (_data.ContainsKey(networkID)) { peerList = _data[networkID]; } else { peerList = new List <PeerEndPoint>(); _data.Add(networkID, peerList); } foreach (PeerEndPoint peer in peerList) { if (peer.Equals(peerEP)) { peer.UpdateDateAdded(); return; } } peerList.Add(peerEP); } }
public PeerEndPoint[] GetPeers(BinaryID networkID) { lock (_data) { if (_data.ContainsKey(networkID)) { List <PeerEndPoint> peers = _data[networkID]; if (peers.Count > MAX_PEERS_TO_RETURN) { List <PeerEndPoint> finalPeers = new List <PeerEndPoint>(peers); Random rnd = new Random(DateTime.UtcNow.Millisecond); while (finalPeers.Count > MAX_PEERS_TO_RETURN) { finalPeers.RemoveAt(rnd.Next(finalPeers.Count - 1)); } return(finalPeers.ToArray()); } else { return(_data[networkID].ToArray()); } } else { return(new PeerEndPoint[] { }); } } }
public NodeContact FindContactInCurrentBucket(BinaryID nodeID) { _lock.TryEnterReadLock(LOCK_TIMEOUT); try { if (_contacts == null) { return(null); } if (_contacts.ContainsKey(nodeID)) { return(_contacts[nodeID]); } if (_replacementContacts.ContainsKey(nodeID)) { return(_replacementContacts[nodeID]); } return(null); } finally { _lock.ExitReadLock(); } }
public bool RequestPeerStatus(IPEndPoint remotePeerEP) { BinaryID channelName = new BinaryID(ConvertToBinary(remotePeerEP)); object lockObject = new object(); lock (_peerStatusLockList) { _peerStatusLockList.Add(channelName, lockObject); } lock (lockObject) { WriteSignalFrame(channelName, SIGNAL_PEER_STATUS); if (!Monitor.Wait(lockObject, 10000)) { lock (_peerStatusLockList) { _peerStatusLockList.Remove(channelName); } return(false); } return(true); } }
public static NodeContact[] GetClosestContacts(IEnumerable <NodeContact> contacts, BinaryID nodeID, int count) { NodeContact[] closestContacts = new NodeContact[count]; BinaryID[] min = new BinaryID[count]; BinaryID distance; int ubound = count - 1; int i; int j; foreach (NodeContact contact in contacts) { distance = nodeID ^ contact.NodeID; for (i = 0; i < count; i++) { if ((min[i] == null) || (distance < min[i])) { //demote existing values for (j = ubound; j > i; j--) { min[j] = min[j - 1]; closestContacts[j] = closestContacts[j - 1]; } //place current on top min[i] = distance; closestContacts[i] = contact; break; } } } return(closestContacts); }
private void ReadFrom(BinaryReader bR) { switch (bR.ReadByte()) //version { case 1: _fileName = Encoding.UTF8.GetString(bR.ReadBytes(bR.ReadByte())); _contentType = new System.Net.Mime.ContentType(Encoding.UTF8.GetString(bR.ReadBytes(bR.ReadByte()))); _lastModified = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(bR.ReadUInt64()); _fileSize = bR.ReadInt64(); _blockSize = bR.ReadInt32(); _hashAlgo = Encoding.ASCII.GetString(bR.ReadBytes(bR.ReadByte())); _hash = HashAlgorithm.Create(_hashAlgo); int totalBlocks = Convert.ToInt32(Math.Ceiling(Convert.ToDouble((double)_fileSize / _blockSize))); _blockHash = new byte[totalBlocks][]; int hashLength = bR.ReadByte(); for (int i = 0; i < totalBlocks; i++) { _blockHash[i] = bR.ReadBytes(hashLength); } _fileID = ComputeFileID(); break; default: throw new BitChatException("FileMetaData format version not supported."); } }
public FileBlockDataPart(BinaryID fileID, int blockNumber, int blockOffset, ushort length, byte[] blockDataPart) { _fileID = fileID; _blockNumber = blockNumber; _blockOffset = blockOffset; _length = length; _blockDataPart = blockDataPart; }
public static DhtRpcPacket CreateFindNodePacketQuery(NodeContact sourceNode, BinaryID networkID) { DhtRpcPacket packet = new DhtRpcPacket(GetRandomTransactionID(), sourceNode, RpcPacketType.Query, RpcQueryType.FIND_NODE); packet._networkID = networkID; return(packet); }
private void Announce(BinaryID[] networkIDs, IPAddress[] remoteIPs, int times, bool isReply) { List <byte[]> packets = new List <byte[]>(networkIDs.Length); //CREATE ADVERTISEMENT foreach (BinaryID networkID in networkIDs) { byte[] challenge = BinaryID.GenerateRandomID256().ID; using (MemoryStream mS = new MemoryStream(BUFFER_MAX_SIZE)) { //version 1 byte if (isReply) { mS.WriteByte(4); } else { mS.WriteByte(3); } mS.Write(BitConverter.GetBytes(_announcePort), 0, 2); //service port mS.Write(challenge, 0, 32); //challenge using (HMACSHA256 hmacSHA256 = new HMACSHA256(networkID.ID)) { byte[] hmac = hmacSHA256.ComputeHash(challenge); mS.Write(hmac, 0, 32); } packets.Add(mS.ToArray()); } } //SEND ADVERTISEMENT for (int i = 0; i < times; i++) { foreach (byte[] packet in packets) { if (remoteIPs == null) { _listener.Broadcast(packet, 0, packet.Length); } else { foreach (IPAddress remoteIP in remoteIPs) { _listener.SendTo(packet, 0, packet.Length, remoteIP); } } } if (i < times - 1) { Thread.Sleep(ANNOUNCEMENT_RETRY_INTERVAL); } } }
public NodeContact[] GetKClosestContacts(BinaryID networkID) { NodeContact[] contacts = null; KBucket closestBucket = FindClosestBucket(networkID); if (closestBucket._totalContacts >= DhtClient.KADEMLIA_K) { contacts = closestBucket.GetAllContacts(false); if (contacts.Length > DhtClient.KADEMLIA_K) { return(GetClosestContacts(contacts, networkID, DhtClient.KADEMLIA_K)); } else if (contacts.Length == DhtClient.KADEMLIA_K) { return(contacts); } else if (closestBucket._parentBucket == null) { return(contacts); } else { contacts = null; } } while (closestBucket._parentBucket != null) { KBucket parentBucket = closestBucket._parentBucket; if (parentBucket._totalContacts >= DhtClient.KADEMLIA_K) { contacts = parentBucket.GetAllContacts(false); if (contacts.Length > DhtClient.KADEMLIA_K) { return(GetClosestContacts(contacts, networkID, DhtClient.KADEMLIA_K)); } else if (contacts.Length == DhtClient.KADEMLIA_K) { return(contacts); } } closestBucket = parentBucket; } if (contacts == null) { return(closestBucket.GetAllContacts(false)); } else { return(contacts); } }
public FileBlockRequest(Stream s) { BinaryReader bR = new BinaryReader(s); _fileID = new BinaryID(bR.ReadBytes(bR.ReadByte())); _blockNumber = bR.ReadInt32(); _blockOffset = bR.ReadInt32(); _length = bR.ReadUInt16(); }
public void SendBitChatNetworkInvitation(string message) { BinaryID hashedEmailAddress = BitChatNetwork.GetHashedEmailAddress(_connectionManager.Profile.LocalCertificateStore.Certificate.IssuedTo.EmailAddress); byte[] buffer = Encoding.UTF8.GetBytes(message); //send invitation signal with message WriteFrame(SignalType.BitChatNetworkInvitation, hashedEmailAddress, buffer, 0, buffer.Length); }
private void Network_NetworkChanged(BitChatNetwork network, BinaryID newNetworkID) { lock (_chats) { BitChat chat = _chats[network.NetworkID]; _chats.Add(newNetworkID, chat); _chats.Remove(network.NetworkID); } }
public static BinaryID GetChannelName(BinaryID localPeerID, BinaryID remotePeerID, BinaryID networkID) { // this is done to avoid disclosing networkID to passive network sniffing // channelName = hmac( localPeerID XOR remotePeerID, networkID) using (HMACSHA1 hmacSHA1 = new HMACSHA1(networkID.ID)) { return(new BinaryID(hmacSHA1.ComputeHash((localPeerID ^ remotePeerID).ID))); } }
public static byte[] CreateFileUnparticipate(BinaryID fileID) { using (MemoryStream mS = new MemoryStream(fileID.ID.Length + 1)) { mS.WriteByte((byte)BitChatMessageType.FileShareUnparticipate); //1 byte mS.Write(fileID.ID, 0, fileID.ID.Length); return mS.ToArray(); } }
private void _localDiscovery_PeerDiscovered(LocalPeerDiscovery sender, IPEndPoint peerEP, BinaryID networkID) { lock (_networks) { if (_networks.ContainsKey(networkID)) _networks[networkID].MakeConnection(peerEP); } }
private void WriteSignalFrame(BinaryID channelName, byte signal) { Debug.Write("Connection.WriteSignalFrame", _remotePeerEP.ToString() + "; channel:" + channelName.ToString() + "; signal:" + signal); lock (_baseStream) { //write frame signal _writeBufferData[0] = signal; //write channel name Buffer.BlockCopy(channelName.ID, 0, _writeBufferData, 1, 20); //output to base stream _baseStream.Write(_writeBufferData, 0, 21); _baseStream.Flush(); } }
public void StartTracking(BinaryID networkID) { lock (_trackedNetworkIDs) { int i = FindChatHashIndex(networkID); if (i < 0) _trackedNetworkIDs.Add(networkID); ThreadPool.QueueUserWorkItem(AnnounceAsync, new object[] { networkID, null, ANNOUNCEMENT_COUNT, false }); } }
private void RecvDataAsync() { EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); byte[] bufferRecv = new byte[BUFFER_MAX_SIZE]; MemoryStream dataRecv = new MemoryStream(bufferRecv); int bytesRecv; while (true) { try { //receive message from remote bytesRecv = _udpListener.ReceiveFrom(bufferRecv, ref remoteEP); IPEndPoint peerEP = remoteEP as IPEndPoint; bool isSelf = false; foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) { if ((ni.OperationalStatus == OperationalStatus.Up) && (ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)) { foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) { if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { if (peerEP.Address.Equals(ip.Address)) { isSelf = true; break; } } } } if (isSelf) break; } if (isSelf) continue; if (bytesRecv > 0) { #region parse data dataRecv.Position = 0; dataRecv.SetLength(bytesRecv); int version = dataRecv.ReadByte(); switch (version) //version { case 3: case 4: //read remote service port byte[] data = new byte[2]; dataRecv.Read(data, 0, 2); ushort servicePort = BitConverter.ToUInt16(data, 0); IPEndPoint remoteServiceEP = new IPEndPoint(peerEP.Address, servicePort); //read challenge byte[] challenge = new byte[32]; dataRecv.Read(challenge, 0, 32); //read hmac BinaryID recvHMAC = new BinaryID(new byte[32]); dataRecv.Read(recvHMAC.ID, 0, 32); ReceivedPeerInfo(remoteServiceEP, challenge, recvHMAC, (version == 4)); break; default: continue; } #endregion } } catch (ThreadAbortException) { break; } catch { } } }
private int FindChatHashIndex(BinaryID networkID) { for (int i = 0; i < _trackedNetworkIDs.Count; i++) { if (_trackedNetworkIDs[i].Equals(networkID)) return i; } return -1; }
internal Connection AcceptConnectionInitiateProtocol(Stream networkStream, IPEndPoint remotePeerEP) { //read version int version = networkStream.ReadByte(); switch (version) { case 1: //read service port byte[] remoteServicePort = new byte[2]; networkStream.Read(remoteServicePort, 0, 2); remotePeerEP = new IPEndPoint(remotePeerEP.Address, BitConverter.ToUInt16(remoteServicePort, 0)); //read peer id byte[] peerID = new byte[20]; networkStream.Read(peerID, 0, 20); BinaryID remotePeerID = new BinaryID(peerID); //add Connection connection = AddConnection(networkStream, remotePeerID, remotePeerEP); if (connection != null) { //send ok networkStream.WriteByte(0); networkStream.Write(_localPeerID.ID, 0, 20); } else { //send cancel networkStream.WriteByte(1); networkStream.Close(); } return connection; default: networkStream.Close(); throw new IOException("Cannot accept remote connection: protocol version not supported."); } }
private int ReadSecureChannelFrame() { //read secure channel frame //read first block to read the encrypted packet size OffsetStream.StreamRead(_baseStream, _readEncryptedData, 0, _blockSizeBytes); _cryptoDecryptor.TransformBlock(_readEncryptedData, 0, _blockSizeBytes, _readBufferData, 0); _readBufferPosition = _blockSizeBytes; //read frame header 2 byte length int dataLength = BitConverter.ToUInt16(_readBufferData, 0); _readBufferLength = dataLength; dataLength -= _blockSizeBytes; if (_cryptoDecryptor.CanTransformMultipleBlocks) { if (dataLength > 0) { int pendingBlocks = dataLength / _blockSizeBytes; if (dataLength % _blockSizeBytes > 0) pendingBlocks++; int pendingBytes = pendingBlocks * _blockSizeBytes; //read pending blocks OffsetStream.StreamRead(_baseStream, _readEncryptedData, _readBufferPosition, pendingBytes); _cryptoDecryptor.TransformBlock(_readEncryptedData, _readBufferPosition, pendingBytes, _readBufferData, _readBufferPosition); _readBufferPosition += pendingBytes; } } else { while (dataLength > 0) { //read next block OffsetStream.StreamRead(_baseStream, _readEncryptedData, _readBufferPosition, _blockSizeBytes); _cryptoDecryptor.TransformBlock(_readEncryptedData, _readBufferPosition, _blockSizeBytes, _readBufferData, _readBufferPosition); _readBufferPosition += _blockSizeBytes; dataLength -= _blockSizeBytes; } } //read auth hmac BinaryID authHMAC = new BinaryID(new byte[_authHMACSize]); OffsetStream.StreamRead(_baseStream, authHMAC.ID, 0, _authHMACSize); //verify auth hmac with computed hmac BinaryID computedAuthHMAC = new BinaryID(_authHMACDecrypt.ComputeHash(_readEncryptedData, 0, _readBufferPosition)); if (!computedAuthHMAC.Equals(authHMAC)) throw new SecureChannelException(SecureChannelCode.InvalidMessageHMACReceived, _remotePeerEP, _remotePeerCert); _readBufferPosition = 3; //return bytes available in this frame to read return _readBufferLength - _readBufferPosition; }
public FileBlockWanted(BinaryID fileID, int blockNumber) { _fileID = fileID; _blockNumber = blockNumber; }
private Connection AddConnection(Stream networkStream, BinaryID remotePeerID, IPEndPoint remotePeerEP) { lock (_connectionListByConnectionID) { //check for self if (_localPeerID.Equals(remotePeerID)) { _externalSelfEP = new IPEndPoint(remotePeerEP.Address, _externalSelfEP.Port); return null; } string connectionID = remotePeerEP.ToString(); //check for existing connection by connection id if (_connectionListByConnectionID.ContainsKey(connectionID)) return null; //check for existing connection by peer id if (_connectionListByPeerID.ContainsKey(remotePeerID)) { Connection existingConnection = _connectionListByPeerID[remotePeerID]; //compare existing and new peer ip end-point if (AllowNewConnection(existingConnection.RemotePeerEP, remotePeerEP)) { //remove existing connection and allow new connection existingConnection.Dispose(); } else { //keep existing connection return null; } } //add connection Connection connection = new Connection(networkStream, remotePeerID, remotePeerEP, this, _requestHandler); _connectionListByConnectionID.Add(connectionID, connection); _connectionListByPeerID.Add(remotePeerID, connection); //start service connection.Start(); return connection; } }
private Connection MakeConnectionInitiateProtocol(Stream networkStream, IPEndPoint remotePeerEP) { try { //send version networkStream.WriteByte(1); //send service port networkStream.Write(BitConverter.GetBytes(Convert.ToUInt16(_externalSelfEP.Port)), 0, 2); //send peer id networkStream.Write(_localPeerID.ID, 0, 20); //read response int response = networkStream.ReadByte(); if (response == 0) { byte[] buffer = new byte[20]; networkStream.Read(buffer, 0, 20); BinaryID remotePeerID = new BinaryID(buffer); Connection connection = AddConnection(networkStream, remotePeerID, remotePeerEP); if (connection == null) { //check for existing connection again! Connection existingConnection = GetExistingConnection(remotePeerEP); if (existingConnection != null) { networkStream.Dispose(); return existingConnection; } throw new IOException("Cannot connect to remote peer: connection already exists."); } return connection; } else { Thread.Sleep(500); //wait so that other thread gets time to add his connection in list so that this thread can pick same connection to proceed //check for existing connection again! Connection existingConnection = GetExistingConnection(remotePeerEP); if (existingConnection != null) { networkStream.Dispose(); return existingConnection; } throw new IOException("Cannot connect to remote peer: request rejected."); } } catch { networkStream.Dispose(); throw; } }
public void StopLocalAnnouncement(BinaryID networkID) { _localDiscovery.StopTracking(networkID); }
public BitChatNetwork(string networkName, string sharedSecret, BinaryID networkID, Certificate[] knownPeerCerts, IBitChatNetworkManager networkManager, ISecureChannelSecurityManager securityManager) { _type = BitChatNetworkType.GroupChat; _networkName = networkName; _sharedSecret = sharedSecret; _networkManager = networkManager; _securityManager = securityManager; LoadPeers(knownPeerCerts); if (networkID == null) { //compute network id _networkID = new BinaryID(PBKDF2.CreateHMACSHA1(_sharedSecret, Encoding.UTF8.GetBytes(_networkName.ToLower()), 200000).GetBytes(20)); } else { _networkID = networkID; } }
public BitChat CreateBitChat(string networkName, string sharedSecret, BinaryID networkID, Certificate[] knownPeerCerts, BitChatProfile.SharedFileInfo[] sharedFileInfoList, Uri[] trackerURIs) { BitChatNetwork network = new BitChatNetwork(networkName, sharedSecret, networkID, knownPeerCerts, this, this); lock (_networks) { _networks.Add(network.NetworkID, network); } if (trackerURIs == null) trackerURIs = _profile.TrackerURIs; return new BitChat(this, _profile, network, sharedFileInfoList, trackerURIs); }
public void PauseLocalAnnouncement(BinaryID networkID) { _localDiscovery.PauseAnnouncement(networkID); }
private void _listener_ReceivedPeerInfo(IPEndPoint peerEP, byte[] challenge, BinaryID recvHMAC, bool isReply) { if (PeerDiscovered != null) { BinaryID foundNetworkID = null; lock (_trackedNetworkIDs) { foreach (BinaryID networkID in _trackedNetworkIDs) { using (HMACSHA256 hmacSHA256 = new HMACSHA256(networkID.ID)) { BinaryID computedHmac = new BinaryID(hmacSHA256.ComputeHash(challenge)); if (computedHmac.Equals(recvHMAC)) { foundNetworkID = networkID; break; } } } } if (foundNetworkID != null) { PeerInfo peerInfo = new PeerInfo(peerEP, foundNetworkID); bool peerInCache; if (_peerInfoCache.Contains(peerInfo)) { PeerInfo existingPeerInfo = _peerInfoCache[_peerInfoCache.IndexOf(peerInfo)]; if (existingPeerInfo.IsExpired()) { peerInCache = false; _peerInfoCache.Remove(existingPeerInfo); } else { peerInCache = true; } } else { peerInCache = false; } if (!peerInCache) { _peerInfoCache.Add(peerInfo); PeerDiscovered(this, peerEP, foundNetworkID); } if (!isReply) ThreadPool.QueueUserWorkItem(AnnounceAsync, new object[] { foundNetworkID, new IPAddress[] { peerEP.Address }, 1, true }); } } }
public void ResumeLocalAnnouncement(BinaryID networkID) { _localDiscovery.ResumeAnnouncement(networkID); }
private void Announce(BinaryID networkID, IPAddress[] remoteIPs, int times, bool isReply) { //CREATE ADVERTISEMENT byte[] challenge = BinaryID.GenerateRandomID256().ID; byte[] buffer = new byte[BUFFER_MAX_SIZE]; using (MemoryStream mS = new MemoryStream(buffer)) { //version 1 byte if (isReply) mS.WriteByte(4); else mS.WriteByte(3); mS.Write(BitConverter.GetBytes(_announcePort), 0, 2); //service port mS.Write(challenge, 0, 32); //challenge using (HMACSHA256 hmacSHA256 = new HMACSHA256(networkID.ID)) { byte[] hmac = hmacSHA256.ComputeHash(challenge); mS.Write(hmac, 0, 32); } int length = Convert.ToInt32(mS.Position); //SEND ADVERTISEMENT for (int i = 0; i < times; i++) { if (remoteIPs == null) { _listener.Broadcast(buffer, 0, length); } else { foreach (IPAddress remoteIP in remoteIPs) { _listener.SendTo(buffer, 0, length, remoteIP); } } if (i < times - 1) Thread.Sleep(ANNOUNCEMENT_INTERVAL); } } }
public void StopLocalTracking(BinaryID networkID) { _localDiscovery.StopTracking(networkID); }
public void StopTracking(BinaryID networkID) { lock (_trackedNetworkIDs) { int i = FindChatHashIndex(networkID); if (i > -1) _trackedNetworkIDs.RemoveAt(i); } }
private void ChannelRequest(Connection connection, BinaryID channelName, ChannelType type, Stream channel) { try { switch (type) { case ChannelType.BitChatNetwork: BitChatNetwork network; lock (_networks) { network = _networks[channelName]; } SecureChannelStream secureChannel = new SecureChannelServerStream(channel, connection.RemotePeerEP, _profile.LocalCertificateStore, _trustedRootCertificates, this, _supportedCryptoOptions, _reNegotiateOnBytesSent, _reNegotiateAfterSeconds, network.SharedSecret); network.JoinNetwork(secureChannel.RemotePeerCertificate.IssuedTo.EmailAddress.Address, secureChannel, _profile.CheckCertificateRevocationList); break; } } catch { channel.Dispose(); } }
public ChannelStream(Connection connection, BinaryID channelName, ChannelType channelType) { _connection = connection; _channelName = channelName.Clone(); _channelType = channelType; }
public Connection(Stream baseStream, BinaryID remotePeerID, IPEndPoint remotePeerEP, ConnectionManager connectionManager, ChannelRequest requestHandler) { _baseStream = baseStream; _remotePeerID = remotePeerID; _remotePeerEP = remotePeerEP; _connectionManager = connectionManager; _requestHandler = requestHandler; }