static gboolean g_socketpair (GSocketFamily family, GSocketType type, GSocketProtocol protocol, GSocket * gsv[2], GError ** error) { int ret; int sv[2]; ret = socketpair (family, type, protocol, sv); if (ret != 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "socketpair failed: %s", g_strerror (errno)); return FALSE; } gsv[0] = g_socket_new_from_fd (sv[0], error); if (gsv[0] == NULL) { close (sv[0]); close (sv[1]); return FALSE; } gsv[1] = g_socket_new_from_fd (sv[1], error); if (gsv[1] == NULL) { g_object_unref (gsv[0]); gsv[0] = NULL; close (sv[1]); return FALSE; } return TRUE; }
void WorkQueue::registerEventSourceHandler(int fileDescriptor, int condition, PassOwnPtr<WorkItem> item) { GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0)); ASSERT(socket); GRefPtr<GCancellable> cancellable = adoptGRef(g_cancellable_new()); GRefPtr<GSource> dispatchSource = adoptGRef(g_socket_create_source(socket.get(), static_cast<GIOCondition>(condition), cancellable.get())); ASSERT(dispatchSource); EventSource* eventSource = new EventSource(item, this, cancellable.get()); ASSERT(eventSource); g_source_set_callback(dispatchSource.get(), reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWork), eventSource, reinterpret_cast<GDestroyNotify>(&WorkQueue::EventSource::deleteEventSource)); // Set up the event sources under the mutex since this is shared across multiple threads. { MutexLocker locker(m_eventSourcesLock); Vector<EventSource*> sources; EventSourceIterator it = m_eventSources.find(fileDescriptor); if (it != m_eventSources.end()) sources = it->second; sources.append(eventSource); m_eventSources.set(fileDescriptor, sources); } g_source_attach(dispatchSource.get(), m_eventContext); }
static gboolean connect_to_peer (int fd) { g_autoptr(GSocketConnection) stream = NULL; g_autoptr(GSocket) socket = NULL; GError *error = NULL; g_autofree gchar *guid = NULL; gboolean ret = FALSE; socket = g_socket_new_from_fd (fd, &error); if (error != NULL) { g_warning ("Couldn't create socket: %s", error->message); goto out; } stream = g_socket_connection_factory_create_connection (socket); if (!stream) { g_warning ("Couldn't create socket stream"); goto out; } guid = g_dbus_generate_guid (); g_dbus_connection_new (G_IO_STREAM (stream), guid, G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, NULL, NULL, on_peer_acquired, NULL); ret = TRUE; out: g_clear_error (&error); return ret; }
static void _j4status_io_add_systemd(J4statusIOContext *self) { #ifdef ENABLE_SYSTEMD gint fds = sd_listen_fds(TRUE); if ( fds < 0 ) { g_warning("Failed to acquire systemd sockets: %s", g_strerror(-fds)); return; } if ( fds == 0 ) return; gboolean socket_added = FALSE; _j4status_io_add_server(self); GError *error = NULL; gint fd; for ( fd = SD_LISTEN_FDS_START ; fd < SD_LISTEN_FDS_START + fds ; ++fd ) { gint r; r = sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1); if ( r < 0 ) { g_warning("Failed to verify systemd socket type: %s", g_strerror(-r)); continue; } if ( r == 0 ) continue; GSocket *socket; socket = g_socket_new_from_fd(fd, &error); if ( socket == NULL ) { g_warning("Failed to take a socket from systemd: %s", error->message); g_clear_error(&error); continue; } if ( ! g_socket_listener_add_socket(G_SOCKET_LISTENER(self->server), socket, NULL, &error) ) { g_warning("Failed to add systemd socket to server: %s", error->message); g_clear_error(&error); continue; } socket_added = TRUE; } if ( ! socket_added ) { g_object_unref(self->server); self->server = NULL; } #endif /* ENABLE_SYSTEMD */ }
static gboolean setup_handles (GSocket ** sinkhandle, GSocket ** srchandle) { GError *error = NULL; gint sv[3]; // g_assert (*sinkhandle); // g_assert (*srchandle); fail_if (socketpair (PF_UNIX, SOCK_STREAM, 0, sv)); *sinkhandle = g_socket_new_from_fd (sv[1], &error); fail_if (error); fail_if (*sinkhandle == NULL); *srchandle = g_socket_new_from_fd (sv[0], &error); fail_if (error); fail_if (*srchandle == NULL); return TRUE; }
/* Create a netlink socket, bind to it and wrap it in a GSocket */ static gboolean create_netlink_socket (GUPnPLinuxContextManager *self, GError **error) { struct sockaddr_nl sa; int fd, status; GSocket *sock; GError *inner_error; inner_error = NULL; fd = socket (PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (fd == -1) { g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), "Failed to bind to netlink socket"); return FALSE; } memset (&sa, 0, sizeof (sa)); sa.nl_family = AF_NETLINK; /* Listen for interface changes and IP address changes */ sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR; status = bind (fd, (struct sockaddr *) &sa, sizeof (sa)); if (status == -1) { g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), "Failed to bind to netlink socket"); close (fd); return FALSE; } sock = g_socket_new_from_fd (fd, &inner_error); if (sock == NULL) { close (fd); g_propagate_prefixed_error (error, inner_error, "Failed to create GSocket from " "netlink socket"); return FALSE; } g_socket_set_blocking (sock, FALSE); self->priv->netlink_socket = sock; return TRUE; }
bool Connection::open() { int flags = fcntl(m_socketDescriptor, F_GETFL, 0); while (fcntl(m_socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) { if (errno != EINTR) { ASSERT_NOT_REACHED(); return false; } } RefPtr<Connection> protectedThis(this); m_isConnected = true; #if PLATFORM(GTK) || PLATFORM(WPE) GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(m_socketDescriptor, nullptr)); m_socketMonitor.start(socket.get(), G_IO_IN, m_connectionQueue->runLoop(), [protectedThis] (GIOCondition condition) -> gboolean { if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) { protectedThis->connectionDidClose(); return G_SOURCE_REMOVE; } if (condition & G_IO_IN) { protectedThis->readyReadHandler(); return G_SOURCE_CONTINUE; } ASSERT_NOT_REACHED(); return G_SOURCE_REMOVE; }); #elif PLATFORM(EFL) m_connectionQueue->registerSocketEventHandler(m_socketDescriptor, [protectedThis] { protectedThis->readyReadHandler(); }); #endif // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal handler. m_connectionQueue->dispatch([protectedThis] { protectedThis->readyReadHandler(); }); return true; }
void WorkQueue::registerSocketEventHandler(int fileDescriptor, std::function<void ()> function, std::function<void ()> closeFunction) { GRefPtr<GSocket> socket = adoptGRef(g_socket_new_from_fd(fileDescriptor, 0)); ref(); m_socketEventSource.schedule("[WebKit] WorkQueue::SocketEventHandler", [function, closeFunction](GIOCondition condition) { if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) { closeFunction(); return GMainLoopSource::Stop; } if (condition & G_IO_IN) { function(); return GMainLoopSource::Continue; } ASSERT_NOT_REACHED(); return GMainLoopSource::Stop; }, socket.get(), G_IO_IN, [this] { deref(); }, m_eventContext.get()); }
/* coroutine context */ static void *spice_channel_coroutine(void *data) { SpiceChannel *channel = SPICE_CHANNEL(data); spice_channel *c = channel->priv; int ret; guint verify; SPICE_DEBUG("Started background coroutine %p", &c->coroutine); if (spice_session_get_client_provided_socket(c->session)) { if (c->fd < 0) { g_critical("fd not provided!"); goto cleanup; } if (!(c->sock = g_socket_new_from_fd(c->fd, NULL))) { SPICE_DEBUG("Failed to open socket from fd %d", c->fd); return FALSE; } g_socket_set_blocking(c->sock, FALSE); goto connected; } reconnect: c->sock = spice_session_channel_open_host(c->session, c->tls); if (c->sock == NULL) { if (!c->tls) { SPICE_DEBUG("connection failed, trying with TLS port"); c->tls = true; /* FIXME: does that really work with provided fd */ goto reconnect; } else { SPICE_DEBUG("Connect error"); emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_CONNECT); goto cleanup; } } c->has_error = FALSE; if (c->tls) { int rc; c->ctx = SSL_CTX_new(TLSv1_method()); if (c->ctx == NULL) { g_critical("SSL_CTX_new failed"); goto cleanup; } verify = spice_session_get_verify(c->session); if (verify & (SPICE_SESSION_VERIFY_PUBKEY | SPICE_SESSION_VERIFY_HOSTNAME)) { gchar *ca_file; g_object_get(c->session, "ca-file", &ca_file, NULL); if (ca_file) { rc = SSL_CTX_load_verify_locations(c->ctx, ca_file, NULL); if (rc != 1) g_warning("loading ca certs from %s failed", ca_file); g_free(ca_file); if (rc != 1) { if (verify & SPICE_SESSION_VERIFY_PUBKEY) { g_warning("only pubkey active"); verify = SPICE_SESSION_VERIFY_PUBKEY; } else goto cleanup; } } } c->ssl = SSL_new(c->ctx); if (c->ssl == NULL) { g_critical("SSL_new failed"); goto cleanup; } rc = SSL_set_fd(c->ssl, g_socket_get_fd(c->sock)); if (rc <= 0) { g_critical("SSL_set_fd failed"); goto cleanup; } { gchar *hostname, *subject; guint8 *pubkey; guint pubkey_len; g_object_get(c->session, "host", &hostname, "cert-subject", &subject, NULL); spice_session_get_pubkey(c->session, &pubkey, &pubkey_len); c->sslverify = spice_openssl_verify_new(c->ssl, verify, hostname, (char*)pubkey, pubkey_len, subject); g_free(hostname); g_free(subject); } ssl_reconnect: rc = SSL_connect(c->ssl); if (rc <= 0) { rc = SSL_get_error(c->ssl, rc); if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) { g_io_wait(c->sock, G_IO_OUT|G_IO_ERR|G_IO_HUP); goto ssl_reconnect; } else { g_warning("%s: SSL_connect: %s", c->name, ERR_error_string(rc, NULL)); emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_ERROR_TLS); goto cleanup; } } } connected: c->state = SPICE_CHANNEL_STATE_LINK_HDR; spice_channel_send_link(channel); while ((ret = spice_channel_iterate(channel))) ; /* TODO: improve it, this is a bit hairy, c->coroutine will be overwritten on (re)connect, so we skip the normal cleanup path. Ideally, we shouldn't use the same channel structure? */ if (c->state == SPICE_CHANNEL_STATE_CONNECTING) { g_object_unref(channel); goto end; } cleanup: SPICE_DEBUG("Coroutine exit"); SPICE_CHANNEL_GET_CLASS(channel)->channel_disconnect(channel); g_idle_add(spice_channel_delayed_unref, data); end: /* Co-routine exits now - the SpiceChannel object may no longer exist, so don't do anything else now unless you like SEGVs */ exit(1); return NULL; }
static gboolean cockpit_web_server_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { CockpitWebServer *server = COCKPIT_WEB_SERVER (initable); gboolean ret = FALSE; gboolean failed = FALSE; int n, fd; server->socket_service = g_socket_service_new (); n = sd_listen_fds (0); if (n > 0) { /* We got file descriptors passed in, use those. */ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { GSocket *s = NULL; gboolean b; int type; socklen_t l = sizeof (type); /* * HACK: Workaround g_error() happy code in GSocket * https://bugzilla.gnome.org/show_bug.cgi?id=746339 */ if (getsockopt (fd, SOL_SOCKET, SO_TYPE, &type, &l) < 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "invalid socket passed via systemd activation: %d: %s", fd, g_strerror (errno)); goto out; } s = g_socket_new_from_fd (fd, error); if (s == NULL) { g_prefix_error (error, "Failed to acquire passed socket %i: ", fd); goto out; } b = cockpit_web_server_add_socket (server, s, error); g_object_unref (s); if (!b) { g_prefix_error (error, "Failed to add listener for socket %i: ", fd); goto out; } } server->socket_activated = TRUE; } else { /* No fds passed in, let's listen on our own. */ if (server->port == 0) { server->port = g_socket_listener_add_any_inet_port (G_SOCKET_LISTENER (server->socket_service), NULL, error); failed = (server->port == 0); } else if (server->port > 0) { failed = !g_socket_listener_add_inet_port (G_SOCKET_LISTENER (server->socket_service), server->port, NULL, error); } if (failed) { g_prefix_error (error, "Failed to bind to port %d: ", server->port); goto out; } } g_signal_connect (server->socket_service, "incoming", G_CALLBACK (on_incoming), server); ret = TRUE; out: return ret; }
static gboolean g_network_monitor_netlink_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { GNetworkMonitorNetlink *nl = G_NETWORK_MONITOR_NETLINK (initable); gint sockfd, val; struct sockaddr_nl snl; /* We create the socket the old-school way because sockaddr_netlink * can't be represented as a GSocketAddress */ sockfd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (sockfd == -1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Could not create network monitor: %s"), g_strerror (errno)); return FALSE; } snl.nl_family = AF_NETLINK; snl.nl_pid = snl.nl_pad = 0; snl.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE; if (bind (sockfd, (struct sockaddr *)&snl, sizeof (snl)) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Could not create network monitor: %s"), g_strerror (errno)); close (sockfd); return FALSE; } val = 1; if (setsockopt (sockfd, SOL_SOCKET, SO_PASSCRED, &val, sizeof (val)) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Could not create network monitor: %s"), g_strerror (errno)); close (sockfd); return FALSE; } nl->priv->sock = g_socket_new_from_fd (sockfd, error); if (error) { g_prefix_error (error, "%s", _("Could not create network monitor: ")); close (sockfd); return FALSE; } /* Request the current state */ if (!request_dump (nl, error)) return FALSE; /* And read responses; since we haven't yet marked the socket * non-blocking, each call will block until a message is received. */ while (nl->priv->dump_networks) { if (!read_netlink_messages (NULL, G_IO_IN, nl)) break; } g_socket_set_blocking (nl->priv->sock, FALSE); nl->priv->source = g_socket_create_source (nl->priv->sock, G_IO_IN, NULL); g_source_set_callback (nl->priv->source, (GSourceFunc) read_netlink_messages, nl, NULL); g_source_attach (nl->priv->source, g_main_context_get_thread_default ()); return TRUE; }
static gboolean cockpit_web_server_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { CockpitWebServer *server = COCKPIT_WEB_SERVER (initable); gboolean ret = FALSE; gboolean failed; int n, fd; server->socket_service = g_socket_service_new (); n = sd_listen_fds (0); if (n > 0) { /* We got file descriptors passed in, use those. */ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { GSocket *s = NULL; gboolean b; s = g_socket_new_from_fd (fd, error); if (s == NULL) { g_prefix_error (error, "Failed to acquire passed socket %i: ", fd); goto out; } b = g_socket_listener_add_socket (G_SOCKET_LISTENER (server->socket_service), s, NULL, error); g_object_unref (s); if (!b) { g_prefix_error (error, "Failed to add listener for socket %i: ", fd); goto out; } } server->socket_activated = TRUE; } else { /* No fds passed in, let's listen on our own. */ if (server->port == 0) { server->port = g_socket_listener_add_any_inet_port (G_SOCKET_LISTENER (server->socket_service), NULL, error); failed = (server->port == 0); } else { failed = !g_socket_listener_add_inet_port (G_SOCKET_LISTENER (server->socket_service), server->port, NULL, error); } if (failed) { g_prefix_error (error, "Failed to bind to port %d: ", server->port); goto out; } } g_signal_connect (server->socket_service, "incoming", G_CALLBACK (on_incoming), server); ret = TRUE; out: return ret; }
static GDBusConnection* get_connection_for_path (gchar *sysroot, gboolean force_peer, GPid *out_peer_pid, GCancellable *cancellable, GError **error) { glnx_unref_object GDBusConnection *connection = NULL; glnx_unref_object GSocketConnection *stream = NULL; glnx_unref_object GSocket *socket = NULL; _cleanup_peer_ GPid peer_pid = 0; gchar buffer[16]; int pair[2]; const gchar *args[] = { "rpm-ostree", "start-daemon", "--sysroot", sysroot, "--dbus-peer", buffer, NULL }; /* This is only intended for use by installed tests. * Note that it disregards the 'sysroot' and 'force_peer' options * and assumes the service activation command has been configured * to use the desired system root path. */ if (g_getenv ("RPMOSTREE_USE_SESSION_BUS") != NULL) { if (sysroot != NULL) g_warning ("RPMOSTREE_USE_SESSION_BUS set, ignoring --sysroot=%s", sysroot); /* NB: as opposed to other early returns, this is _also_ a happy path */ GDBusConnection *ret = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error); if (!ret) return glnx_prefix_error_null (error, "Connecting to session bus"); return ret; } if (sysroot == NULL) sysroot = "/"; if (g_strcmp0 ("/", sysroot) == 0 && force_peer == FALSE) { /* NB: as opposed to other early returns, this is _also_ a happy path */ GDBusConnection *ret = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); if (!ret) return glnx_prefix_error_null (error, "Connecting to system bus"); return ret; } g_print ("Running in single user mode. Be sure no other users are modifying the system\n"); if (socketpair (AF_UNIX, SOCK_STREAM, 0, pair) < 0) return glnx_null_throw_errno_prefix (error, "couldn't create socket pair"); g_snprintf (buffer, sizeof (buffer), "%d", pair[1]); socket = g_socket_new_from_fd (pair[0], error); if (socket == NULL) { close (pair[0]); close (pair[1]); return NULL; } if (!g_spawn_async (NULL, (gchar **)args, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &peer_pid, error)) { close (pair[1]); return NULL; } stream = g_socket_connection_factory_create_connection (socket); connection = g_dbus_connection_new_sync (G_IO_STREAM (stream), NULL, G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, cancellable, error); if (!connection) return NULL; *out_peer_pid = peer_pid; peer_pid = 0; return connection; }
int init_netlink(GMainLoop *loop) { GSocket *gsocket = NULL; int socket_fd = 0; GSource *source; struct sockaddr_nl my_nla; struct nlmsghdr *nl_hdr; char buff[BUFF_SIZE]; struct cn_msg *cn_hdr; enum proc_cn_mcast_op *mcop_msg; /* create socket */ /* * Create an endpoint for communication. Use the kernel user * interface device (PF_NETLINK) which is a datagram oriented * service (SOCK_DGRAM). The protocol used is the connector * protocol (NETLINK_CONNECTOR) */ socket_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (socket_fd == -1) { g_warning ("netlink: failed to create socket: %s", g_strerror(errno)); return 1; } my_nla.nl_family = AF_NETLINK; my_nla.nl_groups = CN_IDX_PROC; my_nla.nl_pid = getpid(); my_nla.nl_pad = 0; if (bind(socket_fd, (struct sockaddr *)&my_nla, sizeof(my_nla)) < 0) { g_warning("netlink: binding sk_nl error: %s\n", g_strerror(errno)); g_warning("netlink: realtime monitoring disabled. compile kernel with PROC_EVENTS enabled"); goto out; } gsocket = g_socket_new_from_fd(socket_fd, NULL); if(gsocket == NULL) { g_warning("netlink: can't create socket"); goto out; } nl_hdr = (struct nlmsghdr *)buff; cn_hdr = (struct cn_msg *)NLMSG_DATA(nl_hdr); mcop_msg = (enum proc_cn_mcast_op*)&cn_hdr->data[0]; g_debug("netlink: sending proc connector: PROC_CN_MCAST_LISTEN... "); memset(buff, 0, sizeof(buff)); *mcop_msg = PROC_CN_MCAST_LISTEN; /* test if PROC_CN_MCAST_LISTEN will success */ netlink_proc_listening = FALSE; g_socket_set_timeout(gsocket, 10); /* fill the netlink header */ nl_hdr->nlmsg_len = SEND_MESSAGE_LEN; nl_hdr->nlmsg_type = NLMSG_DONE; nl_hdr->nlmsg_flags = 0; nl_hdr->nlmsg_seq = 0; nl_hdr->nlmsg_pid = getpid(); /* fill the connector header */ cn_hdr->id.idx = CN_IDX_PROC; cn_hdr->id.val = CN_VAL_PROC; cn_hdr->seq = 0; cn_hdr->ack = 0; cn_hdr->len = sizeof(enum proc_cn_mcast_op); g_debug("netlink: sending netlink message len=%d, cn_msg len=%d\n", nl_hdr->nlmsg_len, (int) sizeof(struct cn_msg)); if (send(socket_fd, nl_hdr, nl_hdr->nlmsg_len, 0) != nl_hdr->nlmsg_len) { g_warning("netlink: failed to send proc connector mcast ctl op!: %s\n", g_strerror(errno)); } g_debug("sent\n"); /* socket has data */ source = g_socket_create_source (gsocket, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, NULL); g_source_set_callback (source, (GSourceFunc) nl_connection_handler, loop, NULL); g_source_attach (source, NULL); return 0; out: return 1; }