Discussion:
[Firebird-devel] Unix domain socket support (i.e. AF_UNIX or AF_LOCAL socket)
grostoon
2006-12-05 21:58:47 UTC
Permalink
Hi all,

I'm currently adding support for Unix domain socket to firebird 1.5.3. My goal is to be able
to make the super server listen on a unix socket rather than a TCP socket. This way, no TCP port is reserved on the system, making the database access purely local. And compare to binding to 127.0.0.1, the unix socket has (I think) at least 2 advantages :

=> you can really control who (in term of UID/GIDs) can open (so connect) the unix socket thanks to the file permissions set on the socket path whereas with a TCP socket on 127.0.0.1, all local users can connect whatever their UID/GIDs are.

=> unix sockets are often twice as fast as TCP sockets.

Well, I really think unix socket is a valuable feature...
At this time, what I've done is just a proof of concept or a prototype. If you feel it an interesting feature, I would appreciate your suggestions.


I use the '@' character in the connection string to separate the socket path from the database path. The connection string then looks like socket-***@database-file-path.
For example, /opt/firebird/.fbsock@/opt/firebird/examples/v5/employees.fdb.

For example, to make the fbserver bind on the unix socket /tmp/.fbsock, one have to edit firedird.conf and define RemoteServicePort and RemoteServiceName variables this way :
RemoteServicePort = 0
RemoteServiceName = /tmp/.fbsock

Notice: it could be also interesting to have the fbserver able to listen on both TCP and unix socket at the same time. It such a case, using RemoteServiceName to specified the unix socket is probably not a good idea. Adding a new configuration variable (LocalServiceName for example) is probably a better solution.

Following are the places where I added code to firebird to implement this feature. It works fine at least with isql, gfix, gbak.

However, I've got a little problem with server startup through fbguard : /etc/init.d/firebird start takes much more time to complete when I activate unix socket than when using classic TCP socket. Moreover, fbguard fails to start fbserver if the unix socket already exists even if /etc/init.d/firebird start report an 'OK' status !
/etc/init.d/firebird stop works fine.

Help would be appreciate.


In src/jrd/isc_file.cpp :
At the beginning of function ISC_analyze_tcp :

// First of all detect unix socket connection
if (*file_name == '/' && (p = strchr(file_name, '@')) != NULL) {
*p = '\0';
strcpy(node_name, file_name);
while (*file_name++ = *++p);
return TRUE;
}

if (!(p = strchr(file_name, INET_FLAG))) {
return FALSE;
}
...


In src/remote/inet.cpp :
I rewrite the INET_connect function the follwing way (it's not perfect, it's just a proof of concept at this time : there should be some #ifdef UNIX to make the unix socket code invisible when compiling for windows) :

PORT DLL_EXPORT INET_connect(TEXT * name,
PACKET * packet,
ISC_STATUS * status_vector,
USHORT flag, SCHAR * dpb, SSHORT dpb_length)
{
/**************************************
*
* I N E T _ c o n n e c t
*
**************************************
*
* Functional description
* Establish half of a communication link. If a connect packet is given,
* the connection is on behalf of a remote interface. Otherwise the connect
* is for a server process.
*
**************************************/
socklen_t l;
int n;
int ux = 0; // set to 1 when unix socket detected
SOCKET s;
PORT port;
TEXT temp[1024];
TEXT *p;
struct sockaddr_in address;
struct sockaddr_un uxaddress; // unix domain socket support (AF_UNIX)
#ifndef VMS
struct servent *service;
TEXT msg[64];
#endif
int optval;
#ifdef DEBUG
{
UCHAR *p;
if (INET_trace & TRACE_operations) {
ib_fprintf(ib_stdout, "INET_connect\n");
ib_fflush(ib_stdout);
};
INET_start_time = inet_debug_timer();
if ((p = (UCHAR*) getenv("INET_force_error")) != NULL) {
INET_force_error = atoi((const char*)p);
}
}
#endif
port = alloc_port(0);
port->port_status_vector = status_vector;
REMOTE_get_timeout_params(port, reinterpret_cast < UCHAR * >(dpb),
dpb_length);
status_vector[0] = gds_arg_gds;
status_vector[1] = 0;
status_vector[2] = gds_arg_end;
#ifdef VMS
ISC_tcp_setup(ISC_wait, gds__completion_ast);
#endif
const TEXT* protocol = NULL;
if (name) {
strcpy(temp, name);
if (*temp == '/') {
/* Unix domain socket (/socket-path@/database-file-path) */
ux = 1;
name = temp;
}
else {
for (p = temp; *p;) {
if (*p++ == '/') {
p[-1] = 0;
name = temp;
protocol = p;
break;
}
}
}
}
if (name && *name) {
if (port->port_connection) {
ALLR_free(port->port_connection);
}
port->port_connection = REMOTE_make_string(name);
}
else {
name = port->port_host->str_data;
}
if (!protocol) {
/*
* For unix socket, RemoteServicePort have to be set to 0 and RemoteServiceName
* have to be defined as the unix socket path. Example :
* RemoteServicePort = 0
* RemoteServiceName = /tmp/.fbsock
*/
const int portno = Config::getRemoteServicePort();
const char* svc = Config::getRemoteServiceName();
if (portno) {
snprintf(temp, sizeof(temp), "%d", portno);
protocol = temp;
}
else {
protocol = svc;
}
if (*protocol == '/') {
// Unix domain socket
ux = 1;
strcpy(temp, protocol);
name = temp;
if (port->port_connection) {
ALLR_free(port->port_connection);
}
port->port_connection = REMOTE_make_string(name);
}
}

/* Set up Inter-Net socket address */
inet_zero((SCHAR *) &address, sizeof(address));
if (ux) {
inet_zero((SCHAR *) &uxaddress, sizeof(uxaddress));
}
#ifdef VMS
/* V M S */
if (!ux && getservport(protocol, "tcp", &address.sin_port) == -1) {
inet_error(port, "getservbyname", isc_net_connect_err, 0);
disconnect(port);
return NULL;
}
if (packet) {
if (!ux && getaddr(name, &address) == -1) {
inet_error(port, "gethostbyname", isc_net_connect_err, 0);
disconnect(port);
return NULL;
}
}
else {
if (!ux) {
address.sin_addr.s_addr = INADDR_ANY;
}
}
#else
/* U N I X style sockets */
if (ux) {
uxaddress.sun_family = AF_LOCAL;
strcpy(uxaddress.sun_path, name);
}
else {
address.sin_family = AF_INET;
}
in_addr host_addr;
if (!ux) {
if (packet) {
// client connection
host_addr = get_host_address(name);
if (host_addr.s_addr == INADDR_NONE) {
sprintf(msg,
"INET/INET_connect: gethostbyname failed, error code = %d",
H_ERRNO);
gds__log(msg, 0);
inet_gen_error(port,
isc_network_error,
isc_arg_string,
port->port_connection->str_data,
isc_arg_gds,
isc_net_lookup_err, isc_arg_gds, isc_host_unknown, 0);
disconnect(port);
return NULL;
}
}
else {
// server connection
host_addr = get_bind_address();
}
inet_copy((SCHAR*) &host_addr, (SCHAR *) &address.sin_addr,
sizeof(address.sin_addr));
}
THREAD_EXIT;
if (!ux) {
service = getservbyname(protocol, "tcp");
}
#ifdef WIN_NT
/* On Windows NT/9x, getservbyname can only accomodate
* 1 call at a time. In this case it returns the error
* WSAEINPROGRESS.
* If this happens, retry the operation a few times.
* NOTE: This still does not guarantee success, but helps.
*/
if (!service) {
if (H_ERRNO == INET_RETRY_ERRNO) {
for (int retry = 0; retry < INET_RETRY_CALL; retry++) {
if ( (service = getservbyname(protocol, "tcp")) )
break;
}
}
}
#endif /* WIN_NT */
THREAD_ENTER;
/* Modification by luz (slightly modified by FSG)
instead of failing here, try applying hard-wired
translation of "gds_db" into "3050"
This way, a connection to a remote FB server
works even from clients with missing "gds_db"
entry in "services" file, which is important
for zero-installation clients.
*/
if (!ux) {
if (!service) {
if (strcmp(protocol, FB_SERVICE_NAME) == 0) {
/* apply hardwired translation */
address.sin_port = htons(FB_SERVICE_PORT);
}
/* modification by FSG 23.MAR.2001 */
else {
/* modification by FSG 23.MAR.2001 */
/* The user has supplied something as protocol
* let's see whether this is a port number
* instead of a service name
*/
address.sin_port = htons(atoi(protocol));
}
if (address.sin_port == 0) {
/* end of modification by FSG */
/* this is the original code */
sprintf(msg,
"INET/INET_connect: getservbyname failed, error code = %d",
H_ERRNO);
gds__log(msg, 0);
inet_gen_error(port,
isc_network_error,
isc_arg_string,
port->port_connection->str_data,
isc_arg_gds,
isc_net_lookup_err,
isc_arg_gds,
isc_service_unknown,
isc_arg_string,
protocol, isc_arg_string, "tcp", 0);
return NULL;
}
}
else {
/* if we have got a service-struct, get port number from there
* (in case of hardwired gds_db to 3050 translation, address.sin_port was
* already set above */
address.sin_port = service->s_port;
}
}
/* end of modifications by luz */
#endif /* VMS */
/* Allocate a port block and initialize a socket for communications */
port->port_handle = (HANDLE) socket(ux ? AF_LOCAL : AF_INET, SOCK_STREAM, 0);
if ((SOCKET) port->port_handle == INVALID_SOCKET)
{
inet_error(port, "socket", isc_net_connect_err, ERRNO);
disconnect(port);
return NULL;
}
/* If we're a host, just make the connection */
if (packet) {
THREAD_EXIT;
if (ux) {
n = connect((SOCKET) port->port_handle,
(struct sockaddr *) &uxaddress, SUN_LEN(&uxaddress));
}
else {
n = connect((SOCKET) port->port_handle,
(struct sockaddr *) &address, sizeof(address));
}
THREAD_ENTER;
if (n != -1 && send_full(port, packet))
return port;
else {
inet_error(port, "connect", isc_net_connect_err, ERRNO);
disconnect(port);
return NULL;
}
}
/* We're a server, so wait for a host to show up */
if (flag & SRVR_multi_client) {
if (!ux) {
socklen_t optlen;
struct linger lingerInfo;
lingerInfo.l_onoff = 0;
lingerInfo.l_linger = 0;
optval = TRUE;
n = setsockopt((SOCKET) port->port_handle, SOL_SOCKET, SO_REUSEADDR,
(SCHAR *) & optval, sizeof(optval));
if (n == -1) {
inet_error(port, "setsockopt REUSE", isc_net_connect_listen_err,
ERRNO);
disconnect(port);
return NULL;
}
/* Get any values for SO_LINGER so that they can be reset during
* disconnect. SO_LINGER should be set by default on the socket
*/
optlen = sizeof(port->port_linger);
n = getsockopt((SOCKET) port->port_handle, SOL_SOCKET, SO_LINGER,
(SCHAR *) & port->port_linger, &optlen);
if (n != 0) /* getsockopt failed */
port->port_linger.l_onoff = 0;
n = setsockopt((SOCKET) port->port_handle, SOL_SOCKET, SO_LINGER,
(SCHAR *) & lingerInfo, sizeof(lingerInfo));
if (n == -1) {
inet_error(port, "setsockopt LINGER", isc_net_connect_listen_err,
ERRNO);
disconnect(port);
return NULL;
}
#ifdef SET_TCP_NO_DELAY
if (Config::getTcpNoNagle()) {
optval = TRUE;
n =
setsockopt((SOCKET) port->port_handle, SOL_SOCKET,
TCP_NODELAY, (SCHAR *) & optval, sizeof(optval));
gds__log("inet log: disabled Nagle algorithm \n");
if (n == -1) {
inet_error(port, "setsockopt TCP_NODELAY",
isc_net_connect_listen_err, ERRNO);
disconnect(port);
return NULL;
}
}
#endif
} /* !ux */
}
if (ux) {
struct stat st;
if (stat(uxaddress.sun_path, &st) == 0 && S_ISSOCK(st.st_mode)) {
// Kind of REUSEADDR for unix socket ...
unlink(uxaddress.sun_path);
}
n = bind((SOCKET) port->port_handle,
(struct sockaddr *) &uxaddress, SUN_LEN(&uxaddress));
}
else {
n = bind((SOCKET) port->port_handle,
(struct sockaddr *) &address, sizeof(address));
}
if (n == -1) {
/* On Linux platform, when the server dies the system holds a port
for some time. */
if (!ux && ERRNO == INET_ADDR_IN_USE) {
int retry;
for (retry = 0; retry < INET_RETRY_CALL; retry++) {
sleep(10);
n = bind((SOCKET) port->port_handle,
(struct sockaddr *) &address, sizeof(address));
if (n == 0)
break;
}
}
else {
inet_error(port, "bind", isc_net_connect_listen_err, ERRNO);
disconnect(port);
return NULL;
}
}
n = listen((SOCKET) port->port_handle, 5);
if (n == -1) {
inet_error(port, "listen", isc_net_connect_listen_err, ERRNO);
return NULL;
}
if (flag & SRVR_multi_client) {
/* Prevent the generation of dummy keepalive packets on the
connect port. */
port->port_dummy_packet_interval = 0;
port->port_dummy_timeout = 0;
port->port_server_flags |= (SRVR_server | SRVR_multi_client);
gds__register_cleanup(exit_handler, (void *) port);
return port;
}
while (true) {
THREAD_EXIT;
if (ux) {
l = sizeof(uxaddress);
s = accept((SOCKET) port->port_handle,
(struct sockaddr *) &uxaddress, &l);
}
else {
l = sizeof(address);
s = accept((SOCKET) port->port_handle,
(struct sockaddr *) &address, &l);
}
if (s == INVALID_SOCKET) {
THREAD_ENTER;
inet_error(port, "accept", isc_net_connect_err, ERRNO);
disconnect(port);
return NULL;
}
#ifdef WIN_NT
if ((flag & SRVR_debug) || !fork(s, flag))
#else
if ((flag & SRVR_debug) || !fork())
#endif
{
THREAD_ENTER;
SOCLOSE((SOCKET) port->port_handle);
port->port_handle = (HANDLE) s;
port->port_server_flags |= SRVR_server;
return port;
}
THREAD_ENTER;
SOCLOSE(s);
}
}


Best regards,

Toon.

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
Alex Peshkov
2006-12-06 08:29:13 UTC
Permalink
Post by grostoon
Hi all,
I'm currently adding support for Unix domain socket to firebird 1.5.3. My goal is to be able
=> you can really control who (in term of UID/GIDs) can open (so connect) the unix socket thanks to the file permissions set on the socket path whereas with a TCP socket on 127.0.0.1, all local users can connect whatever their UID/GIDs are.
=> unix sockets are often twice as fast as TCP sockets.
Well, I really think unix socket is a valuable feature...
At this time, what I've done is just a proof of concept or a prototype. If you feel it an interesting feature, I would appreciate your suggestions.
RemoteServicePort = 0
RemoteServiceName = /tmp/.fbsock
Notice: it could be also interesting to have the fbserver able to listen on both TCP and unix socket at the same time. It such a case, using RemoteServiceName to specified the unix socket is probably not a good idea. Adding a new configuration variable (LocalServiceName for example) is probably a better solution.
Yes, using same names for TCP and Unix sockets is bad.
Post by grostoon
Following are the places where I added code to firebird to implement this feature. It works fine at least with isql, gfix, gbak.
However, I've got a little problem with server startup through fbguard : /etc/init.d/firebird start takes much more time to complete when I activate unix socket than when using classic TCP socket. Moreover, fbguard fails to start fbserver if the unix socket already exists even if /etc/init.d/firebird start report an 'OK' status !
/etc/init.d/firebird stop works fine.
Help would be appreciate.
// First of all detect unix socket connection
*p = '\0';
strcpy(node_name, file_name);
while (*file_name++ = *++p);
return TRUE;
}
if (!(p = strchr(file_name, INET_FLAG))) {
return FALSE;
}
...
Toon, the idea is fine for me, but selected approach is wrong in general.
Have a look how different protocols are handled in windows. There are
separate modules for inet, wnet, xnet. And you should add separate
module for unix sockets instead of adding support for them into IP modules.

Alex.
grostoon
2006-12-11 18:57:58 UTC
Permalink
Alex,

It's ok for me to make unix socket implementation a separate module (I mean
a separate .cpp file). Just like inet.cpp
deals with TCP socket, I'll try to add a uxsock.cpp file. Unix socket high
level programming being not so different from
TCP socket programming, I think I'll "just have" to adapt inet.cpp a bit for
unix socket.

However, I'm not very familiar with FB internals, and I've got a few
questions with the inet.cpp code :
- what are the aux_request / aux_connect functions for ? It seems to be a
protocol to make the fb server bind on a new port.
Am I right and if so, when does this mechanism is used. I mean which
clients make use of this auxiliary connection and when ?
I ask this question to evaluate whether I should port this feature for
unix domain socket or just ignore it.

- Same kind of question for check_proxy. What is this proxy feature ?

- There is also a check_host function that checks for /etc/hosts.equiv or
.rhosts equivalences to authorize or deny access to clients.
So, I think that this has no interest at all when connection through a
unix socket. Right ?

- Are there other important places in the code where I have to make changes
for unix sockets support ?

- Is there somewhere a good technical documentation that gives the details
of firebird internal client / server architecture ?

Regards,

Toon.
Post by Alex Peshkov
Post by grostoon
Hi all,
I'm currently adding support for Unix domain socket to firebird 1.5.3.
My goal is to be able
to make the super server listen on a unix socket rather than a TCP
socket. This way, no TCP port is reserved on the system, making the
database access purely local. And compare to binding to 127.0.0.1, the
=> you can really control who (in term of UID/GIDs) can open (so
connect) the unix socket thanks to the file permissions set on the socket
path whereas with a TCP socket on 127.0.0.1, all local users can connect
whatever their UID/GIDs are.
=> unix sockets are often twice as fast as TCP sockets.
Well, I really think unix socket is a valuable feature...
At this time, what I've done is just a proof of concept or a prototype.
If you feel it an interesting feature, I would appreciate your
suggestions.
path from the database path. The connection string then looks like
For example,
For example, to make the fbserver bind on the unix socket /tmp/.fbsock,
one have to edit firedird.conf and define RemoteServicePort and
RemoteServicePort = 0
RemoteServiceName = /tmp/.fbsock
Notice: it could be also interesting to have the fbserver able to
listen on both TCP and unix socket at the same time. It such a case,
using RemoteServiceName to specified the unix socket is probably not a
good idea. Adding a new configuration variable (LocalServiceName for
example) is probably a better solution.
Yes, using same names for TCP and Unix sockets is bad.
Post by grostoon
Following are the places where I added code to firebird to implement
this feature. It works fine at least with isql, gfix, gbak.
However, I've got a little problem with server startup through fbguard
: /etc/init.d/firebird start takes much more time to complete when I
activate unix socket than when using classic TCP socket. Moreover,
fbguard fails to start fbserver if the unix socket already exists even if
/etc/init.d/firebird start report an 'OK' status !
/etc/init.d/firebird stop works fine.
Help would be appreciate.
// First of all detect unix socket connection
*p = '\0';
strcpy(node_name, file_name);
while (*file_name++ = *++p);
return TRUE;
}
if (!(p = strchr(file_name, INET_FLAG))) {
return FALSE;
}
...
Toon, the idea is fine for me, but selected approach is wrong in general.
Have a look how different protocols are handled in windows. There are
separate modules for inet, wnet, xnet. And you should add separate
module for unix sockets instead of adding support for them into IP modules.
Alex.
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share
your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel
Damyan Ivanov
2006-12-11 20:05:52 UTC
Permalink
Post by grostoon
However, I'm not very familiar with FB internals, and I've got a few
- what are the aux_request / aux_connect functions for ? It seems to be a
protocol to make the fb server bind on a new port.
Am I right and if so, when does this mechanism is used. I mean which
clients make use of this auxiliary connection and when ?
Auxiliary connections are used by regular clients when registering
interest in some events.

Something in the lines of:

client connects to the server (on the normal listening socket)
client registers interest for events.
server tells the client where to connect to get events info
client connects to that auxiliary port (well, socket)
... time passes...
event comes on the auxiliary connection (from server to client).
Post by grostoon
I ask this question to evaluate whether I should port this feature for
unix domain socket or just ignore it.
Better implement it :) Otherwise the uxsock interface will be half-usable.
Post by grostoon
- Same kind of question for check_proxy. What is this proxy feature ?
It is a seldom used feature when client connects to a server and that
server proxies the connection to another server. I am not sure how this
relates to unix sockets. Since this is seldom used, you may leave it for
later :)
Post by grostoon
- There is also a check_host function that checks for /etc/hosts.equiv or
.rhosts equivalences to authorize or deny access to clients.
So, I think that this has no interest at all when connection through a
unix socket. Right ?
Yep. Unix socket connections are obviously coming from the same host.


dam
- --
Damyan Ivanov Modular Software Systems
***@modsoftsys.com
phone +359(2)928-2611, 929-3993 fax +359(2)920-0994
mobile +359(88)856-6067 ***@jabber.minus273.org/Gaim
Alex Peshkov
2006-12-12 08:13:54 UTC
Permalink
Hi, Toon!
Post by grostoon
It's ok for me to make unix socket implementation a separate module (I mean
a separate .cpp file). Just like inet.cpp
deals with TCP socket, I'll try to add a uxsock.cpp file. Unix socket high
level programming being not so different from
TCP socket programming, I think I'll "just have" to adapt inet.cpp a bit for
unix socket.
However, I'm not very familiar with FB internals, and I've got a few
- what are the aux_request / aux_connect functions for ? It seems to be a
protocol to make the fb server bind on a new port.
Yes.
Post by grostoon
Am I right and if so, when does this mechanism is used. I mean which
clients make use of this auxiliary connection and when ?
It's used to support events. When client wants to listen to events, it
opens auxiliary port and when POST event_name is executed, server sends
information about event to client using it.
Post by grostoon
I ask this question to evaluate whether I should port this feature for
unix domain socket or just ignore it.
Most (better say all) features except events should work fine.
Certainly, it's highly desired to port events too. But before starting
it may be good idea to test do they work at AIX at all - I have not
tested :)
Post by grostoon
- Same kind of question for check_proxy. What is this proxy feature ?
Never heard about this feature before. I suppose it's not required for
unix sockets (specially taking into account I've never heard about
someone using it). Appears it deals with converting remote user name,
received via inet connection, to some internal name, which might become
CURRENT_USER value. I've wrote might, because this feature was disabled
as absolutely non-secure since 1.5.3. BTW, is there a legal and secure
way to get actual UNIX user name on the other side of a socket? If yes,
this may be twice interesting.
Post by grostoon
- There is also a check_host function that checks for /etc/hosts.equiv or
.rhosts equivalences to authorize or deny access to clients.
So, I think that this has no interest at all when connection through a
unix socket. Right ?
Yes.
Post by grostoon
- Are there other important places in the code where I have to make changes
for unix sockets support ?
You must start clients listening loop in server.cpp, like it's done now
for TCP. Pay attention - listeners for wnet/xnet behave bad for one
reason. They start separate thread for each incoming connection. On
contrary, inet has a pool of working threads (which may grow or become
smaller when needed), and each time server has job to do (incoming
packet) it takes thread from that pool, assign job to it and wakes it
up. This is much better behavior - it makes number of threads needed
much smaller compared with wnet way. But currently listener thread (on
contrary with wnet/xnet) is main server's thread.
You should start separate thread for unix sockets listener and let it
use common with inet pool of working threads.

A small piece of honey. You need not support old protocols - only P10.
This will let you remove some unneeded code - working with
protocols_to_try2,3. Anyway another side doesn't can't be so old not to
support P10.
Post by grostoon
- Is there somewhere a good technical documentation that gives the details
of firebird internal client / server architecture ?
I'm afraid the only documentation is src. And this list. Feel free to
ask questions when needed.


A.
Rick Debay
2006-12-11 21:00:42 UTC
Permalink
Just like inet.cpp deals with TCP socket, I'll try to add a uxsock.cpp file. Unix socket high level programming being not so different from TCP socket programming, I think I'll "just have" to adapt inet.cpp a bit for unix socket.
If the socket programming is "not so different" is there anything you could extend, instead of copying the whole file? Perhaps TCP socket and Unix socket could extend an abstract socket?

-----Original Message-----
From: firebird-devel-***@lists.sourceforge.net [mailto:firebird-devel-***@lists.sourceforge.net] On Behalf Of grostoon
Sent: Monday, December 11, 2006 1:58 PM
To: firebird-***@lists.sourceforge.net
Subject: Re: [Firebird-devel] Unix domain socket support (i.e. AF_UNIX or

Alex,

It's ok for me to make unix socket implementation a separate module (I mean a separate .cpp file). Just like inet.cpp deals with TCP socket, I'll try to add a uxsock.cpp file. Unix socket high level programming being not so different from TCP socket programming, I think I'll "just have" to adapt inet.cpp a bit for unix socket.

However, I'm not very familiar with FB internals, and I've got a few questions with the inet.cpp code :
- what are the aux_request / aux_connect functions for ? It seems to be a protocol to make the fb server bind on a new port.
Am I right and if so, when does this mechanism is used. I mean which clients make use of this auxiliary connection and when ?
I ask this question to evaluate whether I should port this feature for unix domain socket or just ignore it.

- Same kind of question for check_proxy. What is this proxy feature ?

- There is also a check_host function that checks for /etc/hosts.equiv or .rhosts equivalences to authorize or deny access to clients.
So, I think that this has no interest at all when connection through a unix socket. Right ?

- Are there other important places in the code where I have to make changes for unix sockets support ?

- Is there somewhere a good technical documentation that gives the details of firebird internal client / server architecture ?

Regards,

Toon.
Post by grostoon
Hi all,
I'm currently adding support for Unix domain socket to firebird 1.5.3.
My goal is to be able
to make the super server listen on a unix socket rather than a TCP
socket. This way, no TCP port is reserved on the system, making the
database access purely local. And compare to binding to 127.0.0.1,
=> you can really control who (in term of UID/GIDs) can open (so
connect) the unix socket thanks to the file permissions set on the
socket path whereas with a TCP socket on 127.0.0.1, all local users
can connect whatever their UID/GIDs are.
=> unix sockets are often twice as fast as TCP sockets.
Well, I really think unix socket is a valuable feature...
At this time, what I've done is just a proof of concept or a prototype.
If you feel it an interesting feature, I would appreciate your
suggestions.
socket path from the database path. The connection string then looks
For example,
For example, to make the fbserver bind on the unix socket
/tmp/.fbsock, one have to edit firedird.conf and define
RemoteServicePort = 0
RemoteServiceName = /tmp/.fbsock
Notice: it could be also interesting to have the fbserver able to
listen on both TCP and unix socket at the same time. It such a case,
using RemoteServiceName to specified the unix socket is probably not
a good idea. Adding a new configuration variable (LocalServiceName
for
example) is probably a better solution.
Yes, using same names for TCP and Unix sockets is bad.
Post by grostoon
Following are the places where I added code to firebird to
implement this feature. It works fine at least with isql, gfix, gbak.
However, I've got a little problem with server startup through
fbguard
: /etc/init.d/firebird start takes much more time to complete when I
activate unix socket than when using classic TCP socket. Moreover,
fbguard fails to start fbserver if the unix socket already exists
even if /etc/init.d/firebird start report an 'OK' status !
/etc/init.d/firebird stop works fine.
Help would be appreciate.
// First of all detect unix socket connection
*p = '\0';
strcpy(node_name, file_name);
while (*file_name++ = *++p);
return TRUE;
}
if (!(p = strchr(file_name, INET_FLAG))) {
return FALSE;
}
...
Toon, the idea is fine for me, but selected approach is wrong in general.
Have a look how different protocols are handled in windows. There are
separate modules for inet, wnet, xnet. And you should add separate
module for unix sockets instead of adding support for them into IP
modules.
Alex.
----------------------------------------------------------------------
--- Take Surveys. Earn Cash. Influence the Future of IT Join
SourceForge.net's Techsay panel and you'll get the chance to share
your opinions on IT & business topics through brief surveys - and earn
cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEV
DEV Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel
Disclaimer: This message (including attachments) is confidential and may be privileged. If you have received it by mistake please notify the sender by return e-mail and delete this message from your system. Any unauthorized use or dissemination of this message in whole or in part is strictly prohibited. Please note that e-mails are susceptible to change. RxStrategies, Inc. shall not be liable for the improper or incomplete transmission of the information contained in this communication or for any delay in its receipt or damage to your system. RxStrategies, Inc. does not guarantee that the integrity of this communication has been maintained nor that this communication is free from viruses, interceptions or interference.
Alex Peshkov
2006-12-12 08:19:35 UTC
Permalink
Post by Rick Debay
Just like inet.cpp deals with TCP socket, I'll try to add a uxsock.cpp file. Unix socket high level programming being not so different from TCP socket programming, I think I'll "just have" to adapt inet.cpp a bit for unix socket.
If the socket programming is "not so different" is there anything you could extend, instead of copying the whole file? Perhaps TCP socket and Unix socket could extend an abstract socket?
This idea may be really interesting. It seems it's possible to make
single select() to wait for packets coming from both TCP and Unix
sockets. But I'm not sure which way is easier to deal with.
grostoon
2006-12-12 10:13:32 UTC
Permalink
Post by Alex Peshkov
Post by Rick Debay
Just like inet.cpp deals with TCP socket, I'll try to add a uxsock.cpp
file. Unix socket high level programming being not so different from TCP
socket programming, I think I'll "just have" to adapt inet.cpp a bit for
unix socket.
If the socket programming is "not so different" is there anything you
could extend, instead of copying the whole file? Perhaps TCP socket and
Unix socket could extend an abstract socket?
This idea may be really interesting. It seems it's possible to make
single select() to wait for packets coming from both TCP and Unix
sockets. But I'm not sure which way is easier to deal with.
Yes of course, unix socket descriptors support mostly all operations
supported by tcp socket descriptors : select, read, write,
recv, send, bind, listen, accept, connect, ... and so on.
As you can see in my proof of concept example, modifying only
ISC_analyze_tcp and INET_connect functions a bit make
the fbserver as well as isql, gfix, gbax, work fine with unix socket.
Of course, some setsockopt / getsockopt socket options are meaningless on
unix socket but this is not a big problem to deal
with I think.

Toon.
Post by Alex Peshkov
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share
your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel
Loading...