# include <kernel/kernel.h>
# include <kernel/user.h>
inherit LIB_CONN; /* basic connection object */
object driver; /* driver object */
string buffer; /* buffered input */
/*
* NAME: create()
* DESCRIPTION: initialize
*/
static void create(int clone)
{
if (clone) {
::create("binary");
driver = find_object(DRIVER);
buffer = "";
}
}
/*
* NAME: open()
* DESCRIPTION: open the connection
*/
static void open()
{
::open(allocate(driver->query_tls_size()));
}
/*
* NAME: close()
* DESCRIPTION: close the connection
*/
static void close(int dest)
{
::close(allocate(driver->query_tls_size()), dest);
}
/*
* NAME: add_to_buffer()
* DESCRIPTION: do this where an error is allowed to happen
*/
private void add_to_buffer(mixed *tls, string str)
{
catch {
buffer += str;
} : error("Binary connection buffer overflow");
}
/*
* NAME: receive_message()
* DESCRIPTION: forward a message to listeners
*/
static void receive_message(string str)
{
int mode, len;
string head, pre;
mixed *tls;
add_to_buffer(tls = allocate(driver->query_tls_size()), str);
while (this_object() &&
(mode=query_mode()) != MODE_BLOCK && mode != MODE_DISCONNECT) {
if (mode != MODE_RAW) {
if (sscanf(buffer, "%s\r\n%s", str, buffer) != 0 ||
sscanf(buffer, "%s\n%s", str, buffer) != 0) {
while (sscanf(str, "%s\b%s", head, str) != 0) {
while (sscanf(head, "%s\x7f%s", pre, head) != 0) {
len = strlen(pre);
if (len != 0) {
head = pre[0 .. len - 2] + head;
}
}
len = strlen(head);
if (len != 0) {
str = head[0 .. len - 2] + str;
}
}
while (sscanf(str, "%s\x7f%s", head, str) != 0) {
len = strlen(head);
if (len != 0) {
str = head[0 .. len - 2] + str;
}
}
::receive_message(tls, str);
} else {
break;
}
} else {
if (strlen(buffer) != 0) {
str = buffer;
buffer = "";
::receive_message(tls, str);
}
break;
}
}
}
/*
* NAME: set_mode()
* DESCRIPTION: set the connection mode
*/
void set_mode(int mode)
{
string str;
if (KERNEL() || SYSTEM()) {
::set_mode(mode);
if (mode == MODE_RAW && strlen(buffer) != 0) {
/* flush buffer */
str = buffer;
buffer = "";
::receive_message(nil, str);
}
}
}
/*
* NAME: message()
* DESCRIPTION: send a message to the other side
*/
int message(string str)
{
if (query_mode() < MODE_RAW) {
str = implode(explode("\n" + str + "\n", "\n"), "\r\n");
}
return ::message(str);
}
/*
* NAME: message_done()
* DESCRIPTION: called when output is completed
*/
static void message_done()
{
::message_done(allocate(driver->query_tls_size()));
}
/*
* NAME: open_datagram()
* DESCRIPTION: open a datagram channel for this connection
*/
static void open_datagram()
{
::open_datagram(allocate(driver->query_tls_size()));
}
/*
* NAME: receive_datagram()
* DESCRIPTION: receive a datagram
*/
static void receive_datagram(string str)
{
::receive_datagram(allocate(driver->query_tls_size()), str);
}