Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions builds/cmake/Configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ set(CASE_SENSITIVITY "true")
set(SUPPORT_RAW_DEVICES 1)

set(include_files_list
afunix.h
aio.h
assert.h
atomic.h
Expand Down Expand Up @@ -179,6 +180,7 @@ set(include_files_list
sys/time.h
sys/timeb.h
sys/types.h
sys/un.h
sys/uio.h
sys/wait.h
termio.h
Expand Down
15 changes: 15 additions & 0 deletions builds/install/misc/firebird.conf
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,21 @@
#RemoteServicePort = 3050


# ----------------------------
# Unix domain socket path to be used for client database and service
# connections on platforms with Unix domain socket support. If set,
# the server listens on this socket instead of the TCP service name/port.
# The name should not contain colons, except for a Windows drive letter.
#
# Event notification connections use a separate Unix domain socket in
# the same directory as this socket. Firebird chooses its name as
# fb_event.<server-pid>.<sequence>.
#
# Type: string
#
#RemoteServiceUnixSocket =


# ----------------------------
# The TCP port number to be used for server Event Notification
# messages. The value of 0 (Zero) means that the server will choose
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ AC_CHECK_HEADERS(iconv.h)
AC_CHECK_HEADERS(linux/falloc.h)
AC_CHECK_HEADERS(utime.h)

AC_CHECK_HEADERS(socket.h sys/socket.h sys/sockio.h winsock2.h)
AC_CHECK_HEADERS(afunix.h socket.h sys/socket.h sys/sockio.h sys/un.h winsock2.h)
AC_CHECK_DECLS(SOCK_CLOEXEC,,,[[
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
Expand Down
1 change: 1 addition & 0 deletions doc/Firebird_conf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ DeadThreadsCollection integer default 50
PriorityBoost integer default 5
RemoteServiceName string default gds_db
RemoteServicePort integer default 3050 (TCP port number)
RemoteServiceUnixSocket string default empty (Unix domain socket path)
IpcName string default "FIREBIRD" (Windows only)

MaxUnflushedWrites integer
Expand Down
13 changes: 12 additions & 1 deletion doc/README.connection_strings
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ Examples:
inet://C:\db\mydb.fdb
inet://mydb

Local connection via Unix domain socket:

unix:///run/firebird/firebird.sock:/db/mydb.fdb
unix:///run/firebird/firebird.sock:mydb
unix:///run/firebird/firebird.sock:service_mgr
unix://C:\firebird\firebird.sock:C:\db\mydb.fdb

Local connection via shared memory:

xnet://C:\db\mydb.fdb
Expand All @@ -135,7 +142,11 @@ to connect locally using a specific transport protocol, please specify:

inet://<file path to database or alias>
or
unix://<socket path>:<file path to database or alias>
or
xnet://<file path to database or alias>

Note: XNET (shared memory) protocol is available on Windows only.

Unix domain socket protocol is available on platforms with AF_UNIX support.
The socket path must not contain ':' except for a Windows drive letter, as in
unix://C:\firebird\firebird.sock:C:\db\mydb.fdb.
5 changes: 5 additions & 0 deletions src/common/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ enum ConfigKey
KEY_DEADLOCK_TIMEOUT,
KEY_REMOTE_SERVICE_NAME,
KEY_REMOTE_SERVICE_PORT,
KEY_REMOTE_SERVICE_UNIX_SOCKET,
KEY_IPC_NAME,
KEY_MAX_UNFLUSHED_WRITES,
KEY_MAX_UNFLUSHED_WRITE_TIME,
Expand Down Expand Up @@ -229,6 +230,7 @@ inline constexpr ConfigEntry entries[MAX_CONFIG_KEY] =
{TYPE_INTEGER, "DeadlockTimeout", false, 10}, // seconds
{TYPE_STRING, "RemoteServiceName", false, FB_SERVICE_NAME},
{TYPE_INTEGER, "RemoteServicePort", false, 0},
{TYPE_STRING, "RemoteServiceUnixSocket", true, nullptr},
{TYPE_STRING, "IpcName", false, FB_IPC_NAME},
#ifdef WIN_NT
{TYPE_INTEGER, "MaxUnflushedWrites", false, 100},
Expand Down Expand Up @@ -521,6 +523,9 @@ class Config : public RefCounted, public GlobalStorage
// Service port for INET
CONFIG_GET_PER_DB_KEY(unsigned short, getRemoteServicePort, KEY_REMOTE_SERVICE_PORT, getInt);

// Unix domain socket for remote protocol
CONFIG_GET_GLOBAL_STR(getRemoteServiceUnixSocket, KEY_REMOTE_SERVICE_UNIX_SOCKET);

// Name for IPC-related objects
CONFIG_GET_PER_DB_STR(getIpcName, KEY_IPC_NAME);

Expand Down
6 changes: 6 additions & 0 deletions src/include/gen/autoconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@
/* Define to 1 if you have the <sys/signal.h> header file. */
#cmakedefine HAVE_SYS_SIGNAL_H 1

/* Define to 1 if you have the <afunix.h> header file. */
#cmakedefine HAVE_AFUNIX_H 1

/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H 1

Expand All @@ -351,6 +354,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1

/* Define to 1 if you have the <sys/un.h> header file. */
#cmakedefine HAVE_SYS_UN_H 1

/* Define to 1 if you have the <sys/uio.h> header file. */
#cmakedefine HAVE_SYS_UIO_H 1

Expand Down
1 change: 1 addition & 0 deletions src/include/gen/autoconfig_msvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#endif

/* Headers */
#define HAVE_AFUNIX_H
#define HAVE_ASSERT_H
#define HAVE_CTYPE_H
#undef HAVE_UNISTD_H
Expand Down
70 changes: 68 additions & 2 deletions src/remote/client/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,22 @@
#include <unistd.h>
#endif

#if !defined(WIN_NT)
#include <sys/socket.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#endif

#ifdef WIN_NT
#include <winsock2.h>
#include <process.h>
#endif

#if (defined(WIN_NT) && defined(HAVE_AFUNIX_H)) || defined(HAVE_SYS_UN_H)
#define HAVE_AF_UNIX_SUPPORT
#endif

#if defined(WIN_NT)
#include "../common/isc_proto.h"
#include "../remote/os/win32/xnet_proto.h"
Expand All @@ -93,6 +105,10 @@ const char* const PROTOCOL_INET = "inet";
const char* const PROTOCOL_INET4 = "inet4";
const char* const PROTOCOL_INET6 = "inet6";

#ifdef HAVE_AF_UNIX_SUPPORT
const char* const PROTOCOL_UNIX = "unix";
#endif

#ifdef WIN_NT
const char* const PROTOCOL_XNET = "xnet";
#endif
Expand Down Expand Up @@ -1167,6 +1183,46 @@ static void authReceiveResponse(bool havePacket, ClntAuthBlock& authItr, rem_por

static AtomicCounter remote_event_id;

#ifdef HAVE_AF_UNIX_SUPPORT
static bool analyzeUnixProtocol(PathName& expandedName, PathName& nodeName)
{
nodeName.erase();

const PathName prefix = PathName(PROTOCOL_UNIX) + "://";

if (prefix.length() > expandedName.length())
return false;

if (IgnoreCaseComparator::compare(prefix.c_str(), expandedName.c_str(), prefix.length()) != 0)
return false;

PathName savedName = expandedName;
expandedName.erase(0, prefix.length());

PathName::size_type separator = expandedName.find(':');

#ifdef WIN_NT
if (separator == 1)
{
const char driveLetter = expandedName[0];
if ((driveLetter >= 'A' && driveLetter <= 'Z') || (driveLetter >= 'a' && driveLetter <= 'z'))
separator = expandedName.find(':', separator + 1);
}
#endif

if (separator == PathName::npos || separator == 0 || separator == expandedName.length() - 1)
{
expandedName = savedName;
return false;
}

nodeName = expandedName.substr(0, separator);
expandedName.erase(0, separator + 1);

return true;
}
#endif

static constexpr unsigned ANALYZE_USER_VFY = 0x01;
static constexpr unsigned ANALYZE_LOOPBACK = 0x02;
static constexpr unsigned ANALYZE_MOUNTS = 0x04;
Expand Down Expand Up @@ -7921,14 +7977,24 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
else
#endif

#ifdef HAVE_AF_UNIX_SUPPORT
if (analyzeUnixProtocol(attach_name, node_name))
{
ISC_utf8ToSystem(node_name);
port = INET_analyze(&cBlock, attach_name, node_name.c_str(), flags & ANALYZE_USER_VFY, pb,
cBlock.getConfig(), ref_db_name, cryptCb, AF_UNIX);
}
else
#endif

if (ISC_analyze_protocol(PROTOCOL_INET4, attach_name, node_name, INET_SEPARATOR, needFile))
inet_af = AF_INET;
else if (ISC_analyze_protocol(PROTOCOL_INET6, attach_name, node_name, INET_SEPARATOR, needFile))
inet_af = AF_INET6;

if (inet_af != AF_UNSPEC ||
if (!port && (inet_af != AF_UNSPEC ||
ISC_analyze_protocol(PROTOCOL_INET, attach_name, node_name, INET_SEPARATOR, needFile) ||
ISC_analyze_tcp(attach_name, node_name, needFile))
ISC_analyze_tcp(attach_name, node_name, needFile)))
{
if (node_name.isEmpty())
node_name = INET_LOCALHOST;
Expand Down
Loading
Loading