static void _offer_with_address (TpStreamTubeChannel *self, GHashTable *params) { GValue *addressv = NULL; GError *error = NULL; addressv = tp_address_variant_from_g_socket_address (self->priv->address, &self->priv->socket_type, &error); if (error != NULL) { operation_failed (self, error); g_clear_error (&error); goto finally; } /* Connect the NewRemoteConnection signal */ tp_cli_channel_type_stream_tube_connect_to_new_remote_connection ( TP_CHANNEL (self), _new_remote_connection, NULL, NULL, G_OBJECT (self), &error); if (error != NULL) { operation_failed (self, error); g_clear_error (&error); goto finally; } g_assert (self->priv->parameters == NULL); if (params != NULL) self->priv->parameters = g_hash_table_ref (params); else self->priv->parameters = tp_asv_new (NULL, NULL); g_object_notify (G_OBJECT (self), "parameters"); g_object_notify (G_OBJECT (self), "parameters-vardict"); /* Call Offer */ tp_cli_channel_type_stream_tube_call_offer (TP_CHANNEL (self), -1, self->priv->socket_type, addressv, self->priv->access_control, self->priv->parameters, _channel_offered, NULL, NULL, G_OBJECT (self)); finally: if (addressv != NULL) tp_g_value_slice_free (addressv); }
static int spi_flash_write_status(FlashOps *me, uint8_t status) { int ret = -1; SpiFlash *flash = container_of(me, SpiFlash, ops); uint8_t command_bytes[2]; if (flash->spi->start(flash->spi)) { printf("%s: Failed to start transaction.\n", __func__); return ret; } command_bytes[0] = WriteEnableCommand; if (flash->spi->transfer(flash->spi, NULL, &command_bytes, 1)) { printf("%s: Failed to send write enable command.\n", __func__); goto fail; } if (operation_failed(flash, "WREN") != 0) goto fail; /* * CS needs to be deasserted before any other command can be * issued after WREN. */ if (toggle_cs(flash, "WREN")) goto fail; command_bytes[0] = WriteStatus; command_bytes[1] = status; if (flash->spi->transfer(flash->spi, NULL, &command_bytes, 2)) { printf("%s: Failed to send write status command.\n", __func__); goto fail; } if (operation_failed(flash, "WRSTATUS") == 0) ret = 0; fail: if (flash->spi->stop(flash->spi)) { printf("%s: Failed to stop.\n", __func__); ret = -1; } return ret; }
static void send_credentials_cb (GObject *source, GAsyncResult *result, gpointer user_data) { TpStreamTubeChannel *self = user_data; GError *error = NULL; if (!tp_unix_connection_send_credentials_with_byte_finish ( (GSocketConnection *) source, result, &error)) { DEBUG ("Failed to send credentials: %s", error->message); operation_failed (self, error); g_clear_error (&error); } }
static gboolean client_socket_cb (GSocket *socket, GIOCondition condition, TpStreamTubeChannel *self) { GError *error = NULL; if (!g_socket_check_connect_result (socket, &error)) { DEBUG ("Failed to connect to socket: %s", error->message); operation_failed (self, error); g_error_free (error); return FALSE; } client_socket_connected (self); return FALSE; }
static void _channel_offered (TpChannel *channel, const GError *in_error, gpointer user_data, GObject *obj) { TpStreamTubeChannel *self = (TpStreamTubeChannel *) obj; if (in_error != NULL) { DEBUG ("Failed to Offer Stream Tube: %s", in_error->message); operation_failed (self, in_error); return; } DEBUG ("Stream Tube offered"); g_simple_async_result_complete_in_idle (self->priv->result); tp_clear_object (&self->priv->result); }
/* * Write or erase the flash. To write, pass a buffer and size; to erase, * pass null for the buffer. * This function is guaranteed to be invoked with data not spanning across * writeable/erasable boundaries (page size/block size). */ static int spi_flash_modify(SpiFlash *flash, const void *buffer, uint32_t offset, uint32_t size, uint8_t opcode, const char *opname) { union { uint8_t bytes[4]; // We're using 3 byte addresses. uint32_t whole; } command; int stop_needed = 0; uint32_t rv = -1; do { /* Each write or erase command requires a 'write enable' (WREN) * first. */ if (flash->spi->start(flash->spi)) { printf("%s: Failed to start WREN transaction.\n", __func__); break; } command.bytes[0] = WriteEnableCommand; if (flash->spi->transfer(flash->spi, NULL, &command, 1)) { printf("%s: Failed to send write enable command.\n", __func__); stop_needed = 1; break; } /* * CS needs to be deasserted before any other command can be * issued after WREN. */ if (toggle_cs(flash, "WREN")) break; stop_needed = 1; command.whole = swap_bytes32((opcode << 24) | offset); if (flash->spi->transfer(flash->spi, NULL, &command, 4)) { printf("%s: Failed to send %s command.\n", __func__, opname); break; } if (buffer && flash->spi->transfer(flash->spi, NULL, buffer, size)) { printf("%s: Failed to write data.\n", __func__); break; } stop_needed = 1; if (!operation_failed(flash, opname)) rv = size; } while(0); if (stop_needed && flash->spi->stop(flash->spi)) printf("%s: Failed to stop.\n", __func__); return rv; }
/** * tp_stream_tube_channel_accept_async: * @self: an incoming #TpStreamTubeChannel * @callback: a callback to call when the tube has been accepted * @user_data: data to pass to @callback * * Accept an incoming stream tube. When the tube has been accepted, @callback * will be called. You can then call tp_stream_tube_channel_accept_finish() * to get a #TpStreamTubeConnection connected to the tube. * * Since: 0.13.2 */ void tp_stream_tube_channel_accept_async (TpStreamTubeChannel *self, GAsyncReadyCallback callback, gpointer user_data) { GHashTable *properties; GHashTable *supported_sockets; GError *error = NULL; g_return_if_fail (TP_IS_STREAM_TUBE_CHANNEL (self)); g_return_if_fail (self->priv->result == NULL); if (self->priv->access_control_param != NULL) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Tube has already be accepted"); return; } self->priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, tp_stream_tube_channel_accept_async); properties = _tp_channel_get_immutable_properties (TP_CHANNEL (self)); supported_sockets = tp_asv_get_boxed (properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SUPPORTED_SOCKET_TYPES, TP_HASH_TYPE_SUPPORTED_SOCKET_MAP); if (!_tp_set_socket_address_type_and_access_control_type (supported_sockets, &self->priv->socket_type, &self->priv->access_control, &error)) { operation_failed (self, error); g_clear_error (&error); return; } DEBUG ("Using socket type %u with access control %u", self->priv->socket_type, self->priv->access_control); self->priv->client_socket = _tp_create_client_socket (self->priv->socket_type, &error); if (error != NULL) { DEBUG ("Failed to create socket: %s", error->message); operation_failed (self, error); g_clear_error (&error); return; } switch (self->priv->access_control) { case TP_SOCKET_ACCESS_CONTROL_LOCALHOST: /* Put a dummy value */ self->priv->access_control_param = tp_g_value_slice_new_uint (0); break; case TP_SOCKET_ACCESS_CONTROL_PORT: { GSocketAddress *addr; guint16 port; addr = g_socket_get_local_address (self->priv->client_socket, &error); if (addr == NULL) { DEBUG ("Failed to get local address of client socket: %s", error->message); operation_failed (self, error); g_error_free (error); return; } port = g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)); self->priv->access_control_param = tp_g_value_slice_new_uint (port); g_object_unref (addr); } break; case TP_SOCKET_ACCESS_CONTROL_CREDENTIALS: self->priv->access_control_param = tp_g_value_slice_new_byte ( g_random_int_range (0, G_MAXUINT8)); break; default: g_assert_not_reached (); } /* Call Accept */ tp_cli_channel_type_stream_tube_call_accept (TP_CHANNEL (self), -1, self->priv->socket_type, self->priv->access_control, self->priv->access_control_param, _channel_accepted, NULL, NULL, G_OBJECT (self)); }
static void _channel_accepted (TpChannel *channel, const GValue *addressv, const GError *in_error, gpointer user_data, GObject *obj) { TpStreamTubeChannel *self = (TpStreamTubeChannel *) obj; GSocketAddress *remote_address; GError *error = NULL; if (in_error != NULL) { DEBUG ("Failed to Accept Stream Tube: %s", in_error->message); operation_failed (self, in_error); return; } tp_cli_channel_type_stream_tube_connect_to_new_local_connection ( TP_CHANNEL (self), new_local_connection_cb, NULL, NULL, G_OBJECT (self), &error); if (error != NULL) { DEBUG ("Failed to connect to NewLocalConnection signal"); operation_failed (self, error); g_error_free (error); return; } remote_address = tp_g_socket_address_from_variant (self->priv->socket_type, addressv, &error); if (error != NULL) { DEBUG ("Failed to convert address: %s", error->message); operation_failed (self, error); g_error_free (error); return; } /* Connect to CM */ g_socket_set_blocking (self->priv->client_socket, FALSE); g_socket_connect (self->priv->client_socket, remote_address, NULL, &error); if (error == NULL) { /* Socket is connected */ client_socket_connected (self); goto out; } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING)) { /* We have to wait that the socket is connected */ GSource *source; source = g_socket_create_source (self->priv->client_socket, G_IO_OUT, NULL); g_source_attach (source, g_main_context_get_thread_default ()); g_source_set_callback (source, (GSourceFunc) client_socket_cb, self, NULL); g_error_free (error); g_source_unref (source); } else { DEBUG ("Failed to connect to CM: %s", error->message); operation_failed (self, error); g_error_free (error); } out: g_object_unref (remote_address); }
/** * tp_stream_tube_channel_offer_async: * @self: an outgoing #TpStreamTubeChannel * @params: (allow-none) (transfer none): parameters of the tube, or %NULL * @callback: a callback to call when the tube has been offered * @user_data: data to pass to @callback * * Offer an outgoing stream tube. When the tube has been offered, @callback * will be called. You can then call tp_stream_tube_channel_offer_finish() * to get the result of the operation. * * You have to connect to the #TpStreamTubeChannel::incoming signal to get a * #TpStreamTubeConnection each time a contact establishes a connection to * the tube. * * Since: 0.13.2 */ void tp_stream_tube_channel_offer_async (TpStreamTubeChannel *self, GHashTable *params, GAsyncReadyCallback callback, gpointer user_data) { GHashTable *properties; GHashTable *supported_sockets; GError *error = NULL; g_return_if_fail (TP_IS_STREAM_TUBE_CHANNEL (self)); g_return_if_fail (self->priv->result == NULL); g_return_if_fail (tp_channel_get_requested (TP_CHANNEL (self))); if (self->priv->service != NULL) { g_critical ("Can't reoffer Tube!"); return; } self->priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, tp_stream_tube_channel_offer_async); properties = _tp_channel_get_immutable_properties (TP_CHANNEL (self)); supported_sockets = tp_asv_get_boxed (properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SUPPORTED_SOCKET_TYPES, TP_HASH_TYPE_SUPPORTED_SOCKET_MAP); if (!_tp_set_socket_address_type_and_access_control_type (supported_sockets, &self->priv->socket_type, &self->priv->access_control, &error)) { operation_failed (self, error); g_clear_error (&error); return; } DEBUG ("Using socket type %u with access control %u", self->priv->socket_type, self->priv->access_control); self->priv->service = g_socket_service_new (); switch (self->priv->socket_type) { #ifdef HAVE_GIO_UNIX case TP_SOCKET_ADDRESS_TYPE_UNIX: { self->priv->address = _tp_create_temp_unix_socket ( self->priv->service, &error); /* check there wasn't an error on the final attempt */ if (self->priv->address == NULL) { operation_failed (self, error); g_clear_error (&error); return; } } break; #endif /* HAVE_GIO_UNIX */ case TP_SOCKET_ADDRESS_TYPE_IPV4: case TP_SOCKET_ADDRESS_TYPE_IPV6: { GInetAddress *localhost; GSocketAddress *in_address; localhost = g_inet_address_new_loopback ( self->priv->socket_type == TP_SOCKET_ADDRESS_TYPE_IPV4 ? G_SOCKET_FAMILY_IPV4 : G_SOCKET_FAMILY_IPV6); in_address = g_inet_socket_address_new (localhost, 0); g_socket_listener_add_address ( G_SOCKET_LISTENER (self->priv->service), in_address, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, NULL, &self->priv->address, &error); g_object_unref (localhost); g_object_unref (in_address); if (error != NULL) { operation_failed (self, error); g_clear_error (&error); return; } break; } default: /* should have already errored */ g_assert_not_reached (); break; } tp_g_signal_connect_object (self->priv->service, "incoming", G_CALLBACK (service_incoming_cb), self, 0); g_socket_service_start (self->priv->service); _offer_with_address (self, params); }