static void getaddr(struct sockaddr **dst, int *len, char *name, char *port) { if (*name == '/') { unixaddr(dst, len, name); return; } inetaddr(dst, len, name, port); }
Object* IO::socket_read(STATE, Fixnum* bytes, Fixnum* flags, Fixnum* type) { char buf[1024]; socklen_t alen = sizeof(buf); size_t size = (size_t)bytes->to_native(); String* buffer = String::create_pinned(state, bytes); OnStack<1> variables(state, buffer); ssize_t bytes_read; native_int t = type->to_native(); retry: state->vm()->interrupt_with_signal(); state->vm()->thread()->sleep(state, cTrue); { UnmanagedPhase unmanaged(state); bytes_read = recvfrom(descriptor(state), (char*)buffer->byte_address(), size, flags->to_native(), (struct sockaddr*)buf, &alen); } state->vm()->thread()->sleep(state, cFalse); state->vm()->clear_waiter(); buffer->unpin(); if(bytes_read == -1) { if(errno == EINTR) { if(state->vm()->thread_interrupted_p(state)) return NULL; ensure_open(state); goto retry; } else { Exception::raise_errno_error(state, "read(2) failed"); } return NULL; } buffer->num_bytes(state, Fixnum::from(bytes_read)); if(t == 0) return buffer; // none Array* ary = Array::create(state, 2); ary->set(state, 0, buffer); switch(type->to_native()) { case 1: // ip // Hack from MRI: // OSX doesn't return a 'from' result from recvfrom for connection-oriented sockets if(alen && alen != sizeof(buf)) { ary->set(state, 1, ipaddr(state, (struct sockaddr*)buf, alen)); } else { ary->set(state, 1, cNil); } break; #ifndef RBX_WINDOWS case 2: // unix ary->set(state, 1, unixaddr(state, (struct sockaddr_un*)buf, alen)); break; #endif default: ary->set(state, 1, String::create(state, buf, alen)); } return ary; }