sfml3-rb 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +9 -0
- data/CHANGELOG.md +43 -17
- data/README.md +97 -29
- data/ext/audio/audio_enums.c +58 -20
- data/ext/audio/listener.c +89 -6
- data/ext/audio/music.c +206 -5
- data/ext/audio/sound.c +175 -5
- data/ext/audio/sound_buffer.c +189 -47
- data/ext/audio/sound_buffer_recorder.c +83 -16
- data/ext/audio/sound_recorder.c +172 -52
- data/ext/audio/sound_source_cone.c +108 -29
- data/ext/audio/sound_stream.c +178 -5
- data/ext/core/exceptions.c +10 -8
- data/ext/core/unicode.c +12 -2
- data/ext/ext.c +4 -0
- data/ext/graphics/blend_mode.c +203 -53
- data/ext/graphics/circle.c +271 -4
- data/ext/graphics/color.c +240 -90
- data/ext/graphics/drawable.c +15 -4
- data/ext/graphics/font.c +138 -25
- data/ext/graphics/glyph.c +31 -8
- data/ext/graphics/image.c +180 -37
- data/ext/graphics/polygon.c +293 -26
- data/ext/graphics/rect.c +211 -54
- data/ext/graphics/rectangle.c +279 -26
- data/ext/graphics/render_state.c +116 -2
- data/ext/graphics/render_texture.c +163 -2
- data/ext/graphics/shader.c +283 -17
- data/ext/graphics/shape.c +252 -26
- data/ext/graphics/sprite.c +216 -25
- data/ext/graphics/stencil_mode.c +148 -39
- data/ext/graphics/target.c +67 -22
- data/ext/graphics/target.h +15 -15
- data/ext/graphics/text.c +306 -6
- data/ext/graphics/texture.c +257 -3
- data/ext/graphics/transform.c +178 -5
- data/ext/graphics/transformable.c +126 -2
- data/ext/graphics/vertex.c +79 -2
- data/ext/graphics/vertex_array.c +128 -16
- data/ext/graphics/vertex_buffer.c +124 -2
- data/ext/graphics/view.c +130 -2
- data/ext/network/ftp.c +249 -10
- data/ext/network/http.c +156 -38
- data/ext/network/ip_address.c +107 -26
- data/ext/network/network_enums.c +248 -141
- data/ext/network/packet.c +273 -39
- data/ext/network/socket_selector.c +91 -19
- data/ext/network/tcp_listener.c +75 -16
- data/ext/network/tcp_socket.c +128 -25
- data/ext/network/udp_socket.c +122 -26
- data/ext/ports.rb +7 -0
- data/ext/system/buffer.c +41 -12
- data/ext/system/clock.c +68 -9
- data/ext/system/input_stream.c +94 -42
- data/ext/system/sleep.c +10 -2
- data/ext/system/time.c +172 -34
- data/ext/system/vec2.c +156 -35
- data/ext/system/vec3.c +166 -35
- data/ext/window/clipboard.c +47 -17
- data/ext/window/context.c +59 -9
- data/ext/window/context_settings.c +116 -38
- data/ext/window/cursor.c +39 -9
- data/ext/window/event.c +163 -42
- data/ext/window/joystick.c +69 -3
- data/ext/window/keyboard.c +168 -116
- data/ext/window/mouse.c +36 -2
- data/ext/window/sensor.c +28 -2
- data/ext/window/touch.c +20 -2
- data/ext/window/video_mode.c +90 -19
- data/ext/window/vulkan.c +34 -6
- data/ext/window/window.c +340 -16
- data/lib/sfml/version.rb +1 -1
- data/sig/audio/audio_enums.rbs +30 -0
- data/sig/audio/listener.rbs +16 -0
- data/sig/audio/music.rbs +56 -0
- data/sig/audio/sound.rbs +51 -0
- data/sig/audio/sound_buffer.rbs +17 -0
- data/sig/audio/sound_buffer_recorder.rbs +14 -0
- data/sig/audio/sound_recorder.rbs +17 -0
- data/sig/audio/sound_source_cone.rbs +14 -0
- data/sig/audio/sound_stream.rbs +51 -0
- data/sig/graphics/blend_mode.rbs +29 -0
- data/sig/graphics/circle.rbs +44 -0
- data/sig/graphics/color.rbs +39 -0
- data/sig/graphics/drawable.rbs +5 -0
- data/sig/graphics/font.rbs +20 -0
- data/sig/graphics/glyph.rbs +7 -0
- data/sig/graphics/image.rbs +22 -0
- data/sig/graphics/polygon.rbs +42 -0
- data/sig/graphics/rect.rbs +33 -0
- data/sig/graphics/rectangle.rbs +42 -0
- data/sig/graphics/render_state.rbs +21 -0
- data/sig/graphics/render_texture.rbs +37 -0
- data/sig/graphics/shader.rbs +39 -0
- data/sig/graphics/shape.rbs +38 -0
- data/sig/graphics/sprite.rbs +34 -0
- data/sig/graphics/stencil_mode.rbs +18 -0
- data/sig/graphics/target.rbs +10 -0
- data/sig/graphics/text.rbs +48 -0
- data/sig/graphics/texture.rbs +34 -0
- data/sig/graphics/transform.rbs +37 -0
- data/sig/graphics/transformable.rbs +25 -0
- data/sig/graphics/vertex.rbs +17 -0
- data/sig/graphics/vertex_array.rbs +17 -0
- data/sig/graphics/vertex_buffer.rbs +22 -0
- data/sig/graphics/view.rbs +24 -0
- data/sig/network/ftp.rbs +46 -0
- data/sig/network/http.rbs +27 -0
- data/sig/network/ip_address.rbs +22 -0
- data/sig/network/network_enums.rbs +95 -0
- data/sig/network/packet.rbs +40 -0
- data/sig/network/socket_selector.rbs +14 -0
- data/sig/network/tcp_listener.rbs +13 -0
- data/sig/network/tcp_socket.rbs +18 -0
- data/sig/network/udp_socket.rbs +17 -0
- data/sig/system/buffer.rbs +11 -0
- data/sig/system/clock.rbs +13 -0
- data/sig/system/input_stream.rbs +7 -0
- data/sig/system/sleep.rbs +3 -0
- data/sig/system/time.rbs +28 -0
- data/sig/system/vec2.rbs +26 -0
- data/sig/system/vec3.rbs +27 -0
- data/sig/window/clipboard.rbs +8 -0
- data/sig/window/context.rbs +11 -0
- data/sig/window/context_settings.rbs +20 -0
- data/sig/window/cursor.rbs +6 -0
- data/sig/window/event.rbs +20 -0
- data/sig/window/joystick.rbs +15 -0
- data/sig/window/keyboard.rbs +10 -0
- data/sig/window/mouse.rbs +9 -0
- data/sig/window/sensor.rbs +8 -0
- data/sig/window/touch.rbs +6 -0
- data/sig/window/video_mode.rbs +16 -0
- data/sig/window/vulkan.rbs +7 -0
- data/sig/window/window.rbs +57 -0
- metadata +66 -2
data/ext/network/tcp_listener.c
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
#include "network/tcp_socket.h"
|
|
10
10
|
|
|
11
11
|
typedef struct {
|
|
12
|
-
sfTcpListener
|
|
12
|
+
sfTcpListener* handle;
|
|
13
13
|
} TcpListener;
|
|
14
14
|
|
|
15
15
|
static VALUE rb_cTcpListener;
|
|
16
16
|
|
|
17
|
-
static void TcpListener_free(void
|
|
18
|
-
TcpListener
|
|
17
|
+
static void TcpListener_free(void* ptr) {
|
|
18
|
+
TcpListener* listener = ptr;
|
|
19
19
|
|
|
20
20
|
if (listener->handle != NULL) {
|
|
21
21
|
sfTcpListener_destroy(listener->handle);
|
|
@@ -27,11 +27,10 @@ static void TcpListener_free(void *ptr) {
|
|
|
27
27
|
static const rb_data_type_t TcpListener_data_type = {
|
|
28
28
|
.wrap_struct_name = "SFML::TcpListener",
|
|
29
29
|
.function = {.dmark = NULL, .dfree = TcpListener_free, .dsize = NULL},
|
|
30
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
31
|
-
};
|
|
30
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY};
|
|
32
31
|
|
|
33
|
-
static VALUE TcpListener_wrap(VALUE klass, sfTcpListener
|
|
34
|
-
TcpListener
|
|
32
|
+
static VALUE TcpListener_wrap(VALUE klass, sfTcpListener* handle) {
|
|
33
|
+
TcpListener* ptr;
|
|
35
34
|
|
|
36
35
|
if (handle == NULL) {
|
|
37
36
|
rb_raise(rb_eRuntimeError, "failed to create TCP listener");
|
|
@@ -43,44 +42,100 @@ static VALUE TcpListener_wrap(VALUE klass, sfTcpListener *handle) {
|
|
|
43
42
|
return TypedData_Wrap_Struct(klass, &TcpListener_data_type, ptr);
|
|
44
43
|
}
|
|
45
44
|
|
|
45
|
+
/* call-seq:
|
|
46
|
+
* TcpListener.new -> TcpListener
|
|
47
|
+
*
|
|
48
|
+
* Creates a new TCP listener that is not yet listening.
|
|
49
|
+
*
|
|
50
|
+
* @return [TcpListener]
|
|
51
|
+
*/
|
|
46
52
|
static VALUE TcpListener_new(VALUE klass) {
|
|
47
53
|
return TcpListener_wrap(klass, sfTcpListener_create());
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
/* call-seq:
|
|
57
|
+
* TcpListener.any_port -> Integer
|
|
58
|
+
*
|
|
59
|
+
* Returns the port value that makes #listen bind to an OS-chosen port.
|
|
60
|
+
*
|
|
61
|
+
* @return [Integer] a port value that #listen interprets as "let the OS
|
|
62
|
+
* pick an available port"
|
|
63
|
+
*/
|
|
50
64
|
static VALUE TcpListener_any_port(VALUE klass) {
|
|
51
65
|
return UINT2NUM(sfTcpListener_anyPort());
|
|
52
66
|
}
|
|
53
67
|
|
|
68
|
+
/* call-seq: blocking? -> true or false
|
|
69
|
+
*
|
|
70
|
+
* Returns +true+ if the listener is in blocking mode.
|
|
71
|
+
*
|
|
72
|
+
* @return [Boolean]
|
|
73
|
+
*/
|
|
54
74
|
static VALUE TcpListener_blocking(VALUE self) {
|
|
55
75
|
return BOOL2RB(sfTcpListener_isBlocking(Get_TcpListener_Struct(self)));
|
|
56
76
|
}
|
|
57
77
|
|
|
78
|
+
/* call-seq:
|
|
79
|
+
* blocking=(value) -> value
|
|
80
|
+
*
|
|
81
|
+
* Enables or disables blocking mode according to +value+.
|
|
82
|
+
*
|
|
83
|
+
* @return [Boolean] +value+
|
|
84
|
+
*/
|
|
58
85
|
static VALUE TcpListener_set_blocking(VALUE self, VALUE rb_value) {
|
|
59
86
|
sfTcpListener_setBlocking(Get_TcpListener_Struct(self), RTEST(rb_value));
|
|
60
87
|
return rb_value;
|
|
61
88
|
}
|
|
62
89
|
|
|
90
|
+
/* call-seq: local_port -> Integer
|
|
91
|
+
*
|
|
92
|
+
* Returns the port the listener is bound to, or 0 if it isn't listening.
|
|
93
|
+
*
|
|
94
|
+
* @return [Integer] the port the listener is bound to, or 0 if it isn't
|
|
95
|
+
* listening
|
|
96
|
+
*/
|
|
63
97
|
static VALUE TcpListener_local_port(VALUE self) {
|
|
64
98
|
return UINT2NUM(sfTcpListener_getLocalPort(Get_TcpListener_Struct(self)));
|
|
65
99
|
}
|
|
66
100
|
|
|
67
|
-
|
|
101
|
+
/* call-seq:
|
|
102
|
+
* listen(port, address = IpAddress::ANY) -> Symbol
|
|
103
|
+
*
|
|
104
|
+
* Starts listening for incoming connections on +port+, optionally
|
|
105
|
+
* restricted to a specific local network interface via +address+.
|
|
106
|
+
*
|
|
107
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
108
|
+
*/
|
|
109
|
+
static VALUE TcpListener_listen(int argc, VALUE* argv, VALUE self) {
|
|
68
110
|
VALUE rb_port, rb_address;
|
|
69
111
|
|
|
70
112
|
rb_scan_args(argc, argv, "11", &rb_port, &rb_address);
|
|
71
113
|
|
|
72
|
-
return ID2SYM(rb_intern(socket_status_name(
|
|
73
|
-
Get_TcpListener_Struct(self), (unsigned short)
|
|
74
|
-
|
|
114
|
+
return ID2SYM(rb_intern(socket_status_name(
|
|
115
|
+
sfTcpListener_listen(Get_TcpListener_Struct(self), (unsigned short)NUM2INT(rb_port),
|
|
116
|
+
ip_address_from_rb(rb_address, sfIpAddress_Any)))));
|
|
75
117
|
}
|
|
76
118
|
|
|
119
|
+
/* call-seq: close -> self
|
|
120
|
+
*
|
|
121
|
+
* Stops listening and closes the underlying socket.
|
|
122
|
+
*
|
|
123
|
+
* @return [self]
|
|
124
|
+
*/
|
|
77
125
|
static VALUE TcpListener_close(VALUE self) {
|
|
78
126
|
sfTcpListener_close(Get_TcpListener_Struct(self));
|
|
79
127
|
return self;
|
|
80
128
|
}
|
|
81
129
|
|
|
130
|
+
/* call-seq: accept -> [TcpSocket, Symbol]
|
|
131
|
+
*
|
|
132
|
+
* Blocks (unless #blocking? is +false+) waiting for a client to connect.
|
|
133
|
+
*
|
|
134
|
+
* @return [Array(TcpSocket, Symbol)] the connected socket (or +nil+ if the
|
|
135
|
+
* status isn't +:done+), and a SocketStatus name
|
|
136
|
+
*/
|
|
82
137
|
static VALUE TcpListener_accept(VALUE self) {
|
|
83
|
-
sfTcpSocket
|
|
138
|
+
sfTcpSocket* socket = NULL;
|
|
84
139
|
sfSocketStatus status = sfTcpListener_accept(Get_TcpListener_Struct(self), &socket);
|
|
85
140
|
VALUE rb_result = rb_ary_new_capa(2);
|
|
86
141
|
|
|
@@ -90,8 +145,12 @@ static VALUE TcpListener_accept(VALUE self) {
|
|
|
90
145
|
return rb_result;
|
|
91
146
|
}
|
|
92
147
|
|
|
93
|
-
|
|
94
|
-
|
|
148
|
+
/* Document-class: SFML::TcpListener
|
|
149
|
+
* Listens for and accepts incoming TCP connections, producing connected
|
|
150
|
+
* TcpSocket instances.
|
|
151
|
+
*/
|
|
152
|
+
void Init_TcpListener(VALUE rb_mSFML) {
|
|
153
|
+
rb_cTcpListener = rb_define_class_under(rb_mSFML, "TcpListener", rb_cObject);
|
|
95
154
|
|
|
96
155
|
rb_define_singleton_method(rb_cTcpListener, "new", TcpListener_new, 0);
|
|
97
156
|
rb_define_singleton_method(rb_cTcpListener, "any_port", TcpListener_any_port, 0);
|
|
@@ -108,8 +167,8 @@ VALUE Get_Klass_TcpListener(void) {
|
|
|
108
167
|
return rb_cTcpListener;
|
|
109
168
|
}
|
|
110
169
|
|
|
111
|
-
void
|
|
112
|
-
TcpListener
|
|
170
|
+
void* Get_TcpListener_Struct(VALUE self) {
|
|
171
|
+
TcpListener* ptr;
|
|
113
172
|
TypedData_Get_Struct(self, TcpListener, &TcpListener_data_type, ptr);
|
|
114
173
|
return ptr->handle;
|
|
115
174
|
}
|
data/ext/network/tcp_socket.c
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
#include "system/time.h"
|
|
11
11
|
|
|
12
12
|
typedef struct {
|
|
13
|
-
sfTcpSocket
|
|
13
|
+
sfTcpSocket* handle;
|
|
14
14
|
} TcpSocket;
|
|
15
15
|
|
|
16
16
|
static VALUE rb_cTcpSocket;
|
|
17
17
|
|
|
18
|
-
static void TcpSocket_free(void
|
|
19
|
-
TcpSocket
|
|
18
|
+
static void TcpSocket_free(void* ptr) {
|
|
19
|
+
TcpSocket* socket = ptr;
|
|
20
20
|
|
|
21
21
|
if (socket->handle != NULL) {
|
|
22
22
|
sfTcpSocket_destroy(socket->handle);
|
|
@@ -28,11 +28,10 @@ static void TcpSocket_free(void *ptr) {
|
|
|
28
28
|
static const rb_data_type_t TcpSocket_data_type = {
|
|
29
29
|
.wrap_struct_name = "SFML::TcpSocket",
|
|
30
30
|
.function = {.dmark = NULL, .dfree = TcpSocket_free, .dsize = NULL},
|
|
31
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
32
|
-
};
|
|
31
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY};
|
|
33
32
|
|
|
34
|
-
static VALUE TcpSocket_wrap(VALUE klass, sfTcpSocket
|
|
35
|
-
TcpSocket
|
|
33
|
+
static VALUE TcpSocket_wrap(VALUE klass, sfTcpSocket* handle) {
|
|
34
|
+
TcpSocket* ptr;
|
|
36
35
|
|
|
37
36
|
if (handle == NULL) {
|
|
38
37
|
rb_raise(rb_eRuntimeError, "failed to create TCP socket");
|
|
@@ -44,36 +43,84 @@ static VALUE TcpSocket_wrap(VALUE klass, sfTcpSocket *handle) {
|
|
|
44
43
|
return TypedData_Wrap_Struct(klass, &TcpSocket_data_type, ptr);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
VALUE tcp_socket_from_handle(sfTcpSocket
|
|
46
|
+
VALUE tcp_socket_from_handle(sfTcpSocket* socket) {
|
|
48
47
|
return TcpSocket_wrap(rb_cTcpSocket, socket);
|
|
49
48
|
}
|
|
50
49
|
|
|
50
|
+
/* call-seq:
|
|
51
|
+
* TcpSocket.new -> TcpSocket
|
|
52
|
+
*
|
|
53
|
+
* Creates a new, unconnected TCP socket.
|
|
54
|
+
*
|
|
55
|
+
* @return [TcpSocket] a new, unconnected socket
|
|
56
|
+
*/
|
|
51
57
|
static VALUE TcpSocket_new(VALUE klass) {
|
|
52
58
|
return TcpSocket_wrap(klass, sfTcpSocket_create());
|
|
53
59
|
}
|
|
54
60
|
|
|
61
|
+
/* call-seq: blocking? -> true or false
|
|
62
|
+
*
|
|
63
|
+
* Returns +true+ if the socket is in blocking mode.
|
|
64
|
+
*
|
|
65
|
+
* @return [Boolean]
|
|
66
|
+
*/
|
|
55
67
|
static VALUE TcpSocket_blocking(VALUE self) {
|
|
56
68
|
return BOOL2RB(sfTcpSocket_isBlocking(Get_TcpSocket_Struct(self)));
|
|
57
69
|
}
|
|
58
70
|
|
|
71
|
+
/* call-seq:
|
|
72
|
+
* blocking=(value) -> value
|
|
73
|
+
*
|
|
74
|
+
* Enables or disables blocking mode according to +value+.
|
|
75
|
+
*
|
|
76
|
+
* @return [Boolean] +value+
|
|
77
|
+
*/
|
|
59
78
|
static VALUE TcpSocket_set_blocking(VALUE self, VALUE rb_value) {
|
|
60
79
|
sfTcpSocket_setBlocking(Get_TcpSocket_Struct(self), RTEST(rb_value));
|
|
61
80
|
return rb_value;
|
|
62
81
|
}
|
|
63
82
|
|
|
83
|
+
/* call-seq: local_port -> Integer
|
|
84
|
+
*
|
|
85
|
+
* Returns the local port the socket is bound to.
|
|
86
|
+
*
|
|
87
|
+
* @return [Integer] the local port the socket is bound to, or 0 if it
|
|
88
|
+
* isn't connected
|
|
89
|
+
*/
|
|
64
90
|
static VALUE TcpSocket_local_port(VALUE self) {
|
|
65
91
|
return UINT2NUM(sfTcpSocket_getLocalPort(Get_TcpSocket_Struct(self)));
|
|
66
92
|
}
|
|
67
93
|
|
|
94
|
+
/* call-seq: remote_address -> IpAddress
|
|
95
|
+
*
|
|
96
|
+
* Returns the address of the remote peer.
|
|
97
|
+
*
|
|
98
|
+
* @return [IpAddress] the address of the remote peer, or +IpAddress::NONE+
|
|
99
|
+
* if not connected
|
|
100
|
+
*/
|
|
68
101
|
static VALUE TcpSocket_remote_address(VALUE self) {
|
|
69
102
|
return ip_address_to_rb(sfTcpSocket_getRemoteAddress(Get_TcpSocket_Struct(self)));
|
|
70
103
|
}
|
|
71
104
|
|
|
105
|
+
/* call-seq: remote_port -> Integer
|
|
106
|
+
*
|
|
107
|
+
* Returns the port of the remote peer.
|
|
108
|
+
*
|
|
109
|
+
* @return [Integer] the port of the remote peer, or 0 if not connected
|
|
110
|
+
*/
|
|
72
111
|
static VALUE TcpSocket_remote_port(VALUE self) {
|
|
73
112
|
return UINT2NUM(sfTcpSocket_getRemotePort(Get_TcpSocket_Struct(self)));
|
|
74
113
|
}
|
|
75
114
|
|
|
76
|
-
|
|
115
|
+
/* call-seq:
|
|
116
|
+
* connect(address, port, timeout = Time.zero) -> Symbol
|
|
117
|
+
*
|
|
118
|
+
* Connects to a remote peer, blocking (unless #blocking? is +false+) until
|
|
119
|
+
* connected or +timeout+ elapses.
|
|
120
|
+
*
|
|
121
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
122
|
+
*/
|
|
123
|
+
static VALUE TcpSocket_connect(int argc, VALUE* argv, VALUE self) {
|
|
77
124
|
VALUE rb_address, rb_port, rb_timeout;
|
|
78
125
|
sfTime timeout = sfTime_Zero;
|
|
79
126
|
|
|
@@ -85,22 +132,45 @@ static VALUE TcpSocket_connect(int argc, VALUE *argv, VALUE self) {
|
|
|
85
132
|
|
|
86
133
|
return ID2SYM(rb_intern(socket_status_name(sfTcpSocket_connect(
|
|
87
134
|
Get_TcpSocket_Struct(self), ip_address_from_rb(rb_address, sfIpAddress_None),
|
|
88
|
-
(unsigned short)
|
|
135
|
+
(unsigned short)NUM2INT(rb_port), timeout))));
|
|
89
136
|
}
|
|
90
137
|
|
|
138
|
+
/* call-seq: disconnect -> self
|
|
139
|
+
*
|
|
140
|
+
* Closes the connection.
|
|
141
|
+
*
|
|
142
|
+
* @return [self]
|
|
143
|
+
*/
|
|
91
144
|
static VALUE TcpSocket_disconnect(VALUE self) {
|
|
92
145
|
sfTcpSocket_disconnect(Get_TcpSocket_Struct(self));
|
|
93
146
|
return self;
|
|
94
147
|
}
|
|
95
148
|
|
|
149
|
+
/* call-seq:
|
|
150
|
+
* send(data) -> Symbol
|
|
151
|
+
*
|
|
152
|
+
* Sends the full contents of +data+, blocking (unless #blocking? is
|
|
153
|
+
* +false+) until it is all sent. Prefer #send_partial for non-blocking
|
|
154
|
+
* sockets, since this can return +:not_ready+ having sent only part of
|
|
155
|
+
* the data with no way to know how much.
|
|
156
|
+
*
|
|
157
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
158
|
+
*/
|
|
96
159
|
static VALUE TcpSocket_send(VALUE self, VALUE rb_data) {
|
|
97
160
|
StringValue(rb_data);
|
|
98
161
|
|
|
99
|
-
return ID2SYM(rb_intern(socket_status_name(
|
|
100
|
-
|
|
101
|
-
(size_t) RSTRING_LEN(rb_data)))));
|
|
162
|
+
return ID2SYM(rb_intern(socket_status_name(sfTcpSocket_send(
|
|
163
|
+
Get_TcpSocket_Struct(self), RSTRING_PTR(rb_data), (size_t)RSTRING_LEN(rb_data)))));
|
|
102
164
|
}
|
|
103
165
|
|
|
166
|
+
/* call-seq:
|
|
167
|
+
* send_partial(data) -> [Integer, Symbol]
|
|
168
|
+
*
|
|
169
|
+
* Like #send, but may send only part of +data+ and reports how much.
|
|
170
|
+
*
|
|
171
|
+
* @return [Array(Integer, Symbol)] the number of bytes actually sent, and
|
|
172
|
+
* a SocketStatus name
|
|
173
|
+
*/
|
|
104
174
|
static VALUE TcpSocket_send_partial(VALUE self, VALUE rb_data) {
|
|
105
175
|
size_t sent = 0;
|
|
106
176
|
sfSocketStatus status;
|
|
@@ -109,7 +179,7 @@ static VALUE TcpSocket_send_partial(VALUE self, VALUE rb_data) {
|
|
|
109
179
|
StringValue(rb_data);
|
|
110
180
|
|
|
111
181
|
status = sfTcpSocket_sendPartial(Get_TcpSocket_Struct(self), RSTRING_PTR(rb_data),
|
|
112
|
-
(size_t)
|
|
182
|
+
(size_t)RSTRING_LEN(rb_data), &sent);
|
|
113
183
|
|
|
114
184
|
rb_result = rb_ary_new_capa(2);
|
|
115
185
|
rb_ary_push(rb_result, SIZET2NUM(sent));
|
|
@@ -118,12 +188,19 @@ static VALUE TcpSocket_send_partial(VALUE self, VALUE rb_data) {
|
|
|
118
188
|
return rb_result;
|
|
119
189
|
}
|
|
120
190
|
|
|
121
|
-
/*
|
|
122
|
-
|
|
123
|
-
|
|
191
|
+
/* call-seq:
|
|
192
|
+
* receive(max_length = 1024) -> [String, Symbol]
|
|
193
|
+
*
|
|
194
|
+
* Receive needs a maximum size up front because CSFML fills a caller buffer.
|
|
195
|
+
* Returns [data, status], where data is empty unless the status is :done.
|
|
196
|
+
*
|
|
197
|
+
* @return [Array(String, Symbol)] the bytes received, and a SocketStatus name
|
|
198
|
+
* @raise [ArgumentError] if +max_length+ isn't positive
|
|
199
|
+
*/
|
|
200
|
+
static VALUE TcpSocket_receive(int argc, VALUE* argv, VALUE self) {
|
|
124
201
|
VALUE rb_max_length;
|
|
125
202
|
long max_length = 1024;
|
|
126
|
-
char
|
|
203
|
+
char* buffer;
|
|
127
204
|
size_t received = 0;
|
|
128
205
|
sfSocketStatus status;
|
|
129
206
|
VALUE rb_result;
|
|
@@ -138,12 +215,16 @@ static VALUE TcpSocket_receive(int argc, VALUE *argv, VALUE self) {
|
|
|
138
215
|
rb_raise(rb_eArgError, "maximum length must be positive");
|
|
139
216
|
}
|
|
140
217
|
|
|
141
|
-
buffer = malloc((size_t)
|
|
218
|
+
buffer = malloc((size_t)max_length);
|
|
219
|
+
|
|
220
|
+
if (buffer == NULL) {
|
|
221
|
+
rb_raise(rb_eNoMemError, "failed to allocate receive buffer");
|
|
222
|
+
}
|
|
142
223
|
|
|
143
|
-
status = sfTcpSocket_receive(Get_TcpSocket_Struct(self), buffer, (size_t)
|
|
224
|
+
status = sfTcpSocket_receive(Get_TcpSocket_Struct(self), buffer, (size_t)max_length, &received);
|
|
144
225
|
|
|
145
226
|
rb_result = rb_ary_new_capa(2);
|
|
146
|
-
rb_ary_push(rb_result, rb_str_new(buffer, (long)
|
|
227
|
+
rb_ary_push(rb_result, rb_str_new(buffer, (long)received));
|
|
147
228
|
rb_ary_push(rb_result, ID2SYM(rb_intern(socket_status_name(status))));
|
|
148
229
|
|
|
149
230
|
free(buffer);
|
|
@@ -151,6 +232,14 @@ static VALUE TcpSocket_receive(int argc, VALUE *argv, VALUE self) {
|
|
|
151
232
|
return rb_result;
|
|
152
233
|
}
|
|
153
234
|
|
|
235
|
+
/* call-seq:
|
|
236
|
+
* send_packet(packet) -> Symbol
|
|
237
|
+
*
|
|
238
|
+
* Sends +packet+ over the connection.
|
|
239
|
+
*
|
|
240
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
241
|
+
* @raise [TypeError] if +packet+ is not an SFML::Packet
|
|
242
|
+
*/
|
|
154
243
|
static VALUE TcpSocket_send_packet(VALUE self, VALUE rb_packet) {
|
|
155
244
|
if (!rb_obj_is_kind_of(rb_packet, Get_Klass_Packet())) {
|
|
156
245
|
rb_raise(rb_eTypeError, "expected an SFML::Packet");
|
|
@@ -160,6 +249,15 @@ static VALUE TcpSocket_send_packet(VALUE self, VALUE rb_packet) {
|
|
|
160
249
|
sfTcpSocket_sendPacket(Get_TcpSocket_Struct(self), Get_Packet_Struct(rb_packet)))));
|
|
161
250
|
}
|
|
162
251
|
|
|
252
|
+
/* call-seq:
|
|
253
|
+
* receive_packet(packet) -> Symbol
|
|
254
|
+
*
|
|
255
|
+
* Fills +packet+ (replacing its previous contents) with the next packet
|
|
256
|
+
* received.
|
|
257
|
+
*
|
|
258
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
259
|
+
* @raise [TypeError] if +packet+ is not an SFML::Packet
|
|
260
|
+
*/
|
|
163
261
|
static VALUE TcpSocket_receive_packet(VALUE self, VALUE rb_packet) {
|
|
164
262
|
if (!rb_obj_is_kind_of(rb_packet, Get_Klass_Packet())) {
|
|
165
263
|
rb_raise(rb_eTypeError, "expected an SFML::Packet");
|
|
@@ -169,8 +267,13 @@ static VALUE TcpSocket_receive_packet(VALUE self, VALUE rb_packet) {
|
|
|
169
267
|
sfTcpSocket_receivePacket(Get_TcpSocket_Struct(self), Get_Packet_Struct(rb_packet)))));
|
|
170
268
|
}
|
|
171
269
|
|
|
172
|
-
|
|
173
|
-
|
|
270
|
+
/* Document-class: SFML::TcpSocket
|
|
271
|
+
* A connection-oriented, reliable, byte-stream socket for TCP communication.
|
|
272
|
+
* Connect with #connect (or receive one already connected from
|
|
273
|
+
* TcpListener#accept), then send/receive raw bytes or Packet instances.
|
|
274
|
+
*/
|
|
275
|
+
void Init_TcpSocket(VALUE rb_mSFML) {
|
|
276
|
+
rb_cTcpSocket = rb_define_class_under(rb_mSFML, "TcpSocket", rb_cObject);
|
|
174
277
|
|
|
175
278
|
rb_define_singleton_method(rb_cTcpSocket, "new", TcpSocket_new, 0);
|
|
176
279
|
|
|
@@ -192,8 +295,8 @@ VALUE Get_Klass_TcpSocket(void) {
|
|
|
192
295
|
return rb_cTcpSocket;
|
|
193
296
|
}
|
|
194
297
|
|
|
195
|
-
void
|
|
196
|
-
TcpSocket
|
|
298
|
+
void* Get_TcpSocket_Struct(VALUE self) {
|
|
299
|
+
TcpSocket* ptr;
|
|
197
300
|
TypedData_Get_Struct(self, TcpSocket, &TcpSocket_data_type, ptr);
|
|
198
301
|
return ptr->handle;
|
|
199
302
|
}
|
data/ext/network/udp_socket.c
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
#include "network/packet.h"
|
|
10
10
|
|
|
11
11
|
typedef struct {
|
|
12
|
-
sfUdpSocket
|
|
12
|
+
sfUdpSocket* handle;
|
|
13
13
|
} UdpSocket;
|
|
14
14
|
|
|
15
15
|
static VALUE rb_cUdpSocket;
|
|
16
16
|
|
|
17
|
-
static void UdpSocket_free(void
|
|
18
|
-
UdpSocket
|
|
17
|
+
static void UdpSocket_free(void* ptr) {
|
|
18
|
+
UdpSocket* socket = ptr;
|
|
19
19
|
|
|
20
20
|
if (socket->handle != NULL) {
|
|
21
21
|
sfUdpSocket_destroy(socket->handle);
|
|
@@ -27,11 +27,10 @@ static void UdpSocket_free(void *ptr) {
|
|
|
27
27
|
static const rb_data_type_t UdpSocket_data_type = {
|
|
28
28
|
.wrap_struct_name = "SFML::UdpSocket",
|
|
29
29
|
.function = {.dmark = NULL, .dfree = UdpSocket_free, .dsize = NULL},
|
|
30
|
-
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
31
|
-
};
|
|
30
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY};
|
|
32
31
|
|
|
33
|
-
static VALUE UdpSocket_wrap(VALUE klass, sfUdpSocket
|
|
34
|
-
UdpSocket
|
|
32
|
+
static VALUE UdpSocket_wrap(VALUE klass, sfUdpSocket* handle) {
|
|
33
|
+
UdpSocket* ptr;
|
|
35
34
|
|
|
36
35
|
if (handle == NULL) {
|
|
37
36
|
rb_raise(rb_eRuntimeError, "failed to create UDP socket");
|
|
@@ -43,60 +42,131 @@ static VALUE UdpSocket_wrap(VALUE klass, sfUdpSocket *handle) {
|
|
|
43
42
|
return TypedData_Wrap_Struct(klass, &UdpSocket_data_type, ptr);
|
|
44
43
|
}
|
|
45
44
|
|
|
45
|
+
/* call-seq:
|
|
46
|
+
* UdpSocket.new -> UdpSocket
|
|
47
|
+
*
|
|
48
|
+
* Creates a new, unbound UDP socket.
|
|
49
|
+
*
|
|
50
|
+
* @return [UdpSocket] a new, unbound socket
|
|
51
|
+
*/
|
|
46
52
|
static VALUE UdpSocket_new(VALUE klass) {
|
|
47
53
|
return UdpSocket_wrap(klass, sfUdpSocket_create());
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
/* call-seq:
|
|
57
|
+
* UdpSocket.any_port -> Integer
|
|
58
|
+
*
|
|
59
|
+
* Returns the port value that makes #bind bind to an OS-chosen port.
|
|
60
|
+
*
|
|
61
|
+
* @return [Integer] a port value that #bind interprets as "let the OS pick
|
|
62
|
+
* an available port"
|
|
63
|
+
*/
|
|
50
64
|
static VALUE UdpSocket_any_port(VALUE klass) {
|
|
51
65
|
return UINT2NUM(sfUdpSocket_anyPort());
|
|
52
66
|
}
|
|
53
67
|
|
|
68
|
+
/* call-seq:
|
|
69
|
+
* UdpSocket.max_datagram_size -> Integer
|
|
70
|
+
*
|
|
71
|
+
* Returns the maximum size, in bytes, of a single UDP datagram.
|
|
72
|
+
*
|
|
73
|
+
* @return [Integer] the maximum number of bytes that can be sent in a
|
|
74
|
+
* single UDP datagram (65507)
|
|
75
|
+
*/
|
|
54
76
|
static VALUE UdpSocket_max_datagram_size(VALUE klass) {
|
|
55
77
|
return UINT2NUM(sfUdpSocket_maxDatagramSize());
|
|
56
78
|
}
|
|
57
79
|
|
|
80
|
+
/* call-seq: blocking? -> true or false
|
|
81
|
+
*
|
|
82
|
+
* Returns +true+ if the socket is in blocking mode.
|
|
83
|
+
*
|
|
84
|
+
* @return [Boolean]
|
|
85
|
+
*/
|
|
58
86
|
static VALUE UdpSocket_blocking(VALUE self) {
|
|
59
87
|
return BOOL2RB(sfUdpSocket_isBlocking(Get_UdpSocket_Struct(self)));
|
|
60
88
|
}
|
|
61
89
|
|
|
90
|
+
/* call-seq:
|
|
91
|
+
* blocking=(value) -> value
|
|
92
|
+
*
|
|
93
|
+
* Enables or disables blocking mode according to +value+.
|
|
94
|
+
*
|
|
95
|
+
* @return [Boolean] +value+
|
|
96
|
+
*/
|
|
62
97
|
static VALUE UdpSocket_set_blocking(VALUE self, VALUE rb_value) {
|
|
63
98
|
sfUdpSocket_setBlocking(Get_UdpSocket_Struct(self), RTEST(rb_value));
|
|
64
99
|
return rb_value;
|
|
65
100
|
}
|
|
66
101
|
|
|
102
|
+
/* call-seq: local_port -> Integer
|
|
103
|
+
*
|
|
104
|
+
* Returns the local port the socket is bound to.
|
|
105
|
+
*
|
|
106
|
+
* @return [Integer] the port the socket is bound to, or 0 if not bound
|
|
107
|
+
*/
|
|
67
108
|
static VALUE UdpSocket_local_port(VALUE self) {
|
|
68
109
|
return UINT2NUM(sfUdpSocket_getLocalPort(Get_UdpSocket_Struct(self)));
|
|
69
110
|
}
|
|
70
111
|
|
|
71
|
-
|
|
112
|
+
/* call-seq:
|
|
113
|
+
* bind(port, address = IpAddress::ANY) -> Symbol
|
|
114
|
+
*
|
|
115
|
+
* Binds the socket to a local port, optionally restricted to a specific
|
|
116
|
+
* local network interface via +address+, so it can receive datagrams.
|
|
117
|
+
*
|
|
118
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
119
|
+
*/
|
|
120
|
+
static VALUE UdpSocket_bind(int argc, VALUE* argv, VALUE self) {
|
|
72
121
|
VALUE rb_port, rb_address;
|
|
73
122
|
|
|
74
123
|
rb_scan_args(argc, argv, "11", &rb_port, &rb_address);
|
|
75
124
|
|
|
76
|
-
return ID2SYM(rb_intern(socket_status_name(
|
|
77
|
-
Get_UdpSocket_Struct(self), (unsigned short)
|
|
78
|
-
|
|
125
|
+
return ID2SYM(rb_intern(socket_status_name(
|
|
126
|
+
sfUdpSocket_bind(Get_UdpSocket_Struct(self), (unsigned short)NUM2INT(rb_port),
|
|
127
|
+
ip_address_from_rb(rb_address, sfIpAddress_Any)))));
|
|
79
128
|
}
|
|
80
129
|
|
|
130
|
+
/* call-seq: unbind -> self
|
|
131
|
+
*
|
|
132
|
+
* Unbinds the socket from its local port.
|
|
133
|
+
*
|
|
134
|
+
* @return [self]
|
|
135
|
+
*/
|
|
81
136
|
static VALUE UdpSocket_unbind(VALUE self) {
|
|
82
137
|
sfUdpSocket_unbind(Get_UdpSocket_Struct(self));
|
|
83
138
|
return self;
|
|
84
139
|
}
|
|
85
140
|
|
|
141
|
+
/* call-seq:
|
|
142
|
+
* send(data, address, port) -> Symbol
|
|
143
|
+
*
|
|
144
|
+
* Sends a single datagram to a remote peer. +data+ must be no larger than
|
|
145
|
+
* .max_datagram_size bytes.
|
|
146
|
+
*
|
|
147
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
148
|
+
*/
|
|
86
149
|
static VALUE UdpSocket_send(VALUE self, VALUE rb_data, VALUE rb_address, VALUE rb_port) {
|
|
87
150
|
StringValue(rb_data);
|
|
88
151
|
|
|
89
152
|
return ID2SYM(rb_intern(socket_status_name(sfUdpSocket_send(
|
|
90
|
-
Get_UdpSocket_Struct(self), RSTRING_PTR(rb_data), (size_t)
|
|
91
|
-
ip_address_from_rb(rb_address, sfIpAddress_None), (unsigned short)
|
|
153
|
+
Get_UdpSocket_Struct(self), RSTRING_PTR(rb_data), (size_t)RSTRING_LEN(rb_data),
|
|
154
|
+
ip_address_from_rb(rb_address, sfIpAddress_None), (unsigned short)NUM2INT(rb_port)))));
|
|
92
155
|
}
|
|
93
156
|
|
|
94
|
-
/*
|
|
95
|
-
|
|
96
|
-
|
|
157
|
+
/* call-seq:
|
|
158
|
+
* receive(max_length = 1024) -> [String, IpAddress, Integer, Symbol]
|
|
159
|
+
*
|
|
160
|
+
* Returns [data, IpAddress, port, status]; the address and port are those of
|
|
161
|
+
* the sender.
|
|
162
|
+
*
|
|
163
|
+
* @return [Array(String, IpAddress, Integer, Symbol)]
|
|
164
|
+
* @raise [ArgumentError] if +max_length+ isn't positive
|
|
165
|
+
*/
|
|
166
|
+
static VALUE UdpSocket_receive(int argc, VALUE* argv, VALUE self) {
|
|
97
167
|
VALUE rb_max_length;
|
|
98
168
|
long max_length = 1024;
|
|
99
|
-
char
|
|
169
|
+
char* buffer;
|
|
100
170
|
size_t received = 0;
|
|
101
171
|
sfIpAddress remote_address = sfIpAddress_None;
|
|
102
172
|
unsigned short remote_port = 0;
|
|
@@ -113,13 +183,17 @@ static VALUE UdpSocket_receive(int argc, VALUE *argv, VALUE self) {
|
|
|
113
183
|
rb_raise(rb_eArgError, "maximum length must be positive");
|
|
114
184
|
}
|
|
115
185
|
|
|
116
|
-
buffer = malloc((size_t)
|
|
186
|
+
buffer = malloc((size_t)max_length);
|
|
117
187
|
|
|
118
|
-
|
|
188
|
+
if (buffer == NULL) {
|
|
189
|
+
rb_raise(rb_eNoMemError, "failed to allocate receive buffer");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
status = sfUdpSocket_receive(Get_UdpSocket_Struct(self), buffer, (size_t)max_length, &received,
|
|
119
193
|
&remote_address, &remote_port);
|
|
120
194
|
|
|
121
195
|
rb_result = rb_ary_new_capa(4);
|
|
122
|
-
rb_ary_push(rb_result, rb_str_new(buffer, (long)
|
|
196
|
+
rb_ary_push(rb_result, rb_str_new(buffer, (long)received));
|
|
123
197
|
rb_ary_push(rb_result, ip_address_to_rb(remote_address));
|
|
124
198
|
rb_ary_push(rb_result, UINT2NUM(remote_port));
|
|
125
199
|
rb_ary_push(rb_result, ID2SYM(rb_intern(socket_status_name(status))));
|
|
@@ -129,6 +203,14 @@ static VALUE UdpSocket_receive(int argc, VALUE *argv, VALUE self) {
|
|
|
129
203
|
return rb_result;
|
|
130
204
|
}
|
|
131
205
|
|
|
206
|
+
/* call-seq:
|
|
207
|
+
* send_packet(packet, address, port) -> Symbol
|
|
208
|
+
*
|
|
209
|
+
* Sends +packet+ as a datagram to the given +address+ and +port+.
|
|
210
|
+
*
|
|
211
|
+
* @return [Symbol] a SocketStatus name, +:done+ on success
|
|
212
|
+
* @raise [TypeError] if +packet+ is not an SFML::Packet
|
|
213
|
+
*/
|
|
132
214
|
static VALUE UdpSocket_send_packet(VALUE self, VALUE rb_packet, VALUE rb_address, VALUE rb_port) {
|
|
133
215
|
if (!rb_obj_is_kind_of(rb_packet, Get_Klass_Packet())) {
|
|
134
216
|
rb_raise(rb_eTypeError, "expected an SFML::Packet");
|
|
@@ -136,10 +218,19 @@ static VALUE UdpSocket_send_packet(VALUE self, VALUE rb_packet, VALUE rb_address
|
|
|
136
218
|
|
|
137
219
|
return ID2SYM(rb_intern(socket_status_name(sfUdpSocket_sendPacket(
|
|
138
220
|
Get_UdpSocket_Struct(self), Get_Packet_Struct(rb_packet),
|
|
139
|
-
ip_address_from_rb(rb_address, sfIpAddress_None), (unsigned short)
|
|
221
|
+
ip_address_from_rb(rb_address, sfIpAddress_None), (unsigned short)NUM2INT(rb_port)))));
|
|
140
222
|
}
|
|
141
223
|
|
|
142
|
-
/*
|
|
224
|
+
/* call-seq:
|
|
225
|
+
* receive_packet(packet) -> [IpAddress, Integer, Symbol]
|
|
226
|
+
*
|
|
227
|
+
* Fills +packet+ (replacing its previous contents) with the next datagram
|
|
228
|
+
* received. Returns [IpAddress, port, status], the address and port of the
|
|
229
|
+
* sender.
|
|
230
|
+
*
|
|
231
|
+
* @return [Array(IpAddress, Integer, Symbol)]
|
|
232
|
+
* @raise [TypeError] if +packet+ is not an SFML::Packet
|
|
233
|
+
*/
|
|
143
234
|
static VALUE UdpSocket_receive_packet(VALUE self, VALUE rb_packet) {
|
|
144
235
|
sfIpAddress remote_address = sfIpAddress_None;
|
|
145
236
|
unsigned short remote_port = 0;
|
|
@@ -161,8 +252,13 @@ static VALUE UdpSocket_receive_packet(VALUE self, VALUE rb_packet) {
|
|
|
161
252
|
return rb_result;
|
|
162
253
|
}
|
|
163
254
|
|
|
164
|
-
|
|
165
|
-
|
|
255
|
+
/* Document-class: SFML::UdpSocket
|
|
256
|
+
* A connectionless, unreliable, datagram-oriented socket for UDP
|
|
257
|
+
* communication. Datagrams may be lost, duplicated or arrive out of order,
|
|
258
|
+
* and are capped at .max_datagram_size bytes.
|
|
259
|
+
*/
|
|
260
|
+
void Init_UdpSocket(VALUE rb_mSFML) {
|
|
261
|
+
rb_cUdpSocket = rb_define_class_under(rb_mSFML, "UdpSocket", rb_cObject);
|
|
166
262
|
|
|
167
263
|
rb_define_singleton_method(rb_cUdpSocket, "new", UdpSocket_new, 0);
|
|
168
264
|
rb_define_singleton_method(rb_cUdpSocket, "any_port", UdpSocket_any_port, 0);
|
|
@@ -183,8 +279,8 @@ VALUE Get_Klass_UdpSocket(void) {
|
|
|
183
279
|
return rb_cUdpSocket;
|
|
184
280
|
}
|
|
185
281
|
|
|
186
|
-
void
|
|
187
|
-
UdpSocket
|
|
282
|
+
void* Get_UdpSocket_Struct(VALUE self) {
|
|
283
|
+
UdpSocket* ptr;
|
|
188
284
|
TypedData_Get_Struct(self, UdpSocket, &UdpSocket_data_type, ptr);
|
|
189
285
|
return ptr->handle;
|
|
190
286
|
}
|