forked from nefarius/sm-ext-socket
-
Notifications
You must be signed in to change notification settings - Fork 0
/
socket.inc
488 lines (450 loc) · 16.5 KB
/
socket.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
// socket extension include file
#if defined _socket_included
#endinput
#endif
#define _socket_included
#include <core>
enum SocketType {
SOCKET_TCP = 1,
SOCKET_UDP,
SOCKET_RAW
}
#define EMPTY_HOST 1
#define NO_HOST 2
#define CONNECT_ERROR 3
#define SEND_ERROR 4
#define BIND_ERROR 5
#define RECV_ERROR 6
#define LISTEN_ERROR 7
/*************************************************************************************************/
/******************************************** options ********************************************/
/*************************************************************************************************/
/**
* Options available for SocketSetOption()
*
* @note modifying these options is not required for normal operation, you can skip the whole
* section in most cases.
*/
enum SocketOption {
/**
* If this option is set the socket extension will try to concatenate SocketReceive callbacks.
*
* This will possibly lower the amount of callbacks passed to SourceMod plugins and improve the
* performance. The socket extension will preserve the packet order.
*
* @note this doesn't prevent multiple callbacks, it only reduces them for high load.
* @note this will not truncate packets below 4096 bytes, setting it lower will be ignored
* @note set this option if you expect lots of data in a short timeframe
* @note don't forget to set your buffer sizes at least to the value passed to this function, but
* always at least to 4096
*
* @param cell_t 0(=default) to disable or max. chunk size including \0 terminator in bytes
* @return bool true on success
*/
ConcatenateCallbacks = 1,
/**
* If this option is set the socket extension will enforce a mutex lock in the GameFrame() hook.
*
* This will ensure that callbacks will be processed every gameframe as fast as possible with the
* drawback of potentially creating lag. It's not recommended to set this option for most cases.
* If this option is not set the gameframe will be skipped if quietly obtaining a lock fails.
*
* @note combine this with CallbacksPerFrame for best performance
* @note this option will affect all sockets from all plugins, use it with caution!
*
* @param bool whether to force locking or not
* @return bool true on success
*/
ForceFrameLock,
/**
* This will specify the maximum amount of callbacks processed in every gameframe.
*
* The default value for this option is 1, setting it higher will possibly increase networking
* performance but may cause lag if it's set too high.
* The amount of callbacks actually being processed is limited by not being able to quietly obtain
* a lock (see ForceFrameLock) and the amount of callbacks in the queue.
*
* @note this option will affect all sockets from all plugins, use it with caution!
*
* @param cell_t maximum amount of callbacks per gameframe
* @return bool true on success
*/
CallbacksPerFrame,
/**
* If this option is set the socket will be allowed to send broadcast messages in case the protocol
* supports it. This is a wrapper for setting SO_BROADCAST.
*
* @param bool whether to allow broadcasting or not
* @return bool true on success
*/
SocketBroadcast,
/**
* If this option is set SocketBind() will allow reusing local adresses in case the protocol
* supports it. This is a wrapper for setting SO_REUSEADDR.
*
* @param bool whether to allow broadcasting or not
* @return bool true on success
*/
SocketReuseAddr,
/**
* If this option is set the socket will try to keep the connection alive by periodically sending
* messages if the protocol supports it. This is a wrapper for setting SO_KEEPALIVE.
*
* @param bool whether to allow broadcasting or not
* @return bool true on success
*/
SocketKeepAlive,
/**
* This option specifies how long a socket will wait if it's being closed and its send buffer is
* still filled. This is a wrapper for setting SO_LINGER.
*
* @param cell_t 0 (=default) to disable or time in s
* @return bool true on success
*/
SocketLinger,
/**
* If this option is set out-of-band data will be inlined into the normal receive stream. This is a
* wrapper for setting SO_OOBINLINE.
*
* @param bool whether to inline out-of-band data or not
* @return bool true on success
*/
SocketOOBInline,
/**
* This option specifies how large the send buffer will be. This is a wrapper for setting
* SO_SNDBUF.
*
* @param cell_t size in bytes
* @return bool true on success
*/
SocketSendBuffer,
/**
* This option specifies how large the receive buffer will be. This is a wrapper for setting
* SO_RCVBUF.
*
* @param cell_t size in bytes
* @return bool true on success
*/
SocketReceiveBuffer,
/**
* If this option is set outgoing messages will ignore the default routing facilities if the
* protocol implementation supports it. The remote site should be directly connected to the sender.
* This is a wrapper for setting SO_DONTROUTE.
*
* @param bool whether to skip default routing or not
* @return bool true on success
*/
SocketDontRoute,
/**
* This option specifies the minimum amount of data to receive before processing it. This is a
* wrapper for setting SO_RCVLOWAT.
*
* @note this can probably block the extension, use it with caution!
*
* @param cell_t size in bytes
* @return bool true on success
*/
SocketReceiveLowWatermark,
/**
* This option specifies how long a socket will try to receive data before it times out and
* processes the data. This is a wrapper for setting SO_RCVTIMEO.
*
* @param cell_t 0 (=default) to disable or time in ms
* @return bool true on success
*/
SocketReceiveTimeout,
/**
* This option specifies the minimum amount of data required in the send buffer before starting to
* send it. This is a wrapper for setting SO_SNDLOWAT.
*
* @note this can probably block the extension, use it with caution!
*
* @param cell_t size in bytes
* @return bool true on success
*/
SocketSendLowWatermark,
/**
* This option specifies how long a socket will try to send data before it times out and
* retries it later. This is a wrapper for setting SO_SNDTIMEO.
*
* @param cell_t 0 (=default) to disable or time in ms
* @return bool true on success
*/
SocketSendTimeout,
/**
* If this option is set the socket extension will display debugging messages in the server console/logs.
*
* @param bool whether to enable debugging or not
* @return bool true on success
*/
DebugMode
}
/*************************************************************************************************/
/******************************************* callbacks *******************************************/
/*************************************************************************************************/
/**
* triggered if a normal sockets finished connecting and is ready to be used
*
* @param socket The socket handle pointing to the calling socket
* @param arg The argument set by SocketSetArg()
* @noreturn
*/
funcenum SocketConnectCB
{
public(Handle:socket, any:arg)
};
/**
* triggered if a listening socket received an incoming connection and is ready to be used
*
* @note The child-socket won't work until receive-, disconnect-, and errorcallback for it are set.
*
* @param Handle socket The socket handle pointing to the calling listen-socket
* @param Handle newSocket The socket handle to the newly spawned child socket
* @param String remoteIP The remote IP
* @param any arg The argument set by SocketSetArg() for the listen-socket
* @noreturn
*/
funcenum SocketIncomingCB
{
public(Handle:socket, Handle:newSocket, const String:remoteIP[], remotePort, any:arg)
};
/**
* triggered if a socket receives data
*
* @note This is binary safe if you always use dataSize for operations on receiveData[]
* @note packets may be split up into multiple chunks -> multiple calls to the receive callback
* @note if not set otherwise by SocketSetOption(..., ConcatenateCallbacks, ...) receiveData will
* never be longer than 4096 characters including \0 terminator
*
* @param Handle socket The socket handle pointing to the calling socket
* @param String receiveData The data which arrived, 0-terminated at receiveData[dataSize]
* @param cell_t dataSize The length of the arrived data excluding the 0-termination
* @param any arg The argument set by SocketSetArg() for the socket
* @noreturn
*/
funcenum SocketReceiveCB
{
public(Handle:socket, const String:receiveData[], const dataSize, any:arg)
};
/**
* called after a socket sent all items in its send queue successfully
*
* @param Handle socket The socket handle pointing to the calling socket
* @param any arg The argument set by SocketSetArg() for the socket
* @noreturn
*/
funcenum SocketSendqueueEmptyCB
{
public(Handle:socket, any:arg)
};
/**
* called if a socket has been properly disconnected by the remote side
*
* @note You should call CloseHandle(socket) or reuse the socket before this function ends
*
* @param Handle socket The socket handle pointing to the calling socket
* @param any arg The argument set by SocketSetArg() for the socket
* @noreturn
*/
funcenum SocketDisconnectCB
{
public(Handle:socket, any:arg)
};
/**
* called if an unrecoverable error occured, close the socket without an additional call to a disconnect callback
*
* @note You should call CloseHandle(socket) or reuse the socket before this function ends
*
* @param Handle socket The socket handle pointing to the calling socket
* @param cell_t errorType The error type, see defines above
* @param cell_t errorNum The errno, see errno.h for details
* @param any arg The argument set by SocketSetArg() for the socket
* @noreturn
*/
funcenum SocketErrorCB
{
public(Handle:socket, const errorType, const errorNum, any:arg)
};
/*************************************************************************************************/
/******************************************** natives ********************************************/
/*************************************************************************************************/
/**
* Returns whether a socket is connected or not.
*
* @param socket Socket handle to check
* @return bool The connection status
*/
native bool:SocketIsConnected(Handle:socket);
/**
* Creates a new socket.
*
* @note this function may be relatively expensive, reuse sockets if possible
*
* @param SocketType protocol The protocol to use, SOCKET_TCP is default
* @param SocketErrorCB efunc The error callback
* @return Handle The socket handle. Returns INVALID_HANDLE on failure
*/
native Handle:SocketCreate(SocketType:protocol=SOCKET_TCP, SocketErrorCB:efunc);
/**
* Binds the socket to a local address
*
* @param Handle socket The handle of the socket to be used. * @param String hostname The hostname (or IP) to bind the socket to.
* @param cell_t port The port to bind the socket to.
* @return bool true on success
*/
native bool:SocketBind(Handle:socket, const String:hostname[], port);
/**
* Connects a socket
*
* @note this native is threaded, it may be still running after it executed, use the connect callback
* @note invokes the SocketError callback with errorType = CONNECT_ERROR or EMPTY_HOST if it fails
* @note invokes the SocketConnect callback if it succeeds
*
* @param Handle socket The handle of the socket to be used.
* @param SocketConnectCB cfunc The connect callback
* @param SocketReceiveCB rfunc The receive callback
* @param SocketDisconnectCB dfunc The disconnect callback * @param String hostname The hostname (or IP) to connect to.
* @param cell_t port The port to connect to.
* @noreturn
*/
native SocketConnect(Handle:socket, SocketConnectCB:cfunc, SocketReceiveCB:rfunc, SocketDisconnectCB:dfunc, const String:hostname[], port);
/**
* Disconnects a socket
*
* @note this will not close the handle, the socket will be reset to a state similar to after SocketCreate()
* @note this won't trigger any disconnect/error callbacks
*
* @noreturn
*/
native bool:SocketDisconnect(Handle:socket);
/**
* Makes a socket listen for incoming connections
*
* @param Handle socket The handle of the socket to be used.
* @param SocketIncomingCB ifunc The callback for incoming connections
* @return bool true on success
*/
native bool:SocketListen(Handle:socket, SocketIncomingCB:ifunc);
/**
* Sends data through the socket.
*
* @note specify size for binary safe operation
* @note if size is not specified the \0 terminator will not be included
* @note This native is threaded, it may be still running after it executed (not atomic).
* @note Use the SendqueueEmpty callback to determine when all data has been successfully sent.
* @note The socket extension will ensure that the data will be send in the correct order and split
* the data if required.
*
* @param Handle socket The handle of the socket to be used.
* @param String data The data to send.
* @noreturn */
native SocketSend(Handle:socket, const String:data[], size=-1);
/** * Sends UDP data through the socket to a specific destination.
*
* @note specify size for binary safe operation
* @note if size is not specified the \0 terminator will not be included
* @note This native is threaded, it may be still running after it executed (not atomic).
* @note Use the SendqueueEmpty callback to determine when all data has been successfully sent.
* @note The socket extension will ensure that the data will be send in the correct order and split
* the data if required.
*
* @param Handle socket The handle of the socket to be used.
* @param String data The data to send.
* @param String hostname The hostname (or IP) to send to.
* @param cell_t port The port to send to.
* @noreturn */
native SocketSendTo(Handle:socket, const String:data[], size=-1, const String:hostname[], port);
/**
* Set a socket option.
*
* @param Handle socket The handle of the socket to be used. May be INVALID_HANDLE if not essential.
* @param SocketOption option The option to modify (see enum SocketOption for details).
* @param cellt_ value The value to set the option to.
* @return cell_t 1 on success. */
native SocketSetOption(Handle:socket, SocketOption:option, value);
/**
* Defines the callback function for when the socket receives data
*
* @note this is only useful and required for child-sockets spawned by listen-sockets
* (otherwise you already set it in SocketConnect())
*
* @param Handle socket The handle of the socket to be used.
* @param SocketReceiveCB rfunc The receive callback
* @noreturn
*/
native SocketSetReceiveCallback(Handle:socket, SocketReceiveCB:rfunc);
/**
* Defines the callback function for when the socket sent all items in its send queue
*
* @note this must be called AFTER sending (queueing) the data
* @note if no send-data is queued this will fire the callback itself
* @note the callback is guaranteed to fire
*
* @param Handle socket The handle of the socket to be used.
* @param SocketDisconnectCB dfunc The disconnect callback
* @noreturn
*/
native SocketSetSendqueueEmptyCallback(Handle:socket, SocketSendqueueEmptyCB:sfunc);
/**
* Defines the callback function for when the socket was properly disconnected by the remote side
*
* @note this is only useful and required for child-sockets spawned by listen-sockets
* (otherwise you already set it in SocketConnect())
*
* @param Handle socket The handle of the socket to be used.
* @param SocketDisconnectCB dfunc The disconnect callback
* @noreturn
*/
native SocketSetDisconnectCallback(Handle:socket, SocketDisconnectCB:dfunc);
/**
* Defines the callback function for when the socket triggered an error
*
* @note this is only useful and required for child-sockets spawned by listen-sockets
* (otherwise you already set it in SocketCreate())
*
* @param Handle socket The handle of the socket to be used.
* @param SocketErrorCB efunc The error callback
* @noreturn
*/
native SocketSetErrorCallback(Handle:socket, SocketErrorCB:efunc);
/**
* Sets the argument being passed to callbacks
*
* @param Handle socket The handle of the socket to be used.
* @param any arg The argument to set
* @noreturn
*/
native SocketSetArg(Handle:socket, any:arg);
/**
* Retrieve the local system's hostname as the command "hostname" does.
*
* @param dest Destination string buffer to copy to.
* @param destLen Destination buffer length (includes null terminator).
*
* @return 1 on success
*/
native SocketGetHostName(String:dest[], destLen);
/**
* _________________Do not edit below this line!_______________________
*/
public Extension:__ext_smsock =
{
name = "Socket",
file = "socket.ext",
#if defined AUTOLOAD_EXTENSIONS
autoload = 1,
#else
autoload = 0,
#endif
#if defined REQUIRE_EXTENSIONS
required = 1,
#else
required = 0,
#endif
};