/*- * $Id: echo.c,v 1.23 2002/07/15 20:07:37 jonas Exp $ * * See the file LICENSE for redistribution information. * If you have not received a copy of the license, please contact CodeFactory * by email at info@codefactory.se, or on the web at http://www.codefactory.se/ * You may also write to: CodeFactory AB, SE-903 47, Umeå, Sweden. * * Copyright (c) 2002 Jonas Borgström * Copyright (c) 2002 Daniel Lundin * Copyright (c) 2002 CodeFactory AB. All rights reserved. */ #include #include "echo.h" #include #include static GObjectClass *parent_class = NULL; static gboolean frame_available (RRChannel *channel, RRFrame *frame, GError **error); static void close_confirmation (RRChannel *channel, gint code, const gchar *xml_lang, const gchar *description); static void finalize (GObject *object); static void rr_null_echo_init (GObject *object) { RRNullEcho *echo = RR_NULL_ECHO (object); echo->active_mutex = g_mutex_new (); echo->active_cond = g_cond_new (); } static void rr_null_echo_class_init (GObjectClass *klass) { RRChannelClass *channel_class = (RRChannelClass *)klass; channel_class->frame_available = frame_available; channel_class->close_confirmation = close_confirmation; klass->finalize = finalize; parent_class = g_type_class_peek_parent (klass); } GType rr_null_echo_get_type (void) { static GType rr_type = 0; if (!rr_type) { static GTypeInfo type_info = { sizeof (RRNullEchoClass), NULL, NULL, (GClassInitFunc) rr_null_echo_class_init, NULL, NULL, sizeof (RRNullEcho), 16, (GInstanceInitFunc) rr_null_echo_init }; rr_type = g_type_register_static (RR_TYPE_CHANNEL, "RRNullEcho", &type_info, 0); rr_channel_set_uri (rr_type, NULL_ECHO_URI); } return rr_type; } static void finalize (GObject *object) { RRNullEcho *echo = RR_NULL_ECHO (object); g_mutex_free (echo->active_mutex); g_cond_free (echo->active_cond); parent_class->finalize (object); } static void wait_inactive (RRNullEcho *echo) { g_mutex_lock (echo->active_mutex); while (echo->active) g_cond_wait (echo->active_cond, echo->active_mutex); g_mutex_unlock (echo->active_mutex); } static void set_active (RRNullEcho *echo, gboolean active) { g_mutex_lock (echo->active_mutex); echo->active = active; g_cond_signal (echo->active_cond); g_mutex_unlock (echo->active_mutex); } static gboolean is_active (RRNullEcho *echo) { gboolean active; g_mutex_lock (echo->active_mutex); active = echo->active; g_mutex_unlock (echo->active_mutex); return active; } static void close_confirmation (RRChannel *channel, gint code, const gchar *xml_lang, const gchar *description) { RRNullEcho *echo = RR_NULL_ECHO (channel); if (is_active (echo)) { echo->echo_error = g_error_new (RR_ERROR, /* error domain */ RR_ERROR_OTHER,/* error code */ "Channel closed."); set_active (echo, FALSE); } } static gboolean frame_available (RRChannel *channel, RRFrame *frame, GError **error) { RRNullEcho *echo = RR_NULL_ECHO (channel); switch (frame->type) { case RR_FRAME_TYPE_MSG: /* Return the frame, only the frame type is changed * from MSG to RPY */ g_object_ref (G_OBJECT (frame)); frame->type = RR_FRAME_TYPE_RPY; if (!rr_channel_send_frame (RR_CHANNEL (echo), frame, error)) return FALSE; break; case RR_FRAME_TYPE_RPY: /* Append the data we received to the output buffer */ memcpy (echo->obuffer, frame->payload, frame->size); echo->obuffer += frame->size; /* Are we done? */ if (!frame->more) set_active (echo, FALSE); break; default: echo->echo_error = g_error_new (RR_BEEP_ERROR, RR_BEEP_CODE_SYNTAX_ERROR, "Unexpected frame received."); set_active (echo, FALSE); break; } return TRUE; } gboolean rr_null_echo_trip (RRNullEcho *echo, const guint8 *ibuffer, gsize ilen, guint8 *obuffer, gsize olen, GError **error) { RRMessage *msg; g_return_val_if_fail (RR_IS_NULL_ECHO (echo), FALSE); g_return_val_if_fail (!is_active (echo), FALSE); set_active (echo, TRUE); echo->obuffer = obuffer; msg = rr_message_static_new (RR_FRAME_TYPE_MSG, (guint8 *)ibuffer, ilen, FALSE); if (!rr_channel_send_message (RR_CHANNEL (echo), msg, error)) return FALSE; wait_inactive (echo); if (echo->echo_error) { g_propagate_error (error, echo->echo_error); echo->echo_error = NULL; return FALSE; } return TRUE; }