8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 13:23:02 +01:00

Reworked the remote protocol analyzing logic.

In particular, it resolves the possible problems with the local access to databases on network shares.
Also, it removes any dependencies from EMBEDDED to simplify Alex's cleanup.
Finally, it adds the initial implementation of the Vlad's suggestion (for testing purposes).
This commit is contained in:
dimitr 2010-03-21 13:13:55 +00:00
parent de33a15195
commit 1b732a3579
3 changed files with 143 additions and 96 deletions

View File

@ -34,9 +34,9 @@ enum iscProtocol {ISC_PROTOCOL_LOCAL, ISC_PROTOCOL_TCPIP, ISC_PROTOCOL_WLAN};
#ifndef NO_NFS
bool ISC_analyze_nfs(Firebird::PathName&, Firebird::PathName&);
#endif
bool ISC_analyze_protocol(const char*, Firebird::PathName&, Firebird::PathName&);
bool ISC_analyze_pclan(Firebird::PathName&, Firebird::PathName&);
bool ISC_analyze_tcp(Firebird::PathName&, Firebird::PathName&);
bool ISC_analyze_xnet(Firebird::PathName&, Firebird::PathName&);
bool ISC_check_if_remote(const Firebird::PathName&, bool);
iscProtocol ISC_extract_host(Firebird::PathName&, Firebird::PathName&, bool);
bool ISC_expand_filename(Firebird::PathName&, bool);

View File

@ -295,6 +295,40 @@ bool ISC_analyze_nfs(tstring& expanded_filename, tstring& node_name)
#endif
bool ISC_analyze_protocol(const char* protocol, tstring& expanded_name, tstring& node_name)
{
/**************************************
*
* I S C _ a n a l y z e _ p r o t o c o l
*
**************************************
*
* Functional description
* Analyze a filename for a known protocol prefix.
* If one is found, extract the node name, compute the residual
* file name, and return true. Otherwise return false.
*
**************************************/
node_name.erase();
const PathName prefix = PathName(protocol) + "://";
if (expanded_name.find(prefix) != 0)
{
return false;
}
expanded_name.erase(0, prefix.length());
const size p = expanded_name.find_first_of('/');
if (p != npos)
{
node_name = expanded_name.substr(0, p);
expanded_name.erase(0, node_name.length() + 1);
}
return true;
}
#if defined(WIN_NT)
bool ISC_analyze_pclan(tstring& expanded_name, tstring& node_name)
{

View File

@ -76,9 +76,6 @@
#endif
#if defined(WIN_NT)
#if !defined(EMBEDDED)
#define USE_XNET
#endif
#include "../jrd/isc_proto.h"
#include "../remote/os/win32/wnet_proto.h"
#include "../remote/xnet_proto.h"
@ -89,6 +86,14 @@
#endif // WIN_NT
const char* const PROTOCOL_INET = "inet";
const char* const PROTOCOL_WNET = "wnet";
const char* const PROTOCOL_XNET = "xnet";
const char* const INET_LOCALHOST = "localhost";
const char* const WNET_LOCALHOST = "\\\\.";
using namespace Firebird;
namespace {
@ -4569,98 +4574,90 @@ static rem_port* analyze(PathName& file_name,
* NOTE: The file name must have been expanded prior to this call.
*
**************************************/
#if defined(WIN_NT)
ISC_expand_share(file_name);
#endif
rem_port* port = NULL;
// Analyze the file name to see if a remote connection is required. If not,
// quietly (sic) return.
#if defined(WIN_NT)
if (ISC_analyze_pclan(file_name, node_name)) {
return WNET_analyze(file_name, status_vector, node_name.c_str(), /*user_string,*/ uv_flag);
}
#endif
if (!port)
{
if (ISC_analyze_tcp(file_name, node_name))
{
port = INET_analyze(file_name, status_vector,
node_name.c_str(), user_string, uv_flag, dpb);
if (!port)
{
// retry in case multiclient inet server not forked yet
sleep(2);
port = INET_analyze(file_name, status_vector,
node_name.c_str(), user_string, uv_flag, dpb);
}
}
else
{
#ifndef NO_NFS
if (!port)
{
if (ISC_analyze_nfs(file_name, node_name))
{
port = INET_analyze(file_name, status_vector,
node_name.c_str(), user_string, uv_flag, dpb);
if (!port)
{
// retry in case multiclient inet server not forked yet
sleep(2);
port = INET_analyze(file_name, status_vector,
node_name.c_str(), user_string, uv_flag, dpb);
}
}
}
#endif
}
}
#if defined(USE_XNET)
// all remote attempts have failed, so access locally through the interprocess server
if (!port && node_name.isEmpty())
{
return XNET_analyze(file_name, status_vector, /*node_name.c_str(), user_string,*/ uv_flag);
}
#endif // USE_XNET
#if defined(SUPERCLIENT) && !defined(EMBEDDED)
// Coerce host connections to loopback
#ifdef WIN_NT
if (!port && node_name.isEmpty())
if (ISC_analyze_protocol(PROTOCOL_XNET, file_name, node_name))
{
file_name.insert(0, "\\\\.\\");
if (ISC_analyze_pclan(file_name, node_name))
return WNET_analyze(file_name, status_vector, node_name.c_str(), /*user_string,*/ uv_flag);
return XNET_analyze(file_name, status_vector, uv_flag);
}
#endif // WIN_NT
#ifdef UNIX
if (ISC_analyze_protocol(PROTOCOL_WNET, file_name, node_name) ||
ISC_analyze_pclan(file_name, node_name))
{
if (node_name.isEmpty())
{
node_name = WNET_LOCALHOST;
}
return WNET_analyze(file_name, status_vector, node_name.c_str(), uv_flag);
}
#endif
if (!port && node_name.isEmpty())
if (ISC_analyze_protocol(PROTOCOL_INET, file_name, node_name) ||
ISC_analyze_tcp(file_name, node_name))
{
file_name.insert(0, "localhost:");
if (ISC_analyze_tcp(file_name, node_name))
if (node_name.isEmpty())
{
node_name = INET_LOCALHOST;
}
return INET_analyze(file_name, status_vector,
node_name.c_str(), user_string, uv_flag, dpb);
}
// We have a local connection string. If it's a file on a network share,
// try to connect to the corresponding host remotely.
#ifdef WIN_NT
PathName expanded_name = file_name;
ISC_expand_share(expanded_name);
if (ISC_analyze_pclan(expanded_name, node_name))
{
port = WNET_analyze(expanded_name, status_vector, node_name.c_str(), uv_flag);
}
#endif
#ifndef NO_NFS
PathName expanded_name = file_name;
if (ISC_analyze_nfs(expanded_name, node_name))
{
port = INET_analyze(expanded_name, status_vector,
node_name.c_str(), user_string, uv_flag, dpb);
}
#endif
// We still have a local connection string but failed to connect so far.
// If we're a pure client, attempt connect to the localhost.
#ifdef SUPERCLIENT
if (node_name.isEmpty())
{
#ifdef WIN_NT
if (!port)
{
port = XNET_analyze(file_name, status_vector, uv_flag);
}
#endif // UNIX
if (!port)
{
port = WNET_analyze(file_name, status_vector,
WNET_LOCALHOST, uv_flag);
}
#endif
if (!port)
{
port = INET_analyze(file_name, status_vector,
INET_LOCALHOST, user_string, uv_flag, dpb);
}
}
#endif // SUPERCLIENT
if (port || status_vector[1])
{
return port;
@ -4698,45 +4695,61 @@ static rem_port* analyze_service(PathName& service_name,
// quietly (sic) return.
#if defined(WIN_NT)
if (ISC_analyze_pclan(service_name, node_name)) {
return WNET_analyze(service_name, status_vector, node_name.c_str(), /*user_string,*/ uv_flag);
if (ISC_analyze_protocol(PROTOCOL_XNET, service_name, node_name))
{
return XNET_analyze(service_name, status_vector, uv_flag);
}
if (ISC_analyze_protocol(PROTOCOL_WNET, service_name, node_name) ||
ISC_analyze_pclan(service_name, node_name))
{
if (node_name.isEmpty())
{
node_name = WNET_LOCALHOST;
}
return WNET_analyze(service_name, status_vector, node_name.c_str(), uv_flag);
}
#endif
if (ISC_analyze_protocol(PROTOCOL_INET, service_name, node_name) ||
ISC_analyze_tcp(service_name, node_name))
{
if (node_name.isEmpty())
{
node_name = INET_LOCALHOST;
}
return INET_analyze(service_name, status_vector,
node_name.c_str(), user_string, uv_flag, spb);
}
// We have a local connection string. If we're a pure client,
// attempt connect to a localhost.
#ifdef SUPERCLIENT
if (node_name.isEmpty())
{
#if defined(WIN_NT)
if (!port)
{
port = XNET_analyze(service_name, status_vector, uv_flag);
}
if (!port)
{
port = WNET_analyze(service_name, status_vector,
WNET_LOCALHOST, uv_flag);
}
#endif
if (!port)
{
if (ISC_analyze_tcp(service_name, node_name))
{
port = INET_analyze(service_name, status_vector,
node_name.c_str(), user_string, uv_flag, spb);
INET_LOCALHOST, user_string, uv_flag, spb);
}
}
#if defined(USE_XNET)
// all remote attempts have failed, so access locally through the
// interprocess server
if (!port && node_name.isEmpty()) {
port = XNET_analyze(service_name, status_vector, /*node_name.c_str(), user_string,*/ uv_flag);
}
#endif
#ifdef SUPERCLIENT
#ifdef UNIX
if (!port && node_name.isEmpty())
{
service_name.insert(0, "localhost:");
if (ISC_analyze_tcp(service_name, node_name))
{
return INET_analyze(service_name, status_vector,
node_name.c_str(), user_string, uv_flag, spb);
}
}
#endif // UNIX
#endif // SUPERCLIENT
return port;
}