source: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-socket/src/socket.c@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 27.5 KB
Line 
1/*
2** socket.c - Socket module
3**
4** See Copyright Notice in mruby.h
5*/
6
7#ifdef _WIN32
8 #define _WIN32_WINNT 0x0501
9
10 #include <winsock2.h>
11 #include <ws2tcpip.h>
12 #include <windows.h>
13 #include <winerror.h>
14
15 #define SHUT_RDWR SD_BOTH
16 #ifndef _SSIZE_T_DEFINED
17 typedef int ssize_t;
18 #endif
19 typedef int fsize_t;
20#else
21#if defined(AZURE_SPHERE)
22 #define _GNU_SOURCE
23#endif
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/param.h>
27 #include <sys/un.h>
28 #include <netinet/in.h>
29 #include <netinet/tcp.h>
30 #include <arpa/inet.h>
31 #include <fcntl.h>
32 #include <netdb.h>
33 #include <unistd.h>
34 typedef size_t fsize_t;
35#if defined(AZURE_SPHERE)
36#define F_GETFL 3
37#define F_SETFL 4
38 int gethostname(char *, size_t);
39 int fcntl(int, int, ...);
40#endif
41#endif
42
43#include <stddef.h>
44#include <string.h>
45
46#include "mruby.h"
47#include "mruby/array.h"
48#include "mruby/class.h"
49#include "mruby/data.h"
50#include "mruby/numeric.h"
51#include "mruby/string.h"
52#include "mruby/variable.h"
53#include "mruby/error.h"
54
55#include "mruby/ext/io.h"
56
57#if !defined(HAVE_SA_LEN)
58#if (defined(BSD) && (BSD >= 199006))
59#define HAVE_SA_LEN 1
60#else
61#define HAVE_SA_LEN 0
62#endif
63#endif
64
65#define E_SOCKET_ERROR (mrb_class_get(mrb, "SocketError"))
66
67#if !defined(mrb_cptr)
68#define mrb_cptr_value(m,p) mrb_voidp_value((m),(p))
69#define mrb_cptr(o) mrb_voidp(o)
70#define mrb_cptr_p(o) mrb_voidp_p(o)
71#endif
72
73#ifdef _WIN32
74static const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
75{
76 if (af == AF_INET)
77 {
78 struct sockaddr_in in;
79 memset(&in, 0, sizeof(in));
80 in.sin_family = AF_INET;
81 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
82 getnameinfo((struct sockaddr *)&in, sizeof(struct
83 sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
84 return dst;
85 }
86 else if (af == AF_INET6)
87 {
88 struct sockaddr_in6 in;
89 memset(&in, 0, sizeof(in));
90 in.sin6_family = AF_INET6;
91 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
92 getnameinfo((struct sockaddr *)&in, sizeof(struct
93 sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
94 return dst;
95 }
96 return NULL;
97}
98
99static int inet_pton(int af, const char *src, void *dst)
100{
101 struct addrinfo hints, *res, *ressave;
102
103 memset(&hints, 0, sizeof(struct addrinfo));
104 hints.ai_family = af;
105
106 if (getaddrinfo(src, NULL, &hints, &res) != 0)
107 {
108 printf("Couldn't resolve host %s\n", src);
109 return -1;
110 }
111
112 ressave = res;
113
114 while (res)
115 {
116 memcpy(dst, res->ai_addr, res->ai_addrlen);
117 res = res->ai_next;
118 }
119
120 freeaddrinfo(ressave);
121 return 0;
122}
123
124#endif
125
126static mrb_value
127mrb_addrinfo_getaddrinfo(mrb_state *mrb, mrb_value klass)
128{
129 struct addrinfo hints, *res0, *res;
130 mrb_value ai, ary, family, lastai, nodename, protocol, sa, service, socktype;
131 mrb_int flags;
132 int arena_idx, error;
133 const char *hostname = NULL, *servname = NULL;
134
135 ary = mrb_ary_new(mrb);
136 arena_idx = mrb_gc_arena_save(mrb); /* ary must be on arena! */
137
138 family = socktype = protocol = mrb_nil_value();
139 flags = 0;
140 mrb_get_args(mrb, "oo|oooi", &nodename, &service, &family, &socktype, &protocol, &flags);
141
142 if (mrb_string_p(nodename)) {
143 hostname = RSTRING_CSTR(mrb, nodename);
144 } else if (mrb_nil_p(nodename)) {
145 hostname = NULL;
146 } else {
147 mrb_raise(mrb, E_TYPE_ERROR, "nodename must be String or nil");
148 }
149
150 if (mrb_string_p(service)) {
151 servname = RSTRING_CSTR(mrb, service);
152 } else if (mrb_fixnum_p(service)) {
153 servname = RSTRING_PTR(mrb_fixnum_to_str(mrb, service, 10));
154 } else if (mrb_nil_p(service)) {
155 servname = NULL;
156 } else {
157 mrb_raise(mrb, E_TYPE_ERROR, "service must be String, Fixnum, or nil");
158 }
159
160 memset(&hints, 0, sizeof(hints));
161 hints.ai_flags = (int)flags;
162
163 if (mrb_fixnum_p(family)) {
164 hints.ai_family = (int)mrb_fixnum(family);
165 }
166
167 if (mrb_fixnum_p(socktype)) {
168 hints.ai_socktype = (int)mrb_fixnum(socktype);
169 }
170
171 if (mrb_fixnum_p(protocol)) {
172 hints.ai_protocol = (int)mrb_fixnum(protocol);
173 }
174
175 lastai = mrb_cv_get(mrb, klass, mrb_intern_lit(mrb, "_lastai"));
176 if (mrb_cptr_p(lastai)) {
177 freeaddrinfo((struct addrinfo*)mrb_cptr(lastai));
178 mrb_cv_set(mrb, klass, mrb_intern_lit(mrb, "_lastai"), mrb_nil_value());
179 }
180
181 error = getaddrinfo(hostname, servname, &hints, &res0);
182 if (error) {
183 mrb_raisef(mrb, E_SOCKET_ERROR, "getaddrinfo: %s", gai_strerror(error));
184 }
185 mrb_cv_set(mrb, klass, mrb_intern_lit(mrb, "_lastai"), mrb_cptr_value(mrb, res0));
186
187 for (res = res0; res != NULL; res = res->ai_next) {
188 sa = mrb_str_new(mrb, (char*)res->ai_addr, res->ai_addrlen);
189 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));
190 mrb_ary_push(mrb, ary, ai);
191 mrb_gc_arena_restore(mrb, arena_idx);
192 }
193
194 freeaddrinfo(res0);
195 mrb_cv_set(mrb, klass, mrb_intern_lit(mrb, "_lastai"), mrb_nil_value());
196
197 return ary;
198}
199
200static mrb_value
201mrb_addrinfo_getnameinfo(mrb_state *mrb, mrb_value self)
202{
203 mrb_int flags;
204 mrb_value ary, host, sastr, serv;
205 int error;
206
207 flags = 0;
208 mrb_get_args(mrb, "|i", &flags);
209 host = mrb_str_buf_new(mrb, NI_MAXHOST);
210 serv = mrb_str_buf_new(mrb, NI_MAXSERV);
211
212 sastr = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@sockaddr"));
213 if (!mrb_string_p(sastr)) {
214 mrb_raise(mrb, E_SOCKET_ERROR, "invalid sockaddr");
215 }
216 error = getnameinfo((struct sockaddr *)RSTRING_PTR(sastr), (socklen_t)RSTRING_LEN(sastr), RSTRING_PTR(host), NI_MAXHOST, RSTRING_PTR(serv), NI_MAXSERV, (int)flags);
217 if (error) {
218 mrb_raisef(mrb, E_SOCKET_ERROR, "getnameinfo: %s", gai_strerror(error));
219 }
220 ary = mrb_ary_new_capa(mrb, 2);
221 mrb_str_resize(mrb, host, strlen(RSTRING_PTR(host)));
222 mrb_ary_push(mrb, ary, host);
223 mrb_str_resize(mrb, serv, strlen(RSTRING_PTR(serv)));
224 mrb_ary_push(mrb, ary, serv);
225 return ary;
226}
227
228#ifndef _WIN32
229static mrb_value
230mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self)
231{
232 mrb_value sastr;
233
234 sastr = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@sockaddr"));
235 if (((struct sockaddr *)RSTRING_PTR(sastr))->sa_family != AF_UNIX)
236 mrb_raise(mrb, E_SOCKET_ERROR, "need AF_UNIX address");
237 if (RSTRING_LEN(sastr) < (mrb_int)offsetof(struct sockaddr_un, sun_path) + 1) {
238 return mrb_str_new(mrb, "", 0);
239 } else {
240 return mrb_str_new_cstr(mrb, ((struct sockaddr_un *)RSTRING_PTR(sastr))->sun_path);
241 }
242}
243#endif
244
245static mrb_value
246sa2addrlist(mrb_state *mrb, const struct sockaddr *sa, socklen_t salen)
247{
248 mrb_value ary, host;
249 unsigned short port;
250 const char *afstr;
251
252 switch (sa->sa_family) {
253 case AF_INET:
254 afstr = "AF_INET";
255 port = ((struct sockaddr_in *)sa)->sin_port;
256 break;
257 case AF_INET6:
258 afstr = "AF_INET6";
259 port = ((struct sockaddr_in6 *)sa)->sin6_port;
260 break;
261 default:
262 mrb_raise(mrb, E_ARGUMENT_ERROR, "bad af");
263 return mrb_nil_value();
264 }
265 port = ntohs(port);
266 host = mrb_str_buf_new(mrb, NI_MAXHOST);
267 if (getnameinfo(sa, salen, RSTRING_PTR(host), NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == -1)
268 mrb_sys_fail(mrb, "getnameinfo");
269 mrb_str_resize(mrb, host, strlen(RSTRING_PTR(host)));
270 ary = mrb_ary_new_capa(mrb, 4);
271 mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, afstr));
272 mrb_ary_push(mrb, ary, mrb_fixnum_value(port));
273 mrb_ary_push(mrb, ary, host);
274 mrb_ary_push(mrb, ary, host);
275 return ary;
276}
277
278static int
279socket_fd(mrb_state *mrb, mrb_value sock)
280{
281 return (int)mrb_fixnum(mrb_funcall(mrb, sock, "fileno", 0));
282}
283
284static int
285socket_family(int s)
286{
287 struct sockaddr_storage ss;
288 socklen_t salen;
289
290 salen = sizeof(ss);
291 if (getsockname(s, (struct sockaddr *)&ss, &salen) == -1)
292 return AF_UNSPEC;
293 return ss.ss_family;
294}
295
296static mrb_value
297mrb_basicsocket_getpeereid(mrb_state *mrb, mrb_value self)
298{
299#ifdef HAVE_GETPEEREID
300 mrb_value ary;
301 gid_t egid;
302 uid_t euid;
303 int s;
304
305 s = socket_fd(mrb, self);
306 if (getpeereid(s, &euid, &egid) != 0)
307 mrb_sys_fail(mrb, "getpeereid");
308
309 ary = mrb_ary_new_capa(mrb, 2);
310 mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)euid));
311 mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)egid));
312 return ary;
313#else
314 mrb_raise(mrb, E_RUNTIME_ERROR, "getpeereid is not available on this system");
315 return mrb_nil_value();
316#endif
317}
318
319static mrb_value
320mrb_basicsocket_getpeername(mrb_state *mrb, mrb_value self)
321{
322 struct sockaddr_storage ss;
323 socklen_t salen;
324
325 salen = sizeof(ss);
326 if (getpeername(socket_fd(mrb, self), (struct sockaddr *)&ss, &salen) != 0)
327 mrb_sys_fail(mrb, "getpeername");
328
329 return mrb_str_new(mrb, (char*)&ss, salen);
330}
331
332static mrb_value
333mrb_basicsocket_getsockname(mrb_state *mrb, mrb_value self)
334{
335 struct sockaddr_storage ss;
336 socklen_t salen;
337
338 salen = sizeof(ss);
339 if (getsockname(socket_fd(mrb, self), (struct sockaddr *)&ss, &salen) != 0)
340 mrb_sys_fail(mrb, "getsockname");
341
342 return mrb_str_new(mrb, (char*)&ss, salen);
343}
344
345static mrb_value
346mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self)
347{
348 char opt[8];
349 int s;
350 mrb_int family, level, optname;
351 mrb_value c, data;
352 socklen_t optlen;
353
354 mrb_get_args(mrb, "ii", &level, &optname);
355 s = socket_fd(mrb, self);
356 optlen = sizeof(opt);
357 if (getsockopt(s, (int)level, (int)optname, opt, &optlen) == -1)
358 mrb_sys_fail(mrb, "getsockopt");
359 c = mrb_const_get(mrb, mrb_obj_value(mrb_class_get(mrb, "Socket")), mrb_intern_lit(mrb, "Option"));
360 family = socket_family(s);
361 data = mrb_str_new(mrb, opt, optlen);
362 return mrb_funcall(mrb, c, "new", 4, mrb_fixnum_value(family), mrb_fixnum_value(level), mrb_fixnum_value(optname), data);
363}
364
365static mrb_value
366mrb_basicsocket_recv(mrb_state *mrb, mrb_value self)
367{
368 ssize_t n;
369 mrb_int maxlen, flags = 0;
370 mrb_value buf;
371
372 mrb_get_args(mrb, "i|i", &maxlen, &flags);
373 buf = mrb_str_buf_new(mrb, maxlen);
374 n = recv(socket_fd(mrb, self), RSTRING_PTR(buf), (fsize_t)maxlen, (int)flags);
375 if (n == -1)
376 mrb_sys_fail(mrb, "recv");
377 mrb_str_resize(mrb, buf, (mrb_int)n);
378 return buf;
379}
380
381static mrb_value
382mrb_basicsocket_recvfrom(mrb_state *mrb, mrb_value self)
383{
384 ssize_t n;
385 mrb_int maxlen, flags = 0;
386 mrb_value ary, buf, sa;
387 socklen_t socklen;
388
389 mrb_get_args(mrb, "i|i", &maxlen, &flags);
390 buf = mrb_str_buf_new(mrb, maxlen);
391 socklen = sizeof(struct sockaddr_storage);
392 sa = mrb_str_buf_new(mrb, socklen);
393 n = recvfrom(socket_fd(mrb, self), RSTRING_PTR(buf), (fsize_t)maxlen, (int)flags, (struct sockaddr *)RSTRING_PTR(sa), &socklen);
394 if (n == -1)
395 mrb_sys_fail(mrb, "recvfrom");
396 mrb_str_resize(mrb, buf, (mrb_int)n);
397 mrb_str_resize(mrb, sa, (mrb_int)socklen);
398 ary = mrb_ary_new_capa(mrb, 2);
399 mrb_ary_push(mrb, ary, buf);
400 mrb_ary_push(mrb, ary, sa);
401 return ary;
402}
403
404static mrb_value
405mrb_basicsocket_send(mrb_state *mrb, mrb_value self)
406{
407 ssize_t n;
408 mrb_int flags;
409 mrb_value dest, mesg;
410
411 dest = mrb_nil_value();
412 mrb_get_args(mrb, "Si|S", &mesg, &flags, &dest);
413 if (mrb_nil_p(dest)) {
414 n = send(socket_fd(mrb, self), RSTRING_PTR(mesg), (fsize_t)RSTRING_LEN(mesg), (int)flags);
415 } else {
416 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));
417 }
418 if (n == -1)
419 mrb_sys_fail(mrb, "send");
420 return mrb_fixnum_value((mrb_int)n);
421}
422
423static mrb_value
424mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self)
425{
426 int fd, flags;
427 mrb_bool nonblocking;
428#ifdef _WIN32
429 u_long mode = 1;
430#endif
431
432 mrb_get_args(mrb, "b", &nonblocking);
433 fd = socket_fd(mrb, self);
434#ifdef _WIN32
435 flags = ioctlsocket(fd, FIONBIO, &mode);
436 if (flags != NO_ERROR)
437 mrb_sys_fail(mrb, "ioctlsocket");
438#else
439 flags = fcntl(fd, F_GETFL, 0);
440 if (flags == 1)
441 mrb_sys_fail(mrb, "fcntl");
442 if (nonblocking)
443 flags |= O_NONBLOCK;
444 else
445 flags &= ~O_NONBLOCK;
446 if (fcntl(fd, F_SETFL, flags) == -1)
447 mrb_sys_fail(mrb, "fcntl");
448#endif
449 return mrb_nil_value();
450}
451
452static mrb_value
453mrb_basicsocket_setsockopt(mrb_state *mrb, mrb_value self)
454{
455 int s;
456 mrb_int argc, level = 0, optname;
457 mrb_value optval, so;
458
459 argc = mrb_get_args(mrb, "o|io", &so, &optname, &optval);
460 if (argc == 3) {
461 if (!mrb_fixnum_p(so)) {
462 mrb_raise(mrb, E_ARGUMENT_ERROR, "level is not an integer");
463 }
464 level = mrb_fixnum(so);
465 if (mrb_string_p(optval)) {
466 /* that's good */
467 } else if (mrb_true_p(optval) || mrb_false_p(optval)) {
468 mrb_int i = mrb_test(optval) ? 1 : 0;
469 optval = mrb_str_new(mrb, (char*)&i, sizeof(i));
470 } else if (mrb_fixnum_p(optval)) {
471 if (optname == IP_MULTICAST_TTL || optname == IP_MULTICAST_LOOP) {
472 char uc = (char)mrb_fixnum(optval);
473 optval = mrb_str_new(mrb, &uc, sizeof(uc));
474 } else {
475 mrb_int i = mrb_fixnum(optval);
476 optval = mrb_str_new(mrb, (char*)&i, sizeof(i));
477 }
478 } else {
479 mrb_raise(mrb, E_ARGUMENT_ERROR, "optval should be true, false, an integer, or a string");
480 }
481 } else if (argc == 1) {
482 if (strcmp(mrb_obj_classname(mrb, so), "Socket::Option") != 0)
483 mrb_raise(mrb, E_ARGUMENT_ERROR, "not an instance of Socket::Option");
484 level = mrb_fixnum(mrb_funcall(mrb, so, "level", 0));
485 optname = mrb_fixnum(mrb_funcall(mrb, so, "optname", 0));
486 optval = mrb_funcall(mrb, so, "data", 0);
487 } else {
488 mrb_argnum_error(mrb, argc, 3, 3);
489 }
490
491 s = socket_fd(mrb, self);
492 if (setsockopt(s, (int)level, (int)optname, RSTRING_PTR(optval), (socklen_t)RSTRING_LEN(optval)) == -1)
493 mrb_sys_fail(mrb, "setsockopt");
494 return mrb_fixnum_value(0);
495}
496
497static mrb_value
498mrb_basicsocket_shutdown(mrb_state *mrb, mrb_value self)
499{
500 mrb_int how = SHUT_RDWR;
501
502 mrb_get_args(mrb, "|i", &how);
503 if (shutdown(socket_fd(mrb, self), (int)how) != 0)
504 mrb_sys_fail(mrb, "shutdown");
505 return mrb_fixnum_value(0);
506}
507
508static mrb_value
509mrb_basicsocket_set_is_socket(mrb_state *mrb, mrb_value self)
510{
511 mrb_bool b;
512 struct mrb_io *io_p;
513 mrb_get_args(mrb, "b", &b);
514
515 io_p = (struct mrb_io*)DATA_PTR(self);
516 if (io_p) {
517 io_p->is_socket = b;
518 }
519
520 return mrb_bool_value(b);
521}
522
523static mrb_value
524mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass)
525{
526 mrb_int af, n;
527 char *addr, buf[50];
528
529 mrb_get_args(mrb, "is", &af, &addr, &n);
530 if ((af == AF_INET && n != 4) || (af == AF_INET6 && n != 16))
531 mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
532 if (inet_ntop((int)af, addr, buf, sizeof(buf)) == NULL)
533 mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
534 return mrb_str_new_cstr(mrb, buf);
535}
536
537static mrb_value
538mrb_ipsocket_pton(mrb_state *mrb, mrb_value klass)
539{
540 mrb_int af, n;
541 char *bp, buf[50];
542
543 mrb_get_args(mrb, "is", &af, &bp, &n);
544 if ((size_t)n > sizeof(buf) - 1)
545 mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
546 memcpy(buf, bp, n);
547 buf[n] = '\0';
548
549 if (af == AF_INET) {
550 struct in_addr in;
551 if (inet_pton(AF_INET, buf, (void *)&in.s_addr) != 1)
552 goto invalid;
553 return mrb_str_new(mrb, (char*)&in.s_addr, 4);
554 } else if (af == AF_INET6) {
555 struct in6_addr in6;
556 if (inet_pton(AF_INET6, buf, (void *)&in6.s6_addr) != 1)
557 goto invalid;
558 return mrb_str_new(mrb, (char*)&in6.s6_addr, 16);
559 } else
560 mrb_raise(mrb, E_ARGUMENT_ERROR, "unsupported address family");
561
562invalid:
563 mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
564 return mrb_nil_value(); /* dummy */
565}
566
567static mrb_value
568mrb_ipsocket_recvfrom(mrb_state *mrb, mrb_value self)
569{
570 struct sockaddr_storage ss;
571 socklen_t socklen;
572 mrb_value a, buf, pair;
573 mrb_int flags, maxlen;
574 ssize_t n;
575 int fd;
576
577 fd = socket_fd(mrb, self);
578 flags = 0;
579 mrb_get_args(mrb, "i|i", &maxlen, &flags);
580 buf = mrb_str_buf_new(mrb, maxlen);
581 socklen = sizeof(ss);
582 n = recvfrom(fd, RSTRING_PTR(buf), (fsize_t)maxlen, (int)flags,
583 (struct sockaddr *)&ss, &socklen);
584 if (n == -1) {
585 mrb_sys_fail(mrb, "recvfrom");
586 }
587 mrb_str_resize(mrb, buf, (mrb_int)n);
588 a = sa2addrlist(mrb, (struct sockaddr *)&ss, socklen);
589 pair = mrb_ary_new_capa(mrb, 2);
590 mrb_ary_push(mrb, pair, buf);
591 mrb_ary_push(mrb, pair, a);
592 return pair;
593}
594
595static mrb_value
596mrb_socket_gethostname(mrb_state *mrb, mrb_value cls)
597{
598 mrb_value buf;
599 size_t bufsize;
600
601#ifdef HOST_NAME_MAX
602 bufsize = HOST_NAME_MAX + 1;
603#else
604 bufsize = 256;
605#endif
606 buf = mrb_str_buf_new(mrb, (mrb_int)bufsize);
607 if (gethostname(RSTRING_PTR(buf), (fsize_t)bufsize) != 0)
608 mrb_sys_fail(mrb, "gethostname");
609 mrb_str_resize(mrb, buf, (mrb_int)strlen(RSTRING_PTR(buf)));
610 return buf;
611}
612
613static mrb_value
614mrb_socket_accept(mrb_state *mrb, mrb_value klass)
615{
616 int s1;
617 mrb_int s0;
618
619 mrb_get_args(mrb, "i", &s0);
620 s1 = (int)accept(s0, NULL, NULL);
621 if (s1 == -1) {
622 mrb_sys_fail(mrb, "accept");
623 }
624 return mrb_fixnum_value(s1);
625}
626
627static mrb_value
628mrb_socket_accept2(mrb_state *mrb, mrb_value klass)
629{
630 mrb_value ary, sastr;
631 int s1;
632 mrb_int s0;
633 socklen_t socklen;
634
635 mrb_get_args(mrb, "i", &s0);
636 socklen = sizeof(struct sockaddr_storage);
637 sastr = mrb_str_buf_new(mrb, socklen);
638 s1 = (int)accept(s0, (struct sockaddr *)RSTRING_PTR(sastr), &socklen);
639 if (s1 == -1) {
640 mrb_sys_fail(mrb, "accept");
641 }
642 // XXX: possible descriptor leakage here!
643 mrb_str_resize(mrb, sastr, socklen);
644 ary = mrb_ary_new_capa(mrb, 2);
645 mrb_ary_push(mrb, ary, mrb_fixnum_value(s1));
646 mrb_ary_push(mrb, ary, sastr);
647 return ary;
648}
649
650static mrb_value
651mrb_socket_bind(mrb_state *mrb, mrb_value klass)
652{
653 mrb_value sastr;
654 mrb_int s;
655
656 mrb_get_args(mrb, "iS", &s, &sastr);
657 if (bind((int)s, (struct sockaddr *)RSTRING_PTR(sastr), (socklen_t)RSTRING_LEN(sastr)) == -1) {
658 mrb_sys_fail(mrb, "bind");
659 }
660 return mrb_nil_value();
661}
662
663static mrb_value
664mrb_socket_connect(mrb_state *mrb, mrb_value klass)
665{
666 mrb_value sastr;
667 mrb_int s;
668
669 mrb_get_args(mrb, "iS", &s, &sastr);
670 if (connect((int)s, (struct sockaddr *)RSTRING_PTR(sastr), (socklen_t)RSTRING_LEN(sastr)) == -1) {
671 mrb_sys_fail(mrb, "connect");
672 }
673 return mrb_nil_value();
674}
675
676static mrb_value
677mrb_socket_listen(mrb_state *mrb, mrb_value klass)
678{
679 mrb_int backlog, s;
680
681 mrb_get_args(mrb, "ii", &s, &backlog);
682 if (listen((int)s, (int)backlog) == -1) {
683 mrb_sys_fail(mrb, "listen");
684 }
685 return mrb_nil_value();
686}
687
688static mrb_value
689mrb_socket_sockaddr_family(mrb_state *mrb, mrb_value klass)
690{
691 const struct sockaddr *sa;
692 mrb_value str;
693
694 mrb_get_args(mrb, "S", &str);
695 if ((size_t)RSTRING_LEN(str) < offsetof(struct sockaddr, sa_family) + sizeof(sa->sa_family)) {
696 mrb_raise(mrb, E_SOCKET_ERROR, "invalid sockaddr (too short)");
697 }
698 sa = (const struct sockaddr *)RSTRING_PTR(str);
699 return mrb_fixnum_value(sa->sa_family);
700}
701
702static mrb_value
703mrb_socket_sockaddr_un(mrb_state *mrb, mrb_value klass)
704{
705#ifdef _WIN32
706 mrb_raise(mrb, E_NOTIMP_ERROR, "sockaddr_un unsupported on Windows");
707 return mrb_nil_value();
708#else
709 struct sockaddr_un *sunp;
710 mrb_value path, s;
711
712 mrb_get_args(mrb, "S", &path);
713 if ((size_t)RSTRING_LEN(path) > sizeof(sunp->sun_path) - 1) {
714 mrb_raisef(mrb, E_ARGUMENT_ERROR, "too long unix socket path (max: %d bytes)", (int)sizeof(sunp->sun_path) - 1);
715 }
716 s = mrb_str_buf_new(mrb, sizeof(struct sockaddr_un));
717 sunp = (struct sockaddr_un *)RSTRING_PTR(s);
718#if HAVE_SA_LEN
719 sunp->sun_len = sizeof(struct sockaddr_un);
720#endif
721 sunp->sun_family = AF_UNIX;
722 memcpy(sunp->sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
723 sunp->sun_path[RSTRING_LEN(path)] = '\0';
724 mrb_str_resize(mrb, s, sizeof(struct sockaddr_un));
725 return s;
726#endif
727}
728
729static mrb_value
730mrb_socket_socketpair(mrb_state *mrb, mrb_value klass)
731{
732#ifdef _WIN32
733 mrb_raise(mrb, E_NOTIMP_ERROR, "socketpair unsupported on Windows");
734 return mrb_nil_value();
735#else
736 mrb_value ary;
737 mrb_int domain, type, protocol;
738 int sv[2];
739
740 mrb_get_args(mrb, "iii", &domain, &type, &protocol);
741 if (socketpair(domain, type, protocol, sv) == -1) {
742 mrb_sys_fail(mrb, "socketpair");
743 }
744 // XXX: possible descriptor leakage here!
745 ary = mrb_ary_new_capa(mrb, 2);
746 mrb_ary_push(mrb, ary, mrb_fixnum_value(sv[0]));
747 mrb_ary_push(mrb, ary, mrb_fixnum_value(sv[1]));
748 return ary;
749#endif
750}
751
752static mrb_value
753mrb_socket_socket(mrb_state *mrb, mrb_value klass)
754{
755 mrb_int domain, type, protocol;
756 int s;
757
758 mrb_get_args(mrb, "iii", &domain, &type, &protocol);
759 s = (int)socket((int)domain, (int)type, (int)protocol);
760 if (s == -1)
761 mrb_sys_fail(mrb, "socket");
762 return mrb_fixnum_value(s);
763}
764
765static mrb_value
766mrb_tcpsocket_allocate(mrb_state *mrb, mrb_value klass)
767{
768 struct RClass *c = mrb_class_ptr(klass);
769 enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
770
771 /* copied from mrb_instance_alloc() */
772 if (ttype == 0) ttype = MRB_TT_OBJECT;
773 return mrb_obj_value((struct RObject*)mrb_obj_alloc(mrb, ttype, c));
774}
775
776/* Windows overrides for IO methods on BasicSocket objects.
777 * This is because sockets on Windows are not the same as file
778 * descriptors, and thus functions which operate on file descriptors
779 * will break on socket descriptors.
780 */
781#ifdef _WIN32
782static mrb_value
783mrb_win32_basicsocket_close(mrb_state *mrb, mrb_value self)
784{
785 if (closesocket(socket_fd(mrb, self)) != NO_ERROR)
786 mrb_raise(mrb, E_SOCKET_ERROR, "closesocket unsuccessful");
787 return mrb_nil_value();
788}
789
790#define E_EOF_ERROR (mrb_class_get(mrb, "EOFError"))
791static mrb_value
792mrb_win32_basicsocket_sysread(mrb_state *mrb, mrb_value self)
793{
794 int sd, ret;
795 mrb_value buf = mrb_nil_value();
796 mrb_int maxlen;
797
798 mrb_get_args(mrb, "i|S", &maxlen, &buf);
799 if (maxlen < 0) {
800 return mrb_nil_value();
801 }
802
803 if (mrb_nil_p(buf)) {
804 buf = mrb_str_new(mrb, NULL, maxlen);
805 }
806 if (RSTRING_LEN(buf) != maxlen) {
807 buf = mrb_str_resize(mrb, buf, maxlen);
808 }
809
810 sd = socket_fd(mrb, self);
811 ret = recv(sd, RSTRING_PTR(buf), (int)maxlen, 0);
812
813 switch (ret) {
814 case 0: /* EOF */
815 if (maxlen == 0) {
816 buf = mrb_str_new_cstr(mrb, "");
817 } else {
818 mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
819 }
820 break;
821 case SOCKET_ERROR: /* Error */
822 mrb_sys_fail(mrb, "recv");
823 break;
824 default:
825 if (RSTRING_LEN(buf) != ret) {
826 buf = mrb_str_resize(mrb, buf, ret);
827 }
828 break;
829 }
830
831 return buf;
832}
833
834static mrb_value
835mrb_win32_basicsocket_sysseek(mrb_state *mrb, mrb_value self)
836{
837 mrb_raise(mrb, E_NOTIMP_ERROR, "sysseek not implemented for windows sockets");
838 return mrb_nil_value();
839}
840
841static mrb_value
842mrb_win32_basicsocket_syswrite(mrb_state *mrb, mrb_value self)
843{
844 int n;
845 SOCKET sd;
846 mrb_value str;
847
848 sd = socket_fd(mrb, self);
849 mrb_get_args(mrb, "S", &str);
850 n = send(sd, RSTRING_PTR(str), (int)RSTRING_LEN(str), 0);
851 if (n == SOCKET_ERROR)
852 mrb_sys_fail(mrb, "send");
853 return mrb_fixnum_value(n);
854}
855
856#endif
857
858void
859mrb_mruby_socket_gem_init(mrb_state* mrb)
860{
861 struct RClass *io, *ai, *sock, *bsock, *ipsock, *tcpsock;
862 struct RClass *constants;
863
864#ifdef _WIN32
865 WSADATA wsaData;
866 int result;
867 result = WSAStartup(MAKEWORD(2,2), &wsaData);
868 if (result != NO_ERROR)
869 mrb_raise(mrb, E_RUNTIME_ERROR, "WSAStartup failed");
870#endif
871
872 ai = mrb_define_class(mrb, "Addrinfo", mrb->object_class);
873 mrb_mod_cv_set(mrb, ai, mrb_intern_lit(mrb, "_lastai"), mrb_nil_value());
874 mrb_define_class_method(mrb, ai, "getaddrinfo", mrb_addrinfo_getaddrinfo, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(4));
875 mrb_define_method(mrb, ai, "getnameinfo", mrb_addrinfo_getnameinfo, MRB_ARGS_OPT(1));
876#ifndef _WIN32
877 mrb_define_method(mrb, ai, "unix_path", mrb_addrinfo_unix_path, MRB_ARGS_NONE());
878#endif
879
880 io = mrb_class_get(mrb, "IO");
881
882 bsock = mrb_define_class(mrb, "BasicSocket", io);
883 mrb_define_method(mrb, bsock, "_recvfrom", mrb_basicsocket_recvfrom, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
884 mrb_define_method(mrb, bsock, "_setnonblock", mrb_basicsocket_setnonblock, MRB_ARGS_REQ(1));
885 mrb_define_method(mrb, bsock, "getpeereid", mrb_basicsocket_getpeereid, MRB_ARGS_NONE());
886 mrb_define_method(mrb, bsock, "getpeername", mrb_basicsocket_getpeername, MRB_ARGS_NONE());
887 mrb_define_method(mrb, bsock, "getsockname", mrb_basicsocket_getsockname, MRB_ARGS_NONE());
888 mrb_define_method(mrb, bsock, "getsockopt", mrb_basicsocket_getsockopt, MRB_ARGS_REQ(2));
889 mrb_define_method(mrb, bsock, "recv", mrb_basicsocket_recv, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
890 // #recvmsg(maxlen, flags=0)
891 mrb_define_method(mrb, bsock, "send", mrb_basicsocket_send, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(1));
892 // #sendmsg
893 // #sendmsg_nonblock
894 mrb_define_method(mrb, bsock, "setsockopt", mrb_basicsocket_setsockopt, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(2));
895 mrb_define_method(mrb, bsock, "shutdown", mrb_basicsocket_shutdown, MRB_ARGS_OPT(1));
896 mrb_define_method(mrb, bsock, "_is_socket=", mrb_basicsocket_set_is_socket, MRB_ARGS_REQ(1));
897
898 ipsock = mrb_define_class(mrb, "IPSocket", bsock);
899 mrb_define_class_method(mrb, ipsock, "ntop", mrb_ipsocket_ntop, MRB_ARGS_REQ(1));
900 mrb_define_class_method(mrb, ipsock, "pton", mrb_ipsocket_pton, MRB_ARGS_REQ(2));
901 mrb_define_method(mrb, ipsock, "recvfrom", mrb_ipsocket_recvfrom, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
902
903 tcpsock = mrb_define_class(mrb, "TCPSocket", ipsock);
904 mrb_define_class_method(mrb, tcpsock, "_allocate", mrb_tcpsocket_allocate, MRB_ARGS_NONE());
905 mrb_define_class(mrb, "TCPServer", tcpsock);
906
907 mrb_define_class(mrb, "UDPSocket", ipsock);
908 //#recvfrom_nonblock
909
910 sock = mrb_define_class(mrb, "Socket", bsock);
911 mrb_define_class_method(mrb, sock, "_accept", mrb_socket_accept, MRB_ARGS_REQ(1));
912 mrb_define_class_method(mrb, sock, "_accept2", mrb_socket_accept2, MRB_ARGS_REQ(1));
913 mrb_define_class_method(mrb, sock, "_bind", mrb_socket_bind, MRB_ARGS_REQ(3));
914 mrb_define_class_method(mrb, sock, "_connect", mrb_socket_connect, MRB_ARGS_REQ(3));
915 mrb_define_class_method(mrb, sock, "_listen", mrb_socket_listen, MRB_ARGS_REQ(2));
916 mrb_define_class_method(mrb, sock, "_sockaddr_family", mrb_socket_sockaddr_family, MRB_ARGS_REQ(1));
917 mrb_define_class_method(mrb, sock, "_socket", mrb_socket_socket, MRB_ARGS_REQ(3));
918 //mrb_define_class_method(mrb, sock, "gethostbyaddr", mrb_socket_gethostbyaddr, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
919 //mrb_define_class_method(mrb, sock, "gethostbyname", mrb_socket_gethostbyname, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
920 mrb_define_class_method(mrb, sock, "gethostname", mrb_socket_gethostname, MRB_ARGS_NONE());
921 //mrb_define_class_method(mrb, sock, "getservbyname", mrb_socket_getservbyname, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
922 //mrb_define_class_method(mrb, sock, "getservbyport", mrb_socket_getservbyport, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
923 mrb_define_class_method(mrb, sock, "sockaddr_un", mrb_socket_sockaddr_un, MRB_ARGS_REQ(1));
924 mrb_define_class_method(mrb, sock, "socketpair", mrb_socket_socketpair, MRB_ARGS_REQ(3));
925 //mrb_define_method(mrb, sock, "sysaccept", mrb_socket_accept, MRB_ARGS_NONE());
926
927#ifndef _WIN32
928 mrb_define_class(mrb, "UNIXSocket", bsock);
929 //mrb_define_class_method(mrb, usock, "pair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
930 //mrb_define_class_method(mrb, usock, "socketpair", mrb_unixsocket_open, MRB_ARGS_OPT(2));
931
932 //mrb_define_method(mrb, usock, "recv_io", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
933 //mrb_define_method(mrb, usock, "recvfrom", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
934 //mrb_define_method(mrb, usock, "send_io", mrb_unixsocket_peeraddr, MRB_ARGS_NONE());
935#endif
936
937 /* Windows IO Method Overrides on BasicSocket */
938#ifdef _WIN32
939 mrb_define_method(mrb, bsock, "close", mrb_win32_basicsocket_close, MRB_ARGS_NONE());
940 mrb_define_method(mrb, bsock, "sysread", mrb_win32_basicsocket_sysread, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
941 mrb_define_method(mrb, bsock, "sysseek", mrb_win32_basicsocket_sysseek, MRB_ARGS_REQ(1));
942 mrb_define_method(mrb, bsock, "syswrite", mrb_win32_basicsocket_syswrite, MRB_ARGS_REQ(1));
943#endif
944
945 constants = mrb_define_module_under(mrb, sock, "Constants");
946
947#define define_const(SYM) \
948 do { \
949 mrb_define_const(mrb, constants, #SYM, mrb_fixnum_value(SYM)); \
950 } while (0)
951
952#include "const.cstub"
953}
954
955void
956mrb_mruby_socket_gem_final(mrb_state* mrb)
957{
958 mrb_value ai;
959 ai = mrb_mod_cv_get(mrb, mrb_class_get(mrb, "Addrinfo"), mrb_intern_lit(mrb, "_lastai"));
960 if (mrb_cptr_p(ai)) {
961 freeaddrinfo((struct addrinfo*)mrb_cptr(ai));
962 }
963#ifdef _WIN32
964 WSACleanup();
965#endif
966}
Note: See TracBrowser for help on using the repository browser.