private async void OnMessageAdcget(ADCGETMessage adcgetMessage) { var reqItem = new ContentItem(); if (adcgetMessage.Type == ADCGETType.Tthl) { SendMessageAsync(new ErrorMessage { Error = "File Not Available" }.Raw); return; } if (adcgetMessage.Type == ADCGETType.File) { if (adcgetMessage.Request.StartsWith("TTH/")) { reqItem.Magnet = new Magnet { TTH = adcgetMessage.Request.Remove(0, 4) }; } else { reqItem.Magnet = new Magnet { FileName = adcgetMessage.Request }; } } _requests.Update(1); _isResponding = true; if (!SlotUsed) { var ea = new CancelEventArgs(); OnSlotRequest(ea); if (ea.Cancel) { Logger.Info("Can't start upload to {0}, no slots available", Source); SendMessageAsync(new MaxedOutMessage().Raw); return; } SlotUsed = true; } if (UploadItem == null || UploadItem.Content.Magnet.TTH != reqItem.Magnet.TTH) { var ea = new UploadItemEventArgs { Transfer = this, Content = reqItem }; OnUploadItemNeeded(ea); if (UploadItem != null) { var uea = new UploadItemEventArgs(); OnUploadItemDispose(uea); if (!uea.Handled) { UploadItem.Dispose(); } } UploadItem = ea.UploadItem; if (ea.UploadItem == null) { SendMessageAsync(new ErrorMessage { Error = "File Not Available" }.Raw); return; } } if (adcgetMessage.Start >= UploadItem.Content.Magnet.Size) { SendMessageAsync(new ErrorMessage { Error = "File Not Available" }.Raw); return; } if (adcgetMessage.Start + adcgetMessage.Length > UploadItem.Content.Magnet.Size) { Logger.Warn("Trim ADCGET length to file actual length {0}/{1}", adcgetMessage.Start + adcgetMessage.Length, UploadItem.Content.Magnet.Size); adcgetMessage.Length = UploadItem.Content.Magnet.Size - adcgetMessage.Start; } var uploadItem = UploadItem; if (_disposed || uploadItem == null) { return; } var sw = PerfTimer.StartNew(); await SendAsync(new ADCSNDMessage { Type = ADCGETType.File, Request = adcgetMessage.Request, Start = adcgetMessage.Start, Length = adcgetMessage.Length }.Raw + "|").ConfigureAwait(false); try { if (_disposed) { return; } await uploadItem.SendChunkAsync(this, adcgetMessage.Start, (int)adcgetMessage.Length).ConfigureAwait(false); Stream.Flush(); sw.Stop(); _isResponding = false; ServiceTime.Update((int)sw.ElapsedMilliseconds); } catch (Exception x) { Logger.Error("Upload read error {0} (L:{1}) {2} {3} ms", x.Message, adcgetMessage.Length, uploadItem.Content.SystemPath, sw.ElapsedMilliseconds); Dispose(); } }
protected override void ParseRaw(byte[] buffer, int offset, int length) { if (_disposed) { return; } if (_tail != null) { var newBuffer = new byte[_tail.Length + length]; Buffer.BlockCopy(_tail, 0, newBuffer, 0, _tail.Length); Buffer.BlockCopy(buffer, offset, newBuffer, _tail.Length, length); length = length + _tail.Length; buffer = newBuffer; offset = 0; _tail = null; } if (_binaryMode) { ParseBinary(buffer, offset, length); return; } int cmdEndIndex = offset; while (true) { var prevPos = cmdEndIndex == offset ? offset : cmdEndIndex + 1; cmdEndIndex = Array.IndexOf(buffer, (byte)'|', prevPos, length - (cmdEndIndex - offset)); if (cmdEndIndex == -1) { if (prevPos < length) { _tail = new byte[length - prevPos]; Buffer.BlockCopy(buffer, prevPos, _tail, 0, _tail.Length); } break; } var command = _encoding.GetString(buffer, prevPos, cmdEndIndex - prevPos); if (IncomingMessage != null) { OnIncomingMessage(new MessageEventArgs { Message = command }); } if (command.Length > 0 && command[0] == '$') { // command var spaceIndex = command.IndexOf(' '); var cmdName = spaceIndex == -1 ? command : command.Substring(0, spaceIndex); switch (cmdName) { case "$MyNick": { var arg = MyNickMessage.Parse(command); OnMessageMyNick(ref arg); } break; case "$Supports": { var arg = SupportsMessage.Parse(command); OnMessageSupports(ref arg); } break; case "$Lock": { var arg = LockMessage.Parse(command); OnMessageLock(ref arg); } break; case "$Direction": { var arg = DirectionMessage.Parse(command); OnMessageDirection(ref arg); } break; case "$Error": { var arg = ErrorMessage.Parse(command); OnMessageError(ref arg); } break; case "$Key": { var arg = KeyMessage.Parse(command); OnMessageKey(ref arg); } break; case "$ADCSND": { var arg = ADCSNDMessage.Parse(command); if (OnMessageAdcsnd(ref arg)) { prevPos = cmdEndIndex + 1; if (prevPos < length + offset) { _tail = new byte[length - (prevPos - offset)]; Buffer.BlockCopy(buffer, prevPos, _tail, 0, _tail.Length); } _binaryMode = true; return; } Dispose(); } break; case "$ADCGET": { var arg = ADCGETMessage.Parse(command); OnMessageAdcget(arg); } break; } } } }