int fd_collection::addpipe(int fdrd, int fdwr) { fdcoll_logfunc("fdrd=%d, fdwr=%d", fdrd, fdwr); if (!is_valid_fd(fdrd) || !is_valid_fd(fdwr)) return -1; lock(); // Sanity check to remove any old objects using the same fd!! socket_fd_api* p_fdrd_api_obj = get_sockfd(fdrd); BULLSEYE_EXCLUDE_BLOCK_START if (p_fdrd_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate object (%p)", fdrd, p_fdrd_api_obj); unlock(); handle_close(fdrd, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END socket_fd_api* p_fdwr_api_obj = get_sockfd(fdwr); BULLSEYE_EXCLUDE_BLOCK_START if (p_fdwr_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate object (%p)", fdwr, p_fdwr_api_obj); unlock(); handle_close(fdwr, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END unlock(); p_fdrd_api_obj = new pipeinfo(fdrd); p_fdwr_api_obj = new pipeinfo(fdwr); lock(); BULLSEYE_EXCLUDE_BLOCK_START if (p_fdrd_api_obj == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new pipeinfo (%m)", fdrd); } if (p_fdwr_api_obj == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new pipeinfo (%m)", fdwr); } BULLSEYE_EXCLUDE_BLOCK_END m_p_sockfd_map[fdrd] = p_fdrd_api_obj; m_p_sockfd_map[fdwr] = p_fdwr_api_obj; unlock(); return 0; }
int fd_collection::addepfd(int epfd, int size) { fdcoll_logfunc("epfd=%d", epfd); if (!is_valid_fd(epfd)) return -1; lock(); // Sanity check to remove any old sockinfo object using the same fd!! epfd_info* p_fd_info = get_epfd(epfd); if (p_fd_info) { fdcoll_logwarn("[fd=%d] Deleting old duplicate sockinfo object (%p)", epfd, p_fd_info); unlock(); handle_close(epfd, true); lock(); } unlock(); p_fd_info = new epfd_info(epfd, size); lock(); BULLSEYE_EXCLUDE_BLOCK_START if (p_fd_info == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new sockinfo (%m)", epfd); } BULLSEYE_EXCLUDE_BLOCK_END m_p_epfd_map[epfd] = p_fd_info; m_epfd_lst.push_back(p_fd_info); unlock(); return 0; }
static inline ssize_t tls_pull(gnutls_transport_ptr ptr, void *buf, size_t size) { struct gnutella_socket *s = ptr; ssize_t ret; int saved_errno; socket_check(s); g_assert(is_valid_fd(s->file_desc)); ret = s_read(s->file_desc, buf, size); saved_errno = errno; tls_signal_pending(s); if ((ssize_t) -1 == ret) { tls_set_errno(s, saved_errno); if (!is_temporary_error(saved_errno)) { socket_connection_reset(s); } } else if (0 == ret) { socket_eof(s); } tls_transport_debug("tls_pull", s, size, ret); errno = saved_errno; return ret; }
static struct file_object * file_object_alloc(const int fd, const char * const pathname, int accmode) { static const struct file_object zero_fo; struct file_object *fo; hikset_t *ht; g_return_val_if_fail(fd >= 0, NULL); g_return_val_if_fail(pathname, NULL); g_return_val_if_fail(is_absolute_path(pathname), NULL); g_return_val_if_fail(!file_object_find(pathname, accmode), NULL); ht = file_object_mode_get_table(accmode); g_return_val_if_fail(ht, NULL); WALLOC(fo); *fo = zero_fo; fo->magic = FILE_OBJECT_MAGIC; fo->ref_count = 1; fo->fd = fd; fo->accmode = accmode; fo->pathname = atom_str_get(pathname); file_object_check(fo); g_assert(is_valid_fd(fo->fd)); hikset_insert(ht, fo); return fo; }
/** * Uses fstat() or getsockopt() to determine whether the given file descriptor * is a socket. * * @param fd An arbitrary file descriptor. * @return TRUE if fd is a socket, FALSE otherwise. */ bool is_a_socket(int fd) #ifdef S_ISSOCK { filestat_t sb; return is_valid_fd(fd) && 0 == fstat(fd, &sb) && 0 != S_ISSOCK(sb.st_mode); }
void fd_collection::del_tapfd(int fd) { if (!is_valid_fd(fd)) return; lock(); m_p_tap_map[fd] = NULL; unlock(); }
int close(int fd) { if (!is_valid_fd(fd)) return -1; fd_array[fd].type = FILEIO_TYPE_EMPTY; return 0; }
int fd_collection::add_cq_channel_fd(int cq_ch_fd, ring* p_ring) { fdcoll_logfunc("cq_ch_fd=%d", cq_ch_fd); if (!is_valid_fd(cq_ch_fd)) return -1; lock(); epfd_info* p_fd_info = get_epfd(cq_ch_fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_fd_info) { fdcoll_logwarn("[fd=%d] Deleting old duplicate sockinfo object (%p)", cq_ch_fd, p_fd_info); unlock(); handle_close(cq_ch_fd, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END // Sanity check to remove any old objects using the same fd!! socket_fd_api* p_cq_ch_fd_api_obj = get_sockfd(cq_ch_fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_cq_ch_fd_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate object (%p)", cq_ch_fd, p_cq_ch_fd_api_obj); unlock(); handle_close(cq_ch_fd, true); lock(); } BULLSEYE_EXCLUDE_BLOCK_END // Check if cq_channel_info was already created cq_channel_info* p_cq_ch_info = get_cq_channel_fd(cq_ch_fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_cq_ch_info) { fdcoll_logwarn("cq channel fd already exists in fd_collection"); m_p_cq_channel_map[cq_ch_fd] = NULL; delete p_cq_ch_info; p_cq_ch_info = NULL; } BULLSEYE_EXCLUDE_BLOCK_END unlock(); p_cq_ch_info = new cq_channel_info(p_ring); lock(); BULLSEYE_EXCLUDE_BLOCK_START if (p_cq_ch_info == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new cq_channel_info (%m)", cq_ch_fd); } BULLSEYE_EXCLUDE_BLOCK_END m_p_cq_channel_map[cq_ch_fd] = p_cq_ch_info; unlock(); return 0; }
/** * Standard recv function for the libc. * * @param fd socket file descriptor * @param buf pointer to the array where the packet should be stored * @param len maximum length in bytes of the packet * @param flags currently unused, should be 0 * @return the number of bytes that have been received successfully */ int recv(int fd, void *buf, int len, int flags) { if (!is_valid_fd(fd)) return -1; forth_push((unsigned long)buf); forth_push(len); forth_push(fd_array[fd].read_xt); return forth_eval_pop("EXECUTE"); }
/** * Standard send function for the libc. * * @param fd socket file descriptor * @param buf pointer to the array with the output packet * @param len length in bytes of the packet * @param flags currently unused, should be 0 * @return the number of bytes that have been sent successfully */ int send(int fd, const void *buf, int len, int flags) { if (!is_valid_fd(fd)) return -1; forth_push((unsigned long)buf); forth_push(len); forth_push(fd_array[fd].write_xt); return forth_eval_pop("EXECUTE"); }
/** * Open stream to specified file descriptor. */ ostream_t * ostream_open_fd(int fd) { ostream_t *os; g_assert(is_valid_fd(fd)); os = ostream_alloc(OSTREAM_T_FD); os->u.fd = fd; return os; }
void ZookeeperClient::ZKIOCallback(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask) { if (fd > 0 && !is_valid_fd(fd)) { aeDeleteFileEvent(eventLoop, fd, AE_READABLE | AE_WRITABLE); return; } int events = 0; if (mask & AE_READABLE) { events |= ZOOKEEPER_READ; } if (mask & AE_WRITABLE) { events |= ZOOKEEPER_WRITE; } ZookeeperClient* zk = (ZookeeperClient*) clientData; zhandle_t* zhandler = zk->m_zk; if (0 != events && -1 != fd) { int rc = zookeeper_process(zhandler, events); if (rc != ZOK && !is_valid_fd(fd)) { aeDeleteFileEvent(eventLoop, fd, AE_READABLE | AE_WRITABLE); if (zk->m_zk_fd == fd) { zk->m_zk_fd = -1; } } } if (zhandler != zk->m_zk) { //already closed return; } zk->CheckConn(); }
/** * Acquires a file object for a given pathname and access mode. If * no matching file object exists, NULL is returned. * * @param pathname An absolute pathname. * @return On failure NULL is returned. On success a file object is * returned. */ struct file_object * file_object_open(const char * const pathname, int accmode) { struct file_object *fo; g_return_val_if_fail(pathname, NULL); g_return_val_if_fail(is_absolute_path(pathname), NULL); fo = file_object_find(pathname, accmode); if (fo) { fo->ref_count++; g_assert(is_valid_fd(fo->fd)); } return fo; }
int fd_collection::addtapfd(int tapfd, ring_tap* p_ring) { fdcoll_logfunc("tapfd=%d, p_ring=%p", tapfd, p_ring); if (!is_valid_fd(tapfd)) return -1; lock(); if (get_tapfd(tapfd)) { fdcoll_logwarn("[tapfd=%d] already exist in the collection (ring %p)", tapfd, get_tapfd(tapfd)); return -1; } m_p_tap_map[tapfd] = p_ring; unlock(); return 0; }
int fd_collection::del(int fd, bool b_cleanup, cls **map_type) { fdcoll_logfunc("fd=%d%s", fd, b_cleanup ? ", cleanup case: trying to remove old socket handler":""); if (!is_valid_fd(fd)) return -1; lock(); cls* p_obj = map_type[fd]; if (p_obj) { map_type[fd] = NULL; unlock(); p_obj->clean_obj(); return 0; } if (!b_cleanup) { fdcoll_logdbg("[fd=%d] Could not find related object", fd); } unlock(); return -1; }
static inline ssize_t tls_push(gnutls_transport_ptr ptr, const void *buf, size_t size) { struct gnutella_socket *s = ptr; ssize_t ret; int saved_errno; socket_check(s); g_assert(is_valid_fd(s->file_desc)); ret = s_write(s->file_desc, buf, size); saved_errno = errno; tls_signal_pending(s); if ((ssize_t) -1 == ret) { tls_set_errno(s, saved_errno); if (ECONNRESET == saved_errno || EPIPE == saved_errno) { socket_connection_reset(s); } } tls_transport_debug("tls_push", s, size, ret); errno = saved_errno; return ret; }
/** * Find an existing file object associated with the given pathname * for the given access mode. * * @return If no file object with the given pathname is found NULL * is returned. */ static struct file_object * file_object_find(const char * const pathname, int accmode) { struct file_object *fo; g_return_val_if_fail(ht_file_objects_rdonly, NULL); g_return_val_if_fail(ht_file_objects_wronly, NULL); g_return_val_if_fail(ht_file_objects_rdwr, NULL); g_return_val_if_fail(pathname, NULL); g_return_val_if_fail(is_absolute_path(pathname), NULL); fo = hikset_lookup(file_object_mode_get_table(O_RDWR), pathname); /* * We need to find a more specific file object if looking for O_WRONLY * or O_RDONLY ones. */ if (O_RDWR != accmode) { struct file_object *xfo; xfo = hikset_lookup(file_object_mode_get_table(accmode), pathname); if (xfo != NULL) { g_assert(xfo->accmode == accmode); fo = xfo; } } if (fo) { file_object_check(fo); g_assert(is_valid_fd(fo->fd)); g_assert(0 == strcmp(pathname, fo->pathname)); g_assert(accmode_is_valid(fo->fd, accmode)); g_assert(!fo->removed); } return fo; }
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; }
static inline int is_okay_for_select(int fd) { return is_valid_fd(fd) && (is_running_on_mingw() || UNSIGNED(fd) < FD_SETSIZE); }
/* returns Py_None if the fd is not valid */ static PyObject* create_stdio(PyObject* io, int fd, int write_mode, const char* name, const char* encoding, const char* errors) { PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res; const char* mode; const char* newline; PyObject *line_buffering; int buffering, isatty; _Py_IDENTIFIER(open); _Py_IDENTIFIER(isatty); _Py_IDENTIFIER(TextIOWrapper); _Py_IDENTIFIER(mode); if (!is_valid_fd(fd)) Py_RETURN_NONE; /* stdin is always opened in buffered mode, first because it shouldn't make a difference in common use cases, second because TextIOWrapper depends on the presence of a read1() method which only exists on buffered streams. */ if (Py_UnbufferedStdioFlag && write_mode) buffering = 0; else buffering = -1; if (write_mode) mode = "wb"; else mode = "rb"; buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOi", fd, mode, buffering, Py_None, Py_None, /* encoding, errors */ Py_None, 0); /* newline, closefd */ if (buf == NULL) goto error; if (buffering) { _Py_IDENTIFIER(raw); raw = _PyObject_GetAttrId(buf, &PyId_raw); if (raw == NULL) goto error; } else { raw = buf; Py_INCREF(raw); } text = PyUnicode_FromString(name); if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0) goto error; res = _PyObject_CallMethodId(raw, &PyId_isatty, ""); if (res == NULL) goto error; isatty = PyObject_IsTrue(res); Py_DECREF(res); if (isatty == -1) goto error; if (isatty || Py_UnbufferedStdioFlag) line_buffering = Py_True; else line_buffering = Py_False; Py_CLEAR(raw); Py_CLEAR(text); #ifdef MS_WINDOWS /* sys.stdin: enable universal newline mode, translate "\r\n" and "\r" newlines to "\n". sys.stdout and sys.stderr: translate "\n" to "\r\n". */ newline = NULL; #else /* sys.stdin: split lines at "\n". sys.stdout and sys.stderr: don't translate newlines (use "\n"). */ newline = "\n"; #endif stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO", buf, encoding, errors, newline, line_buffering); Py_CLEAR(buf); if (stream == NULL) goto error; if (write_mode) mode = "w"; else mode = "r"; text = PyUnicode_FromString(mode); if (!text || _PyObject_SetAttrId(stream, &PyId_mode, text) < 0) goto error; Py_CLEAR(text); return stream; error: Py_XDECREF(buf); Py_XDECREF(stream); Py_XDECREF(text); Py_XDECREF(raw); if (PyErr_ExceptionMatches(PyExc_OSError) && !is_valid_fd(fd)) { /* Issue #24891: the file descriptor was closed after the first is_valid_fd() check was called. Ignore the OSError and set the stream to None. */ PyErr_Clear(); Py_RETURN_NONE; } return NULL; }
/* Initialize sys.stdin, stdout, stderr and builtins.open */ static int initstdio(void) { PyObject *iomod = NULL, *wrapper; PyObject *bimod = NULL; PyObject *m; PyObject *std = NULL; int status = 0, fd; PyObject * encoding_attr; char *pythonioencoding = NULL, *encoding, *errors; /* Hack to avoid a nasty recursion issue when Python is invoked in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) { goto error; } Py_DECREF(m); if (!(m = PyImport_ImportModule("encodings.latin_1"))) { goto error; } Py_DECREF(m); if (!(bimod = PyImport_ImportModule("builtins"))) { goto error; } if (!(iomod = PyImport_ImportModule("io"))) { goto error; } if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) { goto error; } /* Set builtins.open */ if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) { Py_DECREF(wrapper); goto error; } Py_DECREF(wrapper); encoding = _Py_StandardStreamEncoding; errors = _Py_StandardStreamErrors; if (!encoding || !errors) { if (!errors) { /* When the LC_CTYPE locale is the POSIX locale ("C locale"), stdin and stdout use the surrogateescape error handler by default, instead of the strict error handler. */ char *loc = setlocale(LC_CTYPE, NULL); if (loc != NULL && strcmp(loc, "C") == 0) errors = "surrogateescape"; } pythonioencoding = Py_GETENV("PYTHONIOENCODING"); if (pythonioencoding) { char *err; pythonioencoding = _PyMem_Strdup(pythonioencoding); if (pythonioencoding == NULL) { PyErr_NoMemory(); goto error; } err = strchr(pythonioencoding, ':'); if (err) { *err = '\0'; err++; if (*err && !_Py_StandardStreamErrors) { errors = err; } } if (*pythonioencoding && !encoding) { encoding = pythonioencoding; } } } /* Set sys.stdin */ fd = fileno(stdin); /* Under some conditions stdin, stdout and stderr may not be connected * and fileno() may point to an invalid file descriptor. For example * GUI apps don't have valid standard streams by default. */ if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); } else { std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors); if (std == NULL) goto error; } /* if (fd < 0) */ PySys_SetObject("__stdin__", std); _PySys_SetObjectId(&PyId_stdin, std); Py_DECREF(std); /* Set sys.stdout */ fd = fileno(stdout); if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); } else { std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors); if (std == NULL) goto error; } /* if (fd < 0) */ PySys_SetObject("__stdout__", std); _PySys_SetObjectId(&PyId_stdout, std); Py_DECREF(std); #if 1 /* Disable this if you have trouble debugging bootstrap stuff */ /* Set sys.stderr, replaces the preliminary stderr */ fd = fileno(stderr); if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); } else { std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace"); if (std == NULL) goto error; } /* if (fd < 0) */ /* Same as hack above, pre-import stderr's codec to avoid recursion when import.c tries to write to stderr in verbose mode. */ encoding_attr = PyObject_GetAttrString(std, "encoding"); if (encoding_attr != NULL) { const char * std_encoding; std_encoding = _PyUnicode_AsString(encoding_attr); if (std_encoding != NULL) { PyObject *codec_info = _PyCodec_Lookup(std_encoding); Py_XDECREF(codec_info); } Py_DECREF(encoding_attr); } PyErr_Clear(); /* Not a fatal error if codec isn't available */ if (PySys_SetObject("__stderr__", std) < 0) { Py_DECREF(std); goto error; } if (_PySys_SetObjectId(&PyId_stderr, std) < 0) { Py_DECREF(std); goto error; } Py_DECREF(std); #endif if (0) { error: status = -1; } /* We won't need them anymore. */ if (_Py_StandardStreamEncoding) { PyMem_RawFree(_Py_StandardStreamEncoding); _Py_StandardStreamEncoding = NULL; } if (_Py_StandardStreamErrors) { PyMem_RawFree(_Py_StandardStreamErrors); _Py_StandardStreamErrors = NULL; } PyMem_Free(pythonioencoding); Py_XDECREF(bimod); Py_XDECREF(iomod); return status; }
int get_selects(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set *efds) { // Initialize FD_ZERO(rfds); FD_ZERO(wfds); FD_ZERO(efds); // Always select tun FD_SET(args->tun, rfds); FD_SET(args->tun, efds); int max = args->tun; // Select ICMP sockets struct icmp_session *i = icmp_session; while (i != NULL) { if (!i->stop) { if (is_valid_fd(i->socket)) { FD_SET(i->socket, efds); FD_SET(i->socket, rfds); if (i->socket > max) max = i->socket; } else { log_android(ANDROID_LOG_WARN, "ICMP socket %d select error %d: %s", i->socket, errno, strerror(errno)); i->stop = 1; } } i = i->next; } // Select UDP sockets struct udp_session *u = udp_session; while (u != NULL) { if (u->state == UDP_ACTIVE) { if (is_valid_fd(u->socket)) { FD_SET(u->socket, efds); FD_SET(u->socket, rfds); if (u->socket > max) max = u->socket; } else { log_android(ANDROID_LOG_WARN, "UDP socket %d select error %d: %s", u->socket, errno, strerror(errno)); u->state = UDP_FINISHING; } } u = u->next; } // Select TCP sockets struct tcp_session *t = tcp_session; while (t != NULL) { // Select sockets if (t->socket >= 0) { if (is_valid_fd(t->socket)) { if (t->state == TCP_LISTEN) { // Check for errors FD_SET(t->socket, efds); // Check for connected = writable FD_SET(t->socket, wfds); if (t->socket > max) max = t->socket; } else if (t->state == TCP_ESTABLISHED || t->state == TCP_CLOSE_WAIT) { // Check errors FD_SET(t->socket, efds); // Check for incoming data if (get_send_window(t) > 0) FD_SET(t->socket, rfds); // Check for outgoing data if (t->forward != NULL) FD_SET(t->socket, wfds); if (t->socket > max) max = t->socket; } } else { log_android(ANDROID_LOG_WARN, "TCP socket %d select error %d: %s", t->socket, errno, strerror(errno)); write_rst(args, t); } } t = t->next; } return max; }
/** * Initiates a new TLS session. * * @return 0 on success, -1 on error. */ int tls_init(struct gnutella_socket *s) { /** * ANON-DH is enabled because we don't use PKI. * DEFLATE is disabled because it seems to cause crashes. * ARCFOUR-40 is disabled because it is deprecated. */ static const char prio_want[] = "NORMAL:+ANON-DH:-ARCFOUR-40:-COMP-DEFLATE"; /* "-COMP-DEFLATE" is causing an error on MinGW with GnuTLS 2.10.2 */ static const char prio_must[] = "NORMAL:+ANON-DH:-ARCFOUR-40"; const bool server = SOCK_CONN_INCOMING == s->direction; struct tls_context *ctx; const char *fn; int e; #define TRY(function) (fn = (#function)), e = function socket_check(s); WALLOC0(ctx); ctx->s = s; s->tls.ctx = ctx; if ( TRY(gnutls_init)(&ctx->session, server ? GNUTLS_SERVER : GNUTLS_CLIENT) ) { ctx->session = NULL; goto failure; } if (TRY(gnutls_priority_set_direct)(ctx->session, prio_want, NULL)) { const char *error; if (TRY(gnutls_priority_set_direct)(ctx->session, prio_must, &error)) { g_warning("%s() failed at \"%s\"", fn, error); goto failure; } } if (TRY(gnutls_credentials_set)(ctx->session, GNUTLS_CRD_CERTIFICATE, cert_cred)) goto failure; gnutls_dh_set_prime_bits(ctx->session, TLS_DH_BITS); #ifdef USE_TLS_CUSTOM_IO gnutls_transport_set_ptr(ctx->session, s); gnutls_transport_set_push_function(ctx->session, tls_push); gnutls_transport_set_pull_function(ctx->session, tls_pull); #if !HAS_TLS(2, 12) /* * This routine has been removed starting TLS 3.0. It was used to disable * the lowat feature, and apparently this is now always the case in recent * TLS versions. --RAM, 2011-09-28 * * It's also flagged as deprecated in 2.12.x, so don't use it there. * --RAM, 2011-12-15 */ gnutls_transport_set_lowat(ctx->session, 0); #endif #else /* !USE_TLS_CUSTOM_IO */ g_assert(is_valid_fd(s->file_desc)); gnutls_transport_set_ptr(ctx->session, int_to_pointer(s->file_desc)); #endif /* USE_TLS_CUSTOM_IO */ if (server) { if (TRY(gnutls_anon_allocate_server_credentials)(&ctx->server_cred)) goto failure; gnutls_anon_set_server_dh_params(ctx->server_cred, get_dh_params()); if (TRY(gnutls_credentials_set)(ctx->session, GNUTLS_CRD_ANON, ctx->server_cred)) goto failure; } else { if (TRY(gnutls_anon_allocate_client_credentials)(&ctx->client_cred)) goto failure; if (TRY(gnutls_credentials_set)(ctx->session, GNUTLS_CRD_ANON, ctx->client_cred)) goto failure; } return 0; failure: g_warning("%s() failed: %s", EMPTY_STRING(fn), gnutls_strerror(e)); tls_free(s); return -1; #undef TRY }
void *handle_events(void *a) { int sdk; fd_set rfds; fd_set wfds; fd_set efds; struct timespec ts; sigset_t blockset; sigset_t emptyset; struct sigaction sa; struct arguments *args = (struct arguments *) a; log_android(ANDROID_LOG_WARN, "Start events tun=%d thread %x", args->tun, thread_id); // Attach to Java JNIEnv *env; jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL); if (rs != JNI_OK) { log_android(ANDROID_LOG_ERROR, "AttachCurrentThread failed"); return NULL; } args->env = env; // Get SDK version sdk = sdk_int(env); int maxsessions = 1024; struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim)) log_android(ANDROID_LOG_WARN, "getrlimit error %d: %s", errno, strerror(errno)); else { maxsessions = (int) (rlim.rlim_cur * 50 / 100); log_android(ANDROID_LOG_WARN, "getrlimit soft %d hard %d max sessions %d", rlim.rlim_cur, rlim.rlim_max, maxsessions); } if (maxsessions > FD_SETSIZE) maxsessions = FD_SETSIZE; // Block SIGUSR1 sigemptyset(&blockset); sigaddset(&blockset, SIGUSR1); sigprocmask(SIG_BLOCK, &blockset, NULL); /// Handle SIGUSR1 sa.sa_sigaction = handle_signal; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGUSR1, &sa, NULL); // Terminate existing sessions not allowed anymore check_allowed(args); stopping = 0; signaled = 0; // Loop while (!stopping) { log_android(ANDROID_LOG_DEBUG, "Loop thread %x", thread_id); // Count sessions int isessions = get_icmp_sessions(); int usessions = get_udp_sessions(); int tsessions = get_tcp_sessions(); int sessions = isessions + usessions + tsessions; // Check sessions check_icmp_sessions(args, sessions, maxsessions); check_udp_sessions(args, sessions, maxsessions); check_tcp_sessions(args, sessions, maxsessions); // https://bugzilla.mozilla.org/show_bug.cgi?id=1093893 int idle = (tsessions + usessions + tsessions == 0 && sdk >= 16); log_android(ANDROID_LOG_DEBUG, "sessions ICMP %d UDP %d TCP %d max %d/%d idle %d sdk %d", isessions, usessions, tsessions, sessions, maxsessions, idle, sdk); // Next event time ts.tv_sec = (sdk < 16 ? 5 : get_select_timeout(sessions, maxsessions)); ts.tv_nsec = 0; sigemptyset(&emptyset); // Check if tun is writable FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); FD_SET(args->tun, &wfds); if (pselect(args->tun + 1, &rfds, &wfds, &efds, &ts, &emptyset) == 0) { log_android(ANDROID_LOG_WARN, "tun not writable"); continue; } // Select int max = get_selects(args, &rfds, &wfds, &efds); int ready = pselect(max + 1, &rfds, &wfds, &efds, idle ? NULL : &ts, &emptyset); if (ready < 0) { if (errno == EINTR) { if (stopping && signaled) { ; log_android(ANDROID_LOG_WARN, "pselect signaled tun %d thread %x", args->tun, thread_id); report_exit(args, NULL); break; } else { log_android(ANDROID_LOG_DEBUG, "pselect interrupted tun %d thread %x", args->tun, thread_id); continue; } } else if (errno == EBADF) { if (is_valid_fd(args->tun)) { log_android(ANDROID_LOG_ERROR, "pselect error %d: %s", errno, strerror(errno)); report_exit(args, "pselect error %d: %s", errno, strerror(errno)); break; } else { log_android(ANDROID_LOG_ERROR, "tun socket %d select error %d: %s", args->tun, errno, strerror(errno)); report_exit(args, "tun socket %d select error %d: %s", args->tun, errno, strerror(errno)); break; } } else { log_android(ANDROID_LOG_ERROR, "pselect tun %d thread %x error %d: %s", args->tun, thread_id, errno, strerror(errno)); report_exit(args, "pselect tun %d thread %x error %d: %s", args->tun, thread_id, errno, strerror(errno)); break; } } if (ready == 0) log_android(ANDROID_LOG_DEBUG, "pselect timeout"); else { log_android(ANDROID_LOG_DEBUG, "pselect ready %d", ready); if (pthread_mutex_lock(&lock)) log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed"); #ifdef PROFILE_EVENTS struct timeval start, end; float mselapsed; gettimeofday(&start, NULL); #endif // Check upstream int error = 0; if (check_tun(args, &rfds, &wfds, &efds, sessions, maxsessions) < 0) error = 1; else { #ifdef PROFILE_EVENTS gettimeofday(&end, NULL); mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 + (end.tv_usec - start.tv_usec) / 1000.0; if (mselapsed > PROFILE_EVENTS) log_android(ANDROID_LOG_WARN, "tun %f", mselapsed); gettimeofday(&start, NULL); #endif // Check ICMP downstream check_icmp_sockets(args, &rfds, &wfds, &efds); // Check UDP downstream check_udp_sockets(args, &rfds, &wfds, &efds); // Check TCP downstream check_tcp_sockets(args, &rfds, &wfds, &efds); } if (pthread_mutex_unlock(&lock)) log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed"); if (error) break; #ifdef PROFILE_EVENTS gettimeofday(&end, NULL); mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 + (end.tv_usec - start.tv_usec) / 1000.0; if (mselapsed > PROFILE_EVENTS) log_android(ANDROID_LOG_WARN, "sockets %f", mselapsed); #endif } } (*env)->DeleteGlobalRef(env, args->instance); // Detach from Java rs = (*jvm)->DetachCurrentThread(jvm); if (rs != JNI_OK) log_android(ANDROID_LOG_ERROR, "DetachCurrentThread failed"); // Cleanup free(args); log_android(ANDROID_LOG_WARN, "Stopped events tun=%d thread %x", args->tun, thread_id); thread_id = 0; return NULL; }
int fd_collection::addsocket(int fd, int domain, int type, bool check_offload /*= false*/) { transport_t transport; const int SOCK_TYPE_MASK = 0xf; int sock_type = type & SOCK_TYPE_MASK; int sock_flags = type & ~SOCK_TYPE_MASK; if (check_offload && !create_offloaded_sockets()) { fdcoll_logdbg("socket [fd=%d, domain=%d, type=%d] is not offloaded by thread rules or by VMA_OFFLOADED_SOCKETS", fd, domain, type); return -1; } // IPV4 domain only (at least today) if (domain != AF_INET) return -1; fdcoll_logfunc("fd=%d", fd); if (!is_valid_fd(fd)) return -1; lock(); // Sanity check to remove any old sockinfo object using the same fd!! socket_fd_api* p_sfd_api_obj = get_sockfd(fd); BULLSEYE_EXCLUDE_BLOCK_START if (p_sfd_api_obj) { fdcoll_logwarn("[fd=%d] Deleting old duplicate sockinfo object (%p)", fd, p_sfd_api_obj); unlock(); handle_close(fd); lock(); } BULLSEYE_EXCLUDE_BLOCK_END unlock(); try { switch (sock_type) { case SOCK_DGRAM: { transport = __vma_match_by_program(PROTO_UDP, safe_mce_sys().app_id); if (transport == TRANS_OS) { fdcoll_logdbg("All UDP rules are consistent and instructing to use OS. TRANSPORT: OS"); return -1; } fdcoll_logdbg("UDP rules are either not consistent or instructing to use VMA. TRANSPORT: VMA"); p_sfd_api_obj = new sockinfo_udp(fd); break; } case SOCK_STREAM: { transport = __vma_match_by_program(PROTO_TCP, safe_mce_sys().app_id); if (transport == TRANS_OS) { fdcoll_logdbg("All TCP rules are consistent and instructing to use OS.transport == USE_OS"); return -1; } fdcoll_logdbg("TCP rules are either not consistent or instructing to use VMA.transport == USE_VMA"); p_sfd_api_obj = new sockinfo_tcp(fd); break; } default: fdcoll_logdbg("unsupported socket type=%d", sock_type); return -1; } } catch (vma_exception& e) { fdcoll_logdbg("recovering from %s", e.what()); return -1; } lock(); BULLSEYE_EXCLUDE_BLOCK_START if (p_sfd_api_obj == NULL) { fdcoll_logpanic("[fd=%d] Failed creating new sockinfo (%m)", fd); } BULLSEYE_EXCLUDE_BLOCK_END if (sock_flags) { if (sock_flags & SOCK_NONBLOCK) p_sfd_api_obj->fcntl(F_SETFL, O_NONBLOCK); if (sock_flags & SOCK_CLOEXEC) p_sfd_api_obj->fcntl(F_SETFD, FD_CLOEXEC); } m_p_sockfd_map[fd] = p_sfd_api_obj; unlock(); return fd; }
void* rover_server_log(void* args) { int retval, maxfd, num_fds;//, minfd, fddiff; char logbuf[k_LogBufSize]; fd_set recv_set; struct timeval timeout; //const char* start_string = "logging started"; //senders_ready = 0; // close(log_new_fd); // close(log_imu_new_fd1); // close(log_imu_new_fd2); // close(log_imu_new_fd3); log_new_fd = -1; log_imu_new_fd1 = -1; //log_imu_new_fd2 = -1; // log_imu_new_fd3 = -1; while (!log_thread_should_die) {//main accept() loop usleep(10000); // printf("At top of rover_server_log main accept loop" // "log_new_fd = %d, log_sockfd = %d, " // "log_imu_new_fd1 = %d, log_imu_new_fd2 = %d " // "log_imu_new_fd3 = %d, log_imu_sockfd = %d\n", // log_new_fd, log_sockfd, log_imu_new_fd1, log_imu_new_fd2, // log_imu_new_fd3, log_imu_sockfd); /* AcceptConnection set to non-blocking, so will spin here until it either gets a valid log_new_fd (and then goes into while loop below) or log_thread_should_die becomes TRUE, which will cause the while loop (and function) to exit. */ if (!is_valid_fd(log_new_fd)) { log_new_fd = AcceptConnection(log_sockfd); if (is_valid_fd(log_new_fd)) printf("Log connection established with log_sockfd = %d," "log_new_fd = %d\n", log_sockfd, log_new_fd); } if ((!is_valid_fd(log_imu_new_fd1))) { log_imu_new_fd1 = AcceptConnection(log_imu_sockfd); if (is_valid_fd(log_imu_new_fd1)) printf("IMU log connection #1 established with log_imu_sockfd = %d," "log_imu_new_fd1 = %d\n", log_imu_sockfd, log_imu_new_fd1); } // if ((!is_valid_fd(log_imu_new_fd2))) // { // log_imu_new_fd2 = AcceptConnection(log_imu_sockfd); // if (is_valid_fd(log_imu_new_fd2)) // printf("IMU log connection #2 established with log_imu_sockfd = %d," // "log_imu_new_fd2 = %d\n", log_imu_sockfd, log_imu_new_fd2); // } // if ((!is_valid_fd(log_imu_new_fd3))) // { // log_imu_new_fd3 = AcceptConnection(log_imu_sockfd); // if (is_valid_fd(log_imu_new_fd3)) // printf("IMU log connection #3 established with log_imu_sockfd = %d," // "log_imu_new_fd3 = %d\n", log_imu_sockfd, log_imu_new_fd3); // } if ((is_valid_fd(log_new_fd)) && (is_valid_fd(log_imu_new_fd1)))// && // (is_valid_fd(log_imu_new_fd2))) // && // (is_valid_fd(log_imu_new_fd3))) { //sort fds here int arr[3] = {log_new_fd, log_imu_new_fd1};//, log_imu_new_fd2};//, log_imu_new_fd3}; maxfd = arr[0]; for (int i = 0; i < 3; i++) { if (arr[i] > maxfd) maxfd = arr[i]; } //printf("all fds valid, maxfd = %d\n", maxfd); while (!log_thread_should_die) { //*************CHECK FDS HERE**************** // printf("log_new_fd = %d, log_sockfd = %d\n", log_new_fd, log_sockfd); // printf("log_imu_new_fd1 = %d, log_imu_sockfd = %d\n", // log_imu_new_fd1, log_imu_sockfd); memset(logbuf, 0, sizeof(logbuf)); //clear buffer //wrapping recv in a select here to ensure loop checks //log_thread_should_die every timeout FD_ZERO(&recv_set); FD_SET(log_new_fd, &recv_set); FD_SET(log_imu_new_fd1, &recv_set); //FD_SET(log_imu_new_fd2, &recv_set); //FD_SET(log_imu_new_fd3, &recv_set); timeout.tv_sec = 0; timeout.tv_usec = 1000 * 10; //10ms timeout //retval = select(log_new_fd+1, &recv_set, NULL, NULL, &timeout); retval = select (maxfd + 1, &recv_set, NULL, NULL, &timeout); if (retval < 0) perror("rover_server_log--select()"); //printf("select error\n"); else if (retval == 0) //timeout continue; //go back to the top of the loop and recheck log_thread_should_die else //retval >= 1-->we have data to receive { num_fds = retval; //this is the number of sockets with data ready //first must see which socket received data if (FD_ISSET(log_new_fd, &recv_set)) { //regular data log if (!rover_server_recv_and_print(log_new_fd, log_file)) break; //break if recv fails (due to error or remote shutdown) //if we get here, we handled the message properly, so decrement //num_fds and go back to top of loop if num_fds == 0 --num_fds; if (num_fds == 0) continue; } else if (FD_ISSET(log_imu_new_fd1, &recv_set)) { //imu data log from 1st connection if (!rover_server_recv_and_print(log_imu_new_fd1, imu_log_file)) break; //break if recv fails (due to error or fd closure) //if we get here, we handled the message properly, so decrement //num_fds and go back to top of loop if num_fds == 0 --num_fds; if (num_fds == 0) continue; } // else if (FD_ISSET(log_imu_new_fd2, &recv_set)) // { //imu data log from 2nd connection // if (!rover_server_recv_and_print(log_imu_new_fd2, imu_log_file)) // break; //break if recv fails (due to error or fd closure) // //if we get here, we handled the message properly, so decrement // //num_fds and go back to top of loop if num_fds == 0 // --num_fds; // if (num_fds == 0) // continue; // } // else if (FD_ISSET(log_imu_new_fd3, &recv_set)) // { //imu data log from 3rd connection // // retval = recv(log_imu_new_fd3, &logbuf, sizeof(logbuf), 0); // // if (retval > 0) //received a valid message in logbuf // // { //only log start message or if all 3 sensors have started // // if (strstr(logbuf, start_string) != NULL) // // { // // fprintf(imu_log_file, "%s\n", logbuf); // // senders_ready++; // // } // // else if (senders_ready == 3) // // fprintf(imu_log_file, "%s\n", logbuf); // // } // // else if (retval < 0) //error // // { //what error handling to do here?? // // printf("retval = %d\n", retval); // // perror("rover_server_log:recv(imu_log_file)"); // // break; // // } // // else // retval == 0 // // {//sender performed orderly shutdown, so don't print to log // // close(log_imu_new_fd3); // // break; // // } // if (!rover_server_recv_and_print(log_imu_new_fd3, imu_log_file)) // break; //break if recv fails (due to error or fd closure) // //if we get here, we handled the message properly, so decrement // //num_fds and go back to top of loop if num_fds == 0 // --num_fds; // if (num_fds == 0) // continue; // } else //unknown fd in recv_set { printf("ERROR: rover_server_log(): unknown fd in recv_set\n"); break; } } //printf("at end of smaller loop\n"); } //printf("at end of big if\n"); } //printf("AT END OF MAIN LOOP\n"); } //we only get here when log_thread_should_die is true //only close those that are still open, after waiting a bit usleep(100000); if (is_valid_fd(log_new_fd)) close(log_new_fd); if (is_valid_fd(log_imu_new_fd1)) close(log_imu_new_fd1); // if (is_valid_fd(log_imu_new_fd2)) // close(log_imu_new_fd2); // if(is_valid_fd(log_imu_new_fd3)) // close(log_imu_new_fd3); return NULL; }