Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

ipsocket.c
Go to the documentation of this file.
1 /************************************************
2
3 ipsocket.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 struct inetsock_arg
14 {
15 VALUE sock;
16 struct {
17 VALUE host, serv;
18 struct addrinfo *res;
19 } remote, local;
20 int type;
21 int fd;
22 };
23
24 static VALUE
25 inetsock_cleanup(struct inetsock_arg *arg)
26 {
27 if (arg->remote.res) {
28 freeaddrinfo(arg->remote.res);
29 arg->remote.res = 0;
30 }
31 if (arg->local.res) {
32 freeaddrinfo(arg->local.res);
33 arg->local.res = 0;
34 }
35 if (arg->fd >= 0) {
36 close(arg->fd);
37 }
38 return Qnil;
39 }
40
41 static VALUE
42 init_inetsock_internal(struct inetsock_arg *arg)
43 {
44 int type = arg->type;
45 struct addrinfo *res;
46 int fd, status = 0;
47 const char *syscall = 0;
48
49 arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, SOCK_STREAM,
50 (type == INET_SERVER) ? AI_PASSIVE : 0);
51 /*
52 * Maybe also accept a local address
53 */
54
55 if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
56 arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, SOCK_STREAM, 0);
57 }
58
59 arg->fd = fd = -1;
60 for (res = arg->remote.res; res; res = res->ai_next) {
61 #if !defined(INET6) && defined(AF_INET6)
62 if (res->ai_family == AF_INET6)
63 continue;
64 #endif
65 status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
66 syscall = "socket(2)";
67 fd = status;
68 if (fd < 0) {
69 continue;
70 }
71 arg->fd = fd;
72 if (type == INET_SERVER) {
73 #if !defined(_WIN32) && !defined(__CYGWIN__)
74 status = 1;
75 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
76 (char*)&status, (socklen_t)sizeof(status));
77 #endif
78 status = bind(fd, res->ai_addr, res->ai_addrlen);
79 syscall = "bind(2)";
80 }
81 else {
82 if (arg->local.res) {
83 status = bind(fd, arg->local.res->ai_addr, arg->local.res->ai_addrlen);
84 syscall = "bind(2)";
85 }
86
87 if (status >= 0) {
88 status = rsock_connect(fd, res->ai_addr, res->ai_addrlen,
89 (type == INET_SOCKS));
90 syscall = "connect(2)";
91 }
92 }
93
94 if (status < 0) {
95 close(fd);
96 arg->fd = fd = -1;
97 continue;
98 } else
99 break;
100 }
101 if (status < 0) {
102 rb_sys_fail(syscall);
103 }
104
105 arg->fd = -1;
106
107 if (type == INET_SERVER) {
108 status = listen(fd, SOMAXCONN);
109 if (status < 0) {
110 close(fd);
111 rb_sys_fail("listen(2)");
112 }
113 }
114
115 /* create new instance */
116 return rsock_init_sock(arg->sock, fd);
117 }
118
119 VALUE
120 rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv,
121 VALUE local_host, VALUE local_serv, int type)
122 {
123 struct inetsock_arg arg;
124 arg.sock = sock;
125 arg.remote.host = remote_host;
126 arg.remote.serv = remote_serv;
127 arg.remote.res = 0;
128 arg.local.host = local_host;
129 arg.local.serv = local_serv;
130 arg.local.res = 0;
131 arg.type = type;
132 arg.fd = -1;
133 return rb_ensure(init_inetsock_internal, (VALUE)&arg,
134 inetsock_cleanup, (VALUE)&arg);
135 }
136
137 static ID id_numeric, id_hostname;
138
139 int
140 rsock_revlookup_flag(VALUE revlookup, int *norevlookup)
141 {
142 #define return_norevlookup(x) {*norevlookup = (x); return 1;}
143 ID id;
144
145 switch (revlookup) {
146 case Qtrue: return_norevlookup(0);
147 case Qfalse: return_norevlookup(1);
148 case Qnil: break;
149 default:
150 Check_Type(revlookup, T_SYMBOL);
151 id = SYM2ID(revlookup);
152 if (id == id_numeric) return_norevlookup(1);
153 if (id == id_hostname) return_norevlookup(0);
154 rb_raise(rb_eArgError, "invalid reverse_lookup flag: :%s", rb_id2name(id));
155 }
156 return 0;
157 #undef return_norevlookup
158 }
159
160 /*
161 * call-seq:
162 * ipsocket.addr([reverse_lookup]) => [address_family, port, hostname, numeric_address]
163 *
164 * Returns the local address as an array which contains
165 * address_family, port, hostname and numeric_address.
166 *
167 * If +reverse_lookup+ is +true+ or +:hostname+,
168 * hostname is obtained from numeric_address using reverse lookup.
169 * Or if it is +false+, or +:numeric+,
170 * hostname is same as numeric_address.
171 * Or if it is +nil+ or ommitted, obeys to +ipsocket.do_not_reverse_lookup+.
172 * See +Socket.getaddrinfo+ also.
173 *
174 * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
175 * p sock.addr #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
176 * p sock.addr(true) #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
177 * p sock.addr(false) #=> ["AF_INET", 49429, "192.168.0.128", "192.168.0.128"]
178 * p sock.addr(:hostname) #=> ["AF_INET", 49429, "hal", "192.168.0.128"]
179 * p sock.addr(:numeric) #=> ["AF_INET", 49429, "192.168.0.128", "192.168.0.128"]
180 * }
181 *
182 */
183 static VALUE
184 ip_addr(int argc, VALUE *argv, VALUE sock)
185 {
186 rb_io_t *fptr;
187 struct sockaddr_storage addr;
188 socklen_t len = (socklen_t)sizeof addr;
189 int norevlookup;
190
191 GetOpenFile(sock, fptr);
192
193 if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
194 norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
195 if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
196 rb_sys_fail("getsockname(2)");
197 return rsock_ipaddr((struct sockaddr*)&addr, norevlookup);
198 }
199
200 /*
201 * call-seq:
202 * ipsocket.peeraddr([reverse_lookup]) => [address_family, port, hostname, numeric_address]
203 *
204 * Returns the remote address as an array which contains
205 * address_family, port, hostname and numeric_address.
206 * It is defined for connection oriented socket such as TCPSocket.
207 *
208 * If +reverse_lookup+ is +true+ or +:hostname+,
209 * hostname is obtained from numeric_address using reverse lookup.
210 * Or if it is +false+, or +:numeric+,
211 * hostname is same as numeric_address.
212 * Or if it is +nil+ or ommitted, obeys to +ipsocket.do_not_reverse_lookup+.
213 * See +Socket.getaddrinfo+ also.
214 *
215 * TCPSocket.open("www.ruby-lang.org", 80) {|sock|
216 * p sock.peeraddr #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
217 * p sock.peeraddr(true) #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
218 * p sock.peeraddr(false) #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
219 * p sock.peeraddr(:hostname) #=> ["AF_INET", 80, "carbon.ruby-lang.org", "221.186.184.68"]
220 * p sock.peeraddr(:numeric) #=> ["AF_INET", 80, "221.186.184.68", "221.186.184.68"]
221 * }
222 *
223 */
224 static VALUE
225 ip_peeraddr(int argc, VALUE *argv, VALUE sock)
226 {
227 rb_io_t *fptr;
228 struct sockaddr_storage addr;
229 socklen_t len = (socklen_t)sizeof addr;
230 int norevlookup;
231
232 GetOpenFile(sock, fptr);
233
234 if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
235 norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
236 if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0)
237 rb_sys_fail("getpeername(2)");
238 return rsock_ipaddr((struct sockaddr*)&addr, norevlookup);
239 }
240
241 /*
242 * call-seq:
243 * ipsocket.recvfrom(maxlen) => [mesg, ipaddr]
244 * ipsocket.recvfrom(maxlen, flags) => [mesg, ipaddr]
245 *
246 * Receives a message and return the message as a string and
247 * an address which the message come from.
248 *
249 * _maxlen_ is the maximum number of bytes to receive.
250 *
251 * _flags_ should be a bitwise OR of Socket::MSG_* constants.
252 *
253 * ipaddr is same as IPSocket#{peeraddr,addr}.
254 *
255 * u1 = UDPSocket.new
256 * u1.bind("127.0.0.1", 4913)
257 * u2 = UDPSocket.new
258 * u2.send "uuuu", 0, "127.0.0.1", 4913
259 * p u1.recvfrom(10) #=> ["uuuu", ["AF_INET", 33230, "localhost", "127.0.0.1"]]
260 *
261 */
262 static VALUE
263 ip_recvfrom(int argc, VALUE *argv, VALUE sock)
264 {
265 return rsock_s_recvfrom(sock, argc, argv, RECV_IP);
266 }
267
268 /*
269 * call-seq:
270 * IPSocket.getaddress(host) => ipaddress
271 *
272 * Lookups the IP address of _host_.
273 *
274 * IPSocket.getaddress("localhost") #=> "127.0.0.1"
275 * IPSocket.getaddress("ip6-localhost") #=> "::1"
276 *
277 */
278 static VALUE
279 ip_s_getaddress(VALUE obj, VALUE host)
280 {
281 struct sockaddr_storage addr;
282 struct addrinfo *res = rsock_addrinfo(host, Qnil, SOCK_STREAM, 0);
283
284 /* just take the first one */
285 memcpy(&addr, res->ai_addr, res->ai_addrlen);
286 freeaddrinfo(res);
287
288 return rsock_make_ipaddr((struct sockaddr*)&addr);
289 }
290
291 void
292 rsock_init_ipsocket(void)
293 {
294 /*
295 * Document-class: IPSocket < BasicSocket
296 *
297 * IPSocket is the super class of TCPSocket and UDPSocket.
298 */
299 rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
300 rb_define_method(rb_cIPSocket, "addr", ip_addr, -1);
301 rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, -1);
302 rb_define_method(rb_cIPSocket, "recvfrom", ip_recvfrom, -1);
303 rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
304 rb_undef_method(rb_cIPSocket, "getpeereid");
305
306 id_numeric = rb_intern_const("numeric");
307 id_hostname = rb_intern_const("hostname");
308 }
inetsock_arg
Definition: ipsocket.c:13
rsock_addrinfo
struct addrinfo * rsock_addrinfo(VALUE host, VALUE port, int socktype, int flags)
Definition: raddrinfo.c:371
SOMAXCONN
#define SOMAXCONN
Definition: constdefs.h:1694
rb_cBasicSocket
VALUE rb_cBasicSocket
Definition: init.c:13
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
rb_io_t
Definition: io.h:63
rsock_ipaddr
VALUE rsock_ipaddr(struct sockaddr *sockaddr, int norevlookup)
Definition: raddrinfo.c:383
status
int status
Definition: tcltklib.c:2197
inetsock_arg::serv
VALUE serv
Definition: ipsocket.c:17
rsock_init_sock
VALUE rsock_init_sock(VALUE sock, int fd)
Definition: init.c:43
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
INET_SOCKS
#define INET_SOCKS
Definition: rubysocket.h:173
rb_cIPSocket
VALUE rb_cIPSocket
Definition: init.c:14
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
Qtrue
return Qtrue
Definition: tcltklib.c:9610
AI_PASSIVE
#define AI_PASSIVE
Definition: addrinfo.h:96
FMODE_NOREVLOOKUP
#define FMODE_NOREVLOOKUP
Definition: rubysocket.h:176
ip_peeraddr
static VALUE ip_peeraddr(int argc, VALUE *argv, VALUE sock)
Definition: ipsocket.c:225
rb_undef_method
void rb_undef_method(VALUE klass, const char *name)
Definition: class.c:1362
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:120
rsock_make_ipaddr
VALUE rsock_make_ipaddr(struct sockaddr *addr)
Definition: raddrinfo.c:243
rb_io_t::mode
int mode
Definition: io.h:66
Qfalse
return Qfalse
Definition: tcltklib.c:6779
Qnil
#define Qnil
Definition: tcltklib.c:1896
id_hostname
static ID id_hostname
Definition: ipsocket.c:137
Check_Type
#define Check_Type(v, t)
ID
unsigned long ID
Definition: ripper.y:105
rsock_socket
int rsock_socket(int domain, int type, int proto)
Definition: init.c:276
inetsock_arg::host
VALUE host
Definition: ipsocket.c:17
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
rb_io_t::fd
int fd
Definition: io.h:64
inetsock_cleanup
static VALUE inetsock_cleanup(struct inetsock_arg *arg)
Definition: ipsocket.c:25
init_inetsock_internal
static VALUE init_inetsock_internal(struct inetsock_arg *arg)
Definition: ipsocket.c:42
argv
VALUE * argv
Definition: tcltklib.c:1971
memcpy
memcpy(buf+1, str, len)
id
const int id
Definition: nkf.c:209
inetsock_arg::type
int type
Definition: ipsocket.c:20
rsock_s_recvfrom
VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
Definition: init.c:106
INET_SERVER
#define INET_SERVER
Definition: rubysocket.h:172
freeaddrinfo
void freeaddrinfo(struct addrinfo *ai)
Definition: getaddrinfo.c:211
sockaddr_storage
Definition: rubysocket.h:134
type
int type
Definition: tcltklib.c:111
ip_s_getaddress
static VALUE ip_s_getaddress(VALUE obj, VALUE host)
Definition: ipsocket.c:279
argc
int argc
Definition: tcltklib.c:1970
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
inetsock_arg::fd
int fd
Definition: ipsocket.c:21
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1899
rb_intern_const
#define rb_intern_const(str)
id_numeric
static ID id_numeric
Definition: ipsocket.c:137
addrinfo::ai_protocol
int ai_protocol
Definition: addrinfo.h:135
ip_addr
static VALUE ip_addr(int argc, VALUE *argv, VALUE sock)
Definition: ipsocket.c:184
arg
arg
Definition: ripper.y:1315
T_SYMBOL
#define T_SYMBOL
rubysocket.h
addrinfo::ai_socktype
int ai_socktype
Definition: addrinfo.h:134
rsock_revlookup_flag
int rsock_revlookup_flag(VALUE revlookup, int *norevlookup)
Definition: ipsocket.c:140
return_norevlookup
#define return_norevlookup(x)
RECV_IP
Definition: rubysocket.h:265
rsock_connect
int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
Definition: init.c:373
ip_recvfrom
static VALUE ip_recvfrom(int argc, VALUE *argv, VALUE sock)
Definition: ipsocket.c:263
addrinfo::ai_next
struct addrinfo * ai_next
Definition: addrinfo.h:139
rsock_init_inetsock
VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type)
Definition: ipsocket.c:120
rsock_init_ipsocket
void rsock_init_ipsocket(void)
Definition: ipsocket.c:292
res
Real * res
Definition: bigdecimal.c:1233
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17005
VALUE
unsigned long VALUE
Definition: ripper.y:104
addrinfo::ai_addrlen
size_t ai_addrlen
Definition: addrinfo.h:136
inetsock_arg::remote
struct inetsock_arg::@83 remote
addrinfo
Definition: addrinfo.h:131
inetsock_arg::local
struct inetsock_arg::@83 local
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
addrinfo::ai_addr
struct sockaddr * ai_addr
Definition: addrinfo.h:138
SYM2ID
#define SYM2ID(x)
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
inetsock_arg::sock
VALUE sock
Definition: ipsocket.c:15
inetsock_arg::res
struct addrinfo * res
Definition: ipsocket.c:18
len
size_t len
Definition: tcltklib.c:3568
addrinfo::ai_family
int ai_family
Definition: addrinfo.h:133