1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <glib-object.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include <thrift/c_glib/thrift.h>
26 #include <thrift/c_glib/processor/thrift_multiplexed_processor.h>
27 #include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h>
28 #include <thrift/c_glib/protocol/thrift_compact_protocol_factory.h>
29 #include <thrift/c_glib/server/thrift_server.h>
30 #include <thrift/c_glib/server/thrift_simple_server.h>
31 #include <thrift/c_glib/transport/thrift_buffered_transport.h>
32 #include <thrift/c_glib/transport/thrift_buffered_transport_factory.h>
33 #include <thrift/c_glib/transport/thrift_framed_transport.h>
34 #include <thrift/c_glib/transport/thrift_framed_transport_factory.h>
35 #include <thrift/c_glib/transport/thrift_server_socket.h>
36 #include <thrift/c_glib/transport/thrift_server_transport.h>
37 #include <thrift/c_glib/transport/thrift_transport.h>
38 #include <thrift/c_glib/transport/thrift_transport_factory.h>
39
40 #include "../gen-c_glib/t_test_thrift_test.h"
41 #include "../gen-c_glib/t_test_second_service.h"
42
43 #include "thrift_test_handler.h"
44 #include "thrift_second_service_handler.h"
45
46 /* Our server object, declared globally so it is accessible within the SIGINT
47 signal handler */
48 ThriftServer *server = NULL;
49
50 /* A flag that indicates whether the server was interrupted with SIGINT
51 (i.e. Ctrl-C) so we can tell whether its termination was abnormal */
52 gboolean sigint_received = FALSE;
53
54 /* Handle SIGINT ("Ctrl-C") signals by gracefully stopping the server */
55 static void
sigint_handler(int signal_number)56 sigint_handler (int signal_number)
57 {
58 THRIFT_UNUSED_VAR (signal_number);
59
60 /* Take note we were called */
61 sigint_received = TRUE;
62
63 /* Shut down the server gracefully */
64 if (server != NULL)
65 thrift_server_stop (server);
66 }
67
68 int
main(int argc,char ** argv)69 main (int argc, char **argv)
70 {
71 static gint port = 9090;
72 static gchar *path_option = NULL;
73 static gchar *server_type_option = NULL;
74 static gchar *transport_option = NULL;
75 static gchar *protocol_option = NULL;
76 static gint string_limit = 0;
77 static gint container_limit = 0;
78
79 static
80 GOptionEntry option_entries[] = {
81 { "port", 0, 0, G_OPTION_ARG_INT, &port,
82 "Port number to connect (=9090)", NULL },
83 { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path_option,
84 "Unix socket domain path to connect", NULL },
85 { "server-type", 0, 0, G_OPTION_ARG_STRING, &server_type_option,
86 "Type of server: simple (=simple)", NULL },
87 { "transport", 0, 0, G_OPTION_ARG_STRING, &transport_option,
88 "Transport: buffered, framed (=buffered)", NULL },
89 { "protocol", 0, 0, G_OPTION_ARG_STRING, &protocol_option,
90 "Protocol: binary, compact (=binary)", NULL },
91 { "string-limit", 0, 0, G_OPTION_ARG_INT, &string_limit,
92 "Max string length (=none)", NULL },
93 { "container-limit", 0, 0, G_OPTION_ARG_INT, &container_limit,
94 "Max container length (=none)", NULL },
95 { NULL }
96 };
97
98 gchar *server_name = "simple";
99 gchar *transport_name = "buffered";
100 GType transport_factory_type = THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY;
101 gchar *protocol_name = "binary";
102 GType protocol_factory_type = THRIFT_TYPE_BINARY_PROTOCOL_FACTORY;
103
104 TTestThriftTestHandler *handler;
105 TTestThriftTestHandler *handler_second_service = NULL;
106 ThriftProcessor *processor;
107 ThriftProcessor *processor_test = NULL;
108 ThriftProcessor *processor_second_service = NULL;
109 ThriftServerTransport *server_transport;
110 ThriftTransportFactory *transport_factory;
111 ThriftProtocolFactory *protocol_factory;
112
113 struct sigaction sigint_action;
114
115 GOptionContext *option_context;
116 gboolean options_valid = TRUE;
117
118 GError *error = NULL;
119
120 #if (!GLIB_CHECK_VERSION (2, 36, 0))
121 g_type_init ();
122 #endif
123
124 /* Configure and parse our command-line options */
125 option_context = g_option_context_new (NULL);
126 g_option_context_add_main_entries (option_context,
127 option_entries,
128 NULL);
129 if (g_option_context_parse (option_context,
130 &argc,
131 &argv,
132 &error) == FALSE) {
133 fprintf (stderr, "%s\n", error->message);
134 g_clear_error (&error);
135 g_option_context_free (option_context);
136 return 255;
137 }
138 g_option_context_free (option_context);
139
140 /* Validate the parsed options */
141 if (server_type_option != NULL &&
142 strncmp (server_type_option, "simple", 7) != 0) {
143 fprintf (stderr, "Unknown server type %s\n", protocol_option);
144 options_valid = FALSE;
145 }
146
147 if (protocol_option != NULL) {
148 if (strncmp (protocol_option, "compact", 8) == 0) {
149 protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY;
150 protocol_name = "compact";
151 }
152 else if (strncmp (protocol_option, "multi", 6) == 0) {
153 protocol_name = "binary:multi";
154 }
155 else if (strncmp (protocol_option, "multic", 7) == 0) {
156 protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY;
157 protocol_name = "compact:multic";
158 }
159 else if (strncmp (protocol_option, "binary", 7) != 0) {
160 fprintf (stderr, "Unknown protocol type %s\n", protocol_option);
161 options_valid = FALSE;
162 }
163 }
164
165 if (transport_option != NULL) {
166 if (strncmp (transport_option, "framed", 7) == 0) {
167 transport_factory_type = THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY;
168 transport_name = "framed";
169 }
170 else if (strncmp (transport_option, "buffered", 9) != 0) {
171 fprintf (stderr, "Unknown transport type %s\n", transport_option);
172 options_valid = FALSE;
173 }
174 }
175
176 if (!options_valid)
177 return 254;
178
179 /* Establish all our connection objects */
180 handler = g_object_new (TYPE_THRIFT_TEST_HANDLER,
181 NULL);
182
183
184
185 if(strstr(protocol_name, ":multi")){
186 /* When a multiplexed processor is involved the handler is not
187 registered as usual. We create the processor and the real
188 processor is registered. Multiple processors can be registered
189 at once. This is why we don't have a constructor property */
190 processor = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROCESSOR,
191 NULL);
192
193 handler_second_service = g_object_new (TYPE_SECOND_SERVICE_HANDLER,
194 NULL);
195
196 processor_test = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR,
197 "handler", handler,
198 NULL);
199 processor_second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_PROCESSOR,
200 "handler", handler_second_service,
201 NULL);
202
203 /* We register a test processor with Multiplexed name ThriftTest */
204 if(!thrift_multiplexed_processor_register_processor(processor,
205 "ThriftTest", processor_test,
206 &error)){
207 g_message ("thrift_server_serve: %s",
208 error != NULL ? error->message : "(null)");
209 g_clear_error (&error);
210 }
211 /* We register a second test processor with Multiplexed name SecondService
212 * we are responsible of freeing the processor when it's not used anymore */
213 if(!thrift_multiplexed_processor_register_processor(processor,
214 "SecondService", processor_second_service,
215 &error)){
216 g_message ("thrift_server_serve: %s",
217 error != NULL ? error->message : "(null)");
218 g_clear_error (&error);
219 }
220
221 }else{
222 processor = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR,
223 "handler", handler,
224 NULL);
225 }
226 if (path_option) {
227 server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
228 "path", path_option,
229 NULL);
230 } else {
231 server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
232 "port", port,
233 NULL);
234 }
235 transport_factory = g_object_new (transport_factory_type,
236 NULL);
237
238 if (strstr (protocol_name, "compact") != NULL) {
239 protocol_factory = g_object_new (protocol_factory_type,
240 "string_limit", string_limit,
241 "container_limit", container_limit,
242 NULL);
243 } else {
244 protocol_factory = g_object_new (protocol_factory_type,
245 NULL);
246 }
247
248 server = g_object_new (THRIFT_TYPE_SIMPLE_SERVER,
249 "processor", processor,
250 "server_transport", server_transport,
251 "input_transport_factory", transport_factory,
252 "output_transport_factory", transport_factory,
253 "input_protocol_factory", protocol_factory,
254 "output_protocol_factory", protocol_factory,
255 NULL);
256
257 /* Install our SIGINT handler, which handles Ctrl-C being pressed by stopping
258 the server gracefully */
259 memset (&sigint_action, 0, sizeof (sigint_action));
260 sigint_action.sa_handler = sigint_handler;
261 sigint_action.sa_flags = SA_RESETHAND;
262 sigaction (SIGINT, &sigint_action, NULL);
263
264 if (path_option) {
265 printf ("Starting \"%s\" server (%s/%s) listen on: %s\n",
266 server_name,
267 transport_name,
268 protocol_name,
269 path_option);
270 } else {
271 printf ("Starting \"%s\" server (%s/%s) listen on: %d\n",
272 server_name,
273 transport_name,
274 protocol_name,
275 port);
276 }
277 fflush (stdout);
278
279 /* Serve clients until SIGINT is received (Ctrl-C is pressed) */
280 thrift_server_serve (server, &error);
281
282 /* If the server stopped for any reason other than being interrupted by the
283 user, report the error */
284 if (!sigint_received) {
285 g_message ("thrift_server_serve: %s",
286 error != NULL ? error->message : "(null)");
287 }
288
289 puts ("done.");
290
291 g_clear_error (&error);
292 g_object_unref (server);
293 g_object_unref (protocol_factory);
294 g_object_unref (transport_factory);
295 g_object_unref (server_transport);
296 g_object_unref (processor);
297 g_object_unref (handler);
298 if(handler_second_service){
299 g_object_unref (handler_second_service);
300 }
301 if(processor_test){
302 g_object_unref (processor_test);
303 }
304 if(processor_second_service){
305 g_object_unref (processor_second_service);
306 }
307
308 return 0;
309 }
310