internal void EndAcceptControlConnection(IAsyncResult ar) { try { string _filePath = (string)ar.AsyncState; Socket _clientSocket = controlSocket.EndAccept(ar); NetworkCommunicationManagers.Disconnect(controlSocket); controlSocket = _clientSocket; byte[] _buffer = packFileMetadata(_filePath); NetworkCommunicationManagers.SendIntOverSocket(dataSocket, _buffer.Length); NetworkCommunicationManagers.SendByteArrayOverSocket(dataSocket, _buffer); fileTransferContainer.FileTransferClassInstance = this; managedSendFileOverSockets(_filePath); } catch (Exception) { NetworkCommunicationManagers.Disconnect(controlSocket); NetworkCommunicationManagers.Disconnect(dataSocket); lock (RunningTransfers) { if (fileTransferContainer.status != FileTransferStatus.Cancelled) { fileTransferContainer.status = FileTransferStatus.Error; } } return; } }
internal void managedSendFileOverSockets(string filePath) { fileTransferContainer.filePath = filePath; short _count = 0; const short _INITIAL = 5000; Thread _thread = new Thread(() => monitorControlChannel()); _thread.Name = "Control Socket monitor for " + dataSocket.RemoteEndPoint.ToString(); _thread.IsBackground = true; _thread.Start(); using (FileStream _fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { byte[] _fileBuffer = new byte[FILE_BUFFER_SIZE]; long _size = _fs.Length; try { long _index = 0; //Send the initial chunk of data while (dataSocket.Connected && controlSocket.Connected && _index < _size) { if (fileTransferContainer.status == FileTransferStatus.Paused) { resetEvent.WaitOne(); } _fs.Position = _index; int _read = _fs.Read(_fileBuffer, 0, _fileBuffer.Length); try { NetworkCommunicationManagers.SendIntOverSocket(dataSocket, _read); if (_read != _fileBuffer.Length) { byte[] _temp = new byte[_read]; Buffer.BlockCopy(_fileBuffer, 0, _temp, 0, _read); NetworkCommunicationManagers.SendByteArrayOverSocket(dataSocket, _temp); } else { NetworkCommunicationManagers.SendByteArrayOverSocket(dataSocket, _fileBuffer); } } catch (SocketException) { continue; } _index += _read; _count++; if (_count % 200 == 0) { lock (RunningTransfers) { if (Math.Round(((((double)_index / _size) * 100) - fileTransferContainer.progress), 1) >= 0.1) { fileTransferContainer.progress = (float)Math.Round(((double)_index / _size) * 100, 1); } } } if (_count == _INITIAL) { _count = 0; break; } } //Send the remaining data while (dataSocket.Connected && controlSocket.Connected && _index < _size) { _fs.Position = _index; int _read = _fs.Read(_fileBuffer, 0, _fileBuffer.Length); try { NetworkCommunicationManagers.SendIntOverSocket(dataSocket, _read); if (_read != _fileBuffer.Length) { byte[] _temp = new byte[_read]; Buffer.BlockCopy(_fileBuffer, 0, _temp, 0, _read); NetworkCommunicationManagers.SendByteArrayOverSocket(dataSocket, _temp); } else { NetworkCommunicationManagers.SendByteArrayOverSocket(dataSocket, _fileBuffer); } } catch (SocketException) { continue; } _index += _read; _count++; if (_count % 200 == 0) { lock (RunningTransfers){ if (Math.Round(((((double)_index / _size) * 100) - fileTransferContainer.progress), 1) >= 0.1) { fileTransferContainer.progress = (float)Math.Round((((double)_index / _size) * 100), 1); } } bool _wait = true; while (true) { lock (syncObject) { if (acknowledgedTransfers > 0) { acknowledgedTransfers--; _wait = false; break; } } if (_wait) { Thread.Sleep(100); } } } } if (_index == _size) { lock (RunningTransfers) { fileTransferContainer.progress = 100; fileTransferContainer.status = FileTransferStatus.Finished; } } else { lock (RunningTransfers) { if (fileTransferContainer.status != FileTransferStatus.Cancelled) { fileTransferContainer.status = FileTransferStatus.Error; } } } } catch { lock (RunningTransfers) { if (fileTransferContainer.status != FileTransferStatus.Cancelled) { fileTransferContainer.status = FileTransferStatus.Error; } } } } }
internal bool managedReceiveFileOverSockets(string filePath, long length) { short _count = 0; long _index = 0; int _size = 1; Thread _thread = new Thread(() => monitorControlChannel()); _thread.Name = "Control Socket monitor for " + dataSocket.RemoteEndPoint.ToString(); _thread.IsBackground = true; _thread.Start(); try { using (FileStream _fs = new FileStream(filePath + ".temp", FileMode.CreateNew)) { _fs.SetLength(length); byte[] _buffer; while (dataSocket.Connected && controlSocket.Connected && _index < length) { if (fileTransferContainer.status == FileTransferStatus.Paused) { resetEvent.WaitOne(); } if (!NetworkCommunicationManagers.ReceiveIntOverSocket(dataSocket, out _size)) { continue; } ; _buffer = new byte[_size]; if (!NetworkCommunicationManagers.ReceiveByteArrayOverSocket(dataSocket, out _buffer, _size)) { continue; } ; _fs.Position = _index; _fs.Write(_buffer, 0, _buffer.Length); _index += _size; _count++; if (_count % 200 == 0) { lock (RunningTransfers) { if (Math.Round(((((double)_index / length) * 100) - fileTransferContainer.progress), 1) >= 0.1) { fileTransferContainer.progress = (float)Math.Round((((double)_index / length) * 100), 1); } } _count = 0; ThreadPool.QueueUserWorkItem(state => { lock (controlSocket) { NetworkCommunicationManagers.SendByteArrayOverSocket(controlSocket, new byte[] { (byte)FileTransferCommands.BlockTransferred }); } }); } } } lock (controlSocket) { NetworkCommunicationManagers.SendByteArrayOverSocket(controlSocket, new byte[] { (byte)FileTransferCommands.EndTransfer }); } } catch (ObjectDisposedException) { NetworkCommunicationManagers.Disconnect(controlSocket); NetworkCommunicationManagers.Disconnect(dataSocket); } catch (SocketException) { NetworkCommunicationManagers.Disconnect(controlSocket); NetworkCommunicationManagers.Disconnect(dataSocket); } if (_index < length) { try { File.Delete(filePath + ".temp"); } catch { } lock (RunningTransfers) { if (fileTransferContainer.status != FileTransferStatus.Cancelled) { fileTransferContainer.status = FileTransferStatus.Error; } } return(false); } else { try { File.Move(filePath + ".temp", filePath); } catch (IOException) { try { File.Delete(filePath + ".temp"); } catch { } } lock (RunningTransfers) { fileTransferContainer.status = FileTransferStatus.Finished; fileTransferContainer.progress = 100; } } return(true); }
internal void monitorControlChannel() { try { byte[] arr; FileTransferCommands _command; while (controlSocket.Connected) { if (!NetworkCommunicationManagers.ReceiveByteArrayOverSocket(controlSocket, out arr, 1)) { continue; } _command = (FileTransferCommands)arr[0]; switch (_command) { case FileTransferCommands.BlockTransferred: lock (syncObject) { acknowledgedTransfers++; } break; case FileTransferCommands.EndTransfer: NetworkCommunicationManagers.Disconnect(controlSocket); NetworkCommunicationManagers.Disconnect(dataSocket); return; case FileTransferCommands.Pause: lock (RunningTransfers) { fileTransferContainer.status = FileTransferStatus.Paused; if (fileTransferContainer.pausedBy == PausedBy.None) { fileTransferContainer.pausedBy = PausedBy.OtherPeer; } else if (fileTransferContainer.pausedBy == PausedBy.User) { fileTransferContainer.pausedBy = PausedBy.Both; } } ThreadPool.QueueUserWorkItem(state => { lock (controlSocket) { NetworkCommunicationManagers.SendByteArrayOverSocket(controlSocket, new byte[] { (byte)FileTransferCommands.PauseOrResumeRequestReceived }); } }); break; case FileTransferCommands.PauseOrResumeRequestReceived: lock (RunningTransfers) { if (fileTransferContainer.transferType == FileTransferType.Upload) { if (fileTransferContainer.status == FileTransferStatus.Paused && fileTransferContainer.pausedBy == PausedBy.None) { fileTransferContainer.status = FileTransferStatus.Running; resetEvent.Set(); } } else if (fileTransferContainer.transferType == FileTransferType.Download) { if (fileTransferContainer.pausedBy != PausedBy.None && fileTransferContainer.status == FileTransferStatus.Running) { fileTransferContainer.status = FileTransferStatus.Paused; } } } break; case FileTransferCommands.Resume: lock (RunningTransfers) { if (fileTransferContainer.pausedBy == PausedBy.OtherPeer) { fileTransferContainer.pausedBy = PausedBy.None; fileTransferContainer.status = FileTransferStatus.Running; resetEvent.Set(); } else if (fileTransferContainer.pausedBy == PausedBy.Both) { fileTransferContainer.pausedBy = PausedBy.User; } ThreadPool.QueueUserWorkItem(state => { lock (controlSocket) { NetworkCommunicationManagers.SendByteArrayOverSocket(controlSocket, new byte[] { (byte)FileTransferCommands.PauseOrResumeRequestReceived }); } }); } break; } } } catch (ObjectDisposedException) {} catch (SocketException) {} finally { NetworkCommunicationManagers.Disconnect(controlSocket); NetworkCommunicationManagers.Disconnect(dataSocket); } }