Select Git revision
rsql.pike 4.67 KiB
// Remote SQL server interface
#define RSQL_PORT 3994
#define RSQL_VERSION 1
#if constant(thread_create)
#define LOCK object key=mutex->lock()
#define UNLOCK destruct(key)
static private object(Thread.Mutex) mutex = Thread.Mutex();
#else
#define LOCK
#define UNLOCK
#endif
static object(Stdio.File) sock;
static int seqno = 0;
static private string host, user, pw;
static private int port;
static void low_reconnect()
{
object losock = Stdio.File();
if(sock)
destruct(sock);
if(!losock->connect(host, port|RSQL_PORT))
throw(({"Can't connect to "+host+(port? ":"+port:"")+": "+
strerror(losock->errno())+"\n", backtrace()}));
if(8!=losock->write(sprintf("RSQL%4c", RSQL_VERSION)) ||
losock->read(4) != "SQL!") {
destruct(losock);
throw(({"Initial handshake error on "+host+(port? ":"+port:"")+"\n",
backtrace()}));
}
sock = losock;
if(!do_request('L', ({user,pw}), 1)) {
sock = 0;
if(losock)
destruct(losock);
throw(({"Login refused on "+host+(port? ":"+port:"")+"\n",
backtrace()}));
}
}
static void low_connect(string the_host, int the_port, string the_user,
string the_pw)
{
host = the_host;
port = the_port;
user = the_user;
pw = the_pw;
low_reconnect();
}
static mixed do_request(int cmd, mixed|void arg, int|void noreconnect)
{
LOCK;
if(!sock)
if(noreconnect) {
UNLOCK;
throw(({"No connection\n", backtrace()}));
} else
low_reconnect();
arg = (arg? encode_value(arg) : "");
sock->write(sprintf("?<%c>%4c%4c%s", cmd, ++seqno, sizeof(arg), arg));
string res;
int rlen;
if((res = sock->read(12)) && sizeof(res)==12 &&