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