public Stream RequestBitChatNetworkChannel(BinaryNumber channelName) { ChannelStream channel; lock (_channels) { if (_channels.ContainsKey(channelName)) { throw new ArgumentException("Channel already exists."); } channel = new ChannelStream(this, channelName.Clone()); _channels.Add(channel.ChannelName, channel); } //send connect signal WriteFrame(SignalType.ConnectChannelBitChatNetwork, channelName, null, 0, 0); return(channel); }
private void ReadFrameAsync() { try { //frame parameters int signal; BinaryNumber channelId = new BinaryNumber(new byte[32]); byte[] dataLengthBuffer = new byte[2]; OffsetStream dataStream = new OffsetStream(_baseStream, 0, 0, true, false); while (true) { #region read frame from base stream //read frame signal signal = _baseStream.ReadByte(); if (signal == -1) { return; //End of stream } //read channel id _baseStream.ReadBytes(channelId.Value, 0, 32); //read data length _baseStream.ReadBytes(dataLengthBuffer, 0, 2); dataStream.Reset(0, BitConverter.ToUInt16(dataLengthBuffer, 0), 0); #endregion switch ((ConnectionSignal)signal) { case ConnectionSignal.PingRequest: WriteFrame(ConnectionSignal.PingResponse, channelId, null, 0, 0); break; case ConnectionSignal.PingResponse: //do nothing! break; case ConnectionSignal.ConnectChannelMeshNetwork: #region ConnectChannelMeshNetwork lock (_channels) { if (_channels.ContainsKey(channelId)) { WriteFrame(ConnectionSignal.DisconnectChannel, channelId, null, 0, 0); } else { ChannelStream channel = new ChannelStream(this, channelId.Clone()); _channels.Add(channel.ChannelId, channel); ThreadPool.QueueUserWorkItem(delegate(object state) { try { //done async since the call is blocking and will block the current read thread which can cause DOS _connectionManager.Node.MeshNetworkRequest(this, channel.ChannelId, channel); } catch (Exception ex) { Debug.Write(this.GetType().Name, ex); channel.Dispose(); } }); } } //check if tcp relay is hosted for the channel. reply back tcp relay peers list if available Connection[] connections = _connectionManager.GetTcpRelayServerHostedNetworkConnections(channelId); if (connections.Length > 0) { int count = connections.Length; for (int i = 0; i < connections.Length; i++) { if (connections[i].RemotePeerEP.Equals(_remotePeerEP)) { connections[i] = null; count--; break; } } using (MemoryStream mS = new MemoryStream(128)) { BinaryWriter bW = new BinaryWriter(mS); bW.Write(Convert.ToByte(count)); foreach (Connection connection in connections) { if (connection != null) { connection.RemotePeerEP.WriteTo(bW); } } byte[] data = mS.ToArray(); WriteFrame(ConnectionSignal.MeshNetworkPeers, channelId, data, 0, data.Length); } } #endregion break; case ConnectionSignal.ChannelData: #region ChannelData try { ChannelStream channel = null; lock (_channels) { channel = _channels[channelId]; } channel.FeedReadBuffer(dataStream, _channelWriteTimeout); } catch { } #endregion break; case ConnectionSignal.DisconnectChannel: #region DisconnectChannel try { ChannelStream channel; lock (_channels) { channel = _channels[channelId]; _channels.Remove(channelId); } channel.SetDisconnected(); channel.Dispose(); } catch { } #endregion break; case ConnectionSignal.ConnectChannelTunnel: #region ConnectChannelTunnel if (IsStreamVirtualConnection(_baseStream)) { //nesting virtual connections not allowed WriteFrame(ConnectionSignal.DisconnectChannel, channelId, null, 0, 0); } else { ChannelStream remoteChannel1 = null; lock (_channels) { if (_channels.ContainsKey(channelId)) { WriteFrame(ConnectionSignal.DisconnectChannel, channelId, null, 0, 0); } else { //add first stream into list remoteChannel1 = new ChannelStream(this, channelId.Clone()); _channels.Add(remoteChannel1.ChannelId, remoteChannel1); } } if (remoteChannel1 != null) { EndPoint tunnelToRemotePeerEP = ConvertChannelIdToEp(channelId); //get remote peer ep Connection remotePeerConnection = _connectionManager.GetExistingConnection(tunnelToRemotePeerEP); //get remote channel service if (remotePeerConnection == null) { remoteChannel1.Dispose(); } else { try { //get remote proxy connection channel stream ChannelStream remoteChannel2 = remotePeerConnection.MakeVirtualConnection(_remotePeerEP); //join current and remote stream Joint joint = new Joint(remoteChannel1, remoteChannel2); joint.Disposed += delegate(object sender, EventArgs e) { lock (_tunnelJointList) { _tunnelJointList.Remove(sender as Joint); } }; lock (_tunnelJointList) { _tunnelJointList.Add(joint); } joint.Start(); } catch (Exception ex) { Debug.Write(this.GetType().Name, ex); remoteChannel1.Dispose(); } } } } #endregion break; case ConnectionSignal.ConnectChannelVirtualConnection: #region ConnectChannelVirtualConnection if (IsStreamVirtualConnection(_baseStream)) { //nesting virtual connections not allowed WriteFrame(ConnectionSignal.DisconnectChannel, channelId, null, 0, 0); } else { lock (_channels) { if (_channels.ContainsKey(channelId)) { WriteFrame(ConnectionSignal.DisconnectChannel, channelId, null, 0, 0); } else { //add proxy channel stream into list ChannelStream channel = new ChannelStream(this, channelId.Clone()); _channels.Add(channel.ChannelId, channel); //pass channel as connection async ThreadPool.QueueUserWorkItem(delegate(object state) { try { _connectionManager.AcceptConnectionInitiateProtocol(channel, ConvertChannelIdToEp(channel.ChannelId)); } catch (Exception ex) { Debug.Write(this.GetType().Name, ex); channel.Dispose(); } }); } } } #endregion break; case ConnectionSignal.TcpRelayServerRegisterHostedNetwork: #region TcpRelayServerRegisterHostedNetwork _connectionManager.TcpRelayServerRegisterHostedNetwork(this, channelId.Clone()); _tcpRelayServerModeEnabled = true; #endregion break; case ConnectionSignal.TcpRelayServerUnregisterHostedNetwork: #region TcpRelayServerUnregisterHostedNetwork _connectionManager.TcpRelayServerUnregisterHostedNetwork(this, channelId); #endregion break; case ConnectionSignal.MeshNetworkPeers: #region MeshNetworkPeers { BinaryReader bR = new BinaryReader(dataStream); int count = bR.ReadByte(); List <EndPoint> peerEPs = new List <EndPoint>(count); for (int i = 0; i < count; i++) { peerEPs.Add(EndPointExtension.Parse(bR)); } _connectionManager.Node.ReceivedMeshNetworkPeersViaTcpRelay(this, channelId, peerEPs); } #endregion break; default: throw new IOException("Invalid frame signal."); } //discard any unread data if (dataStream.Length > dataStream.Position) { dataStream.CopyTo(Stream.Null, 1024, Convert.ToInt32(dataStream.Length - dataStream.Position)); } } } catch (ThreadAbortException) { //stopping } catch (Exception ex) { Debug.Write(this.GetType().Name, ex); } finally { Dispose(); } }
public DhtRpcPacket(Stream s) { int version = s.ReadByte(); switch (version) { case -1: throw new EndOfStreamException(); case 2: byte[] buffer = new byte[20]; OffsetStream.StreamRead(s, buffer, 0, 2); _sourceNodePort = BitConverter.ToUInt16(buffer, 0); _type = (DhtRpcType)s.ReadByte(); switch (_type) { case DhtRpcType.PING: break; case DhtRpcType.FIND_NODE: { OffsetStream.StreamRead(s, buffer, 0, 20); _networkID = BinaryNumber.Clone(buffer, 0, 20); int count = s.ReadByte(); _contacts = new NodeContact[count]; for (int i = 0; i < count; i++) { _contacts[i] = new NodeContact(s); } } break; case DhtRpcType.FIND_PEERS: { OffsetStream.StreamRead(s, buffer, 0, 20); _networkID = BinaryNumber.Clone(buffer, 0, 20); int count = s.ReadByte(); _contacts = new NodeContact[count]; for (int i = 0; i < count; i++) { _contacts[i] = new NodeContact(s); } count = s.ReadByte(); _peers = new PeerEndPoint[count]; for (int i = 0; i < count; i++) { _peers[i] = new PeerEndPoint(s); } } break; case DhtRpcType.ANNOUNCE_PEER: { OffsetStream.StreamRead(s, buffer, 0, 20); _networkID = BinaryNumber.Clone(buffer, 0, 20); OffsetStream.StreamRead(s, buffer, 0, 2); _servicePort = BitConverter.ToUInt16(buffer, 0); int count = s.ReadByte(); _peers = new PeerEndPoint[count]; for (int i = 0; i < count; i++) { _peers[i] = new PeerEndPoint(s); } } break; default: throw new IOException("Invalid DHT-RPC type."); } break; default: throw new IOException("DHT-RPC packet version not supported: " + version); } }
private void ReadFrameAsync() { try { //frame parameters int signalType; BinaryNumber channelName = new BinaryNumber(new byte[20]); ushort dataLength; byte[] dataLengthBuffer = new byte[2]; while (true) { #region Read frame from base stream //read frame signal signalType = _baseStream.ReadByte(); if (signalType == -1) { return; //End of stream } //read channel name OffsetStream.StreamRead(_baseStream, channelName.Number, 0, 20); //read data length OffsetStream.StreamRead(_baseStream, dataLengthBuffer, 0, 2); dataLength = BitConverter.ToUInt16(dataLengthBuffer, 0); //read data stream OffsetStream dataStream = null; if (dataLength > 0) { dataStream = new OffsetStream(_baseStream, 0, dataLength, true, false); } #endregion switch ((SignalType)signalType) { case SignalType.NOOP: break; case SignalType.ConnectChannelBitChatNetwork: #region ConnectChannelBitChatNetwork lock (_channels) { if (_channels.ContainsKey(channelName)) { WriteFrame(SignalType.DisconnectChannel, channelName, null, 0, 0); } else { ChannelStream channel = new ChannelStream(this, channelName.Clone()); _channels.Add(channel.ChannelName, channel); BitChatNetworkChannelRequest.BeginInvoke(this, channel.ChannelName, channel, null, null); } } //check if tcp relay is hosted for the channel. reply back tcp relay peers list if available try { List <IPEndPoint> peerEPs = TcpRelayService.GetPeerEPs(channelName, this); if ((peerEPs != null) && (peerEPs.Count > 0)) { using (MemoryStream mS = new MemoryStream(128)) { mS.WriteByte(Convert.ToByte(peerEPs.Count)); foreach (IPEndPoint peerEP in peerEPs) { IPEndPointParser.WriteTo(peerEP, mS); } byte[] data = mS.ToArray(); WriteFrame(SignalType.TcpRelayResponsePeerList, channelName, data, 0, data.Length); } } } catch { } #endregion break; case SignalType.ChannelData: #region ChannelData try { ChannelStream channel = null; lock (_channels) { channel = _channels[channelName]; } channel.FeedReadBuffer(dataStream, _channelWriteTimeout); } catch { } #endregion break; case SignalType.DisconnectChannel: #region DisconnectChannel try { ChannelStream channel; lock (_channels) { channel = _channels[channelName]; _channels.Remove(channelName); } channel.SetDisconnected(); channel.Dispose(); } catch { } #endregion break; case SignalType.ConnectChannelProxyTunnel: #region ConnectChannelProxyTunnel { ChannelStream remoteChannel1 = null; lock (_channels) { if (_channels.ContainsKey(channelName)) { WriteFrame(SignalType.DisconnectChannel, channelName, null, 0, 0); } else { //add first stream into list remoteChannel1 = new ChannelStream(this, channelName.Clone()); _channels.Add(remoteChannel1.ChannelName, remoteChannel1); } } if (remoteChannel1 != null) { IPEndPoint tunnelToRemotePeerEP = ConvertChannelNameToEp(channelName); //get remote peer ep Connection remotePeerConnection = _connectionManager.GetExistingConnection(tunnelToRemotePeerEP); //get remote channel service if (remotePeerConnection == null) { remoteChannel1.Dispose(); } else { try { //get remote proxy connection channel stream ChannelStream remoteChannel2 = remotePeerConnection.RequestProxyConnection(_remotePeerEP); //join current and remote stream Joint joint = new Joint(remoteChannel1, remoteChannel2); joint.Disposed += joint_Disposed; lock (_proxyTunnelJointList) { _proxyTunnelJointList.Add(joint); } joint.Start(); } catch { remoteChannel1.Dispose(); } } } } #endregion break; case SignalType.ConnectChannelProxyConnection: #region ConnectChannelProxyConnection lock (_channels) { if (_channels.ContainsKey(channelName)) { WriteFrame(SignalType.DisconnectChannel, channelName, null, 0, 0); } else { //add proxy channel stream into list ChannelStream channel = new ChannelStream(this, channelName.Clone()); _channels.Add(channel.ChannelName, channel); //pass channel as connection async Thread t = new Thread(delegate(object state) { try { _connectionManager.AcceptConnectionInitiateProtocol(channel, ConvertChannelNameToEp(channel.ChannelName)); } catch { channel.Dispose(); } }); t.IsBackground = true; t.Start(); } } #endregion break; case SignalType.PeerStatusQuery: #region PeerStatusQuery try { if (_connectionManager.IsPeerConnectionAvailable(ConvertChannelNameToEp(channelName))) { WriteFrame(SignalType.PeerStatusAvailable, channelName, null, 0, 0); } } catch { } #endregion break; case SignalType.PeerStatusAvailable: #region PeerStatusAvailable try { lock (_peerStatusLockList) { object lockObject = _peerStatusLockList[channelName]; lock (lockObject) { Monitor.Pulse(lockObject); } } } catch { } #endregion break; case SignalType.StartTcpRelay: #region StartTcpRelay { BinaryNumber[] networkIDs; Uri[] trackerURIs; //read network id list networkIDs = new BinaryNumber[dataStream.ReadByte()]; byte[] XORnetworkID = new byte[20]; for (int i = 0; i < networkIDs.Length; i++) { OffsetStream.StreamRead(dataStream, XORnetworkID, 0, 20); byte[] networkID = new byte[20]; for (int j = 0; j < 20; j++) { networkID[j] = (byte)(channelName.Number[j] ^ XORnetworkID[j]); } networkIDs[i] = new BinaryNumber(networkID); } //read tracker uri list trackerURIs = new Uri[dataStream.ReadByte()]; byte[] data = new byte[255]; for (int i = 0; i < trackerURIs.Length; i++) { int length = dataStream.ReadByte(); OffsetStream.StreamRead(dataStream, data, 0, length); trackerURIs[i] = new Uri(Encoding.UTF8.GetString(data, 0, length)); } lock (_tcpRelays) { foreach (BinaryNumber networkID in networkIDs) { if (!_tcpRelays.ContainsKey(networkID)) { TcpRelayService relay = TcpRelayService.StartTcpRelay(networkID, this, _connectionManager.LocalPort, _connectionManager.IPv4DhtNode, trackerURIs); _tcpRelays.Add(networkID, relay); } } } WriteFrame(SignalType.TcpRelayResponseSuccess, channelName, null, 0, 0); } #endregion break; case SignalType.StopTcpRelay: #region StopTcpRelay { BinaryNumber[] networkIDs; //read network id list networkIDs = new BinaryNumber[dataStream.ReadByte()]; byte[] XORnetworkID = new byte[20]; for (int i = 0; i < networkIDs.Length; i++) { OffsetStream.StreamRead(dataStream, XORnetworkID, 0, 20); byte[] networkID = new byte[20]; for (int j = 0; j < 20; j++) { networkID[j] = (byte)(channelName.Number[j] ^ XORnetworkID[j]); } networkIDs[i] = new BinaryNumber(networkID); } lock (_tcpRelays) { foreach (BinaryNumber networkID in networkIDs) { if (_tcpRelays.ContainsKey(networkID)) { _tcpRelays[networkID].StopTcpRelay(this); _tcpRelays.Remove(networkID); } } } WriteFrame(SignalType.TcpRelayResponseSuccess, channelName, null, 0, 0); } #endregion break; case SignalType.TcpRelayResponseSuccess: #region TcpRelayResponseSuccess try { lock (_tcpRelayRequestLockList) { object lockObject = _tcpRelayRequestLockList[channelName]; lock (lockObject) { Monitor.Pulse(lockObject); } } } catch { } #endregion break; case SignalType.TcpRelayResponsePeerList: #region TcpRelayResponsePeerList { int count = dataStream.ReadByte(); List <IPEndPoint> peerEPs = new List <IPEndPoint>(count); for (int i = 0; i < count; i++) { peerEPs.Add(IPEndPointParser.Parse(dataStream)); } TcpRelayPeersAvailable.BeginInvoke(this, channelName.Clone(), peerEPs, null, null); } #endregion break; case SignalType.BitChatNetworkInvitation: #region ChannelInvitationBitChatNetwork if (_connectionManager.Profile.AllowInboundInvitations) { byte[] buffer = new byte[dataStream.Length]; OffsetStream.StreamRead(dataStream, buffer, 0, buffer.Length); BitChatNetworkInvitation.BeginInvoke(channelName.Clone(), _remotePeerEP, Encoding.UTF8.GetString(buffer, 0, buffer.Length), null, null); } #endregion break; default: throw new IOException("Invalid frame signal type."); } if (dataStream != null) { //discard any unread data if (dataStream.Length > dataStream.Position) { OffsetStream.StreamCopy(dataStream, Stream.Null, 4096); } } } } catch { } finally { Dispose(); } }