/// <summary> /// Complete asynchronous callback by release connection objects and by decrementing number of running tasks. /// </summary> /// <param name="socketState">Connection objects allocated by this task.</param> /// <param name="shutdown">True for normal shutdown and close for abortive shutdown.</param> private void EndCallback(SocketState socketState, bool shutdown) { if (socketState != null) socketState.Close(shutdown); this.EndCallback(); }
/// <summary> /// Called when incoming socket becomes accepted. /// </summary> /// <param name="ar">The result of the asynchronous operation.</param> private void AcceptCallback(IAsyncResult ar) { SocketState socketState = null; Socket serverSocket = (Socket)ar.AsyncState; try { Socket clientSocket = serverSocket.EndAccept(ar); this.acceptCompleted.Set(); socketState = new SocketState(this, clientSocket); byte[] readBuffer = socketState.ReadBuffer; clientSocket.BeginReceive(readBuffer, 0, readBuffer.Length, SocketFlags.None, ReceiveRequestCallback, socketState); // Keep connection open. socketState = null; } catch (ObjectDisposedException) { // Accept interrupted. } catch (Exception error) { this.ReportNestedError(error); } finally { if (socketState != null) socketState.Dispose(); } }
/// <summary> /// Handles client request and stores bug report in repository. /// </summary> /// <param name="state">Socket state object.</param> private void HandleRequestCallback(object state) { SocketState socketState = (SocketState)state; bool shutdown = false; this.BeginCallback(); try { BinaryReader binReader = null; FileStream outputStream = null; try { // Extract data from the stream. FileStream tempStream = socketState.TempStream; tempStream.Seek(0, SeekOrigin.Begin); long dataSize = tempStream.Length; // Message size (DWORD) + protocol signature (DWORD) = 8 bytes. if (dataSize < 8) { throw new ApplicationException("Invalid message size"); } binReader = new BinaryReader(tempStream, Encoding.UTF8); if (BugTrapService.protocolSignature != binReader.ReadUInt32()) { throw new ApplicationException("Unsupported protocol version"); } if (dataSize != binReader.ReadInt32()) { throw new ApplicationException("Invalid message size"); } MessageType messageType = (MessageType)binReader.ReadByte(); if (messageType != MessageType.CompundMessage) { throw new ApplicationException("Unsupported message type"); } CompoundMessageFlags messageFlags = (CompoundMessageFlags)binReader.ReadUInt32(); if (messageFlags != CompoundMessageFlags.None) { throw new ApplicationException("Unsupported message flags"); } string appName = binReader.ReadString(); string appVersion = binReader.ReadString(); string extension = binReader.ReadString(); string email = binReader.ReadString(); if (appName == string.Empty) { appName = "(UNTITLED)"; } string appTitle = appVersion == string.Empty ? appName : appName + ' ' + appVersion; string dirName = GetAppDirName(appTitle); int reportSize = (int)(tempStream.Length - tempStream.Position); if ((this.applicationSettings.MaxReportSize >= 0 && reportSize > this.applicationSettings.MaxReportSize) || reportSize <= 0) { throw new ApplicationException("Report exceeds size limit"); } AppEntry appEntry = new AppEntry(appName, appVersion); if (!this.FindAppEntry(appEntry)) { throw new ApplicationException("Report excluded by filter"); } if (!this.FindReportFileExtension(extension)) { throw new ApplicationException("Invalid report file extension"); } int maxReportNumber = 0, numReports = 0; lock (this.lastReportNumbers) { AppDirInfo appDirInfo; if (this.lastReportNumbers.TryGetValue(dirName, out appDirInfo)) { maxReportNumber = appDirInfo.MaxReportNumber; numReports = appDirInfo.NumReports; } if (this.applicationSettings.ReportsLimit >= 0 && numReports > this.applicationSettings.ReportsLimit) { throw new ApplicationException("Number of reports exceeds the limit"); } if (appDirInfo == null) { appDirInfo = new AppDirInfo(); this.lastReportNumbers[dirName] = appDirInfo; } appDirInfo.NumReports = ++numReports; appDirInfo.MaxReportNumber = ++maxReportNumber; } string reportDir = Path.Combine(this.applicationSettings.ReportPath, dirName); Directory.CreateDirectory(reportDir); string fileName = reportNamePattern + maxReportNumber.ToString() + '.' + extension; outputStream = new FileStream(Path.Combine(reportDir, fileName), FileMode.Create, FileAccess.ReadWrite, FileShare.None); byte[] reportData = new byte[1024]; while (reportSize > 0) { int chunkSize = Math.Min(reportSize, reportData.Length); binReader.Read(reportData, 0, chunkSize); outputStream.Write(reportData, 0, chunkSize); reportSize -= chunkSize; } this.SendEMail(email, appTitle); // Done! shutdown = true; } finally { if (binReader != null) { binReader.Close(); } if (outputStream != null) { outputStream.Close(); } } } catch (Exception error) { this.ReportNestedError(error); } finally { this.EndCallback(socketState, shutdown); } }