1
2
3
4
5
6 using System;
7
8 namespace System.Net.Sockets
9 {
10 public enum ShutdownMode : int
11 {
12 receive = 0, send = 1, both = 2
13 }
14
15 public enum ConnectOptions : int
16 {
17 none = 0, useTls = 1 << 0
18 }
19
20 public class SocketException : Exception
21 {
22 public nothrow SocketException(const string& message_) : base(message_)
23 {
24 }
25 }
26
27 public class TcpSocket
28 {
29 public TcpSocket() : handle(null), connected(false), shutdown(false)
30 {
31 int errorStringHandle = -1;
32 handle = RtCreateSocket(errorStringHandle);
33 if (handle == null)
34 {
35 string errorMessage = RtGetError(errorStringHandle);
36 RtDisposeError(errorStringHandle);
37 throw SocketException(errorMessage);
38 }
39 }
40 public TcpSocket(const string& node, const string& service, ConnectOptions options) : handle(null), connected(false), shutdown(false)
41 {
42 int errorStringHandle = -1;
43 handle = RtConnectSocket(node.Chars(), service.Chars(), cast<int>(options), errorStringHandle);
44 if (handle == null)
45 {
46 string errorMessage = RtGetError(errorStringHandle);
47 RtDisposeError(errorStringHandle);
48 throw SocketException(errorMessage);
49 }
50 else
51 {
52 connected = true;
53 }
54 }
55 public TcpSocket(const string& node, const string& service) : this(node, service, ConnectOptions.none)
56 {
57 }
58 public nothrow TcpSocket(void* handle_) : handle(handle_), connected(true), shutdown(false)
59 {
60 }
61 suppress TcpSocket(const TcpSocket&);
62 suppress void operator=(const TcpSocket&);
63 public nothrow TcpSocket(TcpSocket&& that) : handle(that.handle), connected(that.connected), shutdown(that.shutdown)
64 {
65 that.handle = null;
66 that.connected = false;
67 that.shutdown = false;
68 }
69 public nothrow void operator=(TcpSocket&& that)
70 {
71 Swap(handle, that.handle);
72 Swap(connected, that.connected);
73 Swap(shutdown, that.shutdown);
74 }
75 public ~TcpSocket()
76 {
77 if (handle != null)
78 {
79 if (connected && !shutdown)
80 {
81 try
82 {
83 Shutdown(ShutdownMode.both);
84 }
85 catch (const Exception& ex)
86 {
87 }
88 }
89 if (connected)
90 {
91 int errorStringHandle = -1;
92 RtCloseSocket(handle, errorStringHandle);
93 }
94 RtDestroySocket(handle);
95 }
96 }
97 public void Close()
98 {
99 if (handle != null)
100 {
101 if (connected && !shutdown)
102 {
103 Shutdown(ShutdownMode.both);
104 }
105 int errorStringHandle = -1;
106 if (!RtCloseSocket(handle, errorStringHandle))
107 {
108 string errorMessage = RtGetError(errorStringHandle);
109 RtDisposeError(errorStringHandle);
110 throw SocketException(errorMessage);
111 }
112 handle = null;
113 connected = false;
114 }
115 }
116 public void Connect(const string& node, const string& service)
117 {
118 Connect(node, service, ConnectOptions.none);
119 }
120 public void Connect(const string& node, const string& service, ConnectOptions options)
121 {
122 Close();
123 int errorStringHandle = -1;
124 handle = RtConnectSocket(node.Chars(), service.Chars(), cast<int>(options), errorStringHandle);
125 if (handle == null)
126 {
127 string errorMessage = RtGetError(errorStringHandle);
128 RtDisposeError(errorStringHandle);
129 throw SocketException(errorMessage);
130 }
131 else
132 {
133 connected = true;
134 }
135 }
136 public void Bind(int port)
137 {
138 int errorStringHandle = -1;
139 if (!RtBindSocket(handle, port, errorStringHandle))
140 {
141 string errorMessage = RtGetError(errorStringHandle);
142 RtDisposeError(errorStringHandle);
143 throw SocketException(errorMessage);
144 }
145 }
146 public void Listen(int backLog)
147 {
148 int errorStringHandle = -1;
149 if (!RtListenSocket(handle, backLog, errorStringHandle))
150 {
151 string errorMessage = RtGetError(errorStringHandle);
152 RtDisposeError(errorStringHandle);
153 throw SocketException(errorMessage);
154 }
155 }
156 public TcpSocket Accept()
157 {
158 int errorStringHandle = -1;
159 void* acceptedHandle = RtAcceptSocket(handle, errorStringHandle);
160 if (acceptedHandle == null)
161 {
162 string errorMessage = RtGetError(errorStringHandle);
163 RtDisposeError(errorStringHandle);
164 throw SocketException(errorMessage);
165 }
166 return TcpSocket(acceptedHandle);
167 }
168 public void Shutdown(ShutdownMode mode)
169 {
170 shutdown = true;
171 int errorStringHandle = -1;
172 if (!RtShutdownSocket(handle, cast<int>(mode), errorStringHandle))
173 {
174 string errorMessage = RtGetError(errorStringHandle);
175 RtDisposeError(errorStringHandle);
176 throw SocketException(errorMessage);
177 }
178 }
179 public int Send(byte* buffer, int count)
180 {
181 int errorStringHandle = -1;
182 int result = RtSendSocket(handle, buffer, count, 0, errorStringHandle);
183 if (result < 0)
184 {
185 string errorMessage = RtGetError(errorStringHandle);
186 RtDisposeError(errorStringHandle);
187 throw SocketException(errorMessage);
188 }
189 return result;
190 }
191 public int Receive(byte* buffer, int count)
192 {
193 int errorStringHandle = -1;
194 int result = RtReceiveSocket(handle, buffer, count, 0, errorStringHandle);
195 if (result < 0)
196 {
197 string errorMessage = RtGetError(errorStringHandle);
198 RtDisposeError(errorStringHandle);
199 throw SocketException(errorMessage);
200 }
201 return result;
202 }
203 private void* handle;
204 private bool connected;
205 private bool shutdown;
206 }
207
208 public void Write(TcpSocket& socket, const string& str)
209 {
210 int size = cast<int>(str.Length());
211 byte[4] buffer;
212 MemoryWriter writer(&buffer[0], 4);
213 writer.Write(size);
214 int bytesToSend = 4;
215 int offset = 0;
216 while (bytesToSend > 0)
217 {
218 int bytesSent = socket.Send(&buffer[0] + offset, bytesToSend);
219 bytesToSend = bytesToSend - bytesSent;
220 offset = offset + bytesSent;
221 }
222 byte* p = cast<byte*>(cast<void*>(str.Chars()));
223 int count = size;
224 while (count > 0)
225 {
226 int bytesSent = socket.Send(p, count);
227 p = p + bytesSent;
228 count = count - bytesSent;
229 }
230 }
231
232 public string ReadStr(TcpSocket& socket)
233 {
234 byte[4] buffer;
235 int bytesToReceive = 4;
236 int offset = 0;
237 int bytesReceived = socket.Receive(&buffer[offset], bytesToReceive);
238 if (bytesReceived == 0)
239 {
240 return string();
241 }
242 bytesToReceive = bytesToReceive - bytesReceived;
243 offset = offset + bytesReceived;
244 while (bytesToReceive > 0)
245 {
246 bytesReceived = socket.Receive(&buffer[offset], bytesToReceive);
247 if (bytesReceived == 0)
248 {
249 return string();
250 }
251 bytesToReceive = bytesToReceive - bytesReceived;
252 offset = offset + bytesReceived;
253 }
254 MemoryReader reader(&buffer[0], 4);
255 int size = reader.ReadInt();
256 if (size == 0)
257 {
258 return string();
259 }
260 UniquePtr<byte> mem(cast<byte*>(MemAlloc(size)));
261 offset = 0;
262 bytesToReceive = size;
263 bytesReceived = socket.Receive(mem.Get() + offset, bytesToReceive);
264 if (bytesReceived == 0)
265 {
266 return string();
267 }
268 bytesToReceive = bytesToReceive - bytesReceived;
269 offset = offset + bytesReceived;
270 while (bytesToReceive > 0)
271 {
272 bytesReceived = socket.Receive(mem.Get() + offset, bytesToReceive);
273 if (bytesReceived == 0)
274 {
275 return string();
276 }
277 bytesToReceive = bytesToReceive - bytesReceived;
278 offset = offset + bytesReceived;
279 }
280 string s(cast<const char*>(cast<void*>(mem.Get())), size);
281 return s;
282 }
283 }