Skip to content

Commit 5323498

Browse files
committed
Merge pull request iij#23 from expeditiousRubyist/master
Changed Windows IO overrides to use sysread and syswrite instead
2 parents 8527c78 + c43a083 commit 5323498

File tree

1 file changed

+42
-70
lines changed

1 file changed

+42
-70
lines changed

src/socket.c

Lines changed: 42 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -663,88 +663,59 @@ mrb_win32_basicsocket_close(mrb_state *mrb, mrb_value self)
663663
return mrb_nil_value();
664664
}
665665

666+
#define E_EOF_ERROR (mrb_class_get(mrb, "EOFError"))
666667
static mrb_value
667-
mrb_win32_basicsocket_read(mrb_state *mrb, mrb_value self)
668+
mrb_win32_basicsocket_sysread(mrb_state *mrb, mrb_value self)
668669
{
669-
#define BUF_LEN 4096
670-
char buf[BUF_LEN];
671-
int sd, bytes_read;
672-
mrb_int read_len;
673-
mrb_value str = mrb_str_new(mrb, NULL, 0);
674-
mrb_value len_arg = mrb_nil_value();
675-
676-
/* For compatibility with IO::read, we accept an object instead of just
677-
* an mrb_int. Then we raise an exception if it isn't an mrb_int or nil.
678-
*/
679-
mrb_get_args(mrb, "|o", &len_arg);
680-
if (mrb_fixnum_p(len_arg)) {
681-
read_len = mrb_fixnum(len_arg);
682-
if (read_len < 0) {
683-
mrb_str_cat_cstr(mrb, str, "negative length: ");
684-
mrb_str_append(mrb, str, len_arg);
685-
mrb_str_cat_cstr(mrb, str, " given");
686-
mrb_raise(mrb, E_ARGUMENT_ERROR, mrb_string_value_cstr(mrb, &str));
687-
return mrb_nil_value();
688-
} else if (read_len == 0) {
689-
return str;
690-
}
691-
} else if (mrb_nil_p(len_arg)) {
692-
read_len = 0;
693-
} else {
694-
mrb_str_cat_cstr(mrb, str, "can't convert ");
695-
mrb_str_append(mrb, str, len_arg);
696-
mrb_str_cat_cstr(mrb, str, " into Integer");
697-
mrb_raise(mrb, E_TYPE_ERROR, mrb_string_value_cstr(mrb, &str));
670+
int sd, ret;
671+
mrb_value buf = mrb_nil_value();
672+
mrb_int maxlen;
673+
674+
mrb_get_args(mrb, "i|S", &maxlen, &buf);
675+
if (maxlen < 0) {
698676
return mrb_nil_value();
699677
}
700678

679+
if (mrb_nil_p(buf)) {
680+
buf = mrb_str_new(mrb, NULL, maxlen);
681+
}
682+
if (RSTRING_LEN(buf) != maxlen) {
683+
buf = mrb_str_resize(mrb, buf, maxlen);
684+
}
685+
701686
sd = socket_fd(mrb, self);
702-
bytes_read = 0;
703-
704-
/* Behavior of positive integer argument: read until length bytes have been
705-
* read, or until the socket has closed. */
706-
if (read_len > 0) {
707-
int n = 0;
708-
int max_read_len = BUF_LEN;
709-
int keep_reading = 1;
710-
while (keep_reading) {
711-
if (max_read_len > (read_len - bytes_read))
712-
max_read_len = read_len - bytes_read;
713-
n = recv(sd, buf, max_read_len, 0);
714-
715-
if (n == SOCKET_ERROR) {
716-
mrb_sys_fail(mrb, "recv");
717-
} else if (n == 0) {
718-
keep_reading = 0;
687+
ret = recv(sd, RSTRING_PTR(buf), maxlen, 0);
688+
689+
switch (ret) {
690+
case 0: /* EOF */
691+
if (maxlen == 0) {
692+
buf = mrb_str_new_cstr(mrb, "");
719693
} else {
720-
mrb_str_cat(mrb, str, buf, n);
721-
bytes_read += n;
722-
if (bytes_read >= read_len)
723-
keep_reading = 0;
694+
mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
724695
}
725-
}
726-
}
727-
/* Behavior of nil/default argument: read until socket has closed */
728-
else {
729-
int keep_reading = 1;
730-
while (keep_reading) {
731-
bytes_read = recv(sd, buf, BUF_LEN, 0);
732-
if (bytes_read == SOCKET_ERROR) {
733-
mrb_sys_fail(mrb, "recv");
734-
} else if (bytes_read == 0) {
735-
keep_reading = 0;
736-
} else {
737-
mrb_str_cat(mrb, str, buf, bytes_read);
696+
break;
697+
case SOCKET_ERROR: /* Error */
698+
mrb_sys_fail(mrb, "recv");
699+
break;
700+
default:
701+
if (RSTRING_LEN(buf) != ret) {
702+
buf = mrb_str_resize(mrb, buf, ret);
738703
}
739-
}
704+
break;
740705
}
741706

742-
return str;
743-
#undef BUF_LEN
707+
return buf;
708+
}
709+
710+
static mrb_value
711+
mrb_win32_basicsocket_sysseek(mrb_state *mrb, mrb_value self)
712+
{
713+
mrb_raise(mrb, E_NOTIMP_ERROR, "sysseek not implemented for windows sockets");
714+
return mrb_nil_value();
744715
}
745716

746717
static mrb_value
747-
mrb_win32_basicsocket_write(mrb_state *mrb, mrb_value self)
718+
mrb_win32_basicsocket_syswrite(mrb_state *mrb, mrb_value self)
748719
{
749720
int n;
750721
SOCKET sd;
@@ -842,8 +813,9 @@ mrb_mruby_socket_gem_init(mrb_state* mrb)
842813
/* Windows IO Method Overrides on BasicSocket */
843814
#ifdef _WIN32
844815
mrb_define_method(mrb, bsock, "close", mrb_win32_basicsocket_close, MRB_ARGS_NONE());
845-
mrb_define_method(mrb, bsock, "read", mrb_win32_basicsocket_read, MRB_ARGS_OPT(1));
846-
mrb_define_method(mrb, bsock, "write", mrb_win32_basicsocket_write, MRB_ARGS_REQ(1));
816+
mrb_define_method(mrb, bsock, "sysread", mrb_win32_basicsocket_sysread, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
817+
mrb_define_method(mrb, bsock, "sysseek", mrb_win32_basicsocket_sysseek, MRB_ARGS_REQ(1));
818+
mrb_define_method(mrb, bsock, "syswrite", mrb_win32_basicsocket_syswrite, MRB_ARGS_REQ(1));
847819
#endif
848820

849821
constants = mrb_define_module_under(mrb, sock, "Constants");

0 commit comments

Comments
 (0)