1 // 2 // Mono.WebServer.LingeringNetworkStream 3 // 4 // Authors: 5 // Gonzalo Paniagua Javier (gonzalo@ximian.com) 6 // 7 // (C) Copyright 2004 Novell, Inc. (http://www.novell.com) 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining 10 // a copy of this software and associated documentation files (the 11 // "Software"), to deal in the Software without restriction, including 12 // without limitation the rights to use, copy, modify, merge, publish, 13 // distribute, sublicense, and/or sell copies of the Software, and to 14 // permit persons to whom the Software is furnished to do so, subject to 15 // the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 // 28 29 using System; 30 using System.Net.Sockets; 31 32 namespace Mono.WebServer 33 { 34 public class LingeringNetworkStream : NetworkStream 35 { 36 const int USECONDS_TO_LINGER = 2000000; 37 const int MAX_USECONDS_TO_LINGER = 30000000; 38 // We dont actually use the data from this buffer. So we cache it... 39 static byte [] buffer; 40 LingeringNetworkStream(Socket sock, bool owns)41 public LingeringNetworkStream (Socket sock, bool owns) : base (sock, owns) 42 { 43 EnableLingering = true; 44 OwnsSocket = owns; 45 } 46 47 public bool OwnsSocket { get; private set; } 48 49 public bool EnableLingering { get; set; } 50 LingeringClose()51 void LingeringClose () 52 { 53 int waited = 0; 54 55 if (!Connected) 56 return; 57 58 try { 59 Socket.Shutdown (SocketShutdown.Send); 60 DateTime start = DateTime.UtcNow; 61 while (waited < MAX_USECONDS_TO_LINGER) { 62 int nread = 0; 63 try { 64 if (!Socket.Poll (USECONDS_TO_LINGER, SelectMode.SelectRead)) 65 break; 66 67 if (buffer == null) 68 buffer = new byte [512]; 69 70 nread = Socket.Receive (buffer, 0, buffer.Length, 0); 71 } catch { } 72 73 if (nread == 0) 74 break; 75 76 waited += (int) (DateTime.UtcNow - start).TotalMilliseconds * 1000; 77 } 78 } catch { 79 // ignore - we don't care, we're closing anyway 80 } 81 } 82 Close()83 public override void Close () 84 { 85 if (EnableLingering) { 86 try { 87 LingeringClose (); 88 } finally { 89 base.Close (); 90 } 91 } 92 else 93 base.Close (); 94 } 95 96 public bool Connected { 97 get { return Socket.Connected; } 98 } 99 } 100 } 101