blob: 57d62175139afff667d3168f6115bb64730963f9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <thrift/c_glib/thrift.h>
#include <thrift/c_glib/thrift_application_exception.h>
#include <thrift/c_glib/processor/thrift_dispatch_processor.h>
G_DEFINE_ABSTRACT_TYPE (ThriftDispatchProcessor,
thrift_dispatch_processor,
THRIFT_TYPE_PROCESSOR)
gboolean
thrift_dispatch_processor_process (ThriftProcessor *processor,
ThriftProtocol *in,
ThriftProtocol *out,
GError **error)
{
gchar *fname;
ThriftMessageType mtype;
gint32 seqid;
ThriftDispatchProcessor *dispatch_processor =
THRIFT_DISPATCH_PROCESSOR (processor);
/* Read the start of the message, which we expect to be a method call */
if (thrift_protocol_read_message_begin (in,
&fname,
&mtype,
&seqid,
error) < 0) {
g_warning ("error reading start of message: %s",
(error != NULL) ? (*error)->message : "(null)");
return FALSE;
}
else if (mtype != T_CALL && mtype != T_ONEWAY) {
g_warning ("received invalid message type %d from client", mtype);
return FALSE;
}
/* Dispatch the method call */
return THRIFT_DISPATCH_PROCESSOR_GET_CLASS (dispatch_processor)
->dispatch_call (dispatch_processor,
in,
out,
fname,
seqid,
error);
}
static gboolean
thrift_dispatch_processor_real_dispatch_call (ThriftDispatchProcessor *self,
ThriftProtocol *in,
ThriftProtocol *out,
gchar *fname,
gint32 seqid,
GError **error)
{
ThriftTransport *transport;
ThriftApplicationException *xception;
gchar *message;
gint32 result;
gboolean dispatch_result = FALSE;
THRIFT_UNUSED_VAR (self);
/* By default, return an application exception to the client indicating the
method name is not recognized. */
if ((thrift_protocol_skip (in, T_STRUCT, error) < 0) ||
(thrift_protocol_read_message_end (in, error) < 0))
return FALSE;
g_object_get (in, "transport", &transport, NULL);
result = thrift_transport_read_end (transport, error);
g_object_unref (transport);
if (result < 0)
return FALSE;
if (thrift_protocol_write_message_begin (out,
fname,
T_EXCEPTION,
seqid,
error) < 0)
return FALSE;
message = g_strconcat ("Invalid method name: '", fname, "'", NULL);
g_free (fname);
xception =
g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION,
"type", THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD,
"message", message,
NULL);
g_free (message);
result = thrift_struct_write (THRIFT_STRUCT (xception),
out,
error);
g_object_unref (xception);
if ((result < 0) ||
(thrift_protocol_write_message_end (out, error) < 0))
return FALSE;
g_object_get (out, "transport", &transport, NULL);
dispatch_result =
((thrift_transport_write_end (transport, error) >= 0) &&
(thrift_transport_flush (transport, error) >= 0));
g_object_unref (transport);
return dispatch_result;
}
static void
thrift_dispatch_processor_init (ThriftDispatchProcessor *self)
{
THRIFT_UNUSED_VAR (self);
}
static void
thrift_dispatch_processor_class_init (ThriftDispatchProcessorClass *klass)
{
ThriftProcessorClass *processor_class =
THRIFT_PROCESSOR_CLASS (klass);
/* Implement ThriftProcessor's process method */
processor_class->process = thrift_dispatch_processor_process;
/* Provide a default implement for dispatch_call, which returns an exception
to the client indicating the method name was not recognized */
klass->dispatch_call = thrift_dispatch_processor_real_dispatch_call;
}