1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) Carl-Anton Ingmarsson 2011 <ca.ingmarsson@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 * Author: Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com>
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib/gi18n.h>
26 #include <gio/gnetworking.h>
27
28
29 #include "gvfsafpconnection.h"
30
31 /*
32 * GVfsAfpName
33 */
34 struct _GVfsAfpName
35 {
36 guint32 text_encoding;
37 gchar *str;
38 gsize len;
39
40 gint ref_count;
41 };
42
43 static void
_g_vfs_afp_name_free(GVfsAfpName * afp_name)44 _g_vfs_afp_name_free (GVfsAfpName *afp_name)
45 {
46 g_free (afp_name->str);
47 g_slice_free (GVfsAfpName, afp_name);
48 }
49
50 void
g_vfs_afp_name_unref(GVfsAfpName * afp_name)51 g_vfs_afp_name_unref (GVfsAfpName *afp_name)
52 {
53 if (g_atomic_int_dec_and_test (&afp_name->ref_count))
54 _g_vfs_afp_name_free (afp_name);
55 }
56
57 void
g_vfs_afp_name_ref(GVfsAfpName * afp_name)58 g_vfs_afp_name_ref (GVfsAfpName *afp_name)
59 {
60 g_atomic_int_inc (&afp_name->ref_count);
61 }
62
63 char *
g_vfs_afp_name_get_string(GVfsAfpName * afp_name)64 g_vfs_afp_name_get_string (GVfsAfpName *afp_name)
65 {
66 return g_utf8_normalize (afp_name->str, afp_name->len, G_NORMALIZE_DEFAULT_COMPOSE);
67 }
68
69 GVfsAfpName *
g_vfs_afp_name_new(guint32 text_encoding,gchar * str,gsize len)70 g_vfs_afp_name_new (guint32 text_encoding, gchar *str, gsize len)
71 {
72 GVfsAfpName *afp_name;
73
74 afp_name = g_slice_new (GVfsAfpName);
75 afp_name->ref_count = 1;
76
77 afp_name->text_encoding = text_encoding;
78
79 afp_name->str = str;
80 afp_name->len = len;
81
82 return afp_name;
83 }
84
85 /*
86 * GVfsAfpReply
87 */
88 struct _GVfsAfpReplyClass
89 {
90 GObjectClass parent_class;
91 };
92
93 struct _GVfsAfpReply
94 {
95 GObject parent_instance;
96
97 AfpResultCode result_code;
98
99 char *data;
100 gsize len;
101 gboolean free_data;
102
103 goffset pos;
104 };
105
106 G_DEFINE_TYPE (GVfsAfpReply, g_vfs_afp_reply, G_TYPE_OBJECT);
107
108 static void
g_vfs_afp_reply_init(GVfsAfpReply * reply)109 g_vfs_afp_reply_init (GVfsAfpReply *reply)
110 {
111 reply->data = NULL;
112 reply->len = 0;
113 reply->pos = 0;
114 }
115
116 static void
g_vfs_afp_reply_finalize(GObject * object)117 g_vfs_afp_reply_finalize (GObject *object)
118 {
119 GVfsAfpReply *reply = (GVfsAfpReply *)object;
120
121 if (reply->free_data)
122 g_free (reply->data);
123 }
124
125 static void
g_vfs_afp_reply_class_init(GVfsAfpReplyClass * klass)126 g_vfs_afp_reply_class_init (GVfsAfpReplyClass *klass)
127 {
128 GObjectClass *object_class = G_OBJECT_CLASS (klass);
129
130 object_class->finalize = g_vfs_afp_reply_finalize;
131 }
132
133 static GVfsAfpReply *
g_vfs_afp_reply_new(AfpResultCode result_code,char * data,gsize len,gboolean take_data)134 g_vfs_afp_reply_new (AfpResultCode result_code, char *data, gsize len, gboolean take_data)
135 {
136 GVfsAfpReply *reply;
137
138 reply = g_object_new (G_VFS_TYPE_AFP_REPLY, NULL);
139
140 reply->result_code = result_code;
141 reply->len = len;
142 reply->data = data;
143 reply->free_data = take_data;
144
145 return reply;
146 }
147
148 gboolean
g_vfs_afp_reply_read_byte(GVfsAfpReply * reply,guint8 * byte)149 g_vfs_afp_reply_read_byte (GVfsAfpReply *reply, guint8 *byte)
150 {
151 if ((reply->len - reply->pos) < 1)
152 return FALSE;
153
154 if (byte)
155 *byte = reply->data[reply->pos];
156
157 reply->pos++;
158
159 return TRUE;
160 }
161
162 gboolean
g_vfs_afp_reply_read_int64(GVfsAfpReply * reply,gint64 * val)163 g_vfs_afp_reply_read_int64 (GVfsAfpReply *reply, gint64 *val)
164 {
165 if ((reply->len - reply->pos) < 8)
166 return FALSE;
167
168 if (val)
169 *val = GINT64_FROM_BE (*((gint64 *)(reply->data + reply->pos)));
170
171 reply->pos += 8;
172
173 return TRUE;
174 }
175
176 gboolean
g_vfs_afp_reply_read_int32(GVfsAfpReply * reply,gint32 * val)177 g_vfs_afp_reply_read_int32 (GVfsAfpReply *reply, gint32 *val)
178 {
179 if ((reply->len - reply->pos) < 4)
180 return FALSE;
181
182 if (val)
183 *val = GINT32_FROM_BE (*((gint32 *)(reply->data + reply->pos)));
184
185 reply->pos += 4;
186
187 return TRUE;
188 }
189
190 gboolean
g_vfs_afp_reply_read_int16(GVfsAfpReply * reply,gint16 * val)191 g_vfs_afp_reply_read_int16 (GVfsAfpReply *reply, gint16 *val)
192 {
193 if ((reply->len - reply->pos) < 2)
194 return FALSE;
195
196 if (val)
197 *val = GINT16_FROM_BE (*((gint16 *)(reply->data + reply->pos)));
198
199 reply->pos += 2;
200
201 return TRUE;
202 }
203
204 gboolean
g_vfs_afp_reply_read_uint64(GVfsAfpReply * reply,guint64 * val)205 g_vfs_afp_reply_read_uint64 (GVfsAfpReply *reply, guint64 *val)
206 {
207 if ((reply->len - reply->pos) < 8)
208 return FALSE;
209
210 if (val)
211 *val = GUINT64_FROM_BE (*((guint64 *)(reply->data + reply->pos)));
212
213 reply->pos += 8;
214
215 return TRUE;
216 }
217
218 gboolean
g_vfs_afp_reply_read_uint32(GVfsAfpReply * reply,guint32 * val)219 g_vfs_afp_reply_read_uint32 (GVfsAfpReply *reply, guint32 *val)
220 {
221 if ((reply->len - reply->pos) < 4)
222 return FALSE;
223
224 if (val)
225 *val = GUINT32_FROM_BE (*((guint32 *)(reply->data + reply->pos)));
226
227 reply->pos += 4;
228
229 return TRUE;
230 }
231
232 gboolean
g_vfs_afp_reply_read_uint16(GVfsAfpReply * reply,guint16 * val)233 g_vfs_afp_reply_read_uint16 (GVfsAfpReply *reply, guint16 *val)
234 {
235 if ((reply->len - reply->pos) < 2)
236 return FALSE;
237
238 if (val)
239 *val = GUINT16_FROM_BE (*((guint16 *)(reply->data + reply->pos)));
240
241 reply->pos += 2;
242
243 return TRUE;
244 }
245
246 gboolean
g_vfs_afp_reply_get_data(GVfsAfpReply * reply,gsize size,guint8 ** data)247 g_vfs_afp_reply_get_data (GVfsAfpReply *reply, gsize size, guint8 **data)
248 {
249 if ((reply->len - reply->pos) < size)
250 return FALSE;
251
252 if (data)
253 *data = (guint8 *)(reply->data + reply->pos);
254
255 reply->pos += size;
256
257 return TRUE;
258 }
259
260 gboolean
g_vfs_afp_reply_dup_data(GVfsAfpReply * reply,gsize size,guint8 ** data)261 g_vfs_afp_reply_dup_data (GVfsAfpReply *reply, gsize size, guint8 **data)
262 {
263 if ((reply->len - reply->pos) < size)
264 return FALSE;
265
266 if (data)
267 {
268 *data = g_malloc (size);
269 memcpy (*data, reply->data + reply->pos, size);
270 }
271
272 reply->pos += size;
273
274 return TRUE;
275 }
276
277 gboolean
g_vfs_afp_reply_read_pascal(GVfsAfpReply * reply,gboolean is_utf8,char ** str)278 g_vfs_afp_reply_read_pascal (GVfsAfpReply *reply, gboolean is_utf8, char **str)
279 {
280 guint8 strsize;
281
282 if (!g_vfs_afp_reply_read_byte (reply, &strsize))
283 return FALSE;
284
285 if (strsize > (reply->len - reply->pos))
286 {
287 reply->pos--;
288 return FALSE;
289 }
290
291 if (str)
292 {
293 if (is_utf8)
294 {
295 char *tmp;
296
297 if (!g_vfs_afp_reply_get_data (reply, strsize, (guint8 **)&tmp))
298 {
299 reply->pos--;
300 return FALSE;
301 }
302
303 *str = g_utf8_normalize (tmp, strsize, G_NORMALIZE_DEFAULT_COMPOSE);
304 }
305 else
306 {
307 *str = g_convert (reply->data + reply->pos, strsize,
308 "UTF-8", "MACINTOSH", NULL, NULL, NULL);
309 reply->pos += strsize;
310 }
311 }
312 else
313 {
314 reply->pos += strsize;
315 }
316
317 return TRUE;
318 }
319
320 gboolean
g_vfs_afp_reply_read_afp_name(GVfsAfpReply * reply,gboolean read_text_encoding,GVfsAfpName ** afp_name)321 g_vfs_afp_reply_read_afp_name (GVfsAfpReply *reply, gboolean read_text_encoding,
322 GVfsAfpName **afp_name)
323 {
324 gint old_pos;
325
326 guint32 text_encoding;
327 guint16 len;
328 gchar *str;
329
330 old_pos = reply->pos;
331
332 if (read_text_encoding)
333 {
334 if (!g_vfs_afp_reply_read_uint32 (reply, &text_encoding))
335 return FALSE;
336 }
337 else
338 text_encoding = 0;
339
340 if (!g_vfs_afp_reply_read_uint16 (reply, &len))
341 {
342 reply->pos = old_pos;
343 return FALSE;
344 }
345
346 if (!g_vfs_afp_reply_get_data (reply, len, (guint8 **)&str))
347 {
348 reply->pos = old_pos;
349 return FALSE;
350 }
351
352 if (afp_name)
353 *afp_name = g_vfs_afp_name_new (text_encoding, g_strndup (str, len), len);
354
355 return TRUE;
356
357 }
358
359 gboolean
g_vfs_afp_reply_seek(GVfsAfpReply * reply,goffset offset,GSeekType type)360 g_vfs_afp_reply_seek (GVfsAfpReply *reply, goffset offset, GSeekType type)
361 {
362 goffset absolute;
363
364 switch (type)
365 {
366 case G_SEEK_CUR:
367 absolute = reply->pos + offset;
368 break;
369
370 case G_SEEK_SET:
371 absolute = offset;
372 break;
373
374 case G_SEEK_END:
375 absolute = reply->len + offset;
376 break;
377
378 default:
379 return FALSE;
380 }
381
382 if (absolute < 0 || absolute >= reply->len)
383 return FALSE;
384
385 reply->pos = absolute;
386 return TRUE;
387 }
388
389 gboolean
g_vfs_afp_reply_skip_to_even(GVfsAfpReply * reply)390 g_vfs_afp_reply_skip_to_even (GVfsAfpReply *reply)
391 {
392 if ((reply->pos % 2) == 0)
393 return TRUE;
394
395 if ((reply->len - reply->pos) < 1)
396 return FALSE;
397
398 reply->pos++;
399
400 return TRUE;
401 }
402
403 goffset
g_vfs_afp_reply_get_pos(GVfsAfpReply * reply)404 g_vfs_afp_reply_get_pos (GVfsAfpReply *reply)
405 {
406 return reply->pos;
407 }
408
409 gsize
g_vfs_afp_reply_get_size(GVfsAfpReply * reply)410 g_vfs_afp_reply_get_size (GVfsAfpReply *reply)
411 {
412 return reply->len;
413 }
414
415 AfpResultCode
g_vfs_afp_reply_get_result_code(GVfsAfpReply * reply)416 g_vfs_afp_reply_get_result_code (GVfsAfpReply *reply)
417 {
418 return reply->result_code;
419 }
420
421 /*
422 * GVfsAfpCommand
423 */
424 struct _GVfsAfpCommandClass
425 {
426 GDataOutputStreamClass parent_class;
427 };
428
429 struct _GVfsAfpCommand
430 {
431 GDataOutputStream parent_instance;
432
433 AfpCommandType type;
434
435 char *buf;
436 gsize buf_size;
437 };
438
439 G_DEFINE_TYPE (GVfsAfpCommand, g_vfs_afp_command, G_TYPE_DATA_OUTPUT_STREAM);
440
441
442 static void
g_vfs_afp_command_init(GVfsAfpCommand * comm)443 g_vfs_afp_command_init (GVfsAfpCommand *comm)
444 {
445 }
446
447 static void
g_vfs_afp_command_class_init(GVfsAfpCommandClass * klass)448 g_vfs_afp_command_class_init (GVfsAfpCommandClass *klass)
449 {
450 }
451
452 GVfsAfpCommand *
g_vfs_afp_command_new(AfpCommandType type)453 g_vfs_afp_command_new (AfpCommandType type)
454 {
455 GOutputStream *mem_stream;
456 GVfsAfpCommand *comm;
457
458 mem_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
459 comm = g_object_new (G_VFS_TYPE_AFP_COMMAND,
460 "base-stream", mem_stream,
461 NULL);
462
463 g_object_unref (mem_stream);
464
465 comm->type = type;
466 g_vfs_afp_command_put_byte (comm, type);
467
468 return comm;
469 }
470
471 void
g_vfs_afp_command_put_byte(GVfsAfpCommand * comm,guint8 byte)472 g_vfs_afp_command_put_byte (GVfsAfpCommand *comm, guint8 byte)
473 {
474 g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), byte, NULL, NULL);
475 }
476
477 void
g_vfs_afp_command_put_int16(GVfsAfpCommand * comm,gint16 val)478 g_vfs_afp_command_put_int16 (GVfsAfpCommand *comm, gint16 val)
479 {
480 g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (comm), val, NULL, NULL);
481 }
482
483 void
g_vfs_afp_command_put_int32(GVfsAfpCommand * comm,gint32 val)484 g_vfs_afp_command_put_int32 (GVfsAfpCommand *comm, gint32 val)
485 {
486 g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (comm), val, NULL, NULL);
487 }
488
489 void
g_vfs_afp_command_put_int64(GVfsAfpCommand * comm,gint64 val)490 g_vfs_afp_command_put_int64 (GVfsAfpCommand *comm, gint64 val)
491 {
492 g_data_output_stream_put_int64 (G_DATA_OUTPUT_STREAM (comm), val, NULL, NULL);
493 }
494
495 void
g_vfs_afp_command_put_uint16(GVfsAfpCommand * comm,guint16 val)496 g_vfs_afp_command_put_uint16 (GVfsAfpCommand *comm, guint16 val)
497 {
498 g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (comm), val, NULL, NULL);
499 }
500
501 void
g_vfs_afp_command_put_uint32(GVfsAfpCommand * comm,guint32 val)502 g_vfs_afp_command_put_uint32 (GVfsAfpCommand *comm, guint32 val)
503 {
504 g_data_output_stream_put_uint32 (G_DATA_OUTPUT_STREAM (comm), val, NULL, NULL);
505 }
506
507 void
g_vfs_afp_command_put_uint64(GVfsAfpCommand * comm,guint64 val)508 g_vfs_afp_command_put_uint64 (GVfsAfpCommand *comm, guint64 val)
509 {
510 g_data_output_stream_put_uint64 (G_DATA_OUTPUT_STREAM (comm), val, NULL, NULL);
511 }
512
513 void
g_vfs_afp_command_put_pascal(GVfsAfpCommand * comm,const char * str)514 g_vfs_afp_command_put_pascal (GVfsAfpCommand *comm, const char *str)
515 {
516 size_t len;
517
518 if (str == NULL)
519 {
520 g_vfs_afp_command_put_byte (comm, 0);
521 return;
522 }
523
524 len = MIN (strlen (str), 256);
525
526 g_vfs_afp_command_put_byte (comm, len);
527 g_output_stream_write (G_OUTPUT_STREAM (comm), str, len, NULL, NULL);
528 }
529
530 void
g_vfs_afp_command_put_afp_name(GVfsAfpCommand * comm,GVfsAfpName * afp_name)531 g_vfs_afp_command_put_afp_name (GVfsAfpCommand *comm, GVfsAfpName *afp_name)
532 {
533 g_vfs_afp_command_put_uint32 (comm, afp_name->text_encoding);
534 g_vfs_afp_command_put_uint16 (comm, afp_name->len);
535
536 if (afp_name->len > 0)
537 {
538 g_output_stream_write_all (G_OUTPUT_STREAM (comm), afp_name->str,
539 afp_name->len, NULL, NULL, NULL);
540 }
541 }
542
543 static GVfsAfpName *
filename_to_afp_pathname(const char * filename)544 filename_to_afp_pathname (const char *filename)
545 {
546 gsize len;
547 char *str;
548 gint i;
549
550 while (*filename == '/')
551 filename++;
552
553 len = strlen (filename);
554
555 str = g_malloc (len);
556
557 for (i = 0; i < len; i++)
558 {
559 if (filename[i] == '/')
560 str[i] = '\0';
561 else
562 str[i] = filename[i];
563 }
564
565
566 return g_vfs_afp_name_new (0x08000103, str, len);
567 }
568
569 void
g_vfs_afp_command_put_pathname(GVfsAfpCommand * comm,const char * filename)570 g_vfs_afp_command_put_pathname (GVfsAfpCommand *comm, const char *filename)
571 {
572 GVfsAfpName *pathname;
573
574 /* PathType */
575 g_vfs_afp_command_put_byte (comm, AFP_PATH_TYPE_UTF8_NAME);
576
577 /* Pathname */
578 pathname = filename_to_afp_pathname (filename);
579 g_vfs_afp_command_put_afp_name (comm, pathname);
580 g_vfs_afp_name_unref (pathname);
581 }
582
583 void
g_vfs_afp_command_pad_to_even(GVfsAfpCommand * comm)584 g_vfs_afp_command_pad_to_even (GVfsAfpCommand *comm)
585 {
586 if (g_vfs_afp_command_get_size (comm) % 2 == 1)
587 g_vfs_afp_command_put_byte (comm, 0);
588 }
589
590 gsize
g_vfs_afp_command_get_size(GVfsAfpCommand * comm)591 g_vfs_afp_command_get_size (GVfsAfpCommand *comm)
592 {
593 GMemoryOutputStream *mem_stream;
594
595 mem_stream =
596 G_MEMORY_OUTPUT_STREAM (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (comm)));
597
598 return g_memory_output_stream_get_data_size (mem_stream);
599 }
600
601 char *
g_vfs_afp_command_get_data(GVfsAfpCommand * comm)602 g_vfs_afp_command_get_data (GVfsAfpCommand *comm)
603 {
604 GMemoryOutputStream *mem_stream;
605
606 mem_stream =
607 G_MEMORY_OUTPUT_STREAM (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (comm)));
608
609 return g_memory_output_stream_get_data (mem_stream);
610 }
611
612 void
g_vfs_afp_command_set_buffer(GVfsAfpCommand * comm,char * buf,gsize size)613 g_vfs_afp_command_set_buffer (GVfsAfpCommand *comm, char *buf, gsize size)
614 {
615 g_return_if_fail (buf != NULL);
616 g_return_if_fail (size > 0);
617
618 comm->buf = buf;
619 comm->buf_size = size;
620 }
621
622 /*
623 * GVfsAfpConnection
624 */
625
626 enum {
627 ATTENTION,
628 LAST_SIGNAL
629 };
630
631 static guint signals[LAST_SIGNAL] = {0,};
632
633 typedef struct {
634 guint8 flags;
635 guint8 command;
636 guint16 requestID;
637 union {
638 guint32 errorCode;
639 guint32 writeOffset;
640 };
641 guint32 totalDataLength;
642 guint32 reserved;
643 } DSIHeader;
644
645 enum {
646 STATE_INITIAL,
647 STATE_CONNECTED,
648 STATE_PENDING_CLOSE,
649 STATE_CLOSED
650 };
651
652 struct _GVfsAfpConnectionPrivate
653 {
654 GSocketConnectable *addr;
655 GIOStream *stream;
656
657 /* State */
658 volatile gint atomic_state;
659
660 guint16 request_id;
661 guint16 tickle_id;
662
663 guint32 kRequestQuanta;
664 guint32 kServerReplayCacheSize;
665
666 GThread *worker_thread;
667 GMainContext *worker_context;
668 GMainLoop *worker_loop;
669 GMutex mutex;
670
671 GQueue *request_queue;
672 GHashTable *request_hash;
673
674 /* send loop */
675 gboolean send_loop_running;
676 DSIHeader write_dsi_header;
677
678 /* read loop */
679 GCancellable *read_cancellable;
680 DSIHeader read_dsi_header;
681 char *reply_buf;
682 gboolean free_reply_buf;
683
684 GSList *pending_closes;
685 };
686
687 G_DEFINE_TYPE_WITH_PRIVATE (GVfsAfpConnection, g_vfs_afp_connection, G_TYPE_OBJECT);
688
689 typedef enum
690 {
691 DSI_CLOSE_SESSION = 1,
692 DSI_COMMAND = 2,
693 DSI_GET_STATUS = 3,
694 DSI_OPEN_SESSION = 4,
695 DSI_TICKLE = 5,
696 DSI_WRITE = 6,
697 DSI_ATTENTION = 8
698 } DsiCommand;
699
700 typedef enum
701 {
702 REQUEST_TYPE_COMMAND,
703 REQUEST_TYPE_TICKLE
704 } RequestType;
705
706 typedef struct
707 {
708 RequestType type;
709
710 GVfsAfpCommand *command;
711 char *reply_buf;
712 GTask *task;
713
714 GVfsAfpConnection *conn;
715 } RequestData;
716
717 typedef struct
718 {
719 GMutex mutex;
720 GCond cond;
721 GVfsAfpConnection *conn;
722 GCancellable *cancellable;
723 gboolean res;
724 GError **error;
725 void *data;
726 } SyncData;
727
728 static void
sync_data_init(SyncData * data,GVfsAfpConnection * conn,GError ** error)729 sync_data_init (SyncData *data, GVfsAfpConnection *conn, GError **error)
730 {
731 g_mutex_init (&data->mutex);
732 g_cond_init (&data->cond);
733 data->conn = conn;
734 data->error = error;
735 data->res = FALSE;
736 }
737
738 static void
sync_data_clear(SyncData * data)739 sync_data_clear (SyncData *data)
740 {
741 g_mutex_clear (&data->mutex);
742 g_cond_clear (&data->cond);
743 }
744
745 static void
sync_data_signal(SyncData * data)746 sync_data_signal (SyncData *data)
747 {
748 g_mutex_lock (&data->mutex);
749 g_cond_signal (&data->cond);
750 g_mutex_unlock (&data->mutex);
751 }
752
753 static void
sync_data_wait(SyncData * data)754 sync_data_wait (SyncData *data)
755 {
756 g_mutex_lock (&data->mutex);
757 g_cond_wait (&data->cond, &data->mutex);
758 g_mutex_unlock (&data->mutex);
759 }
760
761 static void send_request_unlocked (GVfsAfpConnection *afp_connection);
762 static void close_connection (GVfsAfpConnection *conn);
763 static void read_reply (GVfsAfpConnection *afp_connection);
764
765 static void
free_request_data(RequestData * req_data)766 free_request_data (RequestData *req_data)
767 {
768 if (req_data->command)
769 g_object_unref (req_data->command);
770 if (req_data->task)
771 g_object_unref (req_data->task);
772
773 g_slice_free (RequestData, req_data);
774 }
775
776 static gboolean
check_open(GVfsAfpConnection * conn,GError ** error)777 check_open (GVfsAfpConnection *conn, GError **error)
778 {
779 GVfsAfpConnectionPrivate *priv = conn->priv;
780
781 /* Acts as memory barrier */
782 gint state = g_atomic_int_get (&priv->atomic_state);
783
784 if (state == STATE_INITIAL)
785 {
786 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
787 _("The connection is not opened"));
788 return FALSE;
789 }
790
791 else if (state == STATE_CLOSED)
792 {
793 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
794 _("The connection is closed"));
795 return FALSE;
796 }
797
798 return TRUE;
799 }
800
801 static void
g_vfs_afp_connection_init(GVfsAfpConnection * afp_connection)802 g_vfs_afp_connection_init (GVfsAfpConnection *afp_connection)
803 {
804 GVfsAfpConnectionPrivate *priv;
805
806 afp_connection->priv = priv = g_vfs_afp_connection_get_instance_private (afp_connection);
807 priv->kRequestQuanta = -1;
808 priv->kServerReplayCacheSize = -1;
809
810 g_mutex_init (&priv->mutex);
811
812 priv->request_queue = g_queue_new ();
813 priv->request_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
814 NULL, (GDestroyNotify)free_request_data);
815 priv->read_cancellable = g_cancellable_new ();
816
817 priv->send_loop_running = FALSE;
818 }
819
820 static void
g_vfs_afp_connection_finalize(GObject * object)821 g_vfs_afp_connection_finalize (GObject *object)
822 {
823 GVfsAfpConnection *afp_connection = (GVfsAfpConnection *)object;
824 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
825
826 g_clear_object (&priv->addr);
827 g_clear_object (&priv->stream);
828 g_clear_object (&priv->read_cancellable);
829
830 g_mutex_clear (&priv->mutex);
831
832 G_OBJECT_CLASS (g_vfs_afp_connection_parent_class)->finalize (object);
833 }
834
835 static void
g_vfs_afp_connection_class_init(GVfsAfpConnectionClass * klass)836 g_vfs_afp_connection_class_init (GVfsAfpConnectionClass *klass)
837 {
838 GObjectClass* object_class = G_OBJECT_CLASS (klass);
839
840 object_class->finalize = g_vfs_afp_connection_finalize;
841
842 signals[ATTENTION] =
843 g_signal_new ("attention",
844 G_TYPE_FROM_CLASS (object_class),
845 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
846 0, NULL, NULL, g_cclosure_marshal_VOID__UINT,
847 G_TYPE_NONE, 1, G_TYPE_UINT);
848 }
849
850 static guint16
get_request_id(GVfsAfpConnection * afp_connection)851 get_request_id (GVfsAfpConnection *afp_connection)
852 {
853 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
854
855 return priv->request_id++;
856 }
857
858 static guint16
get_tickle_id(GVfsAfpConnection * afp_connection)859 get_tickle_id (GVfsAfpConnection *afp_connection)
860 {
861 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
862
863 return priv->tickle_id++;
864 }
865
866 typedef struct
867 {
868 void *buffer;
869 gsize count;
870 gsize bytes_read;
871 } ReadAllData;
872
873 static void
free_read_all_data(ReadAllData * read_data)874 free_read_all_data (ReadAllData *read_data)
875 {
876 g_slice_free (ReadAllData, read_data);
877 }
878
879 static void
read_all_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)880 read_all_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
881 {
882 GInputStream *stream = G_INPUT_STREAM (source_object);
883 GTask *task = G_TASK (user_data);
884 gssize bytes_read;
885 GError *err = NULL;
886 ReadAllData *read_data = g_task_get_task_data (task);
887
888 bytes_read = g_input_stream_read_finish (stream, res, &err);
889 if (bytes_read == -1)
890 {
891 g_task_return_error (task, err);
892 g_object_unref (task);
893 return;
894 }
895 else if (bytes_read == 0)
896 {
897 g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CLOSED, _("Got EOS"));
898 g_object_unref (task);
899 return;
900 }
901
902 read_data->bytes_read += bytes_read;
903 if (read_data->bytes_read < read_data->count)
904 {
905 g_input_stream_read_async (stream,
906 (guint8 *)read_data->buffer + read_data->bytes_read,
907 read_data->count - read_data->bytes_read,
908 g_task_get_priority (task), g_task_get_cancellable (task),
909 read_all_cb, task);
910 return;
911 }
912
913 g_task_return_boolean (task, TRUE);
914 g_object_unref (task);
915 }
916
917 static void
read_all_async(GInputStream * stream,void * buffer,gsize count,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)918 read_all_async (GInputStream *stream,
919 void *buffer,
920 gsize count,
921 int io_priority,
922 GCancellable *cancellable,
923 GAsyncReadyCallback callback,
924 gpointer user_data)
925 {
926 ReadAllData *read_data;
927 GTask *task;
928
929 task = g_task_new (stream, cancellable, callback, user_data);
930 g_task_set_source_tag (task, read_all_async);
931 g_task_set_priority (task, io_priority);
932
933 read_data = g_slice_new0 (ReadAllData);
934 read_data->buffer = buffer;
935 read_data->count = count;
936
937 g_task_set_task_data (task, read_data, (GDestroyNotify)free_read_all_data);
938
939 g_input_stream_read_async (stream, buffer, count, io_priority, cancellable,
940 read_all_cb, task);
941 }
942
943 static gboolean
read_all_finish(GInputStream * stream,GAsyncResult * res,gsize * bytes_read,GError ** error)944 read_all_finish (GInputStream *stream,
945 GAsyncResult *res,
946 gsize *bytes_read,
947 GError **error)
948 {
949 g_return_val_if_fail (g_task_is_valid (res, stream), FALSE);
950 g_return_val_if_fail (g_async_result_is_tagged (res, read_all_async), FALSE);
951
952 if (bytes_read)
953 {
954 ReadAllData *read_data;
955
956 read_data = g_task_get_task_data (G_TASK (res));
957 *bytes_read = read_data->bytes_read;
958 }
959
960 return g_task_propagate_boolean (G_TASK (res), error);
961 }
962
963 static void
dispatch_reply(GVfsAfpConnection * afp_connection)964 dispatch_reply (GVfsAfpConnection *afp_connection)
965 {
966 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
967 DSIHeader *dsi_header = &priv->read_dsi_header;
968
969 switch (dsi_header->command)
970 {
971 case DSI_CLOSE_SESSION:
972 {
973 g_warning ("Server closed session\n");
974 break;
975 }
976
977 case DSI_TICKLE:
978 {
979 RequestData *req_data;
980
981 /* Send back a tickle message */
982 req_data = g_slice_new0 (RequestData);
983 req_data->type = REQUEST_TYPE_TICKLE;
984 req_data->conn = afp_connection;
985
986 /* take lock */
987 g_mutex_lock (&priv->mutex);
988 g_queue_push_head (priv->request_queue, req_data);
989 if (!priv->send_loop_running) {
990 priv->send_loop_running = TRUE;
991 send_request_unlocked (afp_connection);
992 }
993 /* release lock */
994 g_mutex_unlock (&priv->mutex);
995
996 break;
997 }
998
999 case DSI_ATTENTION:
1000 {
1001 guint8 attention_code;
1002
1003 attention_code = priv->reply_buf[0] >> 4;
1004
1005 g_signal_emit (afp_connection, signals[ATTENTION], 0, attention_code);
1006 break;
1007 }
1008
1009 case DSI_COMMAND:
1010 case DSI_WRITE:
1011 {
1012 RequestData *req_data;
1013
1014 req_data = g_hash_table_lookup (priv->request_hash,
1015 GUINT_TO_POINTER ((guint)dsi_header->requestID));
1016 if (req_data)
1017 {
1018 GVfsAfpReply *reply;
1019
1020 reply = g_vfs_afp_reply_new (dsi_header->errorCode, priv->reply_buf,
1021 dsi_header->totalDataLength, priv->free_reply_buf);
1022 priv->free_reply_buf = FALSE;
1023
1024 g_task_return_pointer (req_data->task, reply, g_object_unref);
1025
1026 g_hash_table_remove (priv->request_hash,
1027 GUINT_TO_POINTER ((guint)dsi_header->requestID));
1028 }
1029 break;
1030 }
1031
1032 default:
1033 g_assert_not_reached ();
1034 }
1035 }
1036
1037 static void
read_data_cb(GObject * object,GAsyncResult * res,gpointer user_data)1038 read_data_cb (GObject *object, GAsyncResult *res, gpointer user_data)
1039 {
1040 GInputStream *input = G_INPUT_STREAM (object);
1041 GVfsAfpConnection *afp_connection = G_VFS_AFP_CONNECTION (user_data);
1042 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
1043
1044 gboolean result;
1045 GError *err = NULL;
1046
1047 if (g_atomic_int_get (&priv->atomic_state) == STATE_PENDING_CLOSE)
1048 {
1049 if (!priv->send_loop_running)
1050 close_connection (afp_connection);
1051 return;
1052 }
1053
1054 result = read_all_finish (input, res, NULL, &err);
1055 if (!result)
1056 {
1057 if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CLOSED) ||
1058 g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
1059 {
1060 g_message (_("Host closed connection"));
1061 }
1062 else
1063 {
1064 g_warning ("FAIL!!! \"%s\"\n", err->message);
1065 }
1066 exit (0);
1067 }
1068
1069 dispatch_reply (afp_connection);
1070
1071 if (priv->free_reply_buf)
1072 g_free (priv->reply_buf);
1073 priv->reply_buf = NULL;
1074
1075 read_reply (afp_connection);
1076 }
1077
1078 static void
read_dsi_header_cb(GObject * object,GAsyncResult * res,gpointer user_data)1079 read_dsi_header_cb (GObject *object, GAsyncResult *res, gpointer user_data)
1080 {
1081 GInputStream *input = G_INPUT_STREAM (object);
1082 GVfsAfpConnection *afp_conn = G_VFS_AFP_CONNECTION (user_data);
1083 GVfsAfpConnectionPrivate *priv = afp_conn->priv;
1084
1085 gboolean result;
1086 GError *err = NULL;
1087 DSIHeader *dsi_header;
1088
1089 if (g_atomic_int_get (&priv->atomic_state) == STATE_PENDING_CLOSE)
1090 {
1091 if (!priv->send_loop_running)
1092 close_connection (afp_conn);
1093 return;
1094 }
1095
1096 result = read_all_finish (input, res, NULL, &err);
1097 if (!result)
1098 {
1099 if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CLOSED) ||
1100 g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
1101 {
1102 g_message (_("Host closed connection"));
1103 }
1104 else
1105 {
1106 g_warning ("FAIL!!! \"%s\"\n", err->message);
1107 }
1108 exit (0);
1109 }
1110
1111 dsi_header = &priv->read_dsi_header;
1112
1113 dsi_header->requestID = GUINT16_FROM_BE (dsi_header->requestID);
1114 dsi_header->errorCode = GUINT32_FROM_BE (dsi_header->errorCode);
1115 dsi_header->totalDataLength = GUINT32_FROM_BE (dsi_header->totalDataLength);
1116
1117 if (dsi_header->totalDataLength > 0)
1118 {
1119 RequestData *req_data;
1120
1121 req_data = g_hash_table_lookup (priv->request_hash,
1122 GUINT_TO_POINTER ((guint)dsi_header->requestID));
1123 if (req_data && req_data->reply_buf)
1124 {
1125 priv->reply_buf = req_data->reply_buf;
1126 priv->free_reply_buf = FALSE;
1127 }
1128 else
1129 {
1130 priv->reply_buf = g_malloc (dsi_header->totalDataLength);
1131 priv->free_reply_buf = TRUE;
1132 }
1133
1134 read_all_async (input, priv->reply_buf, dsi_header->totalDataLength,
1135 0, priv->read_cancellable, read_data_cb, afp_conn);
1136
1137 return;
1138 }
1139
1140 dispatch_reply (afp_conn);
1141 read_reply (afp_conn);
1142 }
1143
1144 static void
read_reply(GVfsAfpConnection * afp_connection)1145 read_reply (GVfsAfpConnection *afp_connection)
1146 {
1147 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
1148
1149 GInputStream *input;
1150
1151 if (g_atomic_int_get (&priv->atomic_state) & STATE_PENDING_CLOSE)
1152 {
1153 if (!priv->send_loop_running)
1154 close_connection (afp_connection);
1155 return;
1156 }
1157
1158 input = g_io_stream_get_input_stream (priv->stream);
1159
1160 read_all_async (input, &priv->read_dsi_header, sizeof (DSIHeader), 0,
1161 priv->read_cancellable, read_dsi_header_cb, afp_connection);
1162 }
1163
1164 typedef struct
1165 {
1166 const void *buffer;
1167 gsize count;
1168 gsize bytes_written;
1169 } WriteAllData;
1170
1171 inline static void
free_write_all_data(WriteAllData * write_data)1172 free_write_all_data (WriteAllData *write_data)
1173 {
1174 g_slice_free (WriteAllData, write_data);
1175 }
1176
1177 static void
write_all_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1178 write_all_cb (GObject *source_object,
1179 GAsyncResult *res,
1180 gpointer user_data)
1181 {
1182 GOutputStream *stream = G_OUTPUT_STREAM (source_object);
1183 GTask *task = G_TASK (user_data);
1184 gssize bytes_written;
1185 GError *err = NULL;
1186 WriteAllData *write_data = g_task_get_task_data (task);
1187
1188 bytes_written = g_output_stream_write_finish (stream, res, &err);
1189 if (bytes_written == -1)
1190 {
1191 g_task_return_error (task, err);
1192 g_object_unref (task);
1193 return;
1194 }
1195
1196 write_data->bytes_written += bytes_written;
1197 if (write_data->bytes_written < write_data->count)
1198 {
1199 g_output_stream_write_async (stream,
1200 (const guint8 *)write_data->buffer + write_data->bytes_written,
1201 write_data->count - write_data->bytes_written,
1202 g_task_get_priority (task), g_task_get_cancellable (task),
1203 write_all_cb, task);
1204 return;
1205 }
1206
1207 g_task_return_boolean (task, TRUE);
1208 g_object_unref (task);
1209 }
1210
1211 static void
write_all_async(GOutputStream * stream,const void * buffer,gsize count,int io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1212 write_all_async (GOutputStream *stream,
1213 const void *buffer,
1214 gsize count,
1215 int io_priority,
1216 GCancellable *cancellable,
1217 GAsyncReadyCallback callback,
1218 gpointer user_data)
1219 {
1220 GTask *task;
1221 WriteAllData *write_data;
1222
1223 task = g_task_new (stream, cancellable, callback, user_data);
1224 g_task_set_source_tag (task, write_all_async);
1225 g_task_set_priority (task, io_priority);
1226
1227 write_data = g_slice_new0 (WriteAllData);
1228 write_data->buffer = buffer;
1229 write_data->count = count;
1230
1231 g_task_set_task_data (task, write_data, (GDestroyNotify)free_write_all_data);
1232
1233 g_output_stream_write_async (stream, buffer, count, io_priority, cancellable,
1234 write_all_cb, task);
1235 }
1236
1237 static gboolean
write_all_finish(GOutputStream * stream,GAsyncResult * res,gsize * bytes_written,GError ** error)1238 write_all_finish (GOutputStream *stream,
1239 GAsyncResult *res,
1240 gsize *bytes_written,
1241 GError **error)
1242 {
1243 g_return_val_if_fail (g_task_is_valid (res, stream), FALSE);
1244 g_return_val_if_fail (g_async_result_is_tagged (res, write_all_async), FALSE);
1245
1246 if (bytes_written)
1247 {
1248 WriteAllData *write_data;
1249
1250 write_data = g_task_get_task_data (G_TASK (res));
1251 *bytes_written = write_data->bytes_written;
1252 }
1253
1254 return g_task_propagate_boolean (G_TASK (res), error);
1255 }
1256
1257 #define HANDLE_RES() { \
1258 gboolean result; \
1259 GError *err = NULL; \
1260 \
1261 result = write_all_finish (output, res, NULL, &err); \
1262 if (!result) \
1263 { \
1264 if (req_data->task) \
1265 g_task_return_error (req_data->task, err); \
1266 else \
1267 g_error_free (err); \
1268 \
1269 g_hash_table_remove (priv->request_hash, \
1270 GUINT_TO_POINTER ((guint)GUINT16_FROM_BE (priv->write_dsi_header.requestID))); \
1271 free_request_data (req_data); \
1272 \
1273 g_mutex_lock (&priv->mutex); \
1274 send_request_unlocked (afp_conn); \
1275 g_mutex_unlock (&priv->mutex); \
1276 return; \
1277 } \
1278 }
1279
1280 static void
write_buf_cb(GObject * object,GAsyncResult * res,gpointer user_data)1281 write_buf_cb (GObject *object, GAsyncResult *res, gpointer user_data)
1282 {
1283 GOutputStream *output = G_OUTPUT_STREAM (object);
1284 RequestData *req_data = user_data;
1285 GVfsAfpConnection *afp_conn = req_data->conn;
1286 GVfsAfpConnectionPrivate *priv = afp_conn->priv;
1287
1288 HANDLE_RES ();
1289
1290 g_mutex_lock (&priv->mutex);
1291 send_request_unlocked (afp_conn);
1292 g_mutex_unlock (&priv->mutex);
1293 }
1294
1295 static void
write_command_cb(GObject * object,GAsyncResult * res,gpointer user_data)1296 write_command_cb (GObject *object, GAsyncResult *res, gpointer user_data)
1297 {
1298 GOutputStream *output = G_OUTPUT_STREAM (object);
1299 RequestData *req_data = user_data;
1300 GVfsAfpConnection *afp_conn = req_data->conn;
1301 GVfsAfpConnectionPrivate *priv = afp_conn->priv;
1302
1303 HANDLE_RES ();
1304
1305 if (priv->write_dsi_header.command == DSI_WRITE &&
1306 req_data->command->buf)
1307 {
1308 write_all_async (output, req_data->command->buf, req_data->command->buf_size,
1309 0, NULL, write_buf_cb, req_data);
1310 return;
1311 }
1312
1313 g_mutex_lock (&priv->mutex);
1314 send_request_unlocked (afp_conn);
1315 g_mutex_unlock (&priv->mutex);
1316 }
1317
1318 static void
write_dsi_header_cb(GObject * object,GAsyncResult * res,gpointer user_data)1319 write_dsi_header_cb (GObject *object, GAsyncResult *res, gpointer user_data)
1320 {
1321 GOutputStream *output = G_OUTPUT_STREAM (object);
1322 RequestData *req_data = user_data;
1323 GVfsAfpConnection *afp_conn = req_data->conn;
1324 GVfsAfpConnectionPrivate *priv = afp_conn->priv;
1325
1326 char *data;
1327 gsize size;
1328
1329 HANDLE_RES ();
1330
1331 if (req_data->type == REQUEST_TYPE_TICKLE)
1332 {
1333 g_mutex_lock (&priv->mutex);
1334 send_request_unlocked (afp_conn);
1335 g_mutex_unlock (&priv->mutex);
1336 return;
1337 }
1338
1339 data = g_vfs_afp_command_get_data (req_data->command);
1340 size = g_vfs_afp_command_get_size (req_data->command);
1341
1342 write_all_async (output, data, size, 0, NULL, write_command_cb, req_data);
1343 }
1344
1345 static void
send_request_unlocked(GVfsAfpConnection * afp_connection)1346 send_request_unlocked (GVfsAfpConnection *afp_connection)
1347 {
1348 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
1349
1350 RequestData *req_data;
1351 guint32 writeOffset;
1352 guint8 dsi_command;
1353
1354 while ((req_data = g_queue_pop_head (priv->request_queue)))
1355 {
1356 if (!req_data->task || !g_task_return_error_if_cancelled (req_data->task))
1357 break;
1358 }
1359
1360 if (!req_data) {
1361 priv->send_loop_running = FALSE;
1362 return;
1363 }
1364
1365 switch (req_data->type)
1366 {
1367 case REQUEST_TYPE_TICKLE:
1368 priv->write_dsi_header.flags = 0x00;
1369 priv->write_dsi_header.command = DSI_TICKLE;
1370 priv->write_dsi_header.requestID = GUINT16_TO_BE (get_tickle_id (afp_connection));
1371 priv->write_dsi_header.writeOffset = 0;
1372 priv->write_dsi_header.totalDataLength = 0;
1373 priv->write_dsi_header.reserved = 0;
1374 break;
1375
1376 case REQUEST_TYPE_COMMAND:
1377 {
1378 gsize size;
1379
1380 switch (req_data->command->type)
1381 {
1382 case AFP_COMMAND_WRITE:
1383 writeOffset = 8;
1384 dsi_command = DSI_WRITE;
1385 break;
1386 case AFP_COMMAND_WRITE_EXT:
1387 writeOffset = 20;
1388 dsi_command = DSI_WRITE;
1389 break;
1390
1391 default:
1392 writeOffset = 0;
1393 dsi_command = DSI_COMMAND;
1394 break;
1395 }
1396
1397 priv->write_dsi_header.flags = 0x00;
1398 priv->write_dsi_header.command = dsi_command;
1399 priv->write_dsi_header.requestID = GUINT16_TO_BE (get_request_id (afp_connection));
1400 priv->write_dsi_header.writeOffset = GUINT32_TO_BE (writeOffset);
1401
1402 /* totalDataLength */
1403 size = g_vfs_afp_command_get_size (req_data->command);
1404 if (dsi_command == DSI_WRITE && req_data->command->buf)
1405 size += req_data->command->buf_size;
1406 priv->write_dsi_header.totalDataLength = GUINT32_TO_BE (size);
1407
1408 priv->write_dsi_header.reserved = 0;
1409 break;
1410 }
1411
1412 default:
1413 g_assert_not_reached ();
1414 }
1415
1416 if (req_data->type != REQUEST_TYPE_TICKLE)
1417 g_hash_table_insert (priv->request_hash,
1418 GUINT_TO_POINTER ((guint)GUINT16_FROM_BE (priv->write_dsi_header.requestID)),
1419 req_data);
1420
1421 write_all_async (g_io_stream_get_output_stream (priv->stream),
1422 &priv->write_dsi_header, sizeof (DSIHeader), 0,
1423 NULL, write_dsi_header_cb, req_data);
1424 }
1425
1426 static gboolean
start_send_loop_func(gpointer data)1427 start_send_loop_func (gpointer data)
1428 {
1429 GVfsAfpConnection *conn = data;
1430 GVfsAfpConnectionPrivate *priv = conn->priv;
1431
1432 g_mutex_lock (&priv->mutex);
1433
1434 if (priv->send_loop_running)
1435 goto out;
1436
1437 priv->send_loop_running = TRUE;
1438 send_request_unlocked (conn);
1439
1440 out:
1441 g_mutex_unlock (&priv->mutex);
1442 return G_SOURCE_REMOVE;
1443 }
1444
1445 void
g_vfs_afp_connection_send_command(GVfsAfpConnection * afp_connection,GVfsAfpCommand * command,char * reply_buf,GAsyncReadyCallback callback,GCancellable * cancellable,gpointer user_data)1446 g_vfs_afp_connection_send_command (GVfsAfpConnection *afp_connection,
1447 GVfsAfpCommand *command,
1448 char *reply_buf,
1449 GAsyncReadyCallback callback,
1450 GCancellable *cancellable,
1451 gpointer user_data)
1452 {
1453 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
1454 GTask *task;
1455 GError *err = NULL;
1456 RequestData *req_data;
1457
1458 task = g_task_new (afp_connection, cancellable, callback, user_data);
1459 g_task_set_source_tag (task, g_vfs_afp_connection_send_command);
1460
1461 if (!check_open (afp_connection, &err))
1462 {
1463 g_task_return_error (task, err);
1464 g_object_unref (task);
1465 return;
1466 }
1467
1468 req_data = g_slice_new0 (RequestData);
1469 req_data->type = REQUEST_TYPE_COMMAND;
1470 req_data->command = g_object_ref (command);
1471 req_data->reply_buf = reply_buf;
1472 req_data->conn = afp_connection;
1473 req_data->task = task;
1474
1475 /* Take lock */
1476 g_mutex_lock (&priv->mutex);
1477
1478 g_queue_push_tail (priv->request_queue, req_data);
1479 if (!priv->send_loop_running)
1480 {
1481 g_main_context_invoke (priv->worker_context, start_send_loop_func,
1482 afp_connection);
1483 }
1484
1485 /* Release lock */
1486 g_mutex_unlock (&priv->mutex);
1487 }
1488
1489 GVfsAfpReply *
g_vfs_afp_connection_send_command_finish(GVfsAfpConnection * afp_connection,GAsyncResult * res,GError ** error)1490 g_vfs_afp_connection_send_command_finish (GVfsAfpConnection *afp_connection,
1491 GAsyncResult *res,
1492 GError **error)
1493 {
1494 g_return_val_if_fail (g_task_is_valid (res, afp_connection), NULL);
1495 g_return_val_if_fail (g_async_result_is_tagged (res, g_vfs_afp_connection_send_command), NULL);
1496
1497 return g_task_propagate_pointer (G_TASK (res), error);
1498 }
1499
1500 static gboolean
read_reply_sync(GInputStream * input,DSIHeader * dsi_header,char ** data,GCancellable * cancellable,GError ** error)1501 read_reply_sync (GInputStream *input,
1502 DSIHeader *dsi_header,
1503 char **data,
1504 GCancellable *cancellable,
1505 GError **error)
1506 {
1507 gboolean res;
1508 gsize read_count, bytes_read;
1509
1510 g_assert (dsi_header != NULL);
1511
1512 read_count = sizeof (DSIHeader);
1513 res = g_input_stream_read_all (input, dsi_header, read_count, &bytes_read,
1514 cancellable, error);
1515 if (!res)
1516 return FALSE;
1517
1518 if (bytes_read < read_count)
1519 {
1520 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1521 _("Connection unexpectedly went down"));
1522 return FALSE;
1523 }
1524
1525 dsi_header->requestID = GUINT16_FROM_BE (dsi_header->requestID);
1526 dsi_header->errorCode = GUINT32_FROM_BE (dsi_header->errorCode);
1527 dsi_header->totalDataLength = GUINT32_FROM_BE (dsi_header->totalDataLength);
1528
1529 if (dsi_header->totalDataLength == 0)
1530 {
1531 *data = NULL;
1532 return TRUE;
1533 }
1534
1535 *data = g_malloc (dsi_header->totalDataLength);
1536 read_count = dsi_header->totalDataLength;
1537
1538 res = g_input_stream_read_all (input, *data, read_count, &bytes_read, cancellable, error);
1539 if (!res)
1540 {
1541 g_free (*data);
1542 return FALSE;
1543 }
1544 if (bytes_read < read_count)
1545 {
1546 g_free (*data);
1547 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1548 _("Got unexpected end of stream"));
1549 return FALSE;
1550 }
1551
1552 return TRUE;
1553 }
1554
1555 static gboolean
send_request_sync(GOutputStream * output,DsiCommand command,guint16 request_id,guint32 writeOffset,gsize len,const char * data,GCancellable * cancellable,GError ** error)1556 send_request_sync (GOutputStream *output,
1557 DsiCommand command,
1558 guint16 request_id,
1559 guint32 writeOffset,
1560 gsize len,
1561 const char *data,
1562 GCancellable *cancellable,
1563 GError **error)
1564 {
1565 DSIHeader dsi_header;
1566 gboolean res;
1567 gsize write_count, bytes_written;
1568
1569 dsi_header.flags = 0x00;
1570 dsi_header.command = command;
1571 dsi_header.requestID = GUINT16_TO_BE (request_id);
1572 dsi_header.writeOffset = GUINT32_TO_BE (writeOffset);
1573 dsi_header.totalDataLength = GUINT32_TO_BE (len);
1574 dsi_header.reserved = 0;
1575
1576 write_count = sizeof (DSIHeader);
1577 res = g_output_stream_write_all (output, &dsi_header, write_count,
1578 &bytes_written, cancellable, error);
1579 if (!res)
1580 return FALSE;
1581
1582 if (data == NULL)
1583 return TRUE;
1584
1585 write_count = len;
1586 res = g_output_stream_write_all (output, data, write_count, &bytes_written,
1587 cancellable, error);
1588 if (!res)
1589 return FALSE;
1590
1591 return TRUE;
1592 }
1593
1594 static void
send_command_sync_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1595 send_command_sync_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
1596 {
1597 SyncData *sync_data = user_data;
1598
1599 sync_data->data = g_object_ref (res);
1600 sync_data_signal (sync_data);
1601 }
1602
1603 GVfsAfpReply *
g_vfs_afp_connection_send_command_sync(GVfsAfpConnection * afp_connection,GVfsAfpCommand * command,GCancellable * cancellable,GError ** error)1604 g_vfs_afp_connection_send_command_sync (GVfsAfpConnection *afp_connection,
1605 GVfsAfpCommand *command,
1606 GCancellable *cancellable,
1607 GError **error)
1608 {
1609 SyncData sync_data;
1610 GVfsAfpReply *reply;
1611
1612 if (!check_open (afp_connection, error))
1613 return FALSE;
1614
1615 sync_data_init (&sync_data, afp_connection, NULL);
1616
1617 g_vfs_afp_connection_send_command (afp_connection, command, NULL,
1618 send_command_sync_cb, cancellable, &sync_data);
1619
1620 sync_data_wait (&sync_data);
1621
1622 reply = g_vfs_afp_connection_send_command_finish (afp_connection, sync_data.data,
1623 error);
1624 g_object_unref (sync_data.data);
1625 sync_data_clear (&sync_data);
1626
1627 return reply;
1628 }
1629
1630 static void
close_connection(GVfsAfpConnection * conn)1631 close_connection (GVfsAfpConnection *conn)
1632 {
1633 GVfsAfpConnectionPrivate *priv = conn->priv;
1634
1635 guint16 req_id;
1636 gboolean res;
1637 GError *err = NULL;
1638
1639 GQueue *request_queue;
1640 GSList *pending_closes, *siter;
1641 GHashTable *request_hash;
1642 GHashTableIter iter;
1643 RequestData *req_data;
1644
1645 /* Take lock */
1646 g_mutex_lock (&priv->mutex);
1647
1648 /* Set closed flag */
1649 g_atomic_int_set (&priv->atomic_state, STATE_CLOSED);
1650
1651 request_queue = priv->request_queue;
1652 priv->request_queue = NULL;
1653
1654 request_hash = priv->request_hash;
1655 priv->request_hash = NULL;
1656
1657 pending_closes = priv->pending_closes;
1658 priv->pending_closes = NULL;
1659
1660 /* Release lock */
1661 g_mutex_unlock (&priv->mutex);
1662
1663 /* close DSI session */
1664 req_id = get_request_id (conn);
1665 res = send_request_sync (g_io_stream_get_output_stream (priv->stream),
1666 DSI_CLOSE_SESSION, req_id, 0, 0, NULL,
1667 NULL, &err);
1668 if (!res)
1669 g_io_stream_close (priv->stream, NULL, NULL);
1670 else
1671 res = g_io_stream_close (priv->stream, NULL, &err);
1672
1673 g_clear_object (&priv->stream);
1674
1675 while ((req_data = g_queue_pop_head (request_queue)))
1676 {
1677 g_task_return_new_error (req_data->task, G_IO_ERROR, G_IO_ERROR_CLOSED, "Connection was closed");
1678 free_request_data (req_data);
1679 }
1680
1681 g_hash_table_iter_init (&iter, request_hash);
1682 while (g_hash_table_iter_next (&iter, NULL, (void **)&req_data))
1683 {
1684 g_task_return_new_error (req_data->task, G_IO_ERROR, G_IO_ERROR_CLOSED, "Connection was closed");
1685 free_request_data (req_data);
1686 }
1687
1688 /* quit main_loop */
1689 g_main_loop_quit (priv->worker_loop);
1690 g_main_loop_unref (priv->worker_loop);
1691 g_main_context_unref (priv->worker_context);
1692
1693 for (siter = pending_closes; siter != NULL; siter = siter->next)
1694 {
1695 SyncData *close_data = siter->data;
1696
1697 close_data->res = TRUE;
1698 sync_data_signal (close_data);
1699 }
1700 g_slist_free (pending_closes);
1701 }
1702
1703 gboolean
g_vfs_afp_connection_close_sync(GVfsAfpConnection * afp_connection,GCancellable * cancellable,GError ** error)1704 g_vfs_afp_connection_close_sync (GVfsAfpConnection *afp_connection,
1705 GCancellable *cancellable,
1706 GError **error)
1707 {
1708 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
1709
1710 SyncData close_data;
1711
1712 /* Take lock */
1713 g_mutex_lock (&priv->mutex);
1714
1715 if (!check_open (afp_connection, error)) {
1716 g_mutex_unlock (&priv->mutex);
1717 return FALSE;
1718 }
1719
1720 sync_data_init (&close_data, afp_connection, error);
1721 priv->pending_closes = g_slist_prepend (priv->pending_closes, &close_data);
1722
1723 /* Release lock */
1724 g_mutex_unlock (&priv->mutex);
1725
1726 if (g_atomic_int_compare_and_exchange (&priv->atomic_state, STATE_CONNECTED, STATE_PENDING_CLOSE))
1727 g_cancellable_cancel (priv->read_cancellable);
1728
1729 sync_data_wait (&close_data);
1730
1731
1732 return close_data.res;
1733 }
1734
1735 static gpointer
open_thread_func(gpointer user_data)1736 open_thread_func (gpointer user_data)
1737 {
1738 SyncData *data = user_data;
1739 GVfsAfpConnection *conn = data->conn;
1740 GVfsAfpConnectionPrivate *priv = conn->priv;
1741
1742 GSocketClient *client;
1743 GSocketConnection *connection;
1744 GSocket *socket;
1745 GError *error = NULL;
1746
1747 guint16 req_id;
1748 gboolean res = FALSE;
1749 char *reply;
1750 DSIHeader dsi_header;
1751 guint pos;
1752
1753 client = g_socket_client_new ();
1754 connection = g_socket_client_connect (client,
1755 priv->addr,
1756 data->cancellable, data->error);
1757 g_object_unref (client);
1758
1759 if (!connection)
1760 goto out;
1761
1762 socket = g_socket_connection_get_socket (connection);
1763 if (!g_socket_set_option (socket, IPPROTO_TCP, TCP_NODELAY, TRUE, &error))
1764 {
1765 g_warning ("Could not set TCP_NODELAY: %s\n", error->message);
1766 g_error_free (error);
1767 }
1768 priv->stream = G_IO_STREAM (connection);
1769
1770 req_id = get_request_id (conn);
1771 res = send_request_sync (g_io_stream_get_output_stream (priv->stream),
1772 DSI_OPEN_SESSION, req_id, 0, 0, NULL,
1773 data->cancellable, data->error);
1774 if (!res)
1775 goto out;
1776
1777 res = read_reply_sync (g_io_stream_get_input_stream (priv->stream),
1778 &dsi_header, &reply, data->cancellable, data->error);
1779 if (!res)
1780 goto out;
1781
1782 pos = 0;
1783 while ((dsi_header.totalDataLength - pos) > 2)
1784 {
1785 guint8 optionType;
1786 guint8 optionLength;
1787
1788 optionType = reply[pos++];
1789 optionLength = reply[pos++];
1790
1791 switch (optionType)
1792 {
1793
1794 case 0x00:
1795 if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4)
1796 priv->kRequestQuanta = GUINT32_FROM_BE (*(guint32 *)(reply + pos));
1797
1798 break;
1799
1800 case 0x02:
1801 if (optionLength == 4 && (dsi_header.totalDataLength - pos) >= 4)
1802 priv->kServerReplayCacheSize = GUINT32_FROM_BE (*(guint32 *)(reply + pos));
1803
1804 break;
1805
1806
1807 default:
1808 g_debug ("Unknown DSI option\n");
1809 }
1810
1811 pos += optionLength;
1812 }
1813 g_free (reply);
1814
1815 out:
1816 if (res)
1817 g_atomic_int_set (&priv->atomic_state, STATE_CONNECTED);
1818
1819 /* Signal sync call thread */
1820 data->res = res;
1821 sync_data_signal (data);
1822
1823 /* Return from thread on failure */
1824 if (!res)
1825 {
1826 g_clear_object (&priv->stream);
1827 return NULL;
1828 }
1829
1830 /* Create MainLoop */
1831 priv->worker_context = g_main_context_new ();
1832 priv->worker_loop = g_main_loop_new (priv->worker_context, TRUE);
1833
1834 read_reply (conn);
1835
1836 /* Run mainloop */
1837 g_main_loop_run (priv->worker_loop);
1838
1839 return NULL;
1840 }
1841
1842 gboolean
g_vfs_afp_connection_open_sync(GVfsAfpConnection * afp_connection,GCancellable * cancellable,GError ** error)1843 g_vfs_afp_connection_open_sync (GVfsAfpConnection *afp_connection,
1844 GCancellable *cancellable,
1845 GError **error)
1846 {
1847 GVfsAfpConnectionPrivate *priv = afp_connection->priv;
1848
1849 SyncData data;
1850
1851 sync_data_init (&data, afp_connection, error);
1852 data.cancellable = cancellable;
1853
1854 priv->worker_thread = g_thread_new ("AFP Worker Thread", open_thread_func,
1855 &data);
1856 sync_data_wait (&data);
1857 sync_data_clear (&data);
1858
1859 return data.res;
1860 }
1861
1862 GVfsAfpConnection *
g_vfs_afp_connection_new(GSocketConnectable * addr)1863 g_vfs_afp_connection_new (GSocketConnectable *addr)
1864 {
1865 GVfsAfpConnection *afp_connection;
1866 GVfsAfpConnectionPrivate *priv;
1867
1868 afp_connection = g_object_new (G_VFS_TYPE_AFP_CONNECTION, NULL);
1869 priv = afp_connection->priv;
1870
1871 priv->addr = g_object_ref (addr);
1872
1873 return afp_connection;
1874 }
1875
1876 GVfsAfpReply *
g_vfs_afp_query_server_info(GSocketConnectable * addr,GCancellable * cancellable,GError ** error)1877 g_vfs_afp_query_server_info (GSocketConnectable *addr,
1878 GCancellable *cancellable,
1879 GError **error)
1880 {
1881 GSocketClient *client;
1882 GIOStream *conn;
1883 gboolean res;
1884 DSIHeader dsi_header;
1885 char *data;
1886
1887 client = g_socket_client_new ();
1888 conn = G_IO_STREAM (g_socket_client_connect (client, addr, cancellable, error));
1889 g_object_unref (client);
1890
1891 if (!conn)
1892 return NULL;
1893
1894 res = send_request_sync (g_io_stream_get_output_stream (conn), DSI_GET_STATUS,
1895 0, 0, 0, NULL, cancellable, error);
1896 if (!res)
1897 {
1898 g_object_unref (conn);
1899 return NULL;
1900 }
1901
1902 res = read_reply_sync (g_io_stream_get_input_stream (conn), &dsi_header,
1903 &data, cancellable, error);
1904 if (!res)
1905 {
1906 g_object_unref (conn);
1907 return NULL;
1908 }
1909
1910 g_object_unref (conn);
1911
1912 return g_vfs_afp_reply_new (dsi_header.errorCode, data,
1913 dsi_header.totalDataLength, TRUE);
1914 }
1915
1916 guint32
g_vfs_afp_connection_get_max_request_size(GVfsAfpConnection * afp_connection)1917 g_vfs_afp_connection_get_max_request_size (GVfsAfpConnection *afp_connection)
1918 {
1919 g_return_val_if_fail (G_VFS_IS_AFP_CONNECTION (afp_connection), 0);
1920
1921 return afp_connection->priv->kRequestQuanta;
1922 }
1923