00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "rubysocket.h"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 static VALUE
00025 bsock_s_for_fd(VALUE klass, VALUE fd)
00026 {
00027 rb_io_t *fptr;
00028 VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd));
00029
00030 GetOpenFile(sock, fptr);
00031
00032 return sock;
00033 }
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 static VALUE
00063 bsock_shutdown(int argc, VALUE *argv, VALUE sock)
00064 {
00065 VALUE howto;
00066 int how;
00067 rb_io_t *fptr;
00068
00069 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
00070 rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
00071 }
00072 rb_scan_args(argc, argv, "01", &howto);
00073 if (howto == Qnil)
00074 how = SHUT_RDWR;
00075 else {
00076 how = rsock_shutdown_how_arg(howto);
00077 if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) {
00078 rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR");
00079 }
00080 }
00081 GetOpenFile(sock, fptr);
00082 if (shutdown(fptr->fd, how) == -1)
00083 rb_sys_fail(0);
00084
00085 return INT2FIX(0);
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 static VALUE
00099 bsock_close_read(VALUE sock)
00100 {
00101 rb_io_t *fptr;
00102
00103 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
00104 rb_raise(rb_eSecurityError, "Insecure: can't close socket");
00105 }
00106 GetOpenFile(sock, fptr);
00107 shutdown(fptr->fd, 0);
00108 if (!(fptr->mode & FMODE_WRITABLE)) {
00109 return rb_io_close(sock);
00110 }
00111 fptr->mode &= ~FMODE_READABLE;
00112
00113 return Qnil;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 static VALUE
00132 bsock_close_write(VALUE sock)
00133 {
00134 rb_io_t *fptr;
00135
00136 if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
00137 rb_raise(rb_eSecurityError, "Insecure: can't close socket");
00138 }
00139 GetOpenFile(sock, fptr);
00140 if (!(fptr->mode & FMODE_READABLE)) {
00141 return rb_io_close(sock);
00142 }
00143 shutdown(fptr->fd, 1);
00144 fptr->mode &= ~FMODE_WRITABLE;
00145
00146 return Qnil;
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 static VALUE
00207 bsock_setsockopt(int argc, VALUE *argv, VALUE sock)
00208 {
00209 VALUE lev, optname, val;
00210 int family, level, option;
00211 rb_io_t *fptr;
00212 int i;
00213 char *v;
00214 int vlen;
00215
00216 if (argc == 1) {
00217 lev = rb_funcall(argv[0], rb_intern("level"), 0);
00218 optname = rb_funcall(argv[0], rb_intern("optname"), 0);
00219 val = rb_funcall(argv[0], rb_intern("data"), 0);
00220 }
00221 else {
00222 rb_scan_args(argc, argv, "30", &lev, &optname, &val);
00223 }
00224
00225 rb_secure(2);
00226 GetOpenFile(sock, fptr);
00227 family = rsock_getfamily(fptr->fd);
00228 level = rsock_level_arg(family, lev);
00229 option = rsock_optname_arg(family, level, optname);
00230
00231 switch (TYPE(val)) {
00232 case T_FIXNUM:
00233 i = FIX2INT(val);
00234 goto numval;
00235 case T_FALSE:
00236 i = 0;
00237 goto numval;
00238 case T_TRUE:
00239 i = 1;
00240 numval:
00241 v = (char*)&i; vlen = (int)sizeof(i);
00242 break;
00243 default:
00244 StringValue(val);
00245 v = RSTRING_PTR(val);
00246 vlen = RSTRING_LENINT(val);
00247 break;
00248 }
00249
00250 #define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
00251
00252 rb_io_check_closed(fptr);
00253 if (setsockopt(fptr->fd, level, option, v, vlen) < 0)
00254 rb_sys_fail_path(fptr->pathv);
00255
00256 return INT2FIX(0);
00257 }
00258
00259 #if !defined(__BEOS__)
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 static VALUE
00317 bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
00318 {
00319 int level, option;
00320 socklen_t len;
00321 char *buf;
00322 rb_io_t *fptr;
00323 int family;
00324
00325 GetOpenFile(sock, fptr);
00326 family = rsock_getfamily(fptr->fd);
00327 level = rsock_level_arg(family, lev);
00328 option = rsock_optname_arg(family, level, optname);
00329 len = 256;
00330 buf = ALLOCA_N(char,len);
00331
00332 rb_io_check_closed(fptr);
00333
00334 if (getsockopt(fptr->fd, level, option, buf, &len) < 0)
00335 rb_sys_fail_path(fptr->pathv);
00336
00337 return rsock_sockopt_new(family, level, option, rb_str_new(buf, len));
00338 }
00339 #else
00340 #define bsock_getsockopt rb_f_notimplement
00341 #endif
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 static VALUE
00357 bsock_getsockname(VALUE sock)
00358 {
00359 struct sockaddr_storage buf;
00360 socklen_t len = (socklen_t)sizeof buf;
00361 rb_io_t *fptr;
00362
00363 GetOpenFile(sock, fptr);
00364 if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00365 rb_sys_fail("getsockname(2)");
00366 return rb_str_new((char*)&buf, len);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 static VALUE
00386 bsock_getpeername(VALUE sock)
00387 {
00388 struct sockaddr_storage buf;
00389 socklen_t len = (socklen_t)sizeof buf;
00390 rb_io_t *fptr;
00391
00392 GetOpenFile(sock, fptr);
00393 if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00394 rb_sys_fail("getpeername(2)");
00395 return rb_str_new((char*)&buf, len);
00396 }
00397
00398 #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 static VALUE
00422 bsock_getpeereid(VALUE self)
00423 {
00424 #if defined(HAVE_GETPEEREID)
00425 rb_io_t *fptr;
00426 uid_t euid;
00427 gid_t egid;
00428 GetOpenFile(self, fptr);
00429 if (getpeereid(fptr->fd, &euid, &egid) == -1)
00430 rb_sys_fail("getpeereid");
00431 return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
00432 #elif defined(SO_PEERCRED)
00433 rb_io_t *fptr;
00434 struct ucred cred;
00435 socklen_t len = sizeof(cred);
00436 GetOpenFile(self, fptr);
00437 if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
00438 rb_sys_fail("getsockopt(SO_PEERCRED)");
00439 return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
00440 #elif defined(HAVE_GETPEERUCRED)
00441 rb_io_t *fptr;
00442 ucred_t *uc = NULL;
00443 VALUE ret;
00444 GetOpenFile(self, fptr);
00445 if (getpeerucred(fptr->fd, &uc) == -1)
00446 rb_sys_fail("getpeerucred");
00447 ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
00448 ucred_free(uc);
00449 return ret;
00450 #endif
00451 }
00452 #else
00453 #define bsock_getpeereid rb_f_notimplement
00454 #endif
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 static VALUE
00474 bsock_local_address(VALUE sock)
00475 {
00476 struct sockaddr_storage buf;
00477 socklen_t len = (socklen_t)sizeof buf;
00478 rb_io_t *fptr;
00479
00480 GetOpenFile(sock, fptr);
00481 if (getsockname(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00482 rb_sys_fail("getsockname(2)");
00483 return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 static VALUE
00506 bsock_remote_address(VALUE sock)
00507 {
00508 struct sockaddr_storage buf;
00509 socklen_t len = (socklen_t)sizeof buf;
00510 rb_io_t *fptr;
00511
00512 GetOpenFile(sock, fptr);
00513 if (getpeername(fptr->fd, (struct sockaddr*)&buf, &len) < 0)
00514 rb_sys_fail("getpeername(2)");
00515 return rsock_fd_socket_addrinfo(fptr->fd, (struct sockaddr *)&buf, len);
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 VALUE
00536 rsock_bsock_send(int argc, VALUE *argv, VALUE sock)
00537 {
00538 struct rsock_send_arg arg;
00539 VALUE flags, to;
00540 rb_io_t *fptr;
00541 int n;
00542 rb_blocking_function_t *func;
00543
00544 rb_secure(4);
00545 rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
00546
00547 StringValue(arg.mesg);
00548 if (!NIL_P(to)) {
00549 SockAddrStringValue(to);
00550 to = rb_str_new4(to);
00551 arg.to = (struct sockaddr *)RSTRING_PTR(to);
00552 arg.tolen = (socklen_t)RSTRING_LENINT(to);
00553 func = rsock_sendto_blocking;
00554 }
00555 else {
00556 func = rsock_send_blocking;
00557 }
00558 GetOpenFile(sock, fptr);
00559 arg.fd = fptr->fd;
00560 arg.flags = NUM2INT(flags);
00561 while (rb_thread_fd_writable(arg.fd),
00562 (n = (int)BLOCKING_REGION(func, &arg)) < 0) {
00563 if (rb_io_wait_writable(arg.fd)) {
00564 continue;
00565 }
00566 rb_sys_fail("send(2)");
00567 }
00568 return INT2FIX(n);
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 static VALUE
00585 bsock_do_not_reverse_lookup(VALUE sock)
00586 {
00587 rb_io_t *fptr;
00588
00589 GetOpenFile(sock, fptr);
00590 return (fptr->mode & FMODE_NOREVLOOKUP) ? Qtrue : Qfalse;
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 static VALUE
00606 bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state)
00607 {
00608 rb_io_t *fptr;
00609
00610 rb_secure(4);
00611 GetOpenFile(sock, fptr);
00612 if (RTEST(state)) {
00613 fptr->mode |= FMODE_NOREVLOOKUP;
00614 }
00615 else {
00616 fptr->mode &= ~FMODE_NOREVLOOKUP;
00617 }
00618 return sock;
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 static VALUE
00641 bsock_recv(int argc, VALUE *argv, VALUE sock)
00642 {
00643 return rsock_s_recvfrom(sock, argc, argv, RECV_RECV);
00644 }
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 static VALUE
00692 bsock_recv_nonblock(int argc, VALUE *argv, VALUE sock)
00693 {
00694 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_RECV);
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 static VALUE
00706 bsock_do_not_rev_lookup(void)
00707 {
00708 return rsock_do_not_reverse_lookup?Qtrue:Qfalse;
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 static VALUE
00728 bsock_do_not_rev_lookup_set(VALUE self, VALUE val)
00729 {
00730 rb_secure(4);
00731 rsock_do_not_reverse_lookup = RTEST(val);
00732 return val;
00733 }
00734
00735
00736
00737
00738 void
00739 rsock_init_basicsocket(void)
00740 {
00741 rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
00742 rb_undef_method(rb_cBasicSocket, "initialize");
00743
00744 rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
00745 bsock_do_not_rev_lookup, 0);
00746 rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
00747 bsock_do_not_rev_lookup_set, 1);
00748 rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
00749
00750 rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
00751 rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
00752 rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
00753 rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, -1);
00754 rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
00755 rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
00756 rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
00757 rb_define_method(rb_cBasicSocket, "getpeereid", bsock_getpeereid, 0);
00758 rb_define_method(rb_cBasicSocket, "local_address", bsock_local_address, 0);
00759 rb_define_method(rb_cBasicSocket, "remote_address", bsock_remote_address, 0);
00760 rb_define_method(rb_cBasicSocket, "send", rsock_bsock_send, -1);
00761 rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
00762 rb_define_method(rb_cBasicSocket, "recv_nonblock", bsock_recv_nonblock, -1);
00763 rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup", bsock_do_not_reverse_lookup, 0);
00764 rb_define_method(rb_cBasicSocket, "do_not_reverse_lookup=", bsock_do_not_reverse_lookup_set, 1);
00765
00766 rb_define_method(rb_cBasicSocket, "sendmsg", rsock_bsock_sendmsg, -1);
00767 rb_define_method(rb_cBasicSocket, "sendmsg_nonblock", rsock_bsock_sendmsg_nonblock, -1);
00768 rb_define_method(rb_cBasicSocket, "recvmsg", rsock_bsock_recvmsg, -1);
00769 rb_define_method(rb_cBasicSocket, "recvmsg_nonblock", rsock_bsock_recvmsg_nonblock, -1);
00770
00771 }
00772