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