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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
25 #include <sys/socket.h>
27 #include <netinet/in.h>
29 #include <thrift/c_glib/thrift.h>
30 #include <thrift/c_glib/transport/thrift_socket.h>
31 #include <thrift/c_glib/transport/thrift_transport.h>
32 #include <thrift/c_glib/transport/thrift_server_transport.h>
33 #include <thrift/c_glib/transport/thrift_server_socket.h>
35 /* object properties */
36 enum _ThriftServerSocketProperties
39 PROP_THRIFT_SERVER_SOCKET_PORT
,
40 PROP_THRIFT_SERVER_SOCKET_PATH
,
41 PROP_THRIFT_SERVER_SOCKET_BACKLOG
44 /* define the GError domain string */
45 #define THRIFT_SERVER_SOCKET_ERROR_DOMAIN "thrift-server-socket-error-quark"
47 G_DEFINE_TYPE(ThriftServerSocket
, thrift_server_socket
, THRIFT_TYPE_SERVER_TRANSPORT
)
50 thrift_server_socket_listen (ThriftServerTransport
*transport
, GError
**error
)
52 int enabled
= 1; /* for setsockopt() */
53 ThriftServerSocket
*tsocket
= THRIFT_SERVER_SOCKET (transport
);
55 const int socket_domain
= tsocket
->path
? PF_UNIX
: AF_INET
;
58 if ((tsocket
->sd
= socket (socket_domain
, SOCK_STREAM
, 0)) == -1)
60 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
61 THRIFT_SERVER_SOCKET_ERROR_SOCKET
,
62 "failed to create socket - %s", strerror (errno
));
66 if (setsockopt(tsocket
->sd
, SOL_SOCKET
, SO_REUSEADDR
, &enabled
,
67 sizeof(enabled
)) == -1)
69 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
70 THRIFT_SERVER_SOCKET_ERROR_SETSOCKOPT
,
71 "unable to set SO_REUSEADDR - %s", strerror(errno
));
75 /* bind to the socket */
78 /* create a socket structure */
79 struct sockaddr_un pin
;
80 memset (&pin
, 0, sizeof(pin
));
81 pin
.sun_family
= AF_UNIX
;
82 memcpy(pin
.sun_path
, tsocket
->path
, strlen(tsocket
->path
) + 1);
84 if (bind(tsocket
->sd
, (struct sockaddr
*) &pin
, sizeof(pin
)) == -1)
86 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
87 THRIFT_SERVER_SOCKET_ERROR_BIND
,
88 "failed to bind to path %s: - %s",
89 tsocket
->path
, strerror(errno
));
95 /* create a address structure */
96 struct sockaddr_in pin
;
97 memset (&pin
, 0, sizeof(pin
));
98 pin
.sin_family
= AF_INET
;
99 pin
.sin_addr
.s_addr
= INADDR_ANY
;
100 pin
.sin_port
= htons(tsocket
->port
);
102 if (bind(tsocket
->sd
, (struct sockaddr
*) &pin
, sizeof(pin
)) == -1)
104 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
105 THRIFT_SERVER_SOCKET_ERROR_BIND
,
106 "failed to bind to port %d - %s",
107 tsocket
->port
, strerror(errno
));
112 if (listen(tsocket
->sd
, tsocket
->backlog
) == -1)
116 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
117 THRIFT_SERVER_SOCKET_ERROR_BIND
,
118 "failed to bind to path %s: - %s",
119 tsocket
->path
, strerror(errno
));
124 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
125 THRIFT_SERVER_SOCKET_ERROR_LISTEN
,
126 "failed to listen to port %d - %s",
127 tsocket
->port
, strerror(errno
));
136 thrift_server_socket_accept (ThriftServerTransport
*transport
, GError
**error
)
138 int sd
= THRIFT_INVALID_SOCKET
;
140 struct sockaddr_in address
;
141 ThriftSocket
*socket
= NULL
;
143 ThriftServerSocket
*tsocket
= THRIFT_SERVER_SOCKET (transport
);
145 if ((sd
= accept(tsocket
->sd
, (struct sockaddr
*) &address
, &addrlen
)) == -1)
147 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
148 THRIFT_SERVER_SOCKET_ERROR_ACCEPT
,
149 "failed to accept connection - %s",
154 socket
= g_object_new (THRIFT_TYPE_SOCKET
, NULL
);
157 return THRIFT_TRANSPORT(socket
);
161 thrift_server_socket_close (ThriftServerTransport
*transport
, GError
**error
)
163 ThriftServerSocket
*tsocket
= THRIFT_SERVER_SOCKET (transport
);
165 if (close (tsocket
->sd
) == -1)
167 g_set_error (error
, THRIFT_SERVER_SOCKET_ERROR
,
168 THRIFT_SERVER_SOCKET_ERROR_CLOSE
,
169 "unable to close socket - %s", strerror(errno
));
172 tsocket
->sd
= THRIFT_INVALID_SOCKET
;
177 /* define the GError domain for this implementation */
179 thrift_server_socket_error_quark (void)
181 return g_quark_from_static_string(THRIFT_SERVER_SOCKET_ERROR_DOMAIN
);
184 /* initializes the instance */
186 thrift_server_socket_init (ThriftServerSocket
*socket
)
188 socket
->sd
= THRIFT_INVALID_SOCKET
;
193 thrift_server_socket_finalize (GObject
*object
)
195 ThriftServerSocket
*socket
= THRIFT_SERVER_SOCKET (object
);
197 if (socket
->sd
!= THRIFT_INVALID_SOCKET
)
201 socket
->sd
= THRIFT_INVALID_SOCKET
;
204 /* property accessor */
206 thrift_server_socket_get_property (GObject
*object
, guint property_id
,
207 GValue
*value
, GParamSpec
*pspec
)
209 ThriftServerSocket
*socket
= THRIFT_SERVER_SOCKET (object
);
213 case PROP_THRIFT_SERVER_SOCKET_PORT
:
214 g_value_set_uint (value
, socket
->port
);
216 case PROP_THRIFT_SERVER_SOCKET_PATH
:
217 g_value_set_string (value
, socket
->path
);
219 case PROP_THRIFT_SERVER_SOCKET_BACKLOG
:
220 g_value_set_uint (value
, socket
->backlog
);
223 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
228 /* property mutator */
230 thrift_server_socket_set_property (GObject
*object
, guint property_id
,
231 const GValue
*value
, GParamSpec
*pspec
)
233 ThriftServerSocket
*socket
= THRIFT_SERVER_SOCKET (object
);
237 case PROP_THRIFT_SERVER_SOCKET_PORT
:
238 socket
->port
= g_value_get_uint (value
);
240 case PROP_THRIFT_SERVER_SOCKET_PATH
:
242 g_free(socket
->path
);
244 socket
->path
= g_strdup (g_value_get_string (value
));
246 case PROP_THRIFT_SERVER_SOCKET_BACKLOG
:
247 socket
->backlog
= g_value_get_uint (value
);
250 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
255 /* initializes the class */
257 thrift_server_socket_class_init (ThriftServerSocketClass
*cls
)
259 ThriftServerTransportClass
*tstc
= THRIFT_SERVER_TRANSPORT_CLASS (cls
);
260 GObjectClass
*gobject_class
= G_OBJECT_CLASS (cls
);
261 GParamSpec
*param_spec
= NULL
;
263 /* setup accessors and mutators */
264 gobject_class
->get_property
= thrift_server_socket_get_property
;
265 gobject_class
->set_property
= thrift_server_socket_set_property
;
267 param_spec
= g_param_spec_uint ("port",
269 "Set the port to listen to",
272 9090, /* default by convention */
273 G_PARAM_CONSTRUCT_ONLY
|
275 g_object_class_install_property (gobject_class
,
276 PROP_THRIFT_SERVER_SOCKET_PORT
,
279 param_spec
= g_param_spec_string ("path",
281 "Set the path to listen to",
282 NULL
, /* default value */
283 G_PARAM_CONSTRUCT_ONLY
|
285 g_object_class_install_property (gobject_class
,
286 PROP_THRIFT_SERVER_SOCKET_PATH
,
289 param_spec
= g_param_spec_uint ("backlog",
290 "backlog (construct)",
291 "Set the accept backlog",
295 G_PARAM_CONSTRUCT_ONLY
|
297 g_object_class_install_property (gobject_class
,
298 PROP_THRIFT_SERVER_SOCKET_BACKLOG
,
301 gobject_class
->finalize
= thrift_server_socket_finalize
;
303 tstc
->listen
= thrift_server_socket_listen
;
304 tstc
->accept
= thrift_server_socket_accept
;
305 tstc
->close
= thrift_server_socket_close
;