2 ** socket.c - Socket module
4 ** See Copyright Notice in mruby.h
8 #define _WIN32_WINNT 0x0501
14 #define SHUT_RDWR SD_BOTH
16 #include <sys/types.h>
17 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <netinet/tcp.h>
21 #include <arpa/inet.h>
31 #include "mruby/array.h"
32 #include "mruby/class.h"
33 #include "mruby/data.h"
34 #include "mruby/string.h"
35 #include "mruby/variable.h"
38 #define E_SOCKET_ERROR (mrb_class_get(mrb, "SocketError"))
40 #if !defined(mrb_cptr)
41 #define mrb_cptr_value(m,p) mrb_voidp_value((m),(p))
42 #define mrb_cptr(o) mrb_voidp(o)
43 #define mrb_cptr_p(o) mrb_voidp_p(o)
47 const char *inet_ntop(int af
, const void *src
, char *dst
, socklen_t cnt
)
51 struct sockaddr_in in
;
52 memset(&in
, 0, sizeof(in
));
53 in
.sin_family
= AF_INET
;
54 memcpy(&in
.sin_addr
, src
, sizeof(struct in_addr
));
55 getnameinfo((struct sockaddr
*)&in
, sizeof(struct
56 sockaddr_in
), dst
, cnt
, NULL
, 0, NI_NUMERICHOST
);
59 else if (af
== AF_INET6
)
61 struct sockaddr_in6 in
;
62 memset(&in
, 0, sizeof(in
));
63 in
.sin6_family
= AF_INET6
;
64 memcpy(&in
.sin6_addr
, src
, sizeof(struct in_addr6
));
65 getnameinfo((struct sockaddr
*)&in
, sizeof(struct
66 sockaddr_in6
), dst
, cnt
, NULL
, 0, NI_NUMERICHOST
);
72 int inet_pton(int af
, const char *src
, void *dst
)
74 struct addrinfo hints
, *res
, *ressave
;
76 memset(&hints
, 0, sizeof(struct addrinfo
));
79 if (getaddrinfo(src
, NULL
, &hints
, &res
) != 0)
81 printf("Couldn't resolve host %s\n", src
);
89 memcpy(dst
, res
->ai_addr
, res
->ai_addrlen
);
93 freeaddrinfo(ressave
);
100 mrb_addrinfo_getaddrinfo(mrb_state
*mrb
, mrb_value klass
)
102 struct addrinfo hints
, *res0
, *res
;
103 mrb_value ai
, ary
, family
, lastai
, nodename
, protocol
, sa
, service
, socktype
;
105 int arena_idx
, error
;
106 const char *hostname
= NULL
, *servname
= NULL
;
108 ary
= mrb_ary_new(mrb
);
109 arena_idx
= mrb_gc_arena_save(mrb
); /* ary must be on arena! */
111 family
= socktype
= protocol
= mrb_nil_value();
113 mrb_get_args(mrb
, "oo|oooi", &nodename
, &service
, &family
, &socktype
, &protocol
, &flags
);
115 if (mrb_string_p(nodename
)) {
116 hostname
= mrb_str_to_cstr(mrb
, nodename
);
117 } else if (mrb_nil_p(nodename
)) {
120 mrb_raise(mrb
, E_TYPE_ERROR
, "nodename must be String or nil");
123 if (mrb_string_p(service
)) {
124 servname
= mrb_str_to_cstr(mrb
, service
);
125 } else if (mrb_fixnum_p(service
)) {
126 servname
= mrb_str_to_cstr(mrb
, mrb_funcall(mrb
, service
, "to_s", 0));
127 } else if (mrb_nil_p(service
)) {
130 mrb_raise(mrb
, E_TYPE_ERROR
, "service must be String, Fixnum, or nil");
133 memset(&hints
, 0, sizeof(hints
));
134 hints
.ai_flags
= flags
;
136 if (mrb_fixnum_p(family
)) {
137 hints
.ai_family
= mrb_fixnum(family
);
140 if (mrb_fixnum_p(socktype
)) {
141 hints
.ai_socktype
= mrb_fixnum(socktype
);
144 if (mrb_fixnum_p(protocol
)) {
145 hints
.ai_protocol
= mrb_fixnum(protocol
);
148 lastai
= mrb_cv_get(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"));
149 if (mrb_cptr_p(lastai
)) {
150 freeaddrinfo(mrb_cptr(lastai
));
151 mrb_cv_set(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"), mrb_nil_value());
154 error
= getaddrinfo(hostname
, servname
, &hints
, &res0
);
156 mrb_raisef(mrb
, E_SOCKET_ERROR
, "getaddrinfo: %S", mrb_str_new_cstr(mrb
, gai_strerror(error
)));
158 mrb_cv_set(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"), mrb_cptr_value(mrb
, res0
));
160 for (res
= res0
; res
!= NULL
; res
= res
->ai_next
) {
161 sa
= mrb_str_new(mrb
, (void *)res
->ai_addr
, res
->ai_addrlen
);
162 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
));
163 mrb_ary_push(mrb
, ary
, ai
);
164 mrb_gc_arena_restore(mrb
, arena_idx
);
168 mrb_cv_set(mrb
, klass
, mrb_intern_lit(mrb
, "_lastai"), mrb_nil_value());
174 mrb_addrinfo_getnameinfo(mrb_state
*mrb
, mrb_value self
)
177 mrb_value ary
, host
, sastr
, serv
;
181 mrb_get_args(mrb
, "|i", &flags
);
182 host
= mrb_str_buf_new(mrb
, NI_MAXHOST
);
183 serv
= mrb_str_buf_new(mrb
, NI_MAXSERV
);
185 sastr
= mrb_iv_get(mrb
, self
, mrb_intern_lit(mrb
, "@sockaddr"));
186 if (!mrb_string_p(sastr
)) {
187 mrb_raise(mrb
, E_SOCKET_ERROR
, "invalid sockaddr");
189 error
= getnameinfo((struct sockaddr
*)RSTRING_PTR(sastr
), (socklen_t
)RSTRING_LEN(sastr
), RSTRING_PTR(host
), NI_MAXHOST
, RSTRING_PTR(serv
), NI_MAXSERV
, flags
);
191 mrb_raisef(mrb
, E_SOCKET_ERROR
, "getnameinfo: %s", gai_strerror(error
));
193 ary
= mrb_ary_new_capa(mrb
, 2);
194 mrb_str_resize(mrb
, host
, strlen(RSTRING_PTR(host
)));
195 mrb_ary_push(mrb
, ary
, host
);
196 mrb_str_resize(mrb
, serv
, strlen(RSTRING_PTR(serv
)));
197 mrb_ary_push(mrb
, ary
, serv
);
203 mrb_addrinfo_unix_path(mrb_state
*mrb
, mrb_value self
)
207 sastr
= mrb_iv_get(mrb
, self
, mrb_intern_lit(mrb
, "@sockaddr"));
208 if (((struct sockaddr
*)RSTRING_PTR(sastr
))->sa_family
!= AF_UNIX
)
209 mrb_raise(mrb
, E_SOCKET_ERROR
, "need AF_UNIX address");
210 return mrb_str_new_cstr(mrb
, ((struct sockaddr_un
*)RSTRING_PTR(sastr
))->sun_path
);
215 sa2addrlist(mrb_state
*mrb
, const struct sockaddr
*sa
, socklen_t salen
)
221 switch (sa
->sa_family
) {
224 port
= ((struct sockaddr_in
*)sa
)->sin_port
;
228 port
= ((struct sockaddr_in6
*)sa
)->sin6_port
;
231 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "bad af");
232 return mrb_nil_value();
235 host
= mrb_str_buf_new(mrb
, NI_MAXHOST
);
236 if (getnameinfo(sa
, salen
, RSTRING_PTR(host
), NI_MAXHOST
, NULL
, 0, NI_NUMERICHOST
) == -1)
237 mrb_sys_fail(mrb
, "getnameinfo");
238 mrb_str_resize(mrb
, host
, strlen(RSTRING_PTR(host
)));
239 ary
= mrb_ary_new_capa(mrb
, 4);
240 mrb_ary_push(mrb
, ary
, mrb_str_new_cstr(mrb
, afstr
));
241 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(port
));
242 mrb_ary_push(mrb
, ary
, host
);
243 mrb_ary_push(mrb
, ary
, host
);
248 socket_fd(mrb_state
*mrb
, mrb_value sock
)
250 return mrb_fixnum(mrb_funcall(mrb
, sock
, "fileno", 0));
256 struct sockaddr_storage ss
;
260 if (getsockname(s
, (struct sockaddr
*)&ss
, &salen
) == -1)
266 mrb_basicsocket_getpeereid(mrb_state
*mrb
, mrb_value self
)
268 #ifdef HAVE_GETPEEREID
274 s
= socket_fd(mrb
, self
);
275 if (getpeereid(s
, &euid
, &egid
) != 0)
276 mrb_sys_fail(mrb
, "getpeereid");
278 ary
= mrb_ary_new_capa(mrb
, 2);
279 mrb_ary_push(mrb
, ary
, mrb_fixnum_value((mrb_int
)euid
));
280 mrb_ary_push(mrb
, ary
, mrb_fixnum_value((mrb_int
)egid
));
283 mrb_raise(mrb
, E_RUNTIME_ERROR
, "getpeereid is not avaialble on this system");
284 return mrb_nil_value();
289 mrb_basicsocket_getpeername(mrb_state
*mrb
, mrb_value self
)
291 struct sockaddr_storage ss
;
295 if (getpeername(socket_fd(mrb
, self
), (struct sockaddr
*)&ss
, &salen
) != 0)
296 mrb_sys_fail(mrb
, "getpeername");
298 return mrb_str_new(mrb
, (void *)&ss
, salen
);
302 mrb_basicsocket_getsockname(mrb_state
*mrb
, mrb_value self
)
304 struct sockaddr_storage ss
;
308 if (getsockname(socket_fd(mrb
, self
), (struct sockaddr
*)&ss
, &salen
) != 0)
309 mrb_sys_fail(mrb
, "getsockname");
311 return mrb_str_new(mrb
, (void *)&ss
, salen
);
315 mrb_basicsocket_getsockopt(mrb_state
*mrb
, mrb_value self
)
319 mrb_int family
, level
, optname
;
323 mrb_get_args(mrb
, "ii", &level
, &optname
);
324 s
= socket_fd(mrb
, self
);
325 optlen
= sizeof(opt
);
326 if (getsockopt(s
, level
, optname
, opt
, &optlen
) == -1)
327 mrb_sys_fail(mrb
, "getsockopt");
328 c
= mrb_const_get(mrb
, mrb_obj_value(mrb_class_get(mrb
, "Socket")), mrb_intern_lit(mrb
, "Option"));
329 family
= socket_family(s
);
330 data
= mrb_str_new(mrb
, opt
, optlen
);
331 return mrb_funcall(mrb
, c
, "new", 4, mrb_fixnum_value(family
), mrb_fixnum_value(level
), mrb_fixnum_value(optname
), data
);
335 mrb_basicsocket_recv(mrb_state
*mrb
, mrb_value self
)
338 mrb_int maxlen
, flags
= 0;
341 mrb_get_args(mrb
, "i|i", &maxlen
, &flags
);
342 buf
= mrb_str_buf_new(mrb
, maxlen
);
343 n
= recv(socket_fd(mrb
, self
), RSTRING_PTR(buf
), maxlen
, flags
);
345 mrb_sys_fail(mrb
, "recv");
346 mrb_str_resize(mrb
, buf
, n
);
351 mrb_basicsocket_recvfrom(mrb_state
*mrb
, mrb_value self
)
354 mrb_int maxlen
, flags
= 0;
355 mrb_value ary
, buf
, sa
;
358 mrb_get_args(mrb
, "i|i", &maxlen
, &flags
);
359 buf
= mrb_str_buf_new(mrb
, maxlen
);
360 socklen
= sizeof(struct sockaddr_storage
);
361 sa
= mrb_str_buf_new(mrb
, socklen
);
362 n
= recvfrom(socket_fd(mrb
, self
), RSTRING_PTR(buf
), maxlen
, flags
, (struct sockaddr
*)RSTRING_PTR(sa
), &socklen
);
364 mrb_sys_fail(mrb
, "recvfrom");
365 mrb_str_resize(mrb
, buf
, n
);
366 mrb_str_resize(mrb
, sa
, socklen
);
367 ary
= mrb_ary_new_capa(mrb
, 2);
368 mrb_ary_push(mrb
, ary
, buf
);
369 mrb_ary_push(mrb
, ary
, sa
);
374 mrb_basicsocket_send(mrb_state
*mrb
, mrb_value self
)
378 mrb_value dest
, mesg
;
380 dest
= mrb_nil_value();
381 mrb_get_args(mrb
, "Si|S", &mesg
, &flags
, &dest
);
382 if (mrb_nil_p(dest
)) {
383 n
= send(socket_fd(mrb
, self
), RSTRING_PTR(mesg
), RSTRING_LEN(mesg
), flags
);
385 n
= sendto(socket_fd(mrb
, self
), RSTRING_PTR(mesg
), RSTRING_LEN(mesg
), flags
, (const void *)RSTRING_PTR(dest
), RSTRING_LEN(dest
));
388 mrb_sys_fail(mrb
, "send");
389 return mrb_fixnum_value(n
);
393 mrb_basicsocket_setnonblock(mrb_state
*mrb
, mrb_value self
)
401 mrb_get_args(mrb
, "o", &bool);
402 fd
= socket_fd(mrb
, self
);
404 flags
= ioctlsocket(fd
, FIONBIO
, &mode
);
405 if (flags
!= NO_ERROR
)
406 mrb_sys_fail(mrb
, "ioctlsocket");
408 flags
= fcntl(fd
, F_GETFL
, 0);
410 mrb_sys_fail(mrb
, "fcntl");
414 flags
&= ~O_NONBLOCK
;
415 if (fcntl(fd
, F_SETFL
, flags
) == -1)
416 mrb_sys_fail(mrb
, "fcntl");
418 return mrb_nil_value();
422 mrb_basicsocket_setsockopt(mrb_state
*mrb
, mrb_value self
)
425 mrb_int level
= 0, optname
;
426 mrb_value optval
, so
;
428 argc
= mrb_get_args(mrb
, "o|io", &so
, &optname
, &optval
);
430 if (!mrb_fixnum_p(so
)) {
431 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "level is not an integer");
433 level
= mrb_fixnum(so
);
434 if (mrb_string_p(optval
)) {
436 } else if (mrb_type(optval
) == MRB_TT_TRUE
|| mrb_type(optval
) == MRB_TT_FALSE
) {
437 mrb_int i
= mrb_test(optval
) ? 1 : 0;
438 optval
= mrb_str_new(mrb
, (char *)&i
, sizeof(i
));
439 } else if (mrb_fixnum_p(optval
)) {
440 if (optname
== IP_MULTICAST_TTL
|| optname
== IP_MULTICAST_LOOP
) {
441 char uc
= mrb_fixnum(optval
);
442 optval
= mrb_str_new(mrb
, &uc
, sizeof(uc
));
444 mrb_int i
= mrb_fixnum(optval
);
445 optval
= mrb_str_new(mrb
, (char *)&i
, sizeof(i
));
448 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "optval should be true, false, an integer, or a string");
450 } else if (argc
== 1) {
451 if (strcmp(mrb_obj_classname(mrb
, so
), "Socket::Option") != 0)
452 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "not an instance of Socket::Option");
453 level
= mrb_fixnum(mrb_funcall(mrb
, so
, "level", 0));
454 optname
= mrb_fixnum(mrb_funcall(mrb
, so
, "optname", 0));
455 optval
= mrb_funcall(mrb
, so
, "data", 0);
457 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "wrong number of arguments (%d for 3)", argc
);
460 s
= socket_fd(mrb
, self
);
461 if (setsockopt(s
, level
, optname
, RSTRING_PTR(optval
), RSTRING_LEN(optval
)) == -1)
462 mrb_sys_fail(mrb
, "setsockopt");
463 return mrb_fixnum_value(0);
467 mrb_basicsocket_shutdown(mrb_state
*mrb
, mrb_value self
)
469 mrb_int how
= SHUT_RDWR
;
471 mrb_get_args(mrb
, "|i", &how
);
472 if (shutdown(socket_fd(mrb
, self
), how
) != 0)
473 mrb_sys_fail(mrb
, "shutdown");
474 return mrb_fixnum_value(0);
478 mrb_ipsocket_ntop(mrb_state
*mrb
, mrb_value klass
)
483 mrb_get_args(mrb
, "is", &af
, &addr
, &n
);
484 if ((af
== AF_INET
&& n
!= 4) || (af
== AF_INET6
&& n
!= 16))
485 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
486 if (inet_ntop(af
, addr
, buf
, sizeof(buf
)) == NULL
)
487 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
488 return mrb_str_new_cstr(mrb
, buf
);
492 mrb_ipsocket_pton(mrb_state
*mrb
, mrb_value klass
)
497 mrb_get_args(mrb
, "is", &af
, &bp
, &n
);
498 if (n
> sizeof(buf
) - 1)
499 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
505 if (inet_pton(AF_INET
, buf
, (void *)&in
.s_addr
) != 1)
507 return mrb_str_new(mrb
, (char *)&in
.s_addr
, 4);
508 } else if (af
== AF_INET6
) {
510 if (inet_pton(AF_INET6
, buf
, (void *)&in6
.s6_addr
) != 1)
512 return mrb_str_new(mrb
, (char *)&in6
.s6_addr
, 16);
514 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "unsupported address family");
517 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "invalid address");
518 return mrb_nil_value(); /* dummy */
522 mrb_ipsocket_recvfrom(mrb_state
*mrb
, mrb_value self
)
524 struct sockaddr_storage ss
;
526 mrb_value a
, buf
, pair
;
527 mrb_int flags
, maxlen
, n
;
530 fd
= socket_fd(mrb
, self
);
532 mrb_get_args(mrb
, "i|i", &maxlen
, &flags
);
533 buf
= mrb_str_buf_new(mrb
, maxlen
);
534 socklen
= sizeof(ss
);
535 n
= recvfrom(fd
, RSTRING_PTR(buf
), maxlen
, flags
,
536 (struct sockaddr
*)&ss
, &socklen
);
538 mrb_sys_fail(mrb
, "recvfrom");
540 mrb_str_resize(mrb
, buf
, n
);
541 a
= sa2addrlist(mrb
, (struct sockaddr
*)&ss
, socklen
);
542 pair
= mrb_ary_new_capa(mrb
, 2);
543 mrb_ary_push(mrb
, pair
, buf
);
544 mrb_ary_push(mrb
, pair
, a
);
549 mrb_socket_gethostname(mrb_state
*mrb
, mrb_value cls
)
555 bufsize
= HOST_NAME_MAX
+ 1;
559 buf
= mrb_str_buf_new(mrb
, bufsize
);
560 if (gethostname(RSTRING_PTR(buf
), bufsize
) != 0)
561 mrb_sys_fail(mrb
, "gethostname");
562 mrb_str_resize(mrb
, buf
, strlen(RSTRING_PTR(buf
)));
567 mrb_socket_accept(mrb_state
*mrb
, mrb_value klass
)
569 mrb_value ary
, sastr
;
574 mrb_get_args(mrb
, "i", &s0
);
575 socklen
= sizeof(struct sockaddr_storage
);
576 sastr
= mrb_str_buf_new(mrb
, socklen
);
577 s1
= accept(s0
, (struct sockaddr
*)RSTRING_PTR(sastr
), &socklen
);
579 mrb_sys_fail(mrb
, "accept");
581 // XXX: possible descriptor leakage here!
582 mrb_str_resize(mrb
, sastr
, socklen
);
583 ary
= mrb_ary_new_capa(mrb
, 2);
584 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(s1
));
585 mrb_ary_push(mrb
, ary
, sastr
);
590 mrb_socket_bind(mrb_state
*mrb
, mrb_value klass
)
595 mrb_get_args(mrb
, "iS", &s
, &sastr
);
596 if (bind((int)s
, (struct sockaddr
*)RSTRING_PTR(sastr
), (socklen_t
)RSTRING_LEN(sastr
)) == -1) {
597 mrb_sys_fail(mrb
, "bind");
599 return mrb_nil_value();
603 mrb_socket_connect(mrb_state
*mrb
, mrb_value klass
)
608 mrb_get_args(mrb
, "iS", &s
, &sastr
);
609 if (connect((int)s
, (struct sockaddr
*)RSTRING_PTR(sastr
), (socklen_t
)RSTRING_LEN(sastr
)) == -1) {
610 mrb_sys_fail(mrb
, "connect");
612 return mrb_nil_value();
616 mrb_socket_listen(mrb_state
*mrb
, mrb_value klass
)
620 mrb_get_args(mrb
, "ii", &s
, &backlog
);
621 if (listen((int)s
, (int)backlog
) == -1) {
622 mrb_sys_fail(mrb
, "listen");
624 return mrb_nil_value();
628 mrb_socket_sockaddr_family(mrb_state
*mrb
, mrb_value klass
)
632 mrb_get_args(mrb
, "S", &sa
);
634 if (RSTRING_LEN(sa
) < offsetof(struct sockaddr
, sa_family
) + sizeof(sa_family_t
)) {
635 mrb_raisef(mrb
, E_SOCKET_ERROR
, "invalid sockaddr (too short)");
638 if (RSTRING_LEN(sa
) < sizeof(struct sockaddr
)) {
639 mrb_raisef(mrb
, E_SOCKET_ERROR
, "invalid sockaddr (too short)");
642 return mrb_fixnum_value(((struct sockaddr
*)RSTRING_PTR(sa
))->sa_family
);
646 mrb_socket_sockaddr_un(mrb_state
*mrb
, mrb_value klass
)
649 mrb_raise(mrb
, E_NOTIMP_ERROR
, "sockaddr_un unsupported on Windows");
650 return mrb_nil_value();
652 struct sockaddr_un
*sunp
;
655 mrb_get_args(mrb
, "S", &path
);
656 if (RSTRING_LEN(path
) > sizeof(sunp
->sun_path
) - 1) {
657 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "too long unix socket path (max: %ubytes)", (unsigned int)sizeof(sunp
->sun_path
) - 1);
659 s
= mrb_str_buf_new(mrb
, sizeof(struct sockaddr_un
));
660 sunp
= (struct sockaddr_un
*)RSTRING_PTR(s
);
661 sunp
->sun_family
= AF_UNIX
;
662 memcpy(sunp
->sun_path
, RSTRING_PTR(path
), RSTRING_LEN(path
));
663 sunp
->sun_path
[RSTRING_LEN(path
)] = '\0';
664 mrb_str_resize(mrb
, s
, sizeof(struct sockaddr_un
));
670 mrb_socket_socketpair(mrb_state
*mrb
, mrb_value klass
)
673 mrb_raise(mrb
, E_NOTIMP_ERROR
, "socketpair unsupported on Windows");
674 return mrb_nil_value();
677 mrb_int domain
, type
, protocol
;
680 mrb_get_args(mrb
, "iii", &domain
, &type
, &protocol
);
681 if (socketpair(domain
, type
, protocol
, sv
) == -1) {
682 mrb_sys_fail(mrb
, "socketpair");
684 // XXX: possible descriptor leakage here!
685 ary
= mrb_ary_new_capa(mrb
, 2);
686 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(sv
[0]));
687 mrb_ary_push(mrb
, ary
, mrb_fixnum_value(sv
[1]));
693 mrb_socket_socket(mrb_state
*mrb
, mrb_value klass
)
695 mrb_int domain
, type
, protocol
;
698 mrb_get_args(mrb
, "iii", &domain
, &type
, &protocol
);
699 s
= socket(domain
, type
, protocol
);
701 mrb_sys_fail(mrb
, "socket");
702 return mrb_fixnum_value(s
);
706 mrb_tcpsocket_allocate(mrb_state
*mrb
, mrb_value klass
)
708 struct RClass
*c
= mrb_class_ptr(klass
);
709 enum mrb_vtype ttype
= MRB_INSTANCE_TT(c
);
711 /* copied from mrb_instance_alloc() */
712 if (ttype
== 0) ttype
= MRB_TT_OBJECT
;
713 return mrb_obj_value((struct RObject
*)mrb_obj_alloc(mrb
, ttype
, c
));
716 /* Windows overrides for IO methods on BasicSocket objects.
717 * This is because sockets on Windows are not the same as file
718 * descriptors, and thus functions which operate on file descriptors
719 * will break on socket descriptors.
723 mrb_win32_basicsocket_close(mrb_state
*mrb
, mrb_value self
)
725 if (closesocket(socket_fd(mrb
, self
)) != NO_ERROR
)
726 mrb_raise(mrb
, E_SOCKET_ERROR
, "closesocket unsuccessful");
727 return mrb_nil_value();
730 #define E_EOF_ERROR (mrb_class_get(mrb, "EOFError"))
732 mrb_win32_basicsocket_sysread(mrb_state
*mrb
, mrb_value self
)
735 mrb_value buf
= mrb_nil_value();
738 mrb_get_args(mrb
, "i|S", &maxlen
, &buf
);
740 return mrb_nil_value();
743 if (mrb_nil_p(buf
)) {
744 buf
= mrb_str_new(mrb
, NULL
, maxlen
);
746 if (RSTRING_LEN(buf
) != maxlen
) {
747 buf
= mrb_str_resize(mrb
, buf
, maxlen
);
750 sd
= socket_fd(mrb
, self
);
751 ret
= recv(sd
, RSTRING_PTR(buf
), maxlen
, 0);
756 buf
= mrb_str_new_cstr(mrb
, "");
758 mrb_raise(mrb
, E_EOF_ERROR
, "sysread failed: End of File");
761 case SOCKET_ERROR
: /* Error */
762 mrb_sys_fail(mrb
, "recv");
765 if (RSTRING_LEN(buf
) != ret
) {
766 buf
= mrb_str_resize(mrb
, buf
, ret
);
775 mrb_win32_basicsocket_sysseek(mrb_state
*mrb
, mrb_value self
)
777 mrb_raise(mrb
, E_NOTIMP_ERROR
, "sysseek not implemented for windows sockets");
778 return mrb_nil_value();
782 mrb_win32_basicsocket_syswrite(mrb_state
*mrb
, mrb_value self
)
788 sd
= socket_fd(mrb
, self
);
789 mrb_get_args(mrb
, "S", &str
);
790 n
= send(sd
, RSTRING_PTR(str
), RSTRING_LEN(str
), 0);
791 if (n
== SOCKET_ERROR
)
792 mrb_sys_fail(mrb
, "send");
793 return mrb_fixnum_value(n
);
799 mrb_mruby_socket_gem_init(mrb_state
* mrb
)
801 struct RClass
*io
, *ai
, *sock
, *bsock
, *ipsock
, *tcpsock
;
802 struct RClass
*constants
;
807 result
= WSAStartup(MAKEWORD(2,2), &wsaData
);
808 if (result
!= NO_ERROR
)
809 mrb_raise(mrb
, E_RUNTIME_ERROR
, "WSAStartup failed");
811 struct RClass
*usock
;
814 ai
= mrb_define_class(mrb
, "Addrinfo", mrb
->object_class
);
815 mrb_mod_cv_set(mrb
, ai
, mrb_intern_lit(mrb
, "_lastai"), mrb_nil_value());
816 mrb_define_class_method(mrb
, ai
, "getaddrinfo", mrb_addrinfo_getaddrinfo
, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(4));
817 mrb_define_method(mrb
, ai
, "getnameinfo", mrb_addrinfo_getnameinfo
, MRB_ARGS_OPT(1));
819 mrb_define_method(mrb
, ai
, "unix_path", mrb_addrinfo_unix_path
, MRB_ARGS_NONE());
822 io
= mrb_class_get(mrb
, "IO");
824 bsock
= mrb_define_class(mrb
, "BasicSocket", io
);
825 mrb_define_method(mrb
, bsock
, "_recvfrom", mrb_basicsocket_recvfrom
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
826 mrb_define_method(mrb
, bsock
, "_setnonblock", mrb_basicsocket_setnonblock
, MRB_ARGS_REQ(1));
827 mrb_define_method(mrb
, bsock
, "getpeereid", mrb_basicsocket_getpeereid
, MRB_ARGS_NONE());
828 mrb_define_method(mrb
, bsock
, "getpeername", mrb_basicsocket_getpeername
, MRB_ARGS_NONE());
829 mrb_define_method(mrb
, bsock
, "getsockname", mrb_basicsocket_getsockname
, MRB_ARGS_NONE());
830 mrb_define_method(mrb
, bsock
, "getsockopt", mrb_basicsocket_getsockopt
, MRB_ARGS_REQ(2));
831 mrb_define_method(mrb
, bsock
, "recv", mrb_basicsocket_recv
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
832 // #recvmsg(maxlen, flags=0)
833 mrb_define_method(mrb
, bsock
, "send", mrb_basicsocket_send
, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(1));
836 mrb_define_method(mrb
, bsock
, "setsockopt", mrb_basicsocket_setsockopt
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(2));
837 mrb_define_method(mrb
, bsock
, "shutdown", mrb_basicsocket_shutdown
, MRB_ARGS_OPT(1));
839 ipsock
= mrb_define_class(mrb
, "IPSocket", bsock
);
840 mrb_define_class_method(mrb
, ipsock
, "ntop", mrb_ipsocket_ntop
, MRB_ARGS_REQ(1));
841 mrb_define_class_method(mrb
, ipsock
, "pton", mrb_ipsocket_pton
, MRB_ARGS_REQ(2));
842 mrb_define_method(mrb
, ipsock
, "recvfrom", mrb_ipsocket_recvfrom
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
844 tcpsock
= mrb_define_class(mrb
, "TCPSocket", ipsock
);
845 mrb_define_class_method(mrb
, tcpsock
, "_allocate", mrb_tcpsocket_allocate
, MRB_ARGS_NONE());
846 mrb_define_class(mrb
, "TCPServer", tcpsock
);
848 mrb_define_class(mrb
, "UDPSocket", ipsock
);
851 sock
= mrb_define_class(mrb
, "Socket", bsock
);
852 mrb_define_class_method(mrb
, sock
, "_accept", mrb_socket_accept
, MRB_ARGS_REQ(1));
853 mrb_define_class_method(mrb
, sock
, "_bind", mrb_socket_bind
, MRB_ARGS_REQ(3));
854 mrb_define_class_method(mrb
, sock
, "_connect", mrb_socket_connect
, MRB_ARGS_REQ(3));
855 mrb_define_class_method(mrb
, sock
, "_listen", mrb_socket_listen
, MRB_ARGS_REQ(2));
856 mrb_define_class_method(mrb
, sock
, "_sockaddr_family", mrb_socket_sockaddr_family
, MRB_ARGS_REQ(1));
857 mrb_define_class_method(mrb
, sock
, "_socket", mrb_socket_socket
, MRB_ARGS_REQ(3));
858 //mrb_define_class_method(mrb, sock, "gethostbyaddr", mrb_socket_gethostbyaddr, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
859 //mrb_define_class_method(mrb, sock, "gethostbyname", mrb_socket_gethostbyname, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
860 mrb_define_class_method(mrb
, sock
, "gethostname", mrb_socket_gethostname
, MRB_ARGS_NONE());
861 //mrb_define_class_method(mrb, sock, "getservbyname", mrb_socket_getservbyname, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
862 //mrb_define_class_method(mrb, sock, "getservbyport", mrb_socket_getservbyport, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
863 mrb_define_class_method(mrb
, sock
, "sockaddr_un", mrb_socket_sockaddr_un
, MRB_ARGS_REQ(1));
864 mrb_define_class_method(mrb
, sock
, "socketpair", mrb_socket_socketpair
, MRB_ARGS_REQ(3));
865 //mrb_define_method(mrb, sock, "sysaccept", mrb_socket_accept, MRB_ARGS_NONE());
868 usock
= mrb_define_class(mrb
, "UNIXSocket", bsock
);
870 //mrb_define_class_method(mrb, usock, "pair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
871 //mrb_define_class_method(mrb, usock, "socketpair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
873 //mrb_define_method(mrb, usock, "recv_io", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
874 //mrb_define_method(mrb, usock, "recvfrom", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
875 //mrb_define_method(mrb, usock, "send_io", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
877 /* Windows IO Method Overrides on BasicSocket */
879 mrb_define_method(mrb
, bsock
, "close", mrb_win32_basicsocket_close
, MRB_ARGS_NONE());
880 mrb_define_method(mrb
, bsock
, "sysread", mrb_win32_basicsocket_sysread
, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
881 mrb_define_method(mrb
, bsock
, "sysseek", mrb_win32_basicsocket_sysseek
, MRB_ARGS_REQ(1));
882 mrb_define_method(mrb
, bsock
, "syswrite", mrb_win32_basicsocket_syswrite
, MRB_ARGS_REQ(1));
885 constants
= mrb_define_module_under(mrb
, sock
, "Constants");
887 #define define_const(SYM) \
889 mrb_define_const(mrb, constants, #SYM, mrb_fixnum_value(SYM)); \
892 #include "const.cstub"
896 mrb_mruby_socket_gem_final(mrb_state
* mrb
)
899 ai
= mrb_mod_cv_get(mrb
, mrb_class_get(mrb
, "Addrinfo"), mrb_intern_lit(mrb
, "_lastai"));
900 if (mrb_cptr_p(ai
)) {
901 freeaddrinfo(mrb_cptr(ai
));