Skip to content

Commit

Permalink
Add support for the Mud Server Status Protocol
Browse files Browse the repository at this point in the history
While the protocol is somewhat dead some spiders use it.
http://tintin.sourceforge.net/mssp/
  • Loading branch information
cotillion committed Nov 20, 2016
1 parent 6550a24 commit 6da1fe5
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 4 deletions.
1 change: 1 addition & 0 deletions comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ void remove_interactive(struct interactive *, int);
void interactive_input(struct interactive *, char *);
void gmcp_input(struct interactive *, char *);
void *new_player(void *, struct sockaddr_storage *, socklen_t, u_short);
void mssp_request(struct interactive *ip);
80 changes: 80 additions & 0 deletions comm1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,3 +1162,83 @@ gmcp_input(struct interactive *ip, char *cp)
}
}
}

void
mssp_request(struct interactive *ip)
{
struct svalue *ret = NULL;
struct gdexception exception_frame;
struct allocation_pool pool = EMPTY_ALLOCATION_POOL;

exception_frame.e_exception = NULL;
exception_frame.e_catch = 0;

command_giver = ip->ob;
current_object = NULL;
current_interactive = command_giver;

if (setjmp(exception_frame.e_context)) {
exception = exception_frame.e_exception;
clear_state();
} else {
exception = &exception_frame;
push_object(ip->ob);
ret = apply_master_ob(M_INCOMING_MSSP, 1);
exception = NULL;

if (ret == NULL || ret->type != T_MAPPING) {
printf("incoming_mssp in the master did not return a mapping\n");
return;
}

struct mapping *m = ret->u.map;
mssp_t *mssp[card_mapping(m)];
size_t mssp_count = 0;

for (int i = 0; i < m->size; i++) {
for (struct apair *p = m->pairs[i]; p; p = p->next) {
struct svalue key = p->arg;
struct svalue val = p->val;
mssp_t *variable = NULL;

if (key.type != T_STRING)
continue;

if (val.type == T_STRING || val.type == T_NUMBER) {
variable = pool_alloc(&pool, sizeof(mssp_t) + 1 * sizeof(char *));
variable->name = (u_char *)key.u.string;
variable->size = 1;

if (val.type == T_STRING) {
variable->values[0] = (u_char *)val.u.string;
} else {
size_t needed = snprintf(NULL, 0, "%lld", val.u.number) + 1;
char *str = pool_alloc(&pool, needed);
snprintf(str, needed, "%lld", val.u.number);
variable->values[0] = (u_char *)str;
}
}

if (val.type == T_POINTER) {
variable = pool_alloc(&pool, sizeof(mssp_t) + val.u.vec->size * sizeof(char *));
variable->name = (u_char *)key.u.string;
variable->size = val.u.vec->size;

for (int y = 0; y < val.u.vec->size; y++) {
struct svalue *aval = &val.u.vec->item[y];
variable->values[y] = (u_char *)"";
if (aval->type == T_STRING) {
variable->values[y] = (u_char *)aval->u.string;
}
}
}

if (variable != NULL)
mssp[mssp_count++] = variable;
}
}

telnet_output_mssp(ip->tp, mssp, mssp_count);
pool_free(&pool);
}
}
5 changes: 5 additions & 0 deletions master.n
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,8 @@ object_name
# gmcp
#######
incoming_gmcp
#
#
# mssp
#######
incoming_mssp
1 change: 0 additions & 1 deletion parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,6 @@ struct svalue *
one_parse(struct vector *obvec, char *pat, struct vector *wvec, int *cix_in,
int *fail, struct svalue *prep_param)
{
char ch;
struct svalue *pval;
static struct svalue stmp = { T_NUMBER };
char *str1, *str2;
Expand Down
67 changes: 65 additions & 2 deletions telnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
#define TELNET_CANQ_SIZE (1024 * 8)
#define TELNET_RAWQ_SIZE (1024 * 4)
#define TELNET_OPTQ_SIZE (1024)
#define TELNET_OUTQ_SIZE (16*1024)
#define TELNET_OUTQ_SIZE (32*1024)

/*
* Output Queue Flow Control Parameters.
Expand Down Expand Up @@ -294,6 +294,34 @@ telnet_output_gmcp(telnet_t *tp, u_char *cp)
return 1;
}


int
telnet_output_mssp(telnet_t *tp, mssp_t *vars[], size_t count)
{
nqueue_t *nq;
nq = tp->t_outq;

nq_putc(nq, IAC);
nq_putc(nq, SB);
nq_putc(nq, TELOPT_MSSP);

for (size_t i = 0; i < count; i++) {
nq_putc(nq, MSSP_VAR);
nq_puts(nq, vars[i]->name);

for (size_t k = 0; k < vars[i]->size; k++) {
nq_putc(nq, MSSP_VAL);
nq_puts(nq, vars[i]->values[k]);
}
}

nq_putc(nq, IAC);
nq_putc(nq, SE);

telnet_enabw(tp);
return 1;
}

/*
* Notify an interactive object that the Telnet session has been disconnected.
*/
Expand Down Expand Up @@ -529,6 +557,9 @@ telnet_get_optp(telnet_t *tp, u_char opt)
case TELOPT_GMCP:
return &tp->t_optb[OP_GMCP];

case TELOPT_MSSP:
return &tp->t_optb[OP_MSSP];

default:
return NULL;
}
Expand Down Expand Up @@ -684,6 +715,8 @@ telnet_ack_lenab(telnet_t *tp, u_char opt)
case TELOPT_GMCP:
tp->t_flags |= TF_GMCP;
break;
case TELOPT_MSSP:
break;
}
}

Expand Down Expand Up @@ -861,6 +894,29 @@ telnet_disable_gmcp(telnet_t *tp)
telnet_neg_ldisab(tp, TELOPT_GMCP);
}

/*
* Enable MSSP
*/
void
telnet_enable_mssp(telnet_t *tp)
{
if (nq_avail(tp->t_outq) < 3)
return;

telnet_neg_lenab(tp, TELOPT_MSSP);
}

/*
* Disable MSSP
*/
void
telnet_disable_mssp(telnet_t *tp)
{
if (nq_avail(tp->t_outq) < 3)
return;

telnet_neg_ldisab(tp, TELOPT_MSSP);
}

/*
* Process IAC WILL <option>.
Expand Down Expand Up @@ -1006,6 +1062,12 @@ telnet_do(telnet_t *tp, u_char opt)
return;
}

if (opt == TELOPT_MSSP)
{
mssp_request(tp->t_ip);
return;
}

switch (op->o_us)
{
case OS_NO:
Expand Down Expand Up @@ -1449,8 +1511,9 @@ telnet_accept(void *vp)
tp->t_nd = nd_attach(s, telnet_read, telnet_write, telnet_exception,
NULL, telnet_shutdown, tp);

/* Start negotiation of GMCP */
/* Start negotiation of optional features */
telnet_enable_gmcp(tp);
telnet_enable_mssp(tp);

ip = (void *)new_player(tp, &addr, addrlen, local_port);
if (ip == NULL)
Expand Down
18 changes: 17 additions & 1 deletion telnet.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ typedef struct {
#define OP_SGA 1
#define OP_CDM 2
#define OP_GMCP 3
#define OP_SIZE 4
#define OP_MSSP 4
#define OP_SIZE 5

/*
* Telnet Control Block.
Expand Down Expand Up @@ -112,12 +113,27 @@ typedef struct {
#define TS_IAC_DO 8
#define TS_IAC_DONT 9


#define TELOPT_MSSP 70
#define TELOPT_GMCP 201
#define TELOPT_CDM 205

/*
* MSSP Data Block
*/
typedef struct {
u_char *name;
size_t size;
u_char *values[];
} mssp_t;

#define MSSP_VAR 1
#define MSSP_VAL 2

void telnet_detach(telnet_t *);
int telnet_output(telnet_t *, u_char *);
int telnet_output_gmcp(telnet_t *, u_char *);
int telnet_output_mssp(telnet_t *, mssp_t *vars[], size_t count);
void telnet_enable_echo(telnet_t *);
void telnet_disable_echo(telnet_t *);
void telnet_enable_gmcp(telnet_t *);
Expand Down

0 comments on commit 6da1fe5

Please sign in to comment.