/*-
* $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 <jonas@codefactory.se>
* Copyright (c) 2002 Daniel Lundin <daniel@codefactory.se>
* Copyright (c) 2002 CodeFactory AB. All rights reserved.
*/
#include <librr/rr.h>
#include "echo.h"
#include <stdio.h>
#include <string.h>
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;
}
syntax highlighted by Code2HTML, v. 0.9.1