static mrb_value mrb_basicsocket_send(mrb_state *mrb, mrb_value self) { int n; mrb_int flags; mrb_value dest, mesg; dest = mrb_nil_value(); mrb_get_args(mrb, "Si|S", &mesg, &flags, &dest); if (mrb_nil_p(dest)) { n = send(socket_fd(mrb, self), RSTRING_PTR(mesg), RSTRING_LEN(mesg), flags); } else { n = sendto(socket_fd(mrb, self), RSTRING_PTR(mesg), RSTRING_LEN(mesg), flags, (const void *)RSTRING_PTR(dest), RSTRING_LEN(dest)); } if (n == -1) mrb_sys_fail(mrb, "send"); return mrb_fixnum_value(n); }
static mrb_value mrb_basicsocket_getsockname(mrb_state *mrb, mrb_value self) { struct sockaddr_storage ss; socklen_t salen; salen = sizeof(ss); if (getsockname(socket_fd(mrb, self), (struct sockaddr *)&ss, &salen) != 0) mrb_sys_fail(mrb, "getsockname"); return mrb_str_new(mrb, (void *)&ss, salen); }
static mrb_value mrb_basicsocket_recv(mrb_state *mrb, mrb_value self) { int n; mrb_int maxlen, flags = 0; mrb_value buf; mrb_get_args(mrb, "i|i", &maxlen, &flags); buf = mrb_str_buf_new(mrb, maxlen); n = recv(socket_fd(mrb, self), RSTRING_PTR(buf), maxlen, flags); if (n == -1) mrb_sys_fail(mrb, "recv"); mrb_str_resize(mrb, buf, n); return buf; }
static mrb_value mrb_basicsocket_getsockopt(mrb_state *mrb, mrb_value self) { char opt[8]; int s; mrb_int family, level, optname; mrb_value c, data; socklen_t optlen; mrb_get_args(mrb, "ii", &level, &optname); s = socket_fd(mrb, self); optlen = sizeof(opt); if (getsockopt(s, level, optname, opt, &optlen) == -1) mrb_sys_fail(mrb, "getsockopt"); c = mrb_const_get(mrb, mrb_obj_value(mrb_class_get(mrb, "Socket")), mrb_intern_lit(mrb, "Option")); family = socket_family(s); data = mrb_str_new(mrb, opt, optlen); return mrb_funcall(mrb, c, "new", 4, mrb_fixnum_value(family), mrb_fixnum_value(level), mrb_fixnum_value(optname), data); }
static mrb_value mrb_basicsocket_setnonblock(mrb_state *mrb, mrb_value self) { int fd, flags; mrb_value bool; #ifdef _WIN32 u_long mode = 1; #endif mrb_get_args(mrb, "o", &bool); fd = socket_fd(mrb, self); #ifdef _WIN32 flags = ioctlsocket(fd, FIONBIO, &mode); if (flags != NO_ERROR) mrb_sys_fail(mrb, "ioctlsocket"); #else flags = fcntl(fd, F_GETFL, 0); if (flags == 1) mrb_sys_fail(mrb, "fcntl"); if (mrb_test(bool)) flags |= O_NONBLOCK; else
static mrb_value mrb_basicsocket_recvfrom(mrb_state *mrb, mrb_value self) { int n; mrb_int maxlen, flags = 0; mrb_value ary, buf, sa; socklen_t socklen; mrb_get_args(mrb, "i|i", &maxlen, &flags); buf = mrb_str_buf_new(mrb, maxlen); socklen = sizeof(struct sockaddr_storage); sa = mrb_str_buf_new(mrb, socklen); n = recvfrom(socket_fd(mrb, self), RSTRING_PTR(buf), maxlen, flags, (struct sockaddr *)RSTRING_PTR(sa), &socklen); if (n == -1) mrb_sys_fail(mrb, "recvfrom"); mrb_str_resize(mrb, buf, n); mrb_str_resize(mrb, sa, socklen); ary = mrb_ary_new_capa(mrb, 2); mrb_ary_push(mrb, ary, buf); mrb_ary_push(mrb, ary, sa); return ary; }
static mrb_value mrb_basicsocket_getpeereid(mrb_state *mrb, mrb_value self) { #ifdef HAVE_GETPEEREID mrb_value ary; gid_t egid; uid_t euid; int s; s = socket_fd(mrb, self); if (getpeereid(s, &euid, &egid) != 0) mrb_sys_fail(mrb, "getpeereid"); ary = mrb_ary_new_capa(mrb, 2); mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)euid)); mrb_ary_push(mrb, ary, mrb_fixnum_value((mrb_int)egid)); return ary; #else mrb_raise(mrb, E_RUNTIME_ERROR, "getpeereid is not avaialble on this system"); return mrb_nil_value(); #endif }
static inline int emulate_poll_with_select(struct pollfd *fds, unsigned int n, int timeout) { struct timeval tv; unsigned i; fd_set rfds, wfds, efds; int ret, max_fd = -1; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); for (i = 0; i < n; i++) { int fd = cast_to_fd(fds[i].fd); safety_assert(!is_valid_fd(fd) || is_a_socket(fd) || is_a_fifo(fd)); if (!is_okay_for_select(fd) || i >= FD_SETSIZE) { fds[i].revents = POLLERR; continue; } max_fd = MAX(fd, max_fd); fds[i].revents = 0; if (POLLIN & fds[i].events) { FD_SET(socket_fd(fd), &rfds); } if (POLLOUT & fds[i].events) { FD_SET(socket_fd(fd), &wfds); } FD_SET(socket_fd(fd), &efds); } if (timeout >= 0) { tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000UL; } ret = select(max_fd + 1, &rfds, &wfds, &efds, timeout < 0 ? NULL : &tv); if (ret > 0) { n = MIN(n, FD_SETSIZE); /* POLLERR is already set above */ for (i = 0; i < n; i++) { int fd = cast_to_fd(fds[i].fd); if (!is_okay_for_select(fd)) continue; if (FD_ISSET(fd, &rfds)) { fds[i].revents |= POLLIN; } if (FD_ISSET(fd, &wfds)) { fds[i].revents |= POLLOUT; } if (FD_ISSET(fd, &efds)) { fds[i].revents |= POLLERR; } } } else if (ret < 0) { s_warning("error during select(): %m"); } return ret; }
** Last update Fri Jul 4 18:31:02 2014 raphael defreitas */ #include <stdlib.h> #include <sys/select.h> #include "list.h" #include "socket.h" #include "zappy.h" #include "_zappy.h" static void set_fds(t_zc *this) { FD_ZERO(&this->rfds); FD_ZERO(&this->wfds); FD_SET(socket_fd(this->socket), &this->rfds); FD_SET(0, &this->rfds); if (list_length(this->pckts_to_snd) > 0) FD_SET(socket_fd(this->socket), &this->wfds); } static int zc_select(t_zc *this) { t_timeval to; set_fds(this); to = this->timeout; if (to.tv_sec == 0 && to.tv_usec == 0) return (select(FD_SETSIZE, &this->rfds, &this->wfds, NULL, NULL)); return (select(FD_SETSIZE, &this->rfds, &this->wfds, NULL, &to)); }
int main(int argc, char** argv) { enum { UNCRYPT, SETUP_BCB, CLEAR_BCB, UNCRYPT_DEBUG } action; const char* input_path = nullptr; const char* map_file = CACHE_BLOCK_MAP.c_str(); if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) { action = CLEAR_BCB; } else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) { action = SETUP_BCB; } else if (argc == 1) { action = UNCRYPT; } else if (argc == 3) { input_path = argv[1]; map_file = argv[2]; action = UNCRYPT_DEBUG; } else { usage(argv[0]); return 2; } if ((fstab = read_fstab()) == nullptr) { log_uncrypt_error_code(kUncryptFstabReadError); return 1; } if (action == UNCRYPT_DEBUG) { LOG(INFO) << "uncrypt called in debug mode, skip socket communication"; bool success = uncrypt_wrapper(input_path, map_file, -1); if (success) { LOG(INFO) << "uncrypt succeeded"; } else{ LOG(INFO) << "uncrypt failed"; } return success ? 0 : 1; } // c3. The socket is created by init when starting the service. uncrypt // will use the socket to communicate with its caller. android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str())); if (service_socket == -1) { PLOG(ERROR) << "failed to open socket \"" << UNCRYPT_SOCKET << "\""; log_uncrypt_error_code(kUncryptSocketOpenError); return 1; } fcntl(service_socket, F_SETFD, FD_CLOEXEC); if (listen(service_socket, 1) == -1) { PLOG(ERROR) << "failed to listen on socket " << service_socket.get(); log_uncrypt_error_code(kUncryptSocketListenError); return 1; } android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC)); if (socket_fd == -1) { PLOG(ERROR) << "failed to accept on socket " << service_socket.get(); log_uncrypt_error_code(kUncryptSocketAcceptError); return 1; } bool success = false; switch (action) { case UNCRYPT: success = uncrypt_wrapper(input_path, map_file, socket_fd); break; case SETUP_BCB: success = setup_bcb(socket_fd); break; case CLEAR_BCB: success = clear_bcb(socket_fd); break; default: // Should never happen. LOG(ERROR) << "Invalid uncrypt action code: " << action; return 1; } // c13. Read a 4-byte code from the client before uncrypt exits. This is to // ensure the client to receive the last status code before the socket gets // destroyed. int code; if (android::base::ReadFully(socket_fd, &code, 4)) { LOG(INFO) << " received " << code << ", exiting now"; } else { PLOG(ERROR) << "failed to read the code"; } return success ? 0 : 1; }