2 ** socket.c - Socket module
4 ** See Copyright Notice in mruby.h
8 #define _WIN32_WINNT 0x0501
14 #define SHUT_RDWR SD_BOTH
15 #ifndef _SSIZE_T_DEFINED
20 #include <sys/types.h>
21 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <netinet/tcp.h>
25 #include <arpa/inet.h>
29 typedef size_t fsize_t
;
36 #include "mruby/array.h"
37 #include "mruby/class.h"
38 #include "mruby/data.h"
39 #include "mruby/string.h"
40 #include "mruby/variable.h"
43 #include "mruby/ext/io.h"
45 #define E_SOCKET_ERROR (mrb_class_get(mrb, "SocketError"))
47 #if !defined(mrb_cptr)
48 #define mrb_cptr_value(m,p) mrb_voidp_value((m),(p))
49 #define mrb_cptr(o) mrb_voidp(o)
50 #define mrb_cptr_p(o) mrb_voidp_p(o)
54 const char *inet_ntop(int af
, const void *src
, char *dst
, socklen_t cnt
)
58 struct sockaddr_in in
;
59 memset(&in
, 0, sizeof(in
));
60 in
.sin_family
= AF_INET
;
61 memcpy(&in
.sin_addr
, src
, sizeof(struct in_addr
));
62 getnameinfo((struct sockaddr
*)&in
, sizeof(struct
63 sockaddr_in
), dst
, cnt
, NULL
, 0, NI_NUMERICHOST
);
66 else if (af
== AF_INET6
)
68 struct sockaddr_in6 in
;
69 memset(&in
, 0, sizeof(in
));
70 in
.sin6_family
= AF_INET6
;
71 memcpy(&in
.sin6_addr
, src
, sizeof(struct in_addr6
));
72 getnameinfo((struct sockaddr
*)&in
, sizeof(struct
73 sockaddr_in6
), dst
, cnt
, NULL
, 0, NI_NUMERICHOST
);
79 int inet_pton(int af
, const char *src
, void *dst
)
81 struct addrinfo hints
, *res
, *ressave
;
83 memset(&hints
, 0, sizeof(struct addrinfo
));
86 if (getaddrinfo(src
, NULL
, &hints
, &res
) != 0)
88 printf("Couldn't resolve host %s\n", src
);
96 memcpy(dst
, res
->ai_addr
, res
->ai_addrlen
);
100 freeaddrinfo(ressave
);
107 mrb_addrinfo_getaddrinfo(mrb_state
*mrb
, mrb_value klass
)
109 struct addrinfo hints
, *res0
, *res
;
110 mrb_value ai
, ary
, family
, lastai
, nodename
, protocol
, sa
, service
, socktype
;
112 int arena_idx
, error
;
113 const char *hostname
= NULL
, *servname
= NULL
;
115 ary
= mrb_ary_new(mrb
);
116 arena_idx
= mrb_gc_arena_save(mrb
); /* ary must be on arena! */
118 family
= socktype
= protocol
= mrb_nil_value();
120 mrb_get_args(mrb
, "oo|oooi", &nodename
, &service
, &family
, &socktype
, &protocol
, &flags
);
122 if (mrb_string_p(nodename
)) {
123 hostname
= mrb_str_to_cstr(mrb
, nodename
);
124 } else if (mrb_nil_p(nodename
)) {
127 mrb_raise(mrb
, E_TYPE_ERROR
, "nodename must be String or nil");
130 if (mrb_string_p(service
)) {
131 servname
= mrb_str_to_cstr(mrb
, service
);
132 } else if (mrb_fixnum_p(service
)) {
133 servname
= mrb_str_to_cstr(mrb
, mrb_funcall(mrb
, service
, "to_s", 0));
134 } else if (mrb_nil_p(service
)) {
137 mrb_raise(mrb
, E_TYPE_ERROR
, "service must be String, Fixnum, or nil");
140 memset(&hints
, 0, sizeof(hints
));
141 hints
.ai_flags
= (int)flags
;
143 if (mrb_fixnum_p(family
)) {
144 hints
.ai_family
= (int)mrb_fixnum(family
);
147 if (mrb_fixnum_p(socktype
)) {
148 hints
.ai_socktype
= (int)mrb_fixnum(socktype
);
151 if (mrb_fixnum_p(protocol
)) {
152 hints
.ai_protocol
= (int)mrb_fixnum(protocol
);
155 if (mrb_fixnum_p(protocol
)) {
156 hints
.ai_protocol
= mrb_fixnum(protocol
);
159 lastai
= mrb_cv_get(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"));
160 if (mrb_cptr_p(lastai
)) {
161 freeaddrinfo((struct addrinfo
*)mrb_cptr(lastai
));
162 mrb_cv_set(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"), mrb_nil_value());
165 error
= getaddrinfo(hostname
, servname
, &hints
, &res0
);
167 mrb_raisef(mrb
, E_SOCKET_ERROR
, "getaddrinfo: %S", mrb_str_new_cstr(mrb
, gai_strerror(error
)));
169 mrb_cv_set(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"), mrb_cptr_value(mrb
, res0
));
171 for (res
= res0
; res
!= NULL
; res
= res
->ai_next
) {
172 sa
= mrb_str_new(mrb
, (char*)res
->ai_addr
, res
->ai_addrlen
);
173 ai
= mrb_funcall(mrb
, klass
, "new", 4, sa
, mrb_fixnum_value(res
->ai_family
), mrb_fixnum_value(res
->ai_socktype
), mrb_fixnum_value(res
->ai_protocol
));
174 mrb_ary_push(mrb
, ary
, ai
);
175 mrb_gc_arena_restore(mrb
, arena_idx
);
179 mrb_cv_set(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"), mrb_nil_value());
185 mrb_addrinfo_getnameinfo(mrb_state
*mrb
, mrb_value self
)
188 mrb_value ary
, host
, sastr
, serv
;
192 mrb_get_args(mrb
, "|i", &flags
);
193 host
= mrb_str_buf_new(mrb
, NI_MAXHOST
);
194 serv
= mrb_str_buf_new(mrb
, NI_MAXSERV
);
196 sastr
= mrb_iv_get(mrb
, self
, mrb_intern_lit(mrb
, "@sockaddr"));
197 if (!mrb_string_p(sastr
)) {
198 mrb_raise(mrb
, E_SOCKET_ERROR
, "invalid sockaddr");
200 error
= getnameinfo((struct sockaddr
*)RSTRING_PTR(sastr
), (socklen_t
)RSTRING_LEN(sastr
), RSTRING_PTR(host
), NI_MAXHOST
, RSTRING_PTR(serv
), NI_MAXSERV
, (int)flags
);
202 mrb_raisef(mrb
, E_SOCKET_ERROR
, "getnameinfo: %s", gai_strerror(error
));
204 ary
= mrb_ary_new_capa(mrb
, 2);
205 mrb_str_resize(mrb
, host
, strlen(RSTRING_PTR(host
)));
206 mrb_ary_push(mrb
, ary
, host
);
207 mrb_str_resize(mrb
, serv
, strlen(RSTRING_PTR(serv
)));
208 mrb_ary_push(mrb
, ary
, serv
);
214 mrb_addrinfo_unix_path(mrb_state
*mrb
, mrb_value self
)
218 sastr
= mrb_iv_get(mrb
, self
, mrb_intern_lit(mrb
, "@sockaddr"));
219 if (((struct sockaddr
*)RSTRING_PTR(sastr
))->sa_family
!= AF_UNIX
)
220 mrb_raise(mrb
, E_SOCKET_ERROR
, "need AF_UNIX address");
221 return mrb_str_new_cstr(mrb
, ((struct sockaddr_un
*)RSTRING_PTR(sastr
))->sun_path
);
226 sa2addrlist(mrb_state
*mrb
, const struct sockaddr
*sa
, socklen_t salen
)
232 switch (sa
->sa_family
) {
235 port
= ((struct sockaddr_in
*)sa
)->sin_port
;
239 port
= ((struct sockaddr_in6
*)sa
)->sin6_port
;
242 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "bad af");
243 return mrb_nil_value();
246 host
= mrb_str_buf_new(mrb
, NI_MAXHOST
);
247 if (getnameinfo(sa
, salen
, RSTRING_PTR(host
), NI_MAXHOST
, NULL
, 0, NI_NUMERICHOST
) == -1)
248 mrb_sys_fail(mrb
, "getnameinfo");
249 mrb_str_resize(mrb
, host
, strlen(RSTRING_PTR(host
)));
250 ary
= mrb_ary_new_capa(mrb
, 4);
251 mrb_ary_push(mrb
, ary
, mrb_str_new_cstr(mrb
, afstr
));
252 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(port
));
253 mrb_ary_push(mrb
, ary
, host
);
254 mrb_ary_push(mrb
, ary
, host
);
259 socket_fd(mrb_state
*mrb
, mrb_value sock
)
261 return (int)mrb_fixnum(mrb_funcall(mrb
, sock
, "fileno", 0));
267 struct sockaddr_storage ss
;
271 if (getsockname(s
, (struct sockaddr
*)&ss
, &salen
) == -1)
277 mrb_basicsocket_getpeereid(mrb_state
*mrb
, mrb_value self
)
279 #ifdef HAVE_GETPEEREID
285 s
= socket_fd(mrb
, self
);
286 if (getpeereid(s
, &euid
, &egid
) != 0)
287 mrb_sys_fail(mrb
, "getpeereid");
289 ary
= mrb_ary_new_capa(mrb
, 2);
290 mrb_ary_push(mrb
, ary
, mrb_fixnum_value((mrb_int
)euid
));
291 mrb_ary_push(mrb
, ary
, mrb_fixnum_value((mrb_int
)egid
));
294 mrb_raise(mrb
, E_RUNTIME_ERROR
, "getpeereid is not avaialble on this system");
295 return mrb_nil_value();
300 mrb_basicsocket_getpeername(mrb_state
*mrb
, mrb_value self
)
302 struct sockaddr_storage ss
;
306 if (getpeername(socket_fd(mrb
, self
), (struct sockaddr
*)&ss
, &salen
) != 0)
307 mrb_sys_fail(mrb
, "getpeername");
309 return mrb_str_new(mrb
, (char*)&ss
, salen
);
313 mrb_basicsocket_getsockname(mrb_state
*mrb
, mrb_value self
)
315 struct sockaddr_storage ss
;
319 if (getsockname(socket_fd(mrb
, self
), (struct sockaddr
*)&ss
, &salen
) != 0)
320 mrb_sys_fail(mrb
, "getsockname");
322 return mrb_str_new(mrb
, (char*)&ss
, salen
);
326 mrb_basicsocket_getsockopt(mrb_state
*mrb
, mrb_value self
)
330 mrb_int family
, level
, optname
;
334 mrb_get_args(mrb
, "ii", &level
, &optname
);
335 s
= socket_fd(mrb
, self
);
336 optlen
= sizeof(opt
);
337 if (getsockopt(s
, (int)level
, (int)optname
, opt
, &optlen
) == -1)
338 mrb_sys_fail(mrb
, "getsockopt");
339 c
= mrb_const_get(mrb
, mrb_obj_value(mrb_class_get(mrb
, "Socket")), mrb_intern_lit(mrb
, "Option"));
340 family
= socket_family(s
);
341 data
= mrb_str_new(mrb
, opt
, optlen
);
342 return mrb_funcall(mrb
, c
, "new", 4, mrb_fixnum_value(family
), mrb_fixnum_value(level
), mrb_fixnum_value(optname
), data
);
346 mrb_basicsocket_recv(mrb_state
*mrb
, mrb_value self
)
349 mrb_int maxlen
, flags
= 0;
352 mrb_get_args(mrb
, "i|i", &maxlen
, &flags
);
353 buf
= mrb_str_buf_new(mrb
, maxlen
);
354 n
= recv(socket_fd(mrb
, self
), RSTRING_PTR(buf
), (fsize_t
)maxlen
, (int)flags
);
356 mrb_sys_fail(mrb
, "recv");
357 mrb_str_resize(mrb
, buf
, (mrb_int
)n
);
362 mrb_basicsocket_recvfrom(mrb_state
*mrb
, mrb_value self
)
365 mrb_int maxlen
, flags
= 0;
366 mrb_value ary
, buf
, sa
;
369 mrb_get_args(mrb
, "i|i", &maxlen
, &flags
);
370 buf
= mrb_str_buf_new(mrb
, maxlen
);
371 socklen
= sizeof(struct sockaddr_storage
);
372 sa
= mrb_str_buf_new(mrb
, socklen
);
373 n
= recvfrom(socket_fd(mrb
, self
), RSTRING_PTR(buf
), (fsize_t
)maxlen
, (int)flags
, (struct sockaddr
*)RSTRING_PTR(sa
), &socklen
);
375 mrb_sys_fail(mrb
, "recvfrom");
376 mrb_str_resize(mrb
, buf
, (mrb_int
)n
);
377 mrb_str_resize(mrb
, sa
, (mrb_int
)socklen
);
378 ary
= mrb_ary_new_capa(mrb
, 2);
379 mrb_ary_push(mrb
, ary
, buf
);
380 mrb_ary_push(mrb
, ary
, sa
);
385 mrb_basicsocket_send(mrb_state
*mrb
, mrb_value self
)
389 mrb_value dest
, mesg
;
391 dest
= mrb_nil_value();
392 mrb_get_args(mrb
, "Si|S", &mesg
, &flags
, &dest
);
393 if (mrb_nil_p(dest
)) {
394 n
= send(socket_fd(mrb
, self
), RSTRING_PTR(mesg
), (fsize_t
)RSTRING_LEN(mesg
), (int)flags
);
396 n
= sendto(socket_fd(mrb
, self
), RSTRING_PTR(mesg
), (fsize_t
)RSTRING_LEN(mesg
), (int)flags
, (const struct sockaddr
*)RSTRING_PTR(dest
), (fsize_t
)RSTRING_LEN(dest
));
399 mrb_sys_fail(mrb
, "send");
400 return mrb_fixnum_value((mrb_int
)n
);
404 mrb_basicsocket_setnonblock(mrb_state
*mrb
, mrb_value self
)
407 mrb_bool nonblocking
;
412 mrb_get_args(mrb
, "b", &nonblocking
);
413 fd
= socket_fd(mrb
, self
);
415 flags
= ioctlsocket(fd
, FIONBIO
, &mode
);
416 if (flags
!= NO_ERROR
)
417 mrb_sys_fail(mrb
, "ioctlsocket");
419 flags
= fcntl(fd
, F_GETFL
, 0);
421 mrb_sys_fail(mrb
, "fcntl");
425 flags
&= ~O_NONBLOCK
;
426 if (fcntl(fd
, F_SETFL
, flags
) == -1)
427 mrb_sys_fail(mrb
, "fcntl");
429 return mrb_nil_value();
433 mrb_basicsocket_setsockopt(mrb_state
*mrb
, mrb_value self
)
436 mrb_int argc
, level
= 0, optname
;
437 mrb_value optval
, so
;
439 argc
= mrb_get_args(mrb
, "o|io", &so
, &optname
, &optval
);
441 if (!mrb_fixnum_p(so
)) {
442 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "level is not an integer");
444 level
= mrb_fixnum(so
);
445 if (mrb_string_p(optval
)) {
447 } else if (mrb_type(optval
) == MRB_TT_TRUE
|| mrb_type(optval
) == MRB_TT_FALSE
) {
448 mrb_int i
= mrb_test(optval
) ? 1 : 0;
449 optval
= mrb_str_new(mrb
, (char*)&i
, sizeof(i
));
450 } else if (mrb_fixnum_p(optval
)) {
451 if (optname
== IP_MULTICAST_TTL
|| optname
== IP_MULTICAST_LOOP
) {
452 char uc
= (char)mrb_fixnum(optval
);
453 optval
= mrb_str_new(mrb
, &uc
, sizeof(uc
));
455 mrb_int i
= mrb_fixnum(optval
);
456 optval
= mrb_str_new(mrb
, (char*)&i
, sizeof(i
));
459 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "optval should be true, false, an integer, or a string");
461 } else if (argc
== 1) {
462 if (strcmp(mrb_obj_classname(mrb
, so
), "Socket::Option") != 0)
463 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "not an instance of Socket::Option");
464 level
= mrb_fixnum(mrb_funcall(mrb
, so
, "level", 0));
465 optname
= mrb_fixnum(mrb_funcall(mrb
, so
, "optname", 0));
466 optval
= mrb_funcall(mrb
, so
, "data", 0);
468 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "wrong number of arguments (%d for 3)", argc
);
471 s
= socket_fd(mrb
, self
);
472 if (setsockopt(s
, (int)level
, (int)optname
, RSTRING_PTR(optval
), (socklen_t
)RSTRING_LEN(optval
)) == -1)
473 mrb_sys_fail(mrb
, "setsockopt");
474 return mrb_fixnum_value(0);
478 mrb_basicsocket_shutdown(mrb_state
*mrb
, mrb_value self
)
480 mrb_int how
= SHUT_RDWR
;
482 mrb_get_args(mrb
, "|i", &how
);
483 if (shutdown(socket_fd(mrb
, self
), (int)how
) != 0)
484 mrb_sys_fail(mrb
, "shutdown");
485 return mrb_fixnum_value(0);
489 mrb_basicsocket_set_is_socket(mrb_state
*mrb
, mrb_value self
)
493 mrb_get_args(mrb
, "b", &b
);
495 io_p
= (struct mrb_io
*)DATA_PTR(self
);
500 return mrb_bool_value(b
);
504 mrb_ipsocket_ntop(mrb_state
*mrb
, mrb_value klass
)
509 mrb_get_args(mrb
, "is", &af
, &addr
, &n
);
510 if ((af
== AF_INET
&& n
!= 4) || (af
== AF_INET6
&& n
!= 16))
511 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
512 if (inet_ntop((int)af
, addr
, buf
, sizeof(buf
)) == NULL
)
513 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
514 return mrb_str_new_cstr(mrb
, buf
);
518 mrb_ipsocket_pton(mrb_state
*mrb
, mrb_value klass
)
523 mrb_get_args(mrb
, "is", &af
, &bp
, &n
);
524 if ((size_t)n
> sizeof(buf
) - 1)
525 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
531 if (inet_pton(AF_INET
, buf
, (void *)&in
.s_addr
) != 1)
533 return mrb_str_new(mrb
, (char*)&in
.s_addr
, 4);
534 } else if (af
== AF_INET6
) {
536 if (inet_pton(AF_INET6
, buf
, (void *)&in6
.s6_addr
) != 1)
538 return mrb_str_new(mrb
, (char*)&in6
.s6_addr
, 16);
540 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "unsupported address family");
543 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
544 return mrb_nil_value(); /* dummy */
548 mrb_ipsocket_recvfrom(mrb_state
*mrb
, mrb_value self
)
550 struct sockaddr_storage ss
;
552 mrb_value a
, buf
, pair
;
553 mrb_int flags
, maxlen
;
557 fd
= socket_fd(mrb
, self
);
559 mrb_get_args(mrb
, "i|i", &maxlen
, &flags
);
560 buf
= mrb_str_buf_new(mrb
, maxlen
);
561 socklen
= sizeof(ss
);
562 n
= recvfrom(fd
, RSTRING_PTR(buf
), (fsize_t
)maxlen
, (int)flags
,
563 (struct sockaddr
*)&ss
, &socklen
);
565 mrb_sys_fail(mrb
, "recvfrom");
567 mrb_str_resize(mrb
, buf
, (mrb_int
)n
);
568 a
= sa2addrlist(mrb
, (struct sockaddr
*)&ss
, socklen
);
569 pair
= mrb_ary_new_capa(mrb
, 2);
570 mrb_ary_push(mrb
, pair
, buf
);
571 mrb_ary_push(mrb
, pair
, a
);
576 mrb_socket_gethostname(mrb_state
*mrb
, mrb_value cls
)
582 bufsize
= HOST_NAME_MAX
+ 1;
586 buf
= mrb_str_buf_new(mrb
, (mrb_int
)bufsize
);
587 if (gethostname(RSTRING_PTR(buf
), (fsize_t
)bufsize
) != 0)
588 mrb_sys_fail(mrb
, "gethostname");
589 mrb_str_resize(mrb
, buf
, (mrb_int
)strlen(RSTRING_PTR(buf
)));
594 mrb_socket_accept(mrb_state
*mrb
, mrb_value klass
)
596 mrb_value ary
, sastr
;
601 mrb_get_args(mrb
, "i", &s0
);
602 socklen
= sizeof(struct sockaddr_storage
);
603 sastr
= mrb_str_buf_new(mrb
, socklen
);
604 s1
= (int)accept(s0
, (struct sockaddr
*)RSTRING_PTR(sastr
), &socklen
);
606 mrb_sys_fail(mrb
, "accept");
608 // XXX: possible descriptor leakage here!
609 mrb_str_resize(mrb
, sastr
, socklen
);
610 ary
= mrb_ary_new_capa(mrb
, 2);
611 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(s1
));
612 mrb_ary_push(mrb
, ary
, sastr
);
617 mrb_socket_bind(mrb_state
*mrb
, mrb_value klass
)
622 mrb_get_args(mrb
, "iS", &s
, &sastr
);
623 if (bind((int)s
, (struct sockaddr
*)RSTRING_PTR(sastr
), (socklen_t
)RSTRING_LEN(sastr
)) == -1) {
624 mrb_sys_fail(mrb
, "bind");
626 return mrb_nil_value();
630 mrb_socket_connect(mrb_state
*mrb
, mrb_value klass
)
635 mrb_get_args(mrb
, "iS", &s
, &sastr
);
636 if (connect((int)s
, (struct sockaddr
*)RSTRING_PTR(sastr
), (socklen_t
)RSTRING_LEN(sastr
)) == -1) {
637 mrb_sys_fail(mrb
, "connect");
639 return mrb_nil_value();
643 mrb_socket_listen(mrb_state
*mrb
, mrb_value klass
)
647 mrb_get_args(mrb
, "ii", &s
, &backlog
);
648 if (listen((int)s
, (int)backlog
) == -1) {
649 mrb_sys_fail(mrb
, "listen");
651 return mrb_nil_value();
655 mrb_socket_sockaddr_family(mrb_state
*mrb
, mrb_value klass
)
659 mrb_get_args(mrb
, "S", &sa
);
661 if ((size_t)RSTRING_LEN(sa
) < offsetof(struct sockaddr
, sa_family
) + sizeof(sa_family_t
)) {
662 mrb_raisef(mrb
, E_SOCKET_ERROR
, "invalid sockaddr (too short)");
665 if ((size_t)RSTRING_LEN(sa
) < sizeof(struct sockaddr
)) {
666 mrb_raisef(mrb
, E_SOCKET_ERROR
, "invalid sockaddr (too short)");
669 return mrb_fixnum_value(((struct sockaddr
*)RSTRING_PTR(sa
))->sa_family
);
673 mrb_socket_sockaddr_un(mrb_state
*mrb
, mrb_value klass
)
676 mrb_raise(mrb
, E_NOTIMP_ERROR
, "sockaddr_un unsupported on Windows");
677 return mrb_nil_value();
679 struct sockaddr_un
*sunp
;
682 mrb_get_args(mrb
, "S", &path
);
683 if ((size_t)RSTRING_LEN(path
) > sizeof(sunp
->sun_path
) - 1) {
684 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "too long unix socket path (max: %ubytes)", (unsigned int)sizeof(sunp
->sun_path
) - 1);
686 s
= mrb_str_buf_new(mrb
, sizeof(struct sockaddr_un
));
687 sunp
= (struct sockaddr_un
*)RSTRING_PTR(s
);
688 sunp
->sun_family
= AF_UNIX
;
689 memcpy(sunp
->sun_path
, RSTRING_PTR(path
), RSTRING_LEN(path
));
690 sunp
->sun_path
[RSTRING_LEN(path
)] = '\0';
691 mrb_str_resize(mrb
, s
, sizeof(struct sockaddr_un
));
697 mrb_socket_socketpair(mrb_state
*mrb
, mrb_value klass
)
700 mrb_raise(mrb
, E_NOTIMP_ERROR
, "socketpair unsupported on Windows");
701 return mrb_nil_value();
704 mrb_int domain
, type
, protocol
;
707 mrb_get_args(mrb
, "iii", &domain
, &type
, &protocol
);
708 if (socketpair(domain
, type
, protocol
, sv
) == -1) {
709 mrb_sys_fail(mrb
, "socketpair");
711 // XXX: possible descriptor leakage here!
712 ary
= mrb_ary_new_capa(mrb
, 2);
713 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(sv
[0]));
714 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(sv
[1]));
720 mrb_socket_socket(mrb_state
*mrb
, mrb_value klass
)
722 mrb_int domain
, type
, protocol
;
725 mrb_get_args(mrb
, "iii", &domain
, &type
, &protocol
);
726 s
= (int)socket((int)domain
, (int)type
, (int)protocol
);
728 mrb_sys_fail(mrb
, "socket");
729 return mrb_fixnum_value(s
);
733 mrb_tcpsocket_allocate(mrb_state
*mrb
, mrb_value klass
)
735 struct RClass
*c
= mrb_class_ptr(klass
);
736 enum mrb_vtype ttype
= MRB_INSTANCE_TT(c
);
738 /* copied from mrb_instance_alloc() */
739 if (ttype
== 0) ttype
= MRB_TT_OBJECT
;
740 return mrb_obj_value((struct RObject
*)mrb_obj_alloc(mrb
, ttype
, c
));
743 /* Windows overrides for IO methods on BasicSocket objects.
744 * This is because sockets on Windows are not the same as file
745 * descriptors, and thus functions which operate on file descriptors
746 * will break on socket descriptors.
750 mrb_win32_basicsocket_close(mrb_state
*mrb
, mrb_value self
)
752 if (closesocket(socket_fd(mrb
, self
)) != NO_ERROR
)
753 mrb_raise(mrb
, E_SOCKET_ERROR
, "closesocket unsuccessful");
754 return mrb_nil_value();
757 #define E_EOF_ERROR (mrb_class_get(mrb, "EOFError"))
759 mrb_win32_basicsocket_sysread(mrb_state
*mrb
, mrb_value self
)
762 mrb_value buf
= mrb_nil_value();
765 mrb_get_args(mrb
, "i|S", &maxlen
, &buf
);
767 return mrb_nil_value();
770 if (mrb_nil_p(buf
)) {
771 buf
= mrb_str_new(mrb
, NULL
, maxlen
);
773 if (RSTRING_LEN(buf
) != maxlen
) {
774 buf
= mrb_str_resize(mrb
, buf
, maxlen
);
777 sd
= socket_fd(mrb
, self
);
778 ret
= recv(sd
, RSTRING_PTR(buf
), (int)maxlen
, 0);
783 buf
= mrb_str_new_cstr(mrb
, "");
785 mrb_raise(mrb
, E_EOF_ERROR
, "sysread failed: End of File");
788 case SOCKET_ERROR
: /* Error */
789 mrb_sys_fail(mrb
, "recv");
792 if (RSTRING_LEN(buf
) != ret
) {
793 buf
= mrb_str_resize(mrb
, buf
, ret
);
802 mrb_win32_basicsocket_sysseek(mrb_state
*mrb
, mrb_value self
)
804 mrb_raise(mrb
, E_NOTIMP_ERROR
, "sysseek not implemented for windows sockets");
805 return mrb_nil_value();
809 mrb_win32_basicsocket_syswrite(mrb_state
*mrb
, mrb_value self
)
815 sd
= socket_fd(mrb
, self
);
816 mrb_get_args(mrb
, "S", &str
);
817 n
= send(sd
, RSTRING_PTR(str
), (int)RSTRING_LEN(str
), 0);
818 if (n
== SOCKET_ERROR
)
819 mrb_sys_fail(mrb
, "send");
820 return mrb_fixnum_value(n
);
826 mrb_mruby_socket_gem_init(mrb_state
* mrb
)
828 struct RClass
*io
, *ai
, *sock
, *bsock
, *ipsock
, *tcpsock
;
829 struct RClass
*constants
;
834 result
= WSAStartup(MAKEWORD(2,2), &wsaData
);
835 if (result
!= NO_ERROR
)
836 mrb_raise(mrb
, E_RUNTIME_ERROR
, "WSAStartup failed");
839 ai
= mrb_define_class(mrb
, "Addrinfo", mrb
->object_class
);
840 mrb_mod_cv_set(mrb
, ai
, mrb_intern_lit(mrb
, "_lastai"), mrb_nil_value());
841 mrb_define_class_method(mrb
, ai
, "getaddrinfo", mrb_addrinfo_getaddrinfo
, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(4));
842 mrb_define_method(mrb
, ai
, "getnameinfo", mrb_addrinfo_getnameinfo
, MRB_ARGS_OPT(1));
844 mrb_define_method(mrb
, ai
, "unix_path", mrb_addrinfo_unix_path
, MRB_ARGS_NONE());
847 io
= mrb_class_get(mrb
, "IO");
849 bsock
= mrb_define_class(mrb
, "BasicSocket", io
);
850 mrb_define_method(mrb
, bsock
, "_recvfrom", mrb_basicsocket_recvfrom
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
851 mrb_define_method(mrb
, bsock
, "_setnonblock", mrb_basicsocket_setnonblock
, MRB_ARGS_REQ(1));
852 mrb_define_method(mrb
, bsock
, "getpeereid", mrb_basicsocket_getpeereid
, MRB_ARGS_NONE());
853 mrb_define_method(mrb
, bsock
, "getpeername", mrb_basicsocket_getpeername
, MRB_ARGS_NONE());
854 mrb_define_method(mrb
, bsock
, "getsockname", mrb_basicsocket_getsockname
, MRB_ARGS_NONE());
855 mrb_define_method(mrb
, bsock
, "getsockopt", mrb_basicsocket_getsockopt
, MRB_ARGS_REQ(2));
856 mrb_define_method(mrb
, bsock
, "recv", mrb_basicsocket_recv
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
857 // #recvmsg(maxlen, flags=0)
858 mrb_define_method(mrb
, bsock
, "send", mrb_basicsocket_send
, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(1));
861 mrb_define_method(mrb
, bsock
, "setsockopt", mrb_basicsocket_setsockopt
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(2));
862 mrb_define_method(mrb
, bsock
, "shutdown", mrb_basicsocket_shutdown
, MRB_ARGS_OPT(1));
863 mrb_define_method(mrb
, bsock
, "_is_socket=", mrb_basicsocket_set_is_socket
, MRB_ARGS_REQ(1));
865 ipsock
= mrb_define_class(mrb
, "IPSocket", bsock
);
866 mrb_define_class_method(mrb
, ipsock
, "ntop", mrb_ipsocket_ntop
, MRB_ARGS_REQ(1));
867 mrb_define_class_method(mrb
, ipsock
, "pton", mrb_ipsocket_pton
, MRB_ARGS_REQ(2));
868 mrb_define_method(mrb
, ipsock
, "recvfrom", mrb_ipsocket_recvfrom
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
870 tcpsock
= mrb_define_class(mrb
, "TCPSocket", ipsock
);
871 mrb_define_class_method(mrb
, tcpsock
, "_allocate", mrb_tcpsocket_allocate
, MRB_ARGS_NONE());
872 mrb_define_class(mrb
, "TCPServer", tcpsock
);
874 mrb_define_class(mrb
, "UDPSocket", ipsock
);
877 sock
= mrb_define_class(mrb
, "Socket", bsock
);
878 mrb_define_class_method(mrb
, sock
, "_accept", mrb_socket_accept
, MRB_ARGS_REQ(1));
879 mrb_define_class_method(mrb
, sock
, "_bind", mrb_socket_bind
, MRB_ARGS_REQ(3));
880 mrb_define_class_method(mrb
, sock
, "_connect", mrb_socket_connect
, MRB_ARGS_REQ(3));
881 mrb_define_class_method(mrb
, sock
, "_listen", mrb_socket_listen
, MRB_ARGS_REQ(2));
882 mrb_define_class_method(mrb
, sock
, "_sockaddr_family", mrb_socket_sockaddr_family
, MRB_ARGS_REQ(1));
883 mrb_define_class_method(mrb
, sock
, "_socket", mrb_socket_socket
, MRB_ARGS_REQ(3));
884 //mrb_define_class_method(mrb, sock, "gethostbyaddr", mrb_socket_gethostbyaddr, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
885 //mrb_define_class_method(mrb, sock, "gethostbyname", mrb_socket_gethostbyname, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
886 mrb_define_class_method(mrb
, sock
, "gethostname", mrb_socket_gethostname
, MRB_ARGS_NONE());
887 //mrb_define_class_method(mrb, sock, "getservbyname", mrb_socket_getservbyname, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
888 //mrb_define_class_method(mrb, sock, "getservbyport", mrb_socket_getservbyport, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
889 mrb_define_class_method(mrb
, sock
, "sockaddr_un", mrb_socket_sockaddr_un
, MRB_ARGS_REQ(1));
890 mrb_define_class_method(mrb
, sock
, "socketpair", mrb_socket_socketpair
, MRB_ARGS_REQ(3));
891 //mrb_define_method(mrb, sock, "sysaccept", mrb_socket_accept, MRB_ARGS_NONE());
894 mrb_define_class(mrb
, "UNIXSocket", bsock
);
895 //mrb_define_class_method(mrb, usock, "pair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
896 //mrb_define_class_method(mrb, usock, "socketpair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
898 //mrb_define_method(mrb, usock, "recv_io", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
899 //mrb_define_method(mrb, usock, "recvfrom", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
900 //mrb_define_method(mrb, usock, "send_io", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
903 /* Windows IO Method Overrides on BasicSocket */
905 mrb_define_method(mrb
, bsock
, "close", mrb_win32_basicsocket_close
, MRB_ARGS_NONE());
906 mrb_define_method(mrb
, bsock
, "sysread", mrb_win32_basicsocket_sysread
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
907 mrb_define_method(mrb
, bsock
, "sysseek", mrb_win32_basicsocket_sysseek
, MRB_ARGS_REQ(1));
908 mrb_define_method(mrb
, bsock
, "syswrite", mrb_win32_basicsocket_syswrite
, MRB_ARGS_REQ(1));
911 constants
= mrb_define_module_under(mrb
, sock
, "Constants");
913 #define define_const(SYM) \
915 mrb_define_const(mrb, constants, #SYM, mrb_fixnum_value(SYM)); \
918 #include "const.cstub"
922 mrb_mruby_socket_gem_final(mrb_state
* mrb
)
925 ai
= mrb_mod_cv_get(mrb
, mrb_class_get(mrb
, "Addrinfo"), mrb_intern_lit(mrb
, "_lastai"));
926 if (mrb_cptr_p(ai
)) {
927 freeaddrinfo((struct addrinfo
*)mrb_cptr(ai
));