1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Net.Test.Common;
6 
7 namespace System.Net.Sockets.Tests
8 {
9     // Provides a dummy _socket server that accepts connections and echoes data sent
10     public class SocketTestServerAPM : SocketTestServer
11     {
12         private VerboseTestLogging _log;
13 
14         private Socket _socket;
15         private int _receiveBufferSize;
16         private volatile bool _disposed = false;
17 
18         protected sealed override int Port { get { return ((IPEndPoint)_socket.LocalEndPoint).Port; } }
19         public sealed override EndPoint EndPoint { get { return _socket.LocalEndPoint; } }
20 
SocketTestServerAPM(int numConnections, int receiveBufferSize, EndPoint localEndPoint)21         public SocketTestServerAPM(int numConnections, int receiveBufferSize, EndPoint localEndPoint)
22         {
23             _log = VerboseTestLogging.GetInstance();
24             _receiveBufferSize = receiveBufferSize;
25 
26             _socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
27             _socket.Bind(localEndPoint);
28             _socket.Listen(numConnections);
29 
30             _socket.BeginAccept(OnAccept, null);
31         }
32 
Dispose(bool disposing)33         protected override void Dispose(bool disposing)
34         {
35             if (disposing)
36             {
37                 _socket.Dispose();
38                 _disposed = true;
39             }
40         }
41 
OnAccept(IAsyncResult result)42         private void OnAccept(IAsyncResult result)
43         {
44             Socket client = null;
45 
46             if (_disposed)
47             {
48                 return;
49             }
50 
51             try
52             {
53                 client = _socket.EndAccept(result);
54             }
55             catch (SocketException e)
56             {
57                 if (_disposed ||
58                     e.SocketErrorCode == SocketError.OperationAborted ||
59                     e.SocketErrorCode == SocketError.Interrupted)
60                 {
61                     return;
62                 }
63 
64                 throw;
65             }
66             catch (ObjectDisposedException)
67             {
68                 return;
69             }
70 
71             ServerSocketState state = new ServerSocketState(client, _receiveBufferSize);
72             try
73             {
74                 state.Socket.BeginReceive(state.TransferBuffer, 0, state.TransferBuffer.Length, SocketFlags.None, OnReceive, state);
75             }
76             catch (SocketException)
77             {
78             }
79 
80             try
81             {
82                 _socket.BeginAccept(OnAccept, null);
83             }
84             catch (SocketException e)
85             {
86                 if (_disposed ||
87                     e.SocketErrorCode == SocketError.OperationAborted ||
88                     e.SocketErrorCode == SocketError.Interrupted)
89                 {
90                     return;
91                 }
92 
93                 throw;
94             }
95             catch (ObjectDisposedException)
96             {
97             }
98         }
99 
OnReceive(IAsyncResult result)100         private void OnReceive(IAsyncResult result)
101         {
102             ServerSocketState recvState = (ServerSocketState)result.AsyncState;
103 
104             try
105             {
106                 int bytesReceived = recvState.Socket.EndReceive(result);
107                 if (bytesReceived == 0)
108                 {
109                     recvState.Socket.Dispose();
110                     return;
111                 }
112 
113                 ServerSocketState sendState = new ServerSocketState(recvState, bytesReceived);
114 
115                 sendState.Socket.BeginSend(sendState.TransferBuffer, 0, bytesReceived, SocketFlags.None, OnSend, sendState);
116                 recvState.Socket.BeginReceive(
117                     recvState.TransferBuffer,
118                     0,
119                     recvState.TransferBuffer.Length,
120                     SocketFlags.None,
121                     OnReceive,
122                     recvState);
123             }
124             catch (SocketException)
125             {
126                 recvState.Socket.Dispose();
127                 return;
128             }
129             catch (ObjectDisposedException)
130             {
131                 return;
132             }
133         }
134 
OnSend(IAsyncResult result)135         private void OnSend(IAsyncResult result)
136         {
137             ServerSocketState sendState = (ServerSocketState)result.AsyncState;
138 
139             try
140             {
141                 int bytesSent = sendState.Socket.EndSend(result);
142                 if (bytesSent != sendState.TransferBuffer.Length)
143                 {
144                     _log.WriteLine("{2} APM: OnSend {0}bytes - expecting {1}bytes.", bytesSent, sendState.TransferBuffer.Length, sendState.Socket.GetHashCode());
145                 }
146             }
147             catch (SocketException)
148             {
149                 sendState.Socket.Dispose();
150                 return;
151             }
152             catch (ObjectDisposedException)
153             {
154                 return;
155             }
156         }
157 
158         private class ServerSocketState
159         {
160             private Socket __socket;
161             private byte[] _buffer;
162 
ServerSocketState(Socket _socket, int bufferSize)163             public ServerSocketState(Socket _socket, int bufferSize)
164             {
165                 __socket = _socket;
166                 _buffer = new byte[bufferSize];
167             }
168 
ServerSocketState(ServerSocketState original, int count)169             public ServerSocketState(ServerSocketState original, int count)
170             {
171                 __socket = original.__socket;
172                 _buffer = new byte[count];
173                 Buffer.BlockCopy(original._buffer, 0, _buffer, 0, count);
174             }
175 
176             public Socket Socket
177             {
178                 get { return __socket; }
179             }
180 
181             public byte[] TransferBuffer
182             {
183                 get { return _buffer; }
184             }
185         }
186     }
187 }
188