gboolean g_vfs_afp_connection_close (GVfsAfpConnection *afp_connection, GCancellable *cancellable, GError **error) { GVfsAfpConnectionPrivate *priv = afp_connection->priv; guint16 req_id; gboolean res; /* close DSI session */ req_id = get_request_id (afp_connection); res = send_request_sync (g_io_stream_get_output_stream (priv->conn), DSI_CLOSE_SESSION, req_id, 0, 0, NULL, cancellable, error); if (!res) { g_io_stream_close (priv->conn, cancellable, NULL); g_object_unref (priv->conn); return FALSE; } res = g_io_stream_close (priv->conn, cancellable, error); g_object_unref (priv->conn); return res; }
GVfsAfpReply * g_vfs_afp_connection_get_server_info (GVfsAfpConnection *afp_connection, GCancellable *cancellable, GError **error) { GVfsAfpConnectionPrivate *priv = afp_connection->priv; GSocketClient *client; GIOStream *conn; gboolean res; DSIHeader dsi_header; char *data; client = g_socket_client_new (); conn = G_IO_STREAM (g_socket_client_connect (client, priv->addr, cancellable, error)); g_object_unref (client); if (!conn) return NULL; res = send_request_sync (g_io_stream_get_output_stream (conn), DSI_GET_STATUS, 0, 0, 0, NULL, cancellable, error); if (!res) { g_object_unref (conn); return NULL; } res = read_reply_sync (g_io_stream_get_input_stream (conn), &dsi_header, &data, cancellable, error); if (!res) { g_object_unref (conn); return NULL; } g_object_unref (conn); return g_vfs_afp_reply_new (dsi_header.errorCode, data, dsi_header.totalDataLength, TRUE); }
gboolean g_vfs_afp_connection_send_command_sync (GVfsAfpConnection *afp_connection, GVfsAfpCommand *afp_command, GCancellable *cancellable, GError **error) { GVfsAfpConnectionPrivate *priv = afp_connection->priv; DsiCommand dsi_command; guint16 req_id; guint32 writeOffset; /* set dsi_command */ switch (afp_command->type) { case AFP_COMMAND_WRITE: writeOffset = 8; dsi_command = DSI_WRITE; break; case AFP_COMMAND_WRITE_EXT: writeOffset = 20; dsi_command = DSI_WRITE; break; default: writeOffset = 0; dsi_command = DSI_COMMAND; break; } req_id = get_request_id (afp_connection); return send_request_sync (g_io_stream_get_output_stream (priv->conn), dsi_command, req_id, writeOffset, g_vfs_afp_command_get_size (afp_command), g_vfs_afp_command_get_data (afp_command), cancellable, error); }
gboolean g_vfs_afp_connection_open (GVfsAfpConnection *afp_connection, GCancellable *cancellable, GError **error) { GVfsAfpConnectionPrivate *priv = afp_connection->priv; GSocketClient *client; guint16 req_id; gboolean res; char *reply; DSIHeader dsi_header; guint pos; client = g_socket_client_new (); priv->conn = G_IO_STREAM (g_socket_client_connect (client, priv->addr, cancellable, error)); g_object_unref (client); if (!priv->conn) return FALSE; req_id = get_request_id (afp_connection); res = send_request_sync (g_io_stream_get_output_stream (priv->conn), DSI_OPEN_SESSION, req_id, 0, 0, NULL, cancellable, error); if (!res) return FALSE; res = read_reply_sync (g_io_stream_get_input_stream (priv->conn), &dsi_header, &reply, cancellable, error); if (!res) return FALSE; pos = 0; while ((dsi_header.totalDataLength - pos) > 2) { guint8 optionType; guint8 optionLength; optionType = reply[pos++]; optionLength = reply[pos++]; switch (optionType) { case 0x00: if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4) priv->kRequestQuanta = GUINT32_FROM_BE (*(guint32 *)(reply + pos)); break; case 0x02: if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4) priv->kServerReplayCacheSize = GUINT32_FROM_BE (*(guint32 *)(reply + pos)); break; default: g_debug ("Unknown DSI option\n"); } pos += optionLength; } g_free (reply); return TRUE; }
static gpointer open_thread_func (gpointer user_data) { SyncData *data = user_data; GVfsAfpConnection *conn = data->conn; GVfsAfpConnectionPrivate *priv = conn->priv; GSocketClient *client; guint16 req_id; gboolean res = FALSE; char *reply; DSIHeader dsi_header; guint pos; client = g_socket_client_new (); priv->stream = G_IO_STREAM (g_socket_client_connect (client, priv->addr, data->cancellable, data->error)); g_object_unref (client); if (!priv->stream) goto out; req_id = get_request_id (conn); res = send_request_sync (g_io_stream_get_output_stream (priv->stream), DSI_OPEN_SESSION, req_id, 0, 0, NULL, data->cancellable, data->error); if (!res) goto out; res = read_reply_sync (g_io_stream_get_input_stream (priv->stream), &dsi_header, &reply, data->cancellable, data->error); if (!res) goto out; pos = 0; while ((dsi_header.totalDataLength - pos) > 2) { guint8 optionType; guint8 optionLength; optionType = reply[pos++]; optionLength = reply[pos++]; switch (optionType) { case 0x00: if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4) priv->kRequestQuanta = GUINT32_FROM_BE (*(guint32 *)(reply + pos)); break; case 0x02: if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4) priv->kServerReplayCacheSize = GUINT32_FROM_BE (*(guint32 *)(reply + pos)); break; default: g_debug ("Unknown DSI option\n"); } pos += optionLength; } g_free (reply); out: if (res) g_atomic_int_set (&priv->atomic_state, STATE_CONNECTED); /* Signal sync call thread */ data->res = res; sync_data_signal (data); /* Return from thread on failure */ if (!res) { g_clear_object (&priv->stream); return NULL; } /* Create MainLoop */ priv->worker_context = g_main_context_new (); priv->worker_loop = g_main_loop_new (priv->worker_context, TRUE); read_reply (conn); /* Run mainloop */ g_main_loop_run (priv->worker_loop); return NULL; }
static void close_connection (GVfsAfpConnection *conn) { GVfsAfpConnectionPrivate *priv = conn->priv; guint16 req_id; gboolean res; GError *err = NULL; GQueue *request_queue; GSList *pending_closes, *siter; GHashTable *request_hash; GHashTableIter iter; RequestData *req_data; /* Take lock */ g_mutex_lock (&priv->mutex); /* Set closed flag */ g_atomic_int_set (&priv->atomic_state, STATE_CLOSED); request_queue = priv->request_queue; priv->request_queue = NULL; request_hash = priv->request_hash; priv->request_hash = NULL; pending_closes = priv->pending_closes; priv->pending_closes = NULL; /* Release lock */ g_mutex_unlock (&priv->mutex); /* close DSI session */ req_id = get_request_id (conn); res = send_request_sync (g_io_stream_get_output_stream (priv->stream), DSI_CLOSE_SESSION, req_id, 0, 0, NULL, NULL, &err); if (!res) g_io_stream_close (priv->stream, NULL, NULL); else res = g_io_stream_close (priv->stream, NULL, &err); g_clear_object (&priv->stream); #define REQUEST_DATA_CLOSED(request_data) { \ g_simple_async_result_set_from_error (req_data->simple, \ g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "Connection was closed")); \ \ g_simple_async_result_complete_in_idle (req_data->simple); \ free_request_data (req_data); \ } while ((req_data = g_queue_pop_head (request_queue))) { REQUEST_DATA_CLOSED (req_data); } g_hash_table_iter_init (&iter, request_hash); while (g_hash_table_iter_next (&iter, NULL, (void **)&req_data)) { REQUEST_DATA_CLOSED (req_data); } #undef REQUEST_DATA_CLOSED /* quit main_loop */ g_main_loop_quit (priv->worker_loop); g_main_loop_unref (priv->worker_loop); g_main_context_unref (priv->worker_context); for (siter = pending_closes; siter != NULL; siter = siter->next) { SyncData *close_data = siter->data; close_data->res = TRUE; sync_data_signal (close_data); } g_slist_free (pending_closes); }