diff -cr --ignore-space-change dgd/src/comm.c dgd-patched/src/comm.c
*** dgd/src/comm.c Sat Aug 12 19:00:38 1995
--- dgd-patched/src/comm.c Sun Sep 3 13:56:25 1995
***************
*** 20,31 ****
} u;
int inbufsz; /* bytes in input buffer */
int outbufsz; /* bytes in output buffer */
char flags; /* connection flags */
char state; /* telnet state */
- short newlines; /* # of newlines in input buffer */
connection *conn; /* connection */
! char inbuf[INBUF_SIZE]; /* input buffer */
! char outbuf[OUTBUF_SIZE]; /* output buffer */
} user;
/* flags */
--- 20,31 ----
} u;
int inbufsz; /* bytes in input buffer */
int outbufsz; /* bytes in output buffer */
+ int newlines; /* # of newlines in input buffer */
char flags; /* connection flags */
char state; /* telnet state */
connection *conn; /* connection */
! char *inbuf; /* input buffer */
! char *outbuf; /* output buffer */
} user;
/* flags */
***************
*** 33,38 ****
--- 33,41 ----
# define CF_TELNET 0x02 /* telnet connection */
# define CF_GA 0x04 /* send GA after prompt */
# define CF_SEENCR 0x08 /* just seen a CR */
+ # define CF_PORT 0x10 /* port connection */
+ # define CF_DATAGRAM 0x20 /* datagram connection */
+ # define CF_CONNECTING 0x40 /* connection being initiated */
/* state */
# define TS_DATA 0
***************
*** 48,69 ****
static int maxusers; /* max # of users */
static int nusers; /* # of users */
static int newlines; /* # of newlines in all input buffers */
- static long binchars; /* # characters in binary buffers */
static object *this_user; /* current user */
/*
* NAME: comm->init()
* DESCRIPTION: initialize communications
*/
! void comm_init(nusers, telnet_port, binary_port)
! int nusers, telnet_port, binary_port;
{
register int i;
register user **usr;
! conn_init(nusers, telnet_port, binary_port);
! users = ALLOC(user*, maxusers = nusers);
! for (i = nusers, usr = users; i > 0; --i, usr++) {
*usr = (user *) NULL;
}
}
--- 51,71 ----
static int maxusers; /* max # of users */
static int nusers; /* # of users */
static int newlines; /* # of newlines in all input buffers */
static object *this_user; /* current user */
/*
* NAME: comm->init()
* DESCRIPTION: initialize communications
*/
! void comm_init(cf_users)
! int cf_users;
{
register int i;
register user **usr;
! conn_init(cf_users);
! users = ALLOC(user*, maxusers = cf_users);
! for (i = cf_users, usr = users; i > 0; --i, usr++) {
*usr = (user *) NULL;
}
}
***************
*** 80,119 ****
/*
* NAME: comm->new()
! * DESCRIPTION: accept a new connection
*/
! static void comm_new(obj, conn, telnet)
object *obj;
connection *conn;
! bool telnet;
{
! static char init[] = { IAC, WONT, TELOPT_ECHO, IAC, DO, TELOPT_LINEMODE };
register user **usr;
if (obj->flags & (O_USER | O_EDITOR)) {
! error("user object is already used for user or editor");
}
for (usr = users; *usr != (user *) NULL; usr++) ;
mstatic();
! *usr = ALLOC(user, 1);
mdynamic();
(*usr)->u.obj = obj;
obj->flags |= O_USER;
obj->etabi = usr - users;
(*usr)->inbufsz = 0;
(*usr)->outbufsz = 0;
(*usr)->conn = conn;
! if (telnet) {
! /* initialize connection */
! conn_write(conn, init, sizeof(init));
! (*usr)->flags = CF_TELNET | CF_ECHO;
(*usr)->state = TS_DATA;
! (*usr)->newlines = 0;
} else {
! (*usr)->flags = 0;
}
nusers++;
- this_user = obj;
}
/*
--- 82,142 ----
/*
* NAME: comm->new()
! * DESCRIPTION: allocate and init a new user struct (assumes nusers < maxusers)
*/
! static void comm_new(obj, conn, flags)
object *obj;
connection *conn;
! int flags;
{
! static char give_lm[] = { IAC, DO, TELOPT_LINEMODE };
! static char echo_on[] = { IAC, WONT, TELOPT_ECHO };
!
register user **usr;
+ register int size;
if (obj->flags & (O_USER | O_EDITOR)) {
! error("User object is already used for user or editor");
}
+
+ if (flags & CF_PORT) {
+ size = sizeof(user);
+ } else if (flags & CF_TELNET) {
+ size = sizeof(user) + INBUF_SIZE + OUTBUF_SIZE;
+ } else {
+ size = sizeof(user) + OUTBUF_SIZE;
+ }
+
for (usr = users; *usr != (user *) NULL; usr++) ;
mstatic();
! *usr = (user *)ALLOC(char, size);
mdynamic();
(*usr)->u.obj = obj;
obj->flags |= O_USER;
obj->etabi = usr - users;
(*usr)->inbufsz = 0;
(*usr)->outbufsz = 0;
+ (*usr)->newlines = 0;
(*usr)->conn = conn;
! (*usr)->flags = flags;
! if (flags & CF_PORT) {
! (*usr)->inbuf = (char *) NULL;
! (*usr)->outbuf = (char *) NULL;
! } else if (flags & CF_TELNET) {
! (*usr)->inbuf = (char *) *usr + sizeof(user);
! (*usr)->outbuf = (*usr)->inbuf + INBUF_SIZE;
(*usr)->state = TS_DATA;
! if (!(flags & CF_CONNECTING)) {
! if (flags & CF_ECHO) {
! conn_write(conn, echo_on, 3);
! }
! conn_write(conn, give_lm, 3);
! }
} else {
! (*usr)->inbuf = (char *) NULL;
! (*usr)->outbuf = (char *) *usr + sizeof(user);
}
nusers++;
}
/*
***************
*** 128,135 ****
conn_del((*usr)->conn);
if ((*usr)->flags & CF_TELNET) {
newlines -= (*usr)->newlines;
- } else {
- binchars -= (*usr)->inbufsz;
}
obj = (*usr)->u.obj;
obj->flags &= ~O_USER;
--- 151,156 ----
***************
*** 150,155 ****
--- 171,238 ----
}
/*
+ * NAME: comm->listen()
+ * DESCRIPTION: have an object listen to a port
+ */
+ void comm_listen(obj, port, protocol)
+ object *obj;
+ int port, protocol;
+ {
+ register connection *conn;
+ int flags;
+
+ if (nusers >= maxusers)
+ error("Max number of connection/port objects exceeded");
+
+ if (protocol == PRC_TELNET) {
+ flags = CF_TELNET | CF_ECHO | CF_PORT;
+ protocol = PRC_TCP;
+ } else if (protocol == PRC_UDP) {
+ flags = CF_DATAGRAM | CF_PORT;
+ } else {
+ flags = CF_PORT;
+ }
+ conn = conn_listen(port, protocol);
+ if (conn != (connection *) NULL) {
+ comm_new(obj, conn, flags);
+ } else {
+ error("Could not open port");
+ }
+ if (i_call(obj, "open", TRUE, 0)) {
+ i_del_value(sp++);
+ }
+ }
+
+ /*
+ * NAME: comm->connect()
+ * DESCRIPTION: initiate a telnet or tcp connection
+ */
+ void comm_connect(obj, host, port, protocol)
+ object *obj;
+ char *host;
+ int port, protocol;
+ {
+ register connection *conn;
+ int flags;
+
+ if (nusers >= maxusers)
+ error("Max number of connection/port objects exceeded");
+
+ if (protocol == PRC_TELNET) {
+ flags = CF_TELNET | CF_CONNECTING;
+ protocol = PRC_TCP;
+ } else if (protocol == PRC_TCP) {
+ flags = CF_CONNECTING;
+ }
+ conn = conn_connect(host, port, protocol);
+ if (conn != (connection *) NULL) {
+ comm_new(obj, conn, flags);
+ } else {
+ error("Could not initiate connection");
+ }
+ }
+
+ /*
* NAME: comm->send()
* DESCRIPTION: send a message to a user
*/
***************
*** 162,173 ****
register unsigned short len, size;
usr = users[UCHAR(obj->etabi)];
p = str->text;
len = str->len;
if (usr->flags & CF_TELNET) {
- /*
- * telnet connection
- */
size = usr->outbufsz;
q = usr->outbuf + size;
while (len != 0) {
--- 245,259 ----
register unsigned short len, size;
usr = users[UCHAR(obj->etabi)];
+ if (usr->flags & (CF_DATAGRAM | CF_PORT)) {
+ error("Object is not a stream connection");
+ }
+ if (usr->flags & CF_CONNECTING) {
+ error("Connection is not yet ready");
+ }
p = str->text;
len = str->len;
if (usr->flags & CF_TELNET) {
size = usr->outbufsz;
q = usr->outbuf + size;
while (len != 0) {
***************
*** 218,223 ****
--- 304,329 ----
}
/*
+ * NAME: comm->sendto()
+ * DESCRIPTION: send a datagram
+ */
+ void comm_sendto(obj, data, host, port)
+ object *obj;
+ string *data;
+ char *host;
+ int port;
+ {
+ register user *usr;
+
+ usr = users[UCHAR(obj->etabi)];
+ if (usr->flags & CF_DATAGRAM == 0) {
+ error("Object is not a datagram object");
+ }
+ conn_sendto(usr->conn, data->text, data->len, host, port);
+ }
+
+
+ /*
* NAME: comm->echo()
* DESCRIPTION: turn on/off input echoing for a user
*/
***************
*** 229,234 ****
--- 335,342 ----
char buf[3];
usr = users[UCHAR(obj->etabi)];
+ if (usr->flags & CF_CONNECTING)
+ error("Connection is not yet ready");
if ((usr->flags & CF_TELNET) && echo != (usr->flags & CF_ECHO)) {
buf[0] = IAC;
buf[1] = (echo) ? WONT : WILL;
***************
*** 276,399 ****
* NAME: comm->receive()
* DESCRIPTION: receive a message from a user
*/
! object *comm_receive(buf, size)
! char *buf;
! int *size;
{
static int lastuser;
connection *conn;
object *o;
! register int n, i, state, flags, nls;
register char *p, *q;
! if (nusers < maxusers) {
! /*
! * accept new telnet connection
! */
! conn = conn_tnew();
! if (conn != (connection *) NULL) {
! if (ec_push()) {
! conn_del(conn); /* delete connection */
! error((char *) NULL); /* pass on error */
! }
! call_driver_object("telnet_connect", 0);
! ec_pop();
! if (sp->type != T_OBJECT) {
! fatal("driver->telnet_connect() did not return an object");
! }
! d_export();
! comm_new(o = o_object(sp->oindex, sp->u.objcnt), conn, TRUE);
! sp++;
! if (i_call(o, "open", TRUE, 0)) {
i_del_value(sp++);
d_export();
}
comm_flush(TRUE);
}
}
!
if (nusers < maxusers) {
! /*
! * accept new binary connection
! */
! conn = conn_bnew();
if (conn != (connection *) NULL) {
if (ec_push()) {
! conn_del(conn); /* delete connection */
error((char *) NULL); /* pass on error */
}
! call_driver_object("binary_connect", 0);
! ec_pop();
! if (sp->type != T_OBJECT) {
! fatal("driver->binary_connect() did not return an object");
}
d_export();
! comm_new(o = o_object(sp->oindex, sp->u.objcnt), conn, FALSE);
sp++;
! if (i_call(o, "open", TRUE, 0)) {
i_del_value(sp++);
d_export();
}
comm_flush(TRUE);
}
}
!
! /*
! * read input from users
! */
! this_user = (object *) NULL;
! n = conn_select(newlines == 0 && binchars == 0);
! if (n <= 0) {
! /*
! * call_out to do, or timeout
! */
! if (newlines == 0 && binchars == 0) {
! return (object *) NULL;
! }
! } else {
! static char intr[] = { '\177' };
! static char brk[] = { '\034' };
! static char tm[] = { (char) IAC, (char) WILL, (char) TELOPT_TM };
! static char will_sga[] = { (char) IAC, (char) WILL, (char) TELOPT_SGA };
! static char wont_sga[] = { (char) IAC, (char) WONT, (char) TELOPT_SGA };
! static char mode_edit[]= { (char) IAC, (char) SB,
! (char) TELOPT_LINEMODE, (char) LM_MODE,
! (char) MODE_EDIT, (char) IAC, (char) SE };
! register user **usr;
!
! for (i = maxusers, usr = users; i > 0; --i, usr++) {
! if (*usr != (user *) NULL && (*usr)->inbufsz != INBUF_SIZE) {
! p = (*usr)->inbuf + (*usr)->inbufsz;
! n = conn_read((*usr)->conn, p, INBUF_SIZE - (*usr)->inbufsz);
! if (n < 0) {
/*
* bad connection
*/
! comm_del(usr);
! d_export(); /* this cannot be in comm_del() */
! } else if ((*usr)->flags & CF_TELNET) {
! /*
! * telnet mode
! */
! flags = (*usr)->flags;
! state = (*usr)->state;
! nls = (*usr)->newlines;
q = p;
! while (n > 0) {
switch (state) {
case TS_DATA:
switch (UCHAR(*p)) {
- case '\0':
- flags &= ~CF_SEENCR;
- break;
-
case IAC:
state = TS_IAC;
break;
case BS:
case 0x7f:
! if (q != (*usr)->inbuf && q[-1] != LF) {
--q;
}
flags &= ~CF_SEENCR;
--- 384,510 ----
* NAME: comm->receive()
* DESCRIPTION: receive a message from a user
*/
! void comm_receive()
{
static int lastuser;
connection *conn;
object *o;
! register int n;
register char *p, *q;
! this_user = (object *) NULL;
! n = conn_select(newlines == 0);
! if (n > 0 || newlines > 0) {
! static char intr[] = { '\177' };
! static char brk[] = { '\034' };
! static char tm[] = { (char) IAC, (char) WILL,
! (char) TELOPT_TM };
! static char will_sga[] = { (char) IAC, (char) WILL,
! (char) TELOPT_SGA };
! static char wont_sga[] = { (char) IAC, (char) WONT,
! (char) TELOPT_SGA };
! static char mode_edit[] = { (char) IAC, (char) SB,
! (char) TELOPT_LINEMODE,
! (char) LM_MODE, (char) MODE_EDIT,
! (char) IAC, (char) SE };
! register user *usr;
! char buf[INBUF_SIZE];
! Int size;
!
! n = lastuser;
! for (;;) {
! n = (n + 1) % maxusers;
! usr = users[n];
! if (usr != (user *) NULL) {
! if (usr->flags & CF_CONNECTING) {
! int r;
!
! r = conn_connected(usr->conn);
! if (r == 1) {
! usr->flags &= ~CF_CONNECTING;
! this_user = usr->u.obj;
! if (i_call(this_user, "open", TRUE, 0)) {
i_del_value(sp++);
d_export();
}
comm_flush(TRUE);
+ } else if (r == -1) {
+ comm_del(&users[n]);
}
+ } else if (usr->flags & CF_DATAGRAM) {
+ size = conn_recvfrom(usr->conn, buf, INBUF_SIZE);
+ if (size > 0) {
+ lastuser = n;
+ (--sp)->type = T_STRING;
+ str_ref(sp->u.string = str_new(buf, (long) size));
+ (--sp)->type = T_STRING;
+ str_ref(sp->u.string = conn_ipnum(usr->conn));
+ (--sp)->type = T_INT;
+ sp->u.number = conn_port(usr->conn);
+ this_user = usr->u.obj;
+ if (i_call(this_user, "receive_datagram", TRUE, 3)) {
+ i_del_value(sp++);
+ d_export();
}
! return;
! }
! } else if (usr->flags & CF_PORT) {
if (nusers < maxusers) {
! conn = conn_accept(usr->conn);
if (conn != (connection *) NULL) {
+ (--sp)->type = T_STRING;
+ str_ref(sp->u.string = conn_ipnum(conn));
+ (--sp)->type = T_INT;
+ sp->u.number = conn_port(conn);
if (ec_push()) {
! conn_del(conn);
error((char *) NULL); /* pass on error */
}
! this_user = usr->u.obj;
! if (!i_call(this_user, "connection", TRUE, 2) ||
! sp->type != T_OBJECT) {
! error("connection() did not return an object");
}
+ ec_pop();
d_export();
! comm_new(o = o_object(sp->oindex, sp->u.objcnt),
! conn, usr->flags & ~CF_PORT);
sp++;
! this_user = o;
! if (i_call(this_user, "open", TRUE, 0)) {
i_del_value(sp++);
d_export();
}
comm_flush(TRUE);
}
}
! } else if (usr->flags & CF_TELNET) {
! p = usr->inbuf + usr->inbufsz;
! size = conn_read(usr->conn, p, INBUF_SIZE - usr->inbufsz);
! if (size < 0) {
/*
* bad connection
*/
! comm_del(&users[n]);
! continue;
! } else if (size > 0) {
! register int state, flags, nls;
!
! flags = usr->flags;
! state = usr->state;
! nls = usr->newlines;
q = p;
! while (size > 0) {
switch (state) {
case TS_DATA:
switch (UCHAR(*p)) {
case IAC:
state = TS_IAC;
break;
case BS:
case 0x7f:
! if (q != usr->inbuf && q[-1] != LF) {
--q;
}
flags &= ~CF_SEENCR;
***************
*** 449,465 ****
break;
case IP:
! conn_write((*usr)->conn, intr, 1);
state = TS_DATA;
break;
case BREAK:
! conn_write((*usr)->conn, brk, 1);
state = TS_DATA;
break;
default:
- /* let's hope it wasn't important */
state = TS_DATA;
break;
}
--- 560,575 ----
break;
case IP:
! conn_write(usr->conn, intr, 1);
state = TS_DATA;
break;
case BREAK:
! conn_write(usr->conn, brk, 1);
state = TS_DATA;
break;
default:
state = TS_DATA;
break;
}
***************
*** 467,476 ****
case TS_DO:
if (UCHAR(*p) == TELOPT_TM) {
! conn_write((*usr)->conn, tm, 3);
} else if (UCHAR(*p) == TELOPT_SGA) {
flags &= ~CF_GA;
! conn_write((*usr)->conn, will_sga, 3);
}
state = TS_DATA;
break;
--- 577,586 ----
case TS_DO:
if (UCHAR(*p) == TELOPT_TM) {
! conn_write(usr->conn, tm, 3);
} else if (UCHAR(*p) == TELOPT_SGA) {
flags &= ~CF_GA;
! conn_write(usr->conn, will_sga, 3);
}
state = TS_DATA;
break;
***************
*** 478,492 ****
case TS_DONT:
if (UCHAR(*p) == TELOPT_SGA) {
flags |= CF_GA;
! conn_write((*usr)->conn, wont_sga, 3);
}
state = TS_DATA;
break;
case TS_WILL:
if (UCHAR(*p) == TELOPT_LINEMODE) {
! /* linemode confirmed; now request editing */
! conn_write((*usr)->conn, mode_edit, 7);
}
/* fall through */
case TS_WONT:
--- 588,601 ----
case TS_DONT:
if (UCHAR(*p) == TELOPT_SGA) {
flags |= CF_GA;
! conn_write(usr->conn, wont_sga, 3);
}
state = TS_DATA;
break;
case TS_WILL:
if (UCHAR(*p) == TELOPT_LINEMODE) {
! conn_write(usr->conn, mode_edit, 7);
}
/* fall through */
case TS_WONT:
***************
*** 504,590 ****
if (UCHAR(*p) == SE) {
/* end of subnegotiation */
state = TS_DATA;
! } else {
state = TS_SB;
}
break;
}
p++;
! --n;
! }
! (*usr)->flags = flags;
! (*usr)->state = state;
! (*usr)->newlines = nls;
! (*usr)->inbufsz = q - (*usr)->inbuf;
! } else {
! /*
! * binary mode
! */
! (*usr)->inbufsz += n;
! binchars += n;
}
}
! }
! }
!
! if (newlines != 0 || binchars != 0) {
! register user *usr;
!
! n = lastuser;
! for (;;) {
! n = (n + 1) % maxusers;
! usr = users[n];
! if (usr != (user *) NULL && usr->inbufsz != 0) {
! if (usr->flags & CF_TELNET) {
! /*
! * telnet connection
! */
! if (usr->newlines != 0) {
! /*
! * input terminated by \n
! */
p = (char *) memchr(usr->inbuf, LF, usr->inbufsz);
- usr->newlines--;
--newlines;
lastuser = n;
! *size = n = p - usr->inbuf;
! if (n != 0) {
! memcpy(buf, usr->inbuf, n);
}
p++; /* skip \n */
n++;
! usr->inbufsz -= n;
if (usr->inbufsz != 0) {
/* can't rely on memcpy */
for (q = usr->inbuf, n = usr->inbufsz; n > 0; --n) {
*q++ = *p++;
}
}
! return this_user = usr->u.obj;
} else if (usr->inbufsz == INBUF_SIZE) {
/*
* input buffer full
*/
lastuser = n;
! memcpy(buf, usr->inbuf, *size = INBUF_SIZE);
usr->inbufsz = 0;
! return this_user = usr->u.obj;
}
} else {
/*
! * binary connection
*/
lastuser = n;
! binchars -= usr->inbufsz;
! memcpy(buf, usr->inbuf, *size = usr->inbufsz);
! usr->inbufsz = 0;
! return this_user = usr->u.obj;
}
}
}
}
-
- return (object *) NULL;
}
/*
--- 613,699 ----
if (UCHAR(*p) == SE) {
/* end of subnegotiation */
state = TS_DATA;
! } else if (UCHAR(*p) == IAC) {
! /* doubled IAC counts as data */
state = TS_SB;
}
break;
}
p++;
! --size;
}
+ usr->flags = flags;
+ usr->state = state;
+ usr->newlines = nls;
+ usr->inbufsz = q - usr->inbuf;
}
! if (usr->newlines > 0) {
p = (char *) memchr(usr->inbuf, LF, usr->inbufsz);
--newlines;
+ --(usr->newlines);
lastuser = n;
! size = n = p - usr->inbuf;
! if (size != 0) {
! memcpy(buf, usr->inbuf, size);
}
p++; /* skip \n */
n++;
! usr->inbufsz -= size + 1;
if (usr->inbufsz != 0) {
/* can't rely on memcpy */
for (q = usr->inbuf, n = usr->inbufsz; n > 0; --n) {
*q++ = *p++;
}
}
! this_user = usr->u.obj;
! (--sp)->type = T_STRING;
! str_ref(sp->u.string = str_new(buf, (long) size));
! if (i_call(this_user, "receive_message", TRUE, 1)) {
! i_del_value(sp++);
! d_export();
! }
! return;
} else if (usr->inbufsz == INBUF_SIZE) {
/*
* input buffer full
*/
lastuser = n;
! (--sp)->type = T_STRING;
! str_ref(sp->u.string =
! str_new(usr->inbuf, (long) INBUF_SIZE));
usr->inbufsz = 0;
! this_user = usr->u.obj;
! if (i_call(this_user, "receive_message", TRUE, 1)) {
! i_del_value(sp++);
! d_export();
! }
! return;
}
} else {
/*
! * binary mode
*/
+ size = conn_read(usr->conn, buf, INBUF_SIZE);
+ if (size < 0) {
+ comm_del(&users[n]);
+ } else if (size > 0) {
lastuser = n;
! (--sp)->type = T_STRING;
! str_ref(sp->u.string = str_new(buf, (long) size));
! this_user = usr->u.obj;
! if (i_call(this_user, "receive_message", TRUE, 1)) {
! i_del_value(sp++);
! d_export();
}
+ return;
+ }
+ }
+ }
+ if (n == lastuser) {
+ return;
}
}
}
}
/*
***************
*** 594,603 ****
string *comm_ip_number(obj)
object *obj;
{
! char *ipnum;
!
! ipnum = conn_ipnum(users[UCHAR(obj->etabi)]->conn);
! return str_new(ipnum, (long) strlen(ipnum));
}
/*
--- 703,709 ----
string *comm_ip_number(obj)
object *obj;
{
! return conn_ipnum(users[UCHAR(obj->etabi)]->conn);
}
/*
diff -cr --ignore-space-change dgd/src/comm.h dgd-patched/src/comm.h
*** dgd/src/comm.h Tue Jun 6 18:12:12 1995
--- dgd-patched/src/comm.h Sun Sep 3 13:38:03 1995
***************
*** 1,24 ****
# define INBUF_SIZE 2048
# define OUTBUF_SIZE 1024
typedef struct _connection_ connection;
! extern void conn_init P((int, unsigned int, unsigned int));
extern void conn_finish P((void));
! extern connection *conn_tnew P((void));
! extern connection *conn_bnew P((void));
extern void conn_del P((connection*));
extern int conn_select P((int));
extern int conn_read P((connection*, char*, int));
extern int conn_write P((connection*, char*, int));
! extern char *conn_ipnum P((connection*));
! extern void comm_init P((int, int, int));
extern void comm_finish P((void));
extern int comm_send P((object*, string*));
extern void comm_echo P((object*, int));
extern void comm_flush P((int));
! extern object *comm_receive P((char*, int*));
extern string *comm_ip_number P((object*));
extern void comm_close P((object*));
extern object *comm_user P((void));
--- 1,36 ----
# define INBUF_SIZE 2048
# define OUTBUF_SIZE 1024
+ # define PRC_TCP 1
+ # define PRC_UDP 2
+ # define PRC_TELNET 3
+
typedef struct _connection_ connection;
! extern void conn_init P((int));
extern void conn_finish P((void));
! extern connection *conn_listen P((int, int));
! extern connection *conn_accept P((connection*));
! extern connection *conn_connect P((char*, int, int));
! extern int conn_connected P((connection*));
extern void conn_del P((connection*));
extern int conn_select P((int));
+ extern int conn_recvfrom P((connection*, char*, int));
extern int conn_read P((connection*, char*, int));
+ extern void conn_sendto P((connection*, char*, int, char*, int));
extern int conn_write P((connection*, char*, int));
! extern string *conn_ipnum P((connection*));
! extern int conn_port P((connection*));
! extern void comm_init P((int));
extern void comm_finish P((void));
+ extern void comm_listen P((object*, int, int));
+ extern void comm_connect P((object*, char*, int, int));
extern int comm_send P((object*, string*));
+ extern void comm_sendto P((object*, string*, char*, int));
extern void comm_echo P((object*, int));
extern void comm_flush P((int));
! extern void comm_receive P((void));
extern string *comm_ip_number P((object*));
extern void comm_close P((object*));
extern object *comm_user P((void));
diff -cr --ignore-space-change dgd/src/comp/comp.c dgd-patched/src/comp/comp.c
*** dgd/src/comp/comp.c Mon Jul 31 15:15:44 1995
--- dgd-patched/src/comp/comp.c Sun Sep 3 13:38:03 1995
***************
*** 529,536 ****
* NAME: comm->init()
* DESCRIPTION: pretend to initialize communications
*/
! void comm_init(nusers, telnet_port, binary_port)
! int nusers, telnet_port, binary_port;
{
}
--- 529,536 ----
* NAME: comm->init()
* DESCRIPTION: pretend to initialize communications
*/
! void comm_init(nusers)
! int nusers;
{
}
***************
*** 569,574 ****
--- 569,607 ----
*/
void comm_flush(flag)
int flag;
+ {
+ }
+
+ /*
+ * NAME: comm->listen()
+ * DESCRIPTION: pretend to open a port for listening
+ */
+ void comm_listen(obj, port, protocol)
+ object *obj;
+ int port, protocol;
+ {
+ }
+
+ /*
+ * NAME: comm->connect()
+ * DESCRIPTION: pretend to initiate a telnet or tcp connection
+ */
+ void comm_connect(obj, host, port, protocol)
+ object *obj;
+ char *host;
+ int port, protocol;
+ {
+ }
+
+ /*
+ * NAME: comm->sendto()
+ * DESCRIPTION: pretend to send a datagram
+ */
+ void comm_sendto(obj, data, host, port)
+ object *obj;
+ string *data;
+ char *host;
+ int port;
{
}
diff -cr --ignore-space-change dgd/src/config.c dgd-patched/src/config.c
*** dgd/src/config.c Sat Aug 12 19:00:38 1995
--- dgd-patched/src/config.c Sun Sep 3 13:38:03 1995
***************
*** 582,587 ****
--- 582,592 ----
header[16] = (char *) &pdummy.p - (char *) &pdummy.fill; /* pointer align */
header[17] = sizeof(align); /* struct align */
+ /* initialize communications */
+ mstatic();
+ comm_init((int) conf[USERS].u.num);
+ mdynamic();
+
starttime = boottime = P_time();
i_set_cost((Int) conf[MAX_COST].u.num);
if (dumpfile == (char *) NULL) {
***************
*** 598,610 ****
call_driver_object("restored", 0);
}
i_del_value(sp++);
-
- /* initialize communications */
- mstatic();
- comm_init((int) conf[USERS].u.num,
- (int) conf[TELNET_PORT].u.num,
- (int) conf[BINARY_PORT].u.num);
- mdynamic();
}
/*
--- 603,608 ----
diff -cr --ignore-space-change dgd/src/dgd.c dgd-patched/src/dgd.c
*** dgd/src/dgd.c Sun Aug 13 15:25:58 1995
--- dgd-patched/src/dgd.c Sun Sep 3 13:38:04 1995
***************
*** 88,97 ****
int argc;
char **argv;
{
- char buf[INBUF_SIZE];
- int size;
- object *usr;
-
if (argc < 2 || argc > 3) {
P_message("Usage: dgd config_file [dump_file]\012"); /* LF */
return 2;
--- 88,93 ----
***************
*** 164,179 ****
}
/* user input */
! usr = comm_receive(buf, &size);
! if (usr != (object *) NULL) {
! (--sp)->type = T_STRING;
! str_ref(sp->u.string = str_new(buf, (long) size));
! if (i_call(usr, "receive_message", TRUE, 1)) {
! i_del_value(sp++);
comm_flush(TRUE);
- d_export();
- }
- }
/* callouts */
co_call();
--- 160,167 ----
}
/* user input */
! comm_receive();
comm_flush(TRUE);
/* callouts */
co_call();
diff -cr --ignore-space-change dgd/src/host/unix/connect.c dgd-patched/src/host/unix/connect.c
*** dgd/src/host/unix/connect.c Tue Jun 6 18:12:13 1995
--- dgd-patched/src/host/unix/connect.c Sun Sep 3 13:38:04 1995
***************
*** 13,97 ****
struct _connection_ {
int fd; /* file descriptor */
! struct sockaddr_in addr; /* internet address of connection */
struct _connection_ *next; /* next in list */
};
static int nusers; /* # of users */
static connection *connections; /* connections array */
static connection *flist; /* list of free connections */
- static int telnet; /* telnet port socket descriptor */
- static int binary; /* binary port socket descriptor */
static fd_set fds; /* file descriptor bitmap */
static fd_set readfds; /* file descriptor read bitmap */
static int maxfd; /* largest fd opened yet */
/*
* NAME: conn->init()
* DESCRIPTION: initialize connections
*/
! void conn_init(maxusers, telnet_port, binary_port)
int maxusers;
- unsigned int telnet_port, binary_port;
{
- struct sockaddr_in sin;
- struct hostent *host;
register int n;
register connection *conn;
- char buffer[256];
- int on;
-
- gethostname(buffer, sizeof(buffer));
- host = gethostbyname(buffer);
- if (host == (struct hostent *) NULL) {
- perror("gethostbyname");
- exit(2);
- }
-
- telnet = socket(host->h_addrtype, SOCK_STREAM, 0);
- binary = socket(host->h_addrtype, SOCK_STREAM, 0);
- if (telnet < 0 || binary < 0) {
- perror("socket");
- exit(2);
- }
- on = 1;
- if (setsockopt(telnet, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
- sizeof(on)) < 0) {
- perror("setsockopt");
- exit(2);
- }
- on = 1;
- if (setsockopt(binary, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
- sizeof(on)) < 0) {
- perror("setsockopt");
- exit(2);
- }
-
- memset(&sin, '\0', sizeof(sin));
- memcpy(&sin.sin_addr, host->h_addr, host->h_length);
- sin.sin_port = htons(telnet_port);
- sin.sin_family = host->h_addrtype;
- sin.sin_addr.s_addr = INADDR_ANY;
- if (bind(telnet, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
- perror("bind");
- exit(2);
- }
- sin.sin_port = htons(binary_port);
- if (bind(binary, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
- perror("bind");
- exit(2);
- }
-
- if (listen(telnet, 5) < 0 || listen(binary, 5) < 0) {
- perror("listen");
- exit(2);
- }
-
- if (fcntl(telnet, F_SETFL, FNDELAY) < 0 ||
- fcntl(binary, F_SETFL, FNDELAY) < 0) {
- perror("fcntl");
- exit(2);
- }
connections = ALLOC(connection, nusers = maxusers);
for (n = nusers, conn = connections; n > 0; --n, conn++) {
--- 13,43 ----
struct _connection_ {
int fd; /* file descriptor */
! struct sockaddr_in sin; /* peer's address */
struct _connection_ *next; /* next in list */
+ char host[16]; /* ascii ip number of peer */
+ char hostlen; /* length of host string */
};
static int nusers; /* # of users */
static connection *connections; /* connections array */
static connection *flist; /* list of free connections */
static fd_set fds; /* file descriptor bitmap */
+ static fd_set connectfds; /* file descriptor bitmap */
static fd_set readfds; /* file descriptor read bitmap */
+ static fd_set writefds; /* file descriptor write bitmap */
+ static fd_set failfds; /* file descriptor exception bitmap */
static int maxfd; /* largest fd opened yet */
/*
* NAME: conn->init()
* DESCRIPTION: initialize connections
*/
! void conn_init(maxusers)
int maxusers;
{
register int n;
register connection *conn;
connections = ALLOC(connection, nusers = maxusers);
for (n = nusers, conn = connections; n > 0; --n, conn++) {
***************
*** 101,106 ****
--- 47,53 ----
}
FD_ZERO(&fds);
+ FD_ZERO(&connectfds);
}
/*
***************
*** 109,139 ****
*/
void conn_finish()
{
- close(telnet);
- close(binary);
}
/*
! * NAME: conn->tnew()
! * DESCRIPTION: accept a new telnet connection
*/
! connection *conn_tnew()
{
- int fd, len;
- struct sockaddr_in sin;
register connection *conn;
-
- len = sizeof(sin);
- fd = accept(telnet, (struct sockaddr *) &sin, &len);
- if (fd < 0) {
- return (connection *) NULL;
- }
-
conn = flist;
flist = conn->next;
conn->fd = fd;
! memcpy(&conn->addr, (char *) &sin, len);
! FD_SET(fd, &fds);
if (fd > maxfd) {
maxfd = fd;
}
--- 56,78 ----
*/
void conn_finish()
{
}
/*
! * NAME: conn->new()
! * DESCRIPTION: initialize a new connection struct
*/
! static connection *conn_new(fd, sin)
! int fd;
! struct sockaddr_in *sin;
{
register connection *conn;
conn = flist;
flist = conn->next;
conn->fd = fd;
! memcpy(&conn->sin, sin, sizeof(conn->sin));
! strcpy(conn->host, inet_ntoa(sin->sin_addr));
! conn->hostlen = strlen(conn->host);
if (fd > maxfd) {
maxfd = fd;
}
***************
*** 142,175 ****
}
/*
! * NAME: conn->bnew()
! * DESCRIPTION: accept a new binary connection
*/
! connection *conn_bnew()
{
! int fd, len;
struct sockaddr_in sin;
! register connection *conn;
! len = sizeof(sin);
! fd = accept(binary, (struct sockaddr *) &sin, &len);
if (fd < 0) {
return (connection *) NULL;
}
- conn = flist;
- flist = conn->next;
- conn->fd = fd;
- memcpy(&conn->addr, (char *) &sin, len);
FD_SET(fd, &fds);
! if (fd > maxfd) {
! maxfd = fd;
}
! return conn;
}
/*
* NAME: conn->del()
* DESCRIPTION: delete a connection
*/
--- 81,208 ----
}
/*
! * NAME: conn->listen()
! * DESCRIPTION: bind a connection to a local port
! */
! connection *conn_listen(port, protocol)
! int port, protocol;
! {
! int fd;
! static struct sockaddr_in sin;
! int on = 1;
!
! fd = socket(PF_INET, (protocol == PRC_UDP) ? SOCK_DGRAM : SOCK_STREAM, 0);
! if (fd < 0) {
! return (connection *) NULL;
! }
! if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
! sizeof(on)) < 0) {
! close(fd);
! return (connection *) NULL;
! }
!
! sin.sin_family = AF_INET;
! sin.sin_port = htons(port);
! sin.sin_addr.s_addr = INADDR_ANY; /* htonl? */
! if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
! close(fd);
! return (connection *) NULL;
! }
!
! if (protocol != PRC_UDP && listen(fd, 5) < 0) {
! close(fd);
! return (connection *) NULL;
! }
!
! if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
! close(fd);
! return (connection *) NULL;
! }
!
! FD_SET(fd, &fds);
! return conn_new(fd, &sin);
! }
!
! /*
! * NAME: conn->accept()
! * DESCRIPTION: accept a connection
*/
! connection *conn_accept(conn)
! connection *conn;
{
! int fd;
struct sockaddr_in sin;
! int len = sizeof(sin);
! fd = accept(conn->fd, (struct sockaddr *) &sin, &len);
if (fd < 0) {
return (connection *) NULL;
}
FD_SET(fd, &fds);
! return conn_new(fd, &sin);
! }
!
! /*
! * NAME: conn->connect()
! * DESCRIPTION: initiate a tcp connection
! */
! connection *conn_connect(host, port, protocol)
! char *host;
! int port, protocol;
! {
! int fd;
! static struct sockaddr_in sin;
!
! if (protocol != PRC_TCP) {
! return (connection *) NULL;
}
! fd = socket(PF_INET, SOCK_STREAM, 0);
! if (fd < 0) {
! return (connection *) NULL;
! }
!
! if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
! close(fd);
! return (connection *) NULL;
! }
!
! sin.sin_family = AF_INET;
! sin.sin_port = htons(port);
! sin.sin_addr.s_addr = inet_addr(host);
! if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0 &&
! errno != EINPROGRESS) {
! close(fd);
! return (connection *) NULL;
! }
!
! FD_SET(fd, &connectfds);
! return conn_new(fd, &sin);
}
/*
+ * NAME: conn->connected()
+ * DESCRIPTION: mark a connecting socket as active
+ */
+ int conn_connected(conn)
+ register connection *conn;
+ {
+ if (conn->fd == -1)
+ return -1;
+ if (FD_ISSET(conn->fd, &failfds)) {
+ FD_CLR(conn->fd, &connectfds);
+ return -1;
+ } else if (FD_ISSET(conn->fd, &writefds)) {
+ FD_CLR(conn->fd, &connectfds);
+ FD_SET(conn->fd, &fds);
+ return 1;
+ }
+ return 0;
+ }
+
+
+ /*
* NAME: conn->del()
* DESCRIPTION: delete a connection
*/
***************
*** 179,184 ****
--- 212,218 ----
if (conn->fd >= 0) {
close(conn->fd);
FD_CLR(conn->fd, &fds);
+ FD_CLR(conn->fd, &connectfds);
conn->fd = -1;
}
conn->next = flist;
***************
*** 195,204 ****
struct timeval timeout;
memcpy(&readfds, &fds, sizeof(fd_set));
timeout.tv_sec = (int) wait;
timeout.tv_usec = 0;
! return select(maxfd + 1, &readfds, (fd_set *) NULL, (fd_set *) NULL,
! &timeout);
}
/*
--- 229,264 ----
struct timeval timeout;
memcpy(&readfds, &fds, sizeof(fd_set));
+ memcpy(&writefds, &connectfds, sizeof(fd_set));
+ memcpy(&failfds, &connectfds, sizeof(fd_set));
timeout.tv_sec = (int) wait;
timeout.tv_usec = 0;
! return select(maxfd + 1, &readfds, &writefds, &failfds, &timeout);
! }
!
! /*
! * NAME: conn->recvfrom()
! * DESCRIPTION: read a datagram
! */
! int conn_recvfrom(conn, buf, size)
! connection *conn;
! char *buf;
! int size;
! {
! struct sockaddr_in sin;
! int len = sizeof(sin);
!
! if (conn->fd < 0) {
! return -1;
! }
! if (!FD_ISSET(conn->fd, &readfds)) {
! return 0;
! }
! size = recvfrom(conn->fd, buf, size, 0, (struct sockaddr *)&sin, &len);
! memcpy(&(conn->sin), &sin, len);
! strcpy(conn->host, inet_ntoa(sin.sin_addr));
! conn->hostlen = strlen(conn->host);
! return size; /* Size may legitimately be 0 */
}
/*
***************
*** 213,219 ****
if (conn->fd < 0) {
return -1;
}
! if (!FD_ISSET(conn->fd, &readfds)) {
return 0;
}
size = read(conn->fd, buf, size);
--- 273,279 ----
if (conn->fd < 0) {
return -1;
}
! if (!FD_ISSET(conn->fd, &readfds) || size == 0) {
return 0;
}
size = read(conn->fd, buf, size);
***************
*** 221,226 ****
--- 281,304 ----
}
/*
+ * NAME: conn->sendto()
+ * DESCRIPTION: send a datagram
+ */
+ void conn_sendto(conn, data, size, host, port)
+ connection *conn;
+ char *data, *host;
+ int size, port;
+ {
+ static struct sockaddr_in sin;
+ if (conn->fd >= 0) {
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = inet_addr(host);
+ sin.sin_port = htons(port);
+ sendto(conn->fd, data, size, 0, (struct sockaddr *)&sin, sizeof(sin));
+ }
+ }
+
+ /*
* NAME: conn->write()
* DESCRIPTION: write to a connection; return the amount of bytes written
*/
***************
*** 233,238 ****
--- 311,317 ----
if ((size=write(conn->fd, buf, size)) < 0 && errno != EWOULDBLOCK) {
close(conn->fd);
FD_CLR(conn->fd, &fds);
+ FD_CLR(conn->fd, &connectfds);
conn->fd = -1;
}
return size;
***************
*** 244,251 ****
* NAME: conn->ipnum()
* DESCRIPTION: return the ip number of a connection
*/
! char *conn_ipnum(conn)
connection *conn;
{
! return inet_ntoa(conn->addr.sin_addr);
}
--- 323,341 ----
* NAME: conn->ipnum()
* DESCRIPTION: return the ip number of a connection
*/
! string *conn_ipnum(conn)
connection *conn;
{
! return str_new(conn->host, conn->hostlen);
}
+
+ /*
+ * NAME: conn->port()
+ * DESCRIPTION: return the port number of a connection
+ */
+ int conn_port(conn)
+ connection *conn;
+ {
+ return ntohs(conn->sin.sin_port);
+ }
+
diff -cr --ignore-space-change dgd/src/kfun/std.c dgd-patched/src/kfun/std.c
*** dgd/src/kfun/std.c Sat Aug 12 19:00:40 1995
--- dgd-patched/src/kfun/std.c Sun Sep 3 13:38:04 1995
***************
*** 602,615 ****
obj = i_this_object();
if (obj->count != 0) {
! if (obj->flags & O_USER) {
if (sp->type == T_INT) {
comm_echo(obj, sp->u.number != 0);
} else {
num = comm_send(obj, sp->u.string);
}
- } else if ((obj->flags & O_DRIVER) && sp->type == T_STRING) {
- P_message(sp->u.string->text);
}
}
if (sp->type == T_STRING) {
--- 602,615 ----
obj = i_this_object();
if (obj->count != 0) {
! if ((obj->flags & O_DRIVER) && sp->type == T_STRING) {
! P_message(sp->u.string->text);
! } else if (obj->flags & O_USER) {
if (sp->type == T_INT) {
comm_echo(obj, sp->u.number != 0);
} else {
num = comm_send(obj, sp->u.string);
}
}
}
if (sp->type == T_STRING) {
***************
*** 621,626 ****
--- 621,747 ----
}
# endif
+ # ifdef FUNCDEF
+ FUNCDEF("open_port", kf_open_port, p_open_port)
+ # else
+ char p_open_port[] = { C_TYPECHECKED | C_STATIC, T_VOID,
+ 3, T_OBJECT, T_INT, T_STRING };
+
+ /*
+ * NAME: kfun->open_port()
+ * DESCRIPTION: start listening on a port
+ */
+ int kf_open_port()
+ {
+ object *obj;
+ char *str;
+ int protocol;
+
+ obj = i_this_object();
+ if (obj->count == 0) {
+ error("open_port() from destructed object");
+ }
+ if (!(obj->flags & O_DRIVER)) {
+ error("open_port() only from driver object");
+ }
+
+ str = sp->u.string->text;
+ if (strcmp(str, "tcp") == 0) {
+ protocol = PRC_TCP;
+ } else if (strcmp(str, "udp") == 0) {
+ protocol = PRC_UDP;
+ } else if (strcmp(str, "telnet") == 0) {
+ protocol = PRC_TELNET;
+ } else {
+ return 3;
+ }
+
+ obj = o_object(sp[2].oindex, sp[2].u.objcnt);
+ if (obj->flags & (O_USER | O_EDITOR)) {
+ error("object already used for socket or editor");
+ }
+ comm_listen(o_object(sp[2].oindex, sp[2].u.objcnt),
+ sp[1].u.number, protocol);
+ str_del(sp->u.string);
+ sp += 2;
+ sp->type = T_INT;
+ sp->u.number = 0;
+ return 0;
+ }
+ # endif
+
+ # ifdef FUNCDEF
+ FUNCDEF("connect", kf_connect, p_connect)
+ # else
+ char p_connect[] = { C_TYPECHECKED | C_STATIC, T_VOID,
+ 4, T_OBJECT, T_STRING, T_INT, T_STRING };
+
+ /*
+ * NAME: kfun->connect()
+ * DESCRIPTION: initiate an ip connection
+ */
+ int kf_connect()
+ {
+ object *obj;
+ char *str;
+ int protocol;
+
+ obj = i_this_object();
+ if (obj->count == 0) {
+ error("connect() from destructed object");
+ }
+ if (!(obj->flags & O_DRIVER)) {
+ error("connect() only from driver object");
+ }
+
+ str = sp->u.string->text;
+ if (strcmp(str, "tcp") == 0) {
+ protocol = PRC_TCP;
+ } else if (strcmp(str, "telnet") == 0) {
+ protocol = PRC_TELNET;
+ } else {
+ return 4;
+ }
+
+ obj = o_object(sp[3].oindex, sp[3].u.objcnt);
+ if (obj->flags & (O_USER | O_EDITOR)) {
+ error("object already used for socket or editor");
+ }
+ comm_connect(obj, sp[2].u.string->text, sp[1].u.number, protocol);
+ str_del(sp->u.string);
+ str_del(sp[2].u.string);
+ sp += 3;
+ sp->type = T_INT;
+ sp->u.number = 0;
+ return 0;
+ }
+ # endif
+
+ # ifdef FUNCDEF
+ FUNCDEF("send_datagram", kf_send_datagram, p_send_datagram)
+ # else
+ char p_send_datagram[] = { C_TYPECHECKED | C_STATIC, T_VOID,
+ 3, T_STRING, T_STRING, T_INT };
+
+ /*
+ * NAME: kfun->send_datagram()
+ * DESCRIPTION: send a packet to a specific host and port (udp only)
+ */
+ int kf_send_datagram()
+ {
+ object *obj;
+
+ obj = i_this_object();
+ if (obj->count != 0 && obj->flags & O_USER) {
+ comm_sendto(obj, sp[2].u.string, sp[1].u.string->text, sp->u.number);
+ }
+ str_del((++sp)->u.string);
+ str_del((++sp)->u.string);
+ sp->type = T_INT;
+ sp->u.number = 0;
+ return 0;
+ }
+ # endif
# ifdef FUNCDEF
FUNCDEF("time", kf_time, p_time)