Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

udpsocket.c
Go to the documentation of this file.
1 /************************************************
2
3 udpsocket.c -
4
5 created at: Thu Mar 31 12:21:29 JST 1994
6
7 Copyright (C) 1993-2007 Yukihiro Matsumoto
8
9 ************************************************/
10
11 #include "rubysocket.h"
12
13 /*
14 * call-seq:
15 * UDPSocket.new([address_family]) => socket
16 *
17 * Creates a new UDPSocket object.
18 *
19 * _address_family_ should be an integer, a string or a symbol:
20 * Socket::AF_INET, "AF_INET", :INET, etc.
21 *
22 * UDPSocket.new #=> #<UDPSocket:fd 3>
23 * UDPSocket.new(Socket::AF_INET6) #=> #<UDPSocket:fd 4>
24 *
25 */
26 static VALUE
27 udp_init(int argc, VALUE *argv, VALUE sock)
28 {
29 VALUE arg;
30 int family = AF_INET;
31 int fd;
32
33 rb_secure(3);
34 if (rb_scan_args(argc, argv, "01", &arg) == 1) {
35 family = rsock_family_arg(arg);
36 }
37 fd = rsock_socket(family, SOCK_DGRAM, 0);
38 if (fd < 0) {
39 rb_sys_fail("socket(2) - udp");
40 }
41
42 return rsock_init_sock(sock, fd);
43 }
44
45 struct udp_arg
46 {
47 struct rb_addrinfo *res;
48 int fd;
49 };
50
51 static VALUE
52 udp_connect_internal(struct udp_arg *arg)
53 {
54 int fd = arg->fd;
55 struct addrinfo *res;
56
57 for (res = arg->res->ai; res; res = res->ai_next) {
58 if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
59 return Qtrue;
60 }
61 }
62 return Qfalse;
63 }
64
65 /*
66 * call-seq:
67 * udpsocket.connect(host, port) => 0
68 *
69 * Connects _udpsocket_ to _host_:_port_.
70 *
71 * This makes possible to send without destination address.
72 *
73 * u1 = UDPSocket.new
74 * u1.bind("127.0.0.1", 4913)
75 * u2 = UDPSocket.new
76 * u2.connect("127.0.0.1", 4913)
77 * u2.send "uuuu", 0
78 * p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]]
79 *
80 */
81 static VALUE
82 udp_connect(VALUE sock, VALUE host, VALUE port)
83 {
84 rb_io_t *fptr;
85 struct udp_arg arg;
86 VALUE ret;
87
88 rb_secure(3);
89 arg.res = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
90 GetOpenFile(sock, fptr);
91 arg.fd = fptr->fd;
92 ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
93 rsock_freeaddrinfo, (VALUE)arg.res);
94 if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
95 return INT2FIX(0);
96 }
97
98 /*
99 * call-seq:
100 * udpsocket.bind(host, port) #=> 0
101 *
102 * Binds _udpsocket_ to _host_:_port_.
103 *
104 * u1 = UDPSocket.new
105 * u1.bind("127.0.0.1", 4913)
106 * u1.send "message-to-self", 0, "127.0.0.1", 4913
107 * p u1.recvfrom(10) #=> ["message-to", ["AF_INET", 4913, "localhost", "127.0.0.1"]]
108 *
109 */
110 static VALUE
111 udp_bind(VALUE sock, VALUE host, VALUE port)
112 {
113 rb_io_t *fptr;
114 struct rb_addrinfo *res0;
115 struct addrinfo *res;
116
117 rb_secure(3);
118 res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
119 GetOpenFile(sock, fptr);
120 for (res = res0->ai; res; res = res->ai_next) {
121 if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) {
122 continue;
123 }
124 rb_freeaddrinfo(res0);
125 return INT2FIX(0);
126 }
127 rb_freeaddrinfo(res0);
128
129 rsock_sys_fail_host_port("bind(2)", host, port);
130
131 return INT2FIX(0);
132 }
133
134 /*
135 * call-seq:
136 * udpsocket.send(mesg, flags, host, port) => numbytes_sent
137 * udpsocket.send(mesg, flags, sockaddr_to) => numbytes_sent
138 * udpsocket.send(mesg, flags) => numbytes_sent
139 *
140 * Sends _mesg_ via _udpsocket_.
141 *
142 * _flags_ should be a bitwise OR of Socket::MSG_* constants.
143 *
144 * u1 = UDPSocket.new
145 * u1.bind("127.0.0.1", 4913)
146 *
147 * u2 = UDPSocket.new
148 * u2.send "hi", 0, "127.0.0.1", 4913
149 *
150 * mesg, addr = u1.recvfrom(10)
151 * u1.send mesg, 0, addr[3], addr[1]
152 *
153 * p u2.recv(100) #=> "hi"
154 *
155 */
156 static VALUE
157 udp_send(int argc, VALUE *argv, VALUE sock)
158 {
159 VALUE flags, host, port;
160 rb_io_t *fptr;
161 int n;
162 struct rb_addrinfo *res0;
163 struct addrinfo *res;
164 struct rsock_send_arg arg;
165
166 if (argc == 2 || argc == 3) {
167 return rsock_bsock_send(argc, argv, sock);
168 }
169 rb_scan_args(argc, argv, "4", &arg.mesg, &flags, &host, &port);
170
171 StringValue(arg.mesg);
172 res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
173 GetOpenFile(sock, fptr);
174 arg.fd = fptr->fd;
175 arg.flags = NUM2INT(flags);
176 for (res = res0->ai; res; res = res->ai_next) {
177 retry:
178 arg.to = res->ai_addr;
179 arg.tolen = res->ai_addrlen;
180 rb_thread_fd_writable(arg.fd);
181 n = (int)BLOCKING_REGION_FD(rsock_sendto_blocking, &arg);
182 if (n >= 0) {
183 rb_freeaddrinfo(res0);
184 return INT2FIX(n);
185 }
186 if (rb_io_wait_writable(fptr->fd)) {
187 goto retry;
188 }
189 }
190 rb_freeaddrinfo(res0);
191 rsock_sys_fail_host_port("sendto(2)", host, port);
192 return INT2FIX(n);
193 }
194
195 /*
196 * call-seq:
197 * udpsocket.recvfrom_nonblock(maxlen) => [mesg, sender_inet_addr]
198 * udpsocket.recvfrom_nonblock(maxlen, flags) => [mesg, sender_inet_addr]
199 *
200 * Receives up to _maxlen_ bytes from +udpsocket+ using recvfrom(2) after
201 * O_NONBLOCK is set for the underlying file descriptor.
202 * If _maxlen_ is omitted, its default value is 65536.
203 * _flags_ is zero or more of the +MSG_+ options.
204 * The first element of the results, _mesg_, is the data received.
205 * The second element, _sender_inet_addr_, is an array to represent the sender address.
206 *
207 * When recvfrom(2) returns 0,
208 * Socket#recvfrom_nonblock returns an empty string as data.
209 * It means an empty packet.
210 *
211 * === Parameters
212 * * +maxlen+ - the number of bytes to receive from the socket
213 * * +flags+ - zero or more of the +MSG_+ options
214 *
215 * === Example
216 * require 'socket'
217 * s1 = UDPSocket.new
218 * s1.bind("127.0.0.1", 0)
219 * s2 = UDPSocket.new
220 * s2.bind("127.0.0.1", 0)
221 * s2.connect(*s1.addr.values_at(3,1))
222 * s1.connect(*s2.addr.values_at(3,1))
223 * s1.send "aaa", 0
224 * begin # emulate blocking recvfrom
225 * p s2.recvfrom_nonblock(10) #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
226 * rescue IO::WaitReadable
227 * IO.select([s2])
228 * retry
229 * end
230 *
231 * Refer to Socket#recvfrom for the exceptions that may be thrown if the call
232 * to _recvfrom_nonblock_ fails.
233 *
234 * UDPSocket#recvfrom_nonblock may raise any error corresponding to recvfrom(2) failure,
235 * including Errno::EWOULDBLOCK.
236 *
237 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
238 * it is extended by IO::WaitReadable.
239 * So IO::WaitReadable can be used to rescue the exceptions for retrying recvfrom_nonblock.
240 *
241 * === See
242 * * Socket#recvfrom
243 */
244 static VALUE
245 udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
246 {
247 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_IP);
248 }
249
250 void
251 rsock_init_udpsocket(void)
252 {
253 /*
254 * Document-class: UDPSocket < IPSocket
255 *
256 * UDPSocket represents a UDP/IP socket.
257 *
258 */
259 rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
260 rb_define_method(rb_cUDPSocket, "initialize", udp_init, -1);
261 rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
262 rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
263 rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
264 rb_define_method(rb_cUDPSocket, "recvfrom_nonblock", udp_recvfrom_nonblock, -1);
265 }
266
udp_send
static VALUE udp_send(int argc, VALUE *argv, VALUE sock)
Definition: udpsocket.c:157
rsock_init_udpsocket
void rsock_init_udpsocket(void)
Definition: udpsocket.c:251
rsock_send_arg::tolen
socklen_t tolen
Definition: rubysocket.h:322
rsock_sendto_blocking
VALUE rsock_sendto_blocking(void *data)
Definition: init.c:73
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:630
udp_arg::res
struct rb_addrinfo * res
Definition: udpsocket.c:47
Qtrue
#define Qtrue
Definition: ruby.h:426
rb_io_t
Definition: io.h:61
rsock_init_sock
VALUE rsock_init_sock(VALUE sock, int fd)
Definition: init.c:43
rb_cIPSocket
VALUE rb_cIPSocket
Definition: init.c:14
rsock_send_arg::to
struct sockaddr * to
Definition: rubysocket.h:321
rsock_send_arg::mesg
VALUE mesg
Definition: rubysocket.h:320
rsock_send_arg::fd
int fd
Definition: rubysocket.h:319
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:118
udp_bind
static VALUE udp_bind(VALUE sock, VALUE host, VALUE port)
Definition: udpsocket.c:111
udp_connect_internal
static VALUE udp_connect_internal(struct udp_arg *arg)
Definition: udpsocket.c:52
udp_connect
static VALUE udp_connect(VALUE sock, VALUE host, VALUE port)
Definition: udpsocket.c:82
rsock_bsock_send
VALUE rsock_bsock_send(int argc, VALUE *argv, VALUE sock)
Definition: basicsocket.c:542
rb_freeaddrinfo
void rb_freeaddrinfo(struct rb_addrinfo *ai)
Definition: raddrinfo.c:293
rsock_addrinfo
struct rb_addrinfo * rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
Definition: raddrinfo.c:493
udp_recvfrom_nonblock
static VALUE udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
Definition: udpsocket.c:245
rb_thread_fd_writable
int rb_thread_fd_writable(int)
Definition: thread.c:3525
rb_addrinfo
Definition: rubysocket.h:281
udp_init
static VALUE udp_init(int argc, VALUE *argv, VALUE sock)
Definition: udpsocket.c:27
rsock_send_arg
Definition: rubysocket.h:318
rsock_family_arg
int rsock_family_arg(VALUE domain)
Definition: constants.c:43
rsock_socket
int rsock_socket(int domain, int type, int proto)
Definition: init.c:285
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
rb_io_t::fd
int fd
Definition: io.h:62
rb_io_wait_writable
int rb_io_wait_writable(int)
Definition: io.c:1103
udp_arg
Definition: udpsocket.c:45
argc
int argc
Definition: ruby.c:131
Qfalse
#define Qfalse
Definition: ruby.h:425
rsock_freeaddrinfo
VALUE rsock_freeaddrinfo(VALUE arg)
Definition: raddrinfo.c:641
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
rsock_sys_fail_host_port
void rsock_sys_fail_host_port(const char *mesg, VALUE host, VALUE port)
Definition: socket.c:16
VALUE
unsigned long VALUE
Definition: ruby.h:88
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:839
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1976
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rubysocket.h
RECV_IP
Definition: rubysocket.h:331
rb_addrinfo::ai
struct addrinfo * ai
Definition: rubysocket.h:282
rsock_connect
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
Definition: init.c:386
rsock_send_arg::flags
int flags
Definition: rubysocket.h:319
udp_arg::fd
int fd
Definition: udpsocket.c:48
addrinfo::ai_next
struct addrinfo * ai_next
Definition: addrinfo.h:139
rb_secure
void rb_secure(int)
Definition: safe.c:88
addrinfo::ai_addrlen
size_t ai_addrlen
Definition: addrinfo.h:136
addrinfo
Definition: addrinfo.h:131
rsock_s_recvfrom_nonblock
VALUE rsock_s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:179
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
addrinfo::ai_addr
struct sockaddr * ai_addr
Definition: addrinfo.h:138
BLOCKING_REGION_FD
#define BLOCKING_REGION_FD(func, arg)
Definition: rubysocket.h:259
argv
char ** argv
Definition: ruby.c:132
StringValue
#define StringValue(v)
Definition: ruby.h:539
rb_cUDPSocket
VALUE rb_cUDPSocket
Definition: init.c:17