some missing files

This commit is contained in:
psyc://psyced.org/~lynX 2009-01-27 23:02:44 +01:00
parent 61e6cf4f60
commit 699fe68c44
20 changed files with 4284 additions and 0 deletions

42
config/blueprint/README Normal file
View File

@ -0,0 +1,42 @@
==========================================
YOU SHOULD READ THIS MESSAGE IN YOUR local/
DIRECTORY. config/blueprint ONLY CONTAINS
THE DEFAULT COPY OF THE CONFIGURATION. IT
IS NOT IN USE AS YOU RUN THE SERVER. SO
DON'T EDIT ANY FILES IN config/blueprint.
THX ======================================
banner.txt is the file that is shown to
telnet users at login
config.c is currently not being used, really.
config.h is of no interest.
hosts.h lets you specify ip ranges that are
particularely trustworthy or untrustworthy.
init.ls contains the list of classes that
will be compiled at boot-time. it is mostly
useful for debugging, as in a healthy
system any required class can be compiled
at the moment it is used for the first time.
so for production use this is kept to the
bare minimum. only the parts of psyced you
are actually using will be loaded.
local.h hosts your personal tunings to the
psyced system.
path.h lets you rearrange the directories
where the code for the protocol implementations
reside. you don't need to do that normally.
ports.h is generated by the installation
procedure and contains the port numbers you
chose for the services you want to use.
psyconf.h is also generated that way by the
psyconf utility. it contains the settings
from psyced.ini in a form pleasant for LPC.

View File

@ -0,0 +1,8 @@
[connected]
PROTOCOL for SYNCHRONOUS CONFERENCING http://www.psyced.org/
--------------- ___ __ _ _ __ ___ __ ------------------
| \ (__ \ / / | | \
|__/ \ V | |- | )
>>> | (__/ | \__ |__ |_/ <<<

66
config/blueprint/config.c Normal file
View File

@ -0,0 +1,66 @@
// $Id: config.c,v 1.9 2006/11/07 07:58:36 lynx Exp $ vim:syntax=lpc
#include <net.h>
/* a data file or an include can be read by any file in the system but
* we want this information to be readable by the gateway code only
* that's why it has to be lpc code
*/
#ifdef GATEWAY_PATH
/* if you are positive that you want to run your own gateways to
* legacy messaging systems, please insert your gateway credentials
* into the fields below and activate the code by turning #if 0 to #if 1
*
* update: these bot-style gateways are not functional. don't switch
* them to 1 as either the python scripts or the jabber code isn't
* up to date with them.
*/
# define USE_ICQ_GATEWAY 0 // don't change
# define USE_AIM_GATEWAY 0 // don't change
qConfig() {
string p = file_name(previous_object());
# ifdef __COMPAT_MODE__
p = "/"+p;
# endif
P3(("\n%O: config requested by %s\n", ME, p))
# if USE_ICQ_GATEWAY
if (abbrev(GATEWAY_PATH "icq", p)) return
(["host" : "icq.localhost",
"port" : 5234,
"scheme" : "icq",
"name" : "icqlinker",
"secret" : "myicqsecret",
"nickname" : "your uin here",
"password" : "and your password please" ]);
# endif
# if USE_AIM_GATEWAY
if (abbrev(GATEWAY_PATH "aim2", p)) return
(["host" : "aim.localhost",
"port" : 5233,
"scheme" : "aim",
"name" : "aimlinker",
"secret" : "myaimsecret",
"nickname" : "screen name",
"password" : "and your password please" ]);
# endif
}
load() {
# if USE_ICQ_GATEWAY
D(" " GATEWAY_PATH "icq");
load_object(GATEWAY_PATH "icq");
# endif
# if USE_AIM_GATEWAY
D(" " GATEWAY_PATH "aim2");
load_object(GATEWAY_PATH "aim2");
# endif
# ifdef RELAY_OBJECT
D(" " RELAY_OBJECT "\n");
call_out(load_object, 0, RELAY_OBJECT);
# endif
}
#endif

23
config/blueprint/config.h Normal file
View File

@ -0,0 +1,23 @@
// $Id: config.h,v 1.1 2007/04/26 13:34:02 lynx Exp $ // vim:syntax=lpc
//
// This file is not intended to be modified. Make your local changes
// in psyced.ini, and if that wasn't good enough, use local.h.
// If you are integrating psyced with other LPC applications, feel
// free to modify path.h. If you aren't, better leave it as it is.
#ifndef CONFIG_H
# define CONFIG_H
// load local modifications by the admin
# include "local.h"
// load port configuration as generated by psyconf
# include "ports.h"
// load layout of psyced software modules
# include "path.h"
// load psyced.ini settings converted by psyconf
# include "psyconf.h"
#endif

7
config/blueprint/hosts.h Normal file
View File

@ -0,0 +1,7 @@
// Examples of specially enabled or disabled hosts.
//
//
// #define ENABLED_HOSTS "192.168.0.", "10."
//
// #define DISABLED_HOSTS "207.46.197.", "207.46.19."
//

3
config/blueprint/init.ls Normal file
View File

@ -0,0 +1,3 @@
net/user
net/place/basic
local/config

5
config/blueprint/local.h Normal file
View File

@ -0,0 +1,5 @@
// This is local.h for advanced tunings to the psyced runtime and
// LPC compilation process. The format looks just like a regular
// header file for the C language. Settings you can specify
// here are documented at http://about.psyc.eu/Tuning

50
config/blueprint/path.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef _INCLUDE_PATH_H
#define _INCLUDE_PATH_H
#define NET_PATH "/net/"
#define PLACE_PATH "/place/"
#define SERVICE_PATH "/service/"
#define DATA_PATH "/data/"
#define CONFIG_PATH "/local/"
#define DAEMON_PATH NET_PATH "d/"
#define GATEWAY_PATH NET_PATH "gateway/"
// protocol for synchronous conferencing
#define PSYC_PATH "/net/psyc/"
// experimental PSYC 1.0 interface
#define SPYC_PATH "/net/spyc/"
// irc server emulation
#define IRC_PATH "/net/irc/"
// jabber server emulation
#define JABBER_PATH "/net/jabber/"
// telnet access
#define TELNET_PATH "/net/tn/"
// java applet server, uses a very simple protocol
#define APPLET_PATH "/net/applet/"
// accept messages and simple mails via smtp
#define SMTP_PATH "/net/smtp/"
// experimental: access message log via pop3
#define POP3_PATH "/net/pop/"
// experimental: serve as a sip "proxy"
#define SIP_PATH "/net/sip/"
// allow access to subscribed threaded discussion groups via nntp
#define NNTP_PATH "/net/nntp/"
// accept messages and allow lastlog access via wap
#define WAP_PATH "/net/wap/"
// simple http server
#ifndef HTTP_PATH
# define HTTP_PATH "/net/http/"
#endif
#endif

33
config/blueprint/ports.h Normal file
View File

@ -0,0 +1,33 @@
/* this file shall automatically be generated by psyconf.
*
* the values in here may be the same as in services.h
* or they may not. so always be conscious which ones you
* are using to which purpose. -lynX
*/
#echo This is just the demo ports.h. I shouldn't get loaded.
#echo If I do, then you didn't run psyconf successfully!!
#define PSYC_PORT 4404
#define HTTP_PORT 33333
#define HTTPS_PORT 34443
#define IRC_PORT 6667
#define IRCS_PORT 9999
#define JABBER_PORT 5222
#define JABBERS_PORT 5223
#define JABBER_S2S_PORT 5269
#define TELNET_PORT 2323
#define TELNETS_PORT
#define APPLET_PORT 2008
#define SMTP_PORT
#define SMTPS_PORT
#define NTTP_PORT
#define NNTPS_PORT

View File

@ -0,0 +1,68 @@
# These lines are needed on some machines.
MAKE=make
SHELL=@CONFIG_SHELL@
INSTALL=@INSTALL@
mkinstalldirs=$(SHELL) @top_srcdir@/mkinstalldirs
#
CC=@CC@
prefix=@prefix@
exec_prefix=@exec_prefix@
SUBDIRS = indent make_docs xerq
SED = sed
BINDIR=@bindir@
MUD_LIB=@libdir@
ERQ_DIR=@libexecdir@
#PROFIL= -DOPCPROF -DVERBOSE_OPCPROF
#PROFIL=-p -DMARK
#PROFIL=-pg
PROFIL=
#Enable warnings from the compiler, if wanted.
WARN= # no warning options - will work with all compilers :-)
#WARN= -Wall -Wshadow -Dlint
#WARN= -Wall -Wshadow -Wno-parentheses # gcc settings
#
# Optimization and source level debugging options.
# adding a -fomit-frame-pointer on the NeXT (gcc version 1.93 (68k, MIT syntax))
# will corrupt the driver.
HIGH_OPTIMIZE = @OCFLAGS@ # high optimization
MED_OPTIMIZE= @MCFLAGS@ # medium optimization
LOW_OPTIMIZE = @LCFLAGS@ # minimal optimization
NO_OPTIMIZE= @DCFLAGS@ # no optimization; for frequent recompilations.
OPTIMIZE= $(@val_optimize@_OPTIMIZE)
# The main debugging level is define in config.h
# Add additional options here.
DEBUG=
#
MPATH=-DMUD_LIB='"$(MUD_LIB)"' -DBINDIR='"$(BINDIR)"' -DERQ_DIR='"$(ERQ_DIR)"'
#
TOPINC=-I@top_srcdir@
#
CFLAGS= @EXTRA_CFLAGS@ $(OPTIMIZE) $(DEBUG) $(WARN) $(MPATH) $(PROFIL) $(TOPINC)
#
LIBS=@ERQ_LIBS@ -lresolv
#
LDFLAGS=@LDFLAGS@
all: erq@EXEEXT@
FORCE: install
erq@EXEEXT@: erq.c
# $(CC) erq.c -lresolv -o erq@EXEEXT@
$(CC) $(CFLAGS) $(LDFLAGS) erq.c -o erq@EXEEXT@ $(LIBS)
install: erq@EXEEXT@
$(mkinstalldirs) $(BINDIR)
$(INSTALL) erq@EXEEXT@ $(BINDIR)/erq@EXEEXT@
clean:
-rm -f *.o erq@EXEEXT@ *~

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
/* external request demon interface definitions */
#ifndef ERQ_H__
#define ERQ_H__ 1
/* servive request types */
#define ERQ_RLOOKUP 0 /* Lookup ip -> name */
#define ERQ_EXECUTE 1 /* Execute a program */
#define ERQ_FORK 2 /* Fork a program */
#define ERQ_AUTH 3 /* Connect to a remote authd */
#define ERQ_SPAWN 4 /* Spawn a program */
#define ERQ_SEND 5 /* Send data to a program or connection */
#define ERQ_KILL 6 /* Kill a program or connection */
#define ERQ_OPEN_UDP 7 /* Open a UDP socket */
#define ERQ_OPEN_TCP 8 /* Open a TCP connection */
#define ERQ_LISTEN 9 /* Open a TCP accept-socket */
#define ERQ_ACCEPT 10 /* Accept a connection from a accept-socket */
#define ERQ_LOOKUP 11 /* Lookup name -> ip */
#ifdef __IPV6__
#define ERQ_RLOOKUPV6 12 /* Lookup name/ip6 */
#endif
#define ERQ_LOOKUP_SRV 13
/* Additional service request type flags evaluated by efun send_erq().
* The ERQ itself won't get to see it.
*/
#define ERQ_CB_STRING (1 << 31) /* Callback closure takes a string arg */
/* answers from ERQ_EXECUTE / ERQ_FORK */
#define ERQ_OK 0
#define ERQ_SIGNALED 1
#define ERQ_E_NOTFOUND 2 /* process not found by wait */
#define ERQ_E_UNKNOWN 3 /* unknown exit condition from wait() */
#define ERQ_E_ARGLENGTH 4
#define ERQ_E_ARGFORMAT 5
#define ERQ_E_ARGNUMBER 6
#define ERQ_E_ILLEGAL 7
#define ERQ_E_PATHLEN 8
#define ERQ_E_FORKFAIL 9
#define ERQ_E_TICKET 11
#define ERQ_E_INCOMPLETE 12
#define ERQ_E_WOULDBLOCK 13
#define ERQ_E_PIPE 14
#define ERQ_STDOUT 15 /* Normal data received */
#define ERQ_STDERR 16
#define ERQ_EXITED 17 /* Connection closed on EOF */
#define ERQ_E_NSLOTS 18
/* reserved handles */
#define ERQ_HANDLE_RLOOKUP (-1)
#define ERQ_HANDLE_KEEP_HANDLE (-2)
#define ERQ_HANDLE_RLOOKUPV6 (-3)
#endif /* ERQ_H__ */

View File

@ -0,0 +1,215 @@
#include "srv.h"
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <arpa/inet.h> // For solaris
#include <arpa/nameser.h>
#include <resolv.h>
#include <malloc.h>
/* the biggest packet we'll send and receive */
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
#else
#define MAXPACKET 1024
#endif
/* and what we send and receive */
typedef union {
HEADER hdr;
u_char buf[MAXPACKET];
} querybuf;
#ifndef T_SRV
#define T_SRV 33
#endif
void freesrvhost ( struct srvhost * s )
{
struct srvhost * n;
while( s ) {
n = s->next;
/* hack to make double-free visible by causing null dereference */
s->next = NULL;
free( (void *)s );
s = n;
}
}
static int compare( const void * a, const void * b )
{
struct srvhost * aa, * bb;
if ( !a )
return 1;
if ( !b )
return -1;
aa = (struct srvhost *) *(int*)a;
bb = (struct srvhost *) *(int*)b;
if ( aa->pref > bb->pref )
return 1;
if ( aa->pref < bb->pref )
return -1;
if ( aa->rweight > bb->rweight )
return -1;
if ( aa->rweight < bb->rweight )
return 1;
return 0;
}
struct srvhost * getsrv( const char * domain,
const char * service, const char * protocol ) {
querybuf answer; /* answer buffer from nameserver */
int n;
char * zone;
int ancount, qdcount; /* answer count and query count */
HEADER *hp; /* answer buffer header */
struct srvhost **replyarray;
struct srvhost * firsthost;
int answerno;
u_char hostbuf[256];
u_char *msg, *eom, *cp; /* answer buffer positions */
int dlen, type, pref, weight, port;
if ( !domain || !*domain ||
!service || !*service ||
!protocol || !*protocol )
return NULL;
zone = (char *)malloc( strlen( domain ) +
strlen( service ) +
strlen( protocol ) + 20 );
if (zone == NULL)
return NULL;
*zone = '\0';
if (*service != '_') // If service and protocol do not start with a
strcat(zone, "_"); // _, prepend the _ to them...
strcat(zone, service);
strcat(zone, ".");
if (*protocol != '_')
strcat(zone, "_");
strcat(zone, protocol);
strcat(zone, ".");
strcat(zone, domain);
n = res_query( zone, C_IN, T_SRV, (u_char *)&answer, sizeof( answer ) );
(void) free( zone );
zone = NULL;
if ( n < (int)sizeof(HEADER) )
return NULL;
/* valid answer received. skip the query record. */
hp = (HEADER *)&answer;
qdcount = ntohs(hp->qdcount);
ancount = ntohs(hp->ancount);
msg = (u_char *)&answer;
eom = (u_char *)&answer + n;
cp = (u_char *)&answer + sizeof(HEADER);
while ( qdcount-- > 0 && cp < eom ) {
n = dn_expand( msg, eom, cp, (char *)hostbuf, 256 );
if (n < 0)
return NULL;
cp += n + QFIXEDSZ;
}
/* make a big-enough (probably too big) reply array */
replyarray
= (struct srvhost **) malloc( ancount * sizeof(struct srvhost *) );
for( n = 0; n < ancount; n++ )
replyarray[n] = NULL;
answerno = 0;
/* loop through the answer buffer and extract SRV records */
while ( ancount-- > 0 && cp < eom ) {
n = dn_expand( msg, eom, cp, (char *)hostbuf, 256 );
if ( n < 0 ) {
for( n = 0; n < answerno; n++ )
(void) free( replyarray[n] );
(void)free( replyarray );
return NULL;
}
cp += n;
type = _getshort(cp);
cp += sizeof(u_short);
/* class = _getshort(cp); */
cp += sizeof(u_short);
/* ttl = _getlong(cp); */
cp += sizeof(u_long);
dlen = _getshort(cp);
cp += sizeof(u_short);
if ( type != T_SRV ) {
cp += dlen;
continue;
}
pref = _getshort(cp);
cp += sizeof(u_short);
weight = _getshort(cp);
cp += sizeof(u_short);
port = _getshort(cp);
cp += sizeof(u_short);
n = dn_expand( msg, eom, cp, (char *)hostbuf, 256 );
if (n < 0)
break;
cp += n;
replyarray[answerno]
= (struct srvhost *)malloc( sizeof( struct srvhost ) +
strlen( (char *)hostbuf ) );
replyarray[answerno]->pref = pref;
replyarray[answerno]->weight = weight;
if ( weight )
replyarray[answerno]->rweight = 1+random()%( 10000 * weight );
else
replyarray[answerno]->rweight = 0;
replyarray[answerno]->port = port;
replyarray[answerno]->next = NULL;
strcpy( replyarray[answerno]->name, (char *)hostbuf );
answerno++;
}
if (answerno == 0) return NULL;
qsort( replyarray, answerno, sizeof( struct srvhost * ),
compare );
// Recreate a linked list from the sorted array...
for( n = 0; n < answerno; n++ )
replyarray[n]->next = replyarray[n+1];
replyarray[answerno-1]->next = NULL;
firsthost = replyarray[0];
(void) free( replyarray );
return firsthost;
}

View File

@ -0,0 +1,32 @@
/****************************************************************************
** $Id: srv.h,v 1.1 2006/05/22 11:18:10 lynx Exp $
**
** Definition of something or other
**
** Created : 979899
**
** Copyright (C) 1997 by Troll Tech AS. All rights reserved.
**
****************************************************************************/
#ifndef SRV_H
#define SRV_H
struct srvhost {
unsigned int pref;
struct srvhost * next;
unsigned int port;
unsigned int weight;
unsigned int rweight;
char name[1];
};
extern void freesrvhost ( struct srvhost * );
extern struct srvhost * getsrv( const char * domain,
const char * service,
const char * protocol );
#endif

View File

@ -0,0 +1,311 @@
#!/bin/sh
#
# settings/psyced version 4.0
#
# $Id: psyced.settings,v 1.10 2007/05/08 00:52:01 lynx Exp $
#
# LDMUD compilation settings for psyced, the LPC server and client
# implementation of the protocol for synchronous conferencing.
# Please execute this instead of ./configure before compilation.
#
# The latest version of this file is in the psyced-CVS and usually also
# at http://www.psyced.org/dist/config/psyced.settings
# The version in the LDMUD distribution may be slightly outdated.
#
# Documents and download on: http://www.psyced.org
# Information about PSYC: http://www.psyc.eu
#
# the PSYC implementation and library is designed in a way that it should
# easily co-host in a running LPMUD, it just needs a few patches to the
# master object and #includes in simul_efun.
#
# how to multiplex InterMUD and PSYC on the same udp port:
# PSYC UDP packets always start with ".\n".
#
# configure will strip this part from the script.
cp $0 settings/psyced-current
exec ./configure --prefix=/opt/psyced --bindir=/opt/psyced/bin --libdir=/opt/psyced/world --libexec=/opt/psyced/run --with-setting=psyced-current $*
exit
#-- PSYCLPC EXTENSIONS
# compile json c library in, if available
enable_use_json=yes
# compile expat xml & xmpp parser in, if available
enable_use_expat=yes
# enable this if you want use http://about.psyc.eu/psyclpc#Authlocal
enable_use_authlocal=yes
# requires procfs with readable /proc/net/tcp
#
# some kernel configurations show wrong port numbers however,
# in that case the correlation from peer port to user id fails.
# there is however no risk of error (the peer ports are unprivileged
# whereas the 'wrong' ones are privileged ones. could be related to
# iptables or some other port mapping magic).
#-- FILE PATHES
with_master_name=drivers/ldmud/master/master
# unused really
with_swap_file=log/psyced.swap
#-- NETWORKING & DATA BASES
# cool tool that does external name server resolution and more
enable_erq=erq
# the "sorry" message of the built-in ACL isn't flexible enough:
# it cannot output a properly formatted HTTP or PSYC message
# and why shouldn't this be done in LPC anyway?
enable_access_control=no
# zlib compression, really
enable_use_mccp=yes
# Enable support for TLS (Transport Layer Security).
#
# 'no': TLS support is not compiled it
# 'gnu': TLS support using GnuTLS is compiled in if found.
# 'ssl': TLS support using OpenSSL is compiled in if found.
# 'yes': TLS support using either OpenSSL or GnuTLS is compiled in if found.
# The configuration script looks first for OpenSSL, then GnuTLS.
# If both are available, OpenSSL is used.
#
# gnutls does not offer features we need
enable_use_tls=ssl
# SQL storage not implemented. Maybe PSYC synchronization is good enough?
# see http://about.psyc.eu/storage for info.
enable_use_mysql=no
enable_use_pgsql=no
enable_use_sqlite=no
# maximum permitted tcp connections
with_max_players=900
# The maximum number of ports to listen for connections on.
with_maxnumports=33
# size of the buffer for incoming data of each socket
with_size_socket_buffer=32768
# The maximum number of simultaneous connect() calls
with_max_net_connects=33
# how can i set all the other port numbers?
# still using the historic dirty command line hack?
with_portno=4404
# Maximum size of a socket send buffer.
with_set_buffer_size_max=262144
# the PSYC port
with_udp_port=4404
# Enable support for IPv6 (this should better be autodetected!!)
#enable_use_ipv6=no
# Enable the use of pthreads for background socket IO.
enable_use_pthreads=no
# If PThreads are used, this is the max amount of data held pending
# for writing. If the amount is exceeded, the oldest data blocks
# are discarded.
# If 0, any amount of data is allowed.
with_pthread_write_max_size=333333
#-- RUNTIME LIMITS
#
# currently we consider a psyced a friendly environment
# where no coders will abuse cpu time and other limits
# you may want to change this if you have many room coders
# you can lower this value for better debugging
with_max_cost=9999999
#with_catch_reserved_cost=2000
#with_master_reserved_cost=512
enable_dynamic_costs=no
# Maximum function call depth for normal program execution
#with_max_user_trace=60
# Maximum function call depth during error handling.
# It must be bigger than MAX_USER_TRACE (check at compile time).
#with_max_trace=65
# Maximum number of bits in a bit string.
# The limit is more based on considerations of speed than memory consumption.
#with_max_bits=6144
# Allowed number of ed commands per backend cycle (for faster file upload).
#with_allowed_ed_cmds=20
# disabled "mud" limits
with_max_array_size=0
with_max_mapping_size=0
with_max_mapping_keys=0
with_read_file_max_size=0
with_max_byte_transfer=0
with_max_callouts=0
# new, was =100000
with_pthread_write_max_size=0
# Compiler stack size. This value affects the complexity the compiler can
# parse.
#with_compiler_stack_size=400
# Maximum number of local variables
#with_max_local=50
# Maximum size of an expanded preprocessor definition.
#with_defmax=65000
#-- MEMORY ALLOCATION
# slabmalloc seems to interact badly with net/jabber
#with_malloc=sysmalloc
# but other mallocs don't even compile & run
enable_malloc_sbrk=yes
enable_malloc_check=no
enable_malloc_trace=no
enable_malloc_sbrk_trace=no
#enable_malloc_lpc_trace=no, MALLOC_slaballoc
# disabled, sort of
with_reserved_user_size=100000
# hash table sizes. we have many chat strings (like lastlogs), but few objects
# (max: 65536)
with_htable_size=32768
with_otable_size=256
# Size of the hash table for defines, reserved words, identifiers, and
# efun names. This should be several times smaller than HTABLE_SIZE.
#with_itable_size=256
# Size of the apply cache, expressed in the bitsize of its indices.
# The number of entries is 2**cache_bits.
#with_apply_cache_bits=12
# Select whether compiled regular expressions shall be cached, and
# how big the cache shall be (max: 65536).
enable_rxcache_table=yes
with_rxcache_table=4096
#-- TIMER MECHANISMS
# short resets, not strictly necessary but useful
with_time_to_reset=1000
with_time_to_clean_up=9000
#with_time_to_swap=1500
#with_time_to_swap_variables=2500
with_time_to_swap=0
with_time_to_swap_variables=0
#-- MUD FEATURES
# should work in "native" too, after a tweak or two
# however, psyced expects create() to get called instead of reset(0)
enable_compat_mode=yes
enable_strict_euids=no
# The Input escape character.
# If this character is typed as first on the line, the normal input_to()s
# are bypassed.
#with_input_escape="!"
# Define ALLOW_FILENAME_SPACES if the driver should accept space characters
# in filenames. If it is not defined, a hardcoded test for space characters
# is activated.
enable_filename_spaces=yes
with_wizlist_file=no
enable_use_set_light=no
enable_use_set_is_wizard=no
#-- LANGUAGE
enable_use_parse_command=no
enable_use_process_string=no
enable_lpc_nosave=yes
# if turned to yes this causes errors
# in textdb and room history:
enable_share_variables=no
# keep .o files crossplatform
enable_use_system_crypt=no
# Define this to enable LPC structs.
enable_use_structs=no
# new inline closure and function syntax, see doc/LPC/inline-closures
# ... We don't want to use them as yet, but current
# 3.3.5xx doesn't compile properly without! :-(
enable_use_new_inlines=yes
enable_use_alists=no
# we use it for system shout
enable_lpc_array_calls=yes
# only enables the ancient transfer() efun we don't use
enable_use_deprecated=no
# Enable PCRE instead of traditional regexps
# 'no': use traditional regexps by default
# 'no-builtin': use traditional regexps by default, or the builtin PCRE
# package if PCRE is requested
# 'builtin': use PCRE package by default, using the builtin package
# 'yes': use the system's PCRE package if available, otherwise the
# builtin package
enable_use_pcre=yes
#-- COMPILATION
# The optimization level in the generated Makefile
# Settings: no, low, med, high
with_optimize=med
#-- DEBUGGING
# Enable basic run time sanity checks. This will use more time
# and space, but nevertheless you are strongly encouraged to keep
# it defined.
enable_debug=yes
# LPC compiler debug
#enable_yydebug=no
# Disable inlining. Use this to debug obscure crashes, or for
# speed tests.
#enable_no_inlines=no
# Activate debug prints in the telnet machine (lots of output).
#enable_debug_telnet=no
# Activate allocation debug prints in the malloc module (lots of output).
# Supported by: MALLOC_smalloc, MALLOC_slaballoc
#enable_debug_malloc_allocs=no
# The DEBUG level for the ERQ daemon:
# 0 : no debug output
# 1 : standard debug output
# 2 : verbose debug output
with_erq_debug=0
# If TRACE_CODE is enable, the driver keeps a log of TOTAL_TRACE_LENGTH
# most recently execute bytecode instructions.
enable_trace_code=yes
with_total_trace_length=1024
# Enable these for runtime statistics:
# COMM_STAT: number and size of outgoing packets
# APPLY_CACHE_STAT: number of hits and misses in the apply cache
enable_comm_stat=yes
enable_apply_cache_stat=no
# Enable usage statistics of VM instructions.
enable_opcprof=no
enable_verbose_opcprof=no
# Lars' hardcore debug features
#enable_check_object_stat=no
#enable_check_mapping_total=no
#enable_check_object_ref=no
#enable_check_object_gc_ref=no
#enable_dump_gc_refs=no

View File

@ -0,0 +1,3 @@
import net.library;
#include "../../../world/net/psyc/common.c"

35
utility/latency.pike Normal file
View File

@ -0,0 +1,35 @@
# contributed by fippo
Stdio.File socket;
int count;
array(int) start, stop;
void logon(int success) {
socket->set_nonblocking(read_cb);
socket->write(".\n");
}
void read_cb(int id, string data) {
//werror("read_cb:\n%s\n---\n", data);
count++;
if (count == 2) {
start = System.gettimeofday()[..1];
socket->write(":_target\tpsyc://localhost/~fippo\n\n_request_version\n.\n");
}
if (count > 2) {
stop = System.gettimeofday()[..1];
werror("latency is %d\n", (stop[0] - start[0])*1000000 + (stop[1] - start[1]));
if (count < 500) {
socket->write(":_target\tpsyc://localhost/\n\n_request_version\n.\n");
start = stop;
}
}
}
int main() {
socket = Stdio.File();
socket->async_connect("localhost", 4404, logon);
return -1;
}

View File

@ -0,0 +1,440 @@
// $Id: accept.c,v 1.119 2008/08/03 14:21:59 lynx Exp $ // vim:syntax=lpc:ts=8
//
// this file contains the glue between LDMUD and psyced to
// connect the socket ports to appropriately named objects.
//
#include "/local/config.h"
#ifdef Dmaster
# undef DEBUG
# define DEBUG Dmaster
#endif
#include NET_PATH "include/net.h"
#include NET_PATH "include/services.h"
#include DRIVER_PATH "include/driver.h"
#include CONFIG_PATH "config.h"
#include DRIVER_PATH "sys/tls.h"
#ifndef ERR_TLS_NOT_DETECTED
# define ERR_TLS_NOT_DETECTED -31337
# ifdef SPYC_PATH
# echo Warning: TLS autodetect is not enabled in driver.
# endif
#endif
volatile int shutdown_in_progress = 0;
// not part of the master/driver API.. this is called from the library
void notify_shutdown_first(int progress) {
P3(("%O notify_shutdown_first(%O)\n", ME, progress))
shutdown_in_progress = progress;
}
#ifndef UID2NICK
# ifdef _userid_nick_mapping
# define UID2NICK(uid) ([ _userid_nick_mapping ])[uid]
# endif
#endif
/*
* This function is called every time a TCP connection is established.
* It dispatches the ports to the protocol implementations.
* input_to() can't be called from here.
*
* uid is only passed if USE_AUTHLOCAL is built into the driver.
*/
object connect(int uid, int port, string service) {
int peerport;
mixed arg, t;
// now that's a bit of preprocessor magic you don't need to understand.. ;)
D2( if (uid) D("master:connected on port "+ query_mud_port() +" by uid "
+ uid +"\n");
else) {
D3(D("master:connected on port "+query_mud_port()
+" by "+query_ip_name()+"\n");)
}
#ifndef H_DEFAULT_PROMPT
set_prompt("");
#endif
if (shutdown_in_progress) {
PT(("shutdown_in_progress(%O): putting connection from %O on hold\n",
shutdown_in_progress, query_ip_name(ME)))
// put the connection on hold to avoid further reconnects
return clone_object(NET_PATH "utility/onhold");
}
// we dont want the telnet machine most of the time
// but disabling and re-enabling it for telnet doesn't work
switch(port || query_mud_port()) {
#if HAS_PORT(PSYCS_PORT, PSYC_PATH)
case PSYCS_PORT: // inofficial & temporary
# if __EFUN_DEFINED__(tls_want_peer_certificate)
tls_want_peer_certificate(ME);
# endif
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
#endif // fall thru
#if HAS_PORT(PSYC_PORT, PSYC_PATH)
case PSYC_PORT:
#endif
#if HAS_PORT(PSYC_PORT, PSYC_PATH) || HAS_PORT(PSYCS_PORT, PSYC_PATH)
# ifdef DRIVER_HAS_CALL_BY_REFERENCE
arg = ME;
query_ip_number(&arg);
// this assumes network byte order provided by driver
peerport = pointerp(arg) ? (arg[2]*256 + arg[3]) : 0;
if (peerport < 0) peerport = 65536 + peerport;
// no support for non-AF_INET nets yet
if (peerport == PSYC_SERVICE) peerport = 0;
# else
// as long as the object names don't collide, this is okay too
peerport = 65536 + random(9999999);
# endif
# ifdef DRIVER_HAS_RENAMED_CLONES
unless (service) service = "psyc";
t = "S:"+ service + ":"+ query_ip_number();
// tcp peerports cannot be connected to, so we use minus
if (peerport) t += ":-"+peerport;
# else
t = clone_object(PSYC_PATH "server");
# endif
// the psyc backend distinguishes listen ports from peers using minus
D3(D(S("%O -> load(%O, %O)\n", t, query_ip_number(), -peerport));)
return t -> load(query_ip_number(), -peerport);
#endif
#if HAS_PORT(SPYCS_PORT, SPYC_PATH)
case SPYCS_PORT: // inofficial & temporary
# if __EFUN_DEFINED__(tls_want_peer_certificate)
tls_want_peer_certificate(ME);
# endif
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
#endif // fall thru
#if HAS_PORT(SPYC_PORT, SPYC_PATH)
case SPYC_PORT:
#endif
#if HAS_PORT(SPYC_PORT, SPYC_PATH) || HAS_PORT(SPYCS_PORT, SPYC_PATH)
# ifdef DRIVER_HAS_CALL_BY_REFERENCE
arg = ME;
query_ip_number(&arg);
// this assumes network byte order provided by driver
peerport = pointerp(arg) ? (arg[2]*256 + arg[3]) : 0;
if (peerport < 0) peerport = 65536 + peerport;
// no support for non-AF_INET nets yet
if (peerport == SPYC_SERVICE) peerport = 0;
# else
// as long as the object names don't collide, this is okay too
peerport = 65536 + random(9999999);
# endif
# ifdef DRIVER_HAS_RENAMED_CLONES
t = "S:spyc:"+query_ip_number();
// tcp peerports cannot be connected to, so we use minus
if (peerport) t += ":-"+peerport;
# else
t = clone_object(SPYC_PATH "server");
# endif
// the psyc backend distinguishes listen ports from peers using minus
D3(D(S("%O -> load(%O, %O)\n", t, query_ip_number(), -peerport));)
return t -> load(query_ip_number(), -peerport);
#endif
#if HAS_PORT(POP3S_PORT, POP3_PATH)
case POP3S_PORT:
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
return clone_object(POP3_PATH "server");
#endif
#if HAS_PORT(POP3_PORT, POP3_PATH)
case POP3_PORT:
return clone_object(POP3_PATH "server");
#endif
#if HAS_PORT(SMTPS_PORT, NNTP_PATH)
case SMTPS_PORT:
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
return clone_object(SMTP_PATH "server");
#endif
#if HAS_PORT(SMTP_PORT, SMTP_PATH)
case SMTP_PORT:
return clone_object(SMTP_PATH "server");
#endif
// heldensagas little http app
#if HAS_PORT(SHT_PORT, SHT_PATH)
case SHT_PORT:
return clone_object(SHT_PATH "server");
#endif
#if HAS_PORT(NNTPS_PORT, NNTP_PATH)
case NNTPS_PORT:
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
return clone_object(NNTP_PATH "server");
#endif
#if HAS_PORT(NNTP_PORT, NNTP_PATH)
case NNTP_PORT:
return clone_object(NNTP_PATH "server");
#endif
#if HAS_PORT(JABBERS_PORT, JABBER_PATH)
case JABBERS_PORT:
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
return clone_object(JABBER_PATH "server");
#endif
#if HAS_PORT(JABBER_PORT, JABBER_PATH)
case JABBER_PORT:
# if __EFUN_DEFINED__(enable_telnet)
enable_telnet(0); // are you sure!???
# endif
return clone_object(JABBER_PATH "server");
#endif
#if HAS_PORT(JABBER_S2S_PORT, JABBER_PATH)
case JABBER_S2S_PORT:
# ifdef DRIVER_HAS_CALL_BY_REFERENCE
arg = ME;
query_ip_number(&arg);
// this assumes network byte order provided by driver
peerport = pointerp(arg) ? (arg[2]*256 + arg[3]) : 0;
if (peerport < 0) peerport = 65536 + peerport;
if (peerport == JABBER_S2S_SERVICE) peerport = 0;
# else
// as long as the object names don't collide, this is okay too
peerport = 65536 + random(9999999);
# endif
# if __EFUN_DEFINED__(enable_telnet)
enable_telnet(0);
# endif
t = "S:xmpp:"+query_ip_number();
// it's just an object name, but let's be consequent minus peerport
if (peerport) t += ":-"+peerport;
# ifdef _flag_log_sockets_XMPP
SIMUL_EFUN_FILE -> log_file("RAW_XMPP", "\n\n%O: %O -> load(%O, %O)",
ME, t,
# ifdef _flag_log_hosts
query_ip_number(),
# else
"?",
# endif
-peerport);
# endif
P3(("%O -> load(%O, %O)\n", t, query_ip_number(), -peerport))
return t -> load(query_ip_number(), -peerport);
#endif
#if 0 //__EFUN_DEFINED__(enable_binary)
// work in progress
case 8888:
enable_binary();
enable_telnet(0);
return clone_object(NET_PATH "socks/protocol");
case 1935:
enable_binary();
enable_telnet(0);
return clone_object(NET_PATH "rtmp/protocol");
#endif
#if HAS_PORT(IRCS_PORT, IRC_PATH)
case IRCS_PORT:
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
return clone_object(IRC_PATH "server");
#endif
#if HAS_PORT(IRC_PORT, IRC_PATH)
case IRC_PORT:
# if 0 // __EFUN_DEFINED__(enable_telnet)
enable_telnet(0); // shouldn't harm.. but it does!!!
# endif
return clone_object(IRC_PATH "server");
#endif
#if HAS_PORT(APPLET_PORT, APPLET_PATH)
case APPLET_PORT:
# if __EFUN_DEFINED__(enable_telnet)
// enable_telnet(0);
# endif
return clone_object(APPLET_PATH "server");
#endif
#if HAS_PORT(TELNETS_PORT, TELNET_PATH)
case TELNETS_PORT:
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
// we could do the UID2NICK thing here, too, but why should we?
// what do you need tls for on a localhost tcp link?
return clone_object(TELNET_PATH "server");
#endif
#if HAS_PORT(TELNET_PORT, TELNET_PATH)
case TELNET_PORT:
// set_prompt("> ");
// we can't do the usual autodetect here, as telnet users
// don't send first and rather expect the server to prompt
// the correct way to do this: implement telnet nego for tls. bah!
t = clone_object(TELNET_PATH "server");
# ifdef UID2NICK
if (uid && (arg = UID2NICK(uid))) { t -> sName(arg); }
# endif
return t;
#endif
#if HAS_PORT(HTTPS_PORT, HTTP_PATH)
case HTTPS_PORT:
t = tls_init_connection(this_object());
if (t < 0) {
D1( if (t != ERR_TLS_NOT_DETECTED) PP(( "TLS(%O) on %O: %O\n",
t, query_mud_port(), tls_error(t) )); )
#if !HAS_PORT(HTTP_PORT, HTTP_PATH)
// if we have no http port, it may be intentional
return (object)0;
#endif
}
D2( else if (t > 0) PP(( "Setting up TLS connection in the background.\n" )); )
D2( else PP(( "Oh yeah, I'm initializing an https session!\n" )); )
return clone_object(HTTP_PATH "server");
#endif
/* don't fall thru. allow for https: to be available without http: */
#if HAS_PORT(HTTP_PORT, HTTP_PATH)
case HTTP_PORT:
return clone_object(HTTP_PATH "server");
#endif
#if HAS_PORT(MUDS_PORT, MUD_PATH)
case MUDS_PORT:
t = tls_init_connection(this_object());
if (t < 0 && t != ERR_TLS_NOT_DETECTED) PP(( "TLS on %O: %O\n",
query_mud_port(), tls_error(t) ));
return clone_object(MUD_PATH "login");
#endif
#if HAS_PORT(MUD_PORT, MUD_PATH)
default:
// if you want to multiplex psyced with an LPMUD game
// set_prompt("> ");
return clone_object(MUD_PATH "login");
#endif
}
PP(("Received connection on port %O which isn't configured.\n",
query_mud_port()));
return (object)0;
}
#ifdef DRIVER_HAS_RENAMED_CLONES
// named clones -lynx
object compile_object(string file) {
string path, name;
object rob;
# ifdef PSYC_PATH
if (abbrev("S:psyc:", file)) {
rob = clone_object(PSYC_PATH "server");
D2(if (rob) PP(("NAMED CLONE: %O => %s\n", rob, file));)
return rob;
}
if (abbrev("psyc:", file)) {
rob = clone_object(PSYC_PATH "active");
D2(if (rob) PP(("NAMED CLONE: %O => %s\n", rob, file));)
return rob;
}
# endif
# ifdef SPYC_PATH
if (abbrev("S:spyc:", file)) {
rob = clone_object(SPYC_PATH "server");
D2(if (rob) PP(("NAMED CLONE: %O => %s\n", rob, file));)
return rob;
}
if (abbrev("spyc:", file)) {
rob = clone_object(SPYC_PATH "active");
D2(if (rob) PP(("NAMED CLONE: %O => %s\n", rob, file));)
return rob;
}
# endif
# ifdef HTTP_PATH
// match both http:/ and https:/ objects ;D
if (abbrev("http", file)) {
rob = clone_object(HTTP_PATH "fetch");
if (rob) rob->fetch(file[..<3]);
return rob;
}
if (abbrev("xmlrpc:", file)) {
rob = clone_object(HTTP_PATH "xmlrpc");
if (rob) rob->fetch("http://" + file[7..<3]);
return rob;
}
# endif
if (sscanf(file, "%s#%s.c", path, name) && name != "") {
unless (name = SIMUL_EFUN_FILE->legal_name(name))
return (object)0;
rob = clone_object(path);
rob -> sName(name);
D2(if (rob) PP(("NAMED CLONE: %O becomes %s of %s\n",
rob, name, path));)
return rob;
}
if (sscanf(file, "place/%s.c", name) && name != "") {
#ifdef SANDBOX
string t;
#endif
unless (name = SIMUL_EFUN_FILE->legal_name(name))
return (object)0;
#ifdef SANDBOX
if (file_size(t = USER_PATH + name + ".c") != -1) {
rob = t -> sName(name);
D2(if (rob) PP(("USER PLACE loaded: %O becomes %O\n", rob, file));)
} else {
#endif
#ifdef _flag_disable_places_arbitrary
P2(("WARN: cloned places disabled by #define %O\n", file))
return (object)0;
#else
#ifdef _path_archetype_place_default
rob = clone_object(_path_archetype_place_default);
#else
rob = clone_object(NET_PATH "place/default");
#endif
rob -> sName(name);
D2(if (rob) PP(("PLACE CLONED: %O becomes %O\n", rob, file));)
#endif
#ifdef SANDBOX
}
#endif
return rob;
}
if (sscanf(file, "%s/text.c", path) && path != "") {
rob = clone_object(NET_PATH "text");
rob -> sPath(path);
D2(if (rob) PP(("DB CLONED: %O becomes %s/text\n", rob, path));)
return rob;
}
# ifdef JABBER_PATH
if (abbrev("S:xmpp:", file)) {
rob = clone_object(JABBER_PATH "gateway");
D2(if (rob) PP(("NAMED CLONE: %O => %s\n", rob, file));)
return rob;
}
if (abbrev("C:xmpp:", file)) {
rob = clone_object(JABBER_PATH "active");
D2(if (rob) PP(("NAMED CLONE: %O => %s\n", rob, file));)
return rob;
}
# endif
P3(("WARN: could not create %O\n", file))
return (object)0;
}
#endif

32
world/net/include/trust.h Normal file
View File

@ -0,0 +1,32 @@
// $Id: trust.h,v 1.2 2008/07/26 13:18:06 lynx Exp $ // vim:syntax=lpc:ts=8
//
#ifndef _INCLUDE_TRUST_H
#define _INCLUDE_TRUST_H
// all of these need new names to fit the tuning masterplan
#ifndef MAX_EXPOSE_GROUPS
# define MAX_EXPOSE_GROUPS 4 // just the top four ;)
#endif
#ifndef DEFAULT_EXPOSE_GROUPS // change this value in your local.h
# define DEFAULT_EXPOSE_GROUPS 4 // if you want groups to be exposed by
#endif // default like on irc
#ifndef MAX_EXPOSE_FRIENDS
# define MAX_EXPOSE_FRIENDS 8 // just the top eight ;)
#endif
#ifndef DEFAULT_EXPOSE_FRIENDS
# define DEFAULT_EXPOSE_FRIENDS 4 // do not expose yet, until we have
// profiles worth exposing for
#endif
#define TRUST_OVER_NOTIFY 3 // how much /trust counts more
// than notify. the normal value for
// a notify friendship is 8. if a
// medium trust is equivalent to
// that, 3 needs to be added to
// trust 5 to reach notify 8.
#define TRUST_MYSELF (9 + TRUST_OVER_NOTIFY)
// maximum trust
#ifndef EXPOSE_THRESHOLD
# define EXPOSE_THRESHOLD TRUST_MYSELF // at least show it to myself
#endif
#endif

239
world/net/spyc/dispatch.i Normal file
View File

@ -0,0 +1,239 @@
// included by TCP circuit *and* UDP daemon // vim:syntax=lpc
void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
string vname;
mixed vop; // value operation
string t;
mapping vars;
string family;
int glyph;
// check that method is a valid keyword
if (method && !legal_keyword(method)) {
DISPATCHERROR("non legal method");
}
#ifdef PSYC_TCP
// copy() + occasional double modifier ops should be more
// efficient than merge at every packet --lynX
// no one cares about "efficiency" here. please proof your
// bold statements with benchmarks anyway
vars = header_vars + instate;
#else
vars = header_vars;
#endif
// FIXME: this can happen earlier, e.g. in parse.c after
// process_header
// check _source/_context
// this check can be skipped if _source and _context are empty
if ((t = vars["_context"] || vars["_source"])) {
array(mixed) u;
unless (u = parse_uniform(t)) {
DISPATCHERROR("logical source is not an uniform\n")
}
#ifdef PSYC_TCP
unless (qAuthenticated(NAMEPREP(u[UHost]))) {
DISPATCHERROR("non-authenticated host\n")
}
#else
// TODO?
#endif
}
// check that _target is hosted by us
// this check can be skipped if _target is not set
if ((t = vars["_target"])) {
array(mixed) u;
unless (u = parse_uniform(t)) {
DISPATCHERROR("target is not an uniform\n")
}
// FIXME relaying support here?
if (!is_localhost(u[UHost])) {
DISPATCHERROR("target is not configured on this server\n")
}
}
// FIXME: i dont like this block... maybe we decode each variable
// when setting it?
// that would also fit with 0 as varname deletion
// below
foreach(vop : varops) {
vname = vop[0];
// psyc type conversion implementation ( http://about.psyc.eu/Type )
// this does not support register_type() yet, but it is feasible
PSYC_TRY(vname) {
case "_uniform":
case "_page":
case "_entity":
// TODO: check legal uniform
break;
case "_nick":
// TODO: check legal nick
break;
case "_degree":
// only honour the first digit
if (strlen(vop[2]) && vop[2][0] >= '0' && vop[2][0] <= '9')
vop[2] = vop[2][0] - '0';
else {
PT(("type parser _degree: could not handle value %O\n",
vop[2]))
vop[2] = 0;
}
break;
case "_time":
case "_amount":
vop[2] = to_int(vop[2]);
break;
case "_list":
mixed plist = list_parse(vop[2]);
if (plist == -1) {
DISPATCHERROR("could not parse list");
}
vop[2] = plist;
break;
PSYC_SLICE_AND_REPEAT
}
}
// FIXME deliver packet
// this should be a separate function
PT(("SPYC vars is %O\n", vars))
PT(("SPYC method %O\nbody %O\n", method, body))
// delivery rules as usual, but
if (vars["_context"]) {
mixed context;
mixed context_state;
mixed source, target;
if (vars["_source"]) {
P0(("invalid _context %O with _source %O\n",
context, vars["_source"]))
DISPATCHERROR("invalid usage of context with _source");
}
context = find_context(vars["_context"]);
if (!objectp(context)) {
P0(("context %O not found?!\n", vars["_context"]))
return;
}
context_state = context->get_state();
// apply varops to context state
foreach(vop : varops) {
vname = vop[0];
if (!legal_keyword(vname) || abbrev("_INTERNAL", vname)) {
DISPATCHERROR("illegal varname in psyc")
}
switch(vop[1]) { // the glyph
case C_GLYPH_MODIFIER_SET:
vars[vname] = vop[2];
break;
case C_GLYPH_MODIFIER_ASSIGN:
vars[vname] = context_state[vname] = vop[2];
break;
case C_GLYPH_MODIFIER_AUGMENT:
if (!abbrev("_list", vname)) {
DISPATCHERROR("psyc modifier + with non-list arg")
}
// FIXME: duplicates?
context_state[vname] += vop[2];
PT(("current state is %O, augment %O\n", context_state[vname], vop[2]))
break;
case C_GLYPH_MODIFIER_DIMINISH:
if (!abbrev("_list", vname)) {
DISPATCHERROR("psyc modifier + with non-list arg")
}
PT(("current state is %O, diminish %O\n", context_state[vname], vop[2]))
foreach(mixed item : vop[2])
context_state[vname] -= ({ item });
PT(("after dim: %O\n", context_state[vname]))
break;
case C_GLYPH_MODIFIER_QUERY:
DISPATCHERROR("psyc modifier ? not implemented")
break;
}
}
vars = vars + context_state;
// FIXME: is it legal to do this if this has _target?
// there should be no mods then anyway
context->commit_state(context_state);
if (vars["_target"]) {
// FIXME: delivery copycat from below
// beware: source is set to 0 here as it may not be present
target = find_psyc_object(parse_uniform(vars["_target"]));
PT(("target is %O\n", target))
// FIXME: net/entity can not yet deal with 0 method
//
if (objectp(context)) {
context->msg(0, method || "", body, vars, 0, target);
} else {
// FIXME: proper croak back to sender here
P0(("context %O for unicast to %O not found???\n", target))
}
} else {
if (vars["_source_relay"]) {
mixed localrelay;
if ((localrelay = psyc_object(vars["_source_relay"]))) {
P0(("local relay %O\n", localrelay))
vars["_source_relay"] = localrelay;
} else { // NORMALIZE UNIFORM
vars["_source_relay"] = lower_case(vars["_source_relay"]);
}
}
if (objectp(context)) {
// do we need more local object detection here?
context -> castmsg(source, method || "", body, vars);
} else {
// empty contexts are not bad currently
// in the current implementation it only means that no one
// interested in that context is online right now
// FIXME: lines above are about the old stuff where we did
// not have context state
}
}
} else {
if (!vars["_target"] && !vars["_source"]) {
#ifdef PSYC_TCP
circuit_msg(method, vars, body);
#else
P1(("Ignoring a rootMsg from UDP: %O,%O,%O\n", method, vars, body))
#endif
} else {
string source;
mixed target;
if (!vars["_source"]) {
// FIXME: where to set netloc in active
if (!netloc) { // set in sender after _request_features
// FIXME: this is wrong
DISPATCHERROR("Did you forget to request circuit features?");
}
source = netloc;
} else {
// FIXME: a macro NORMALIZE_UNIFORM that may do lower_case please
// not a simple lower_case
source = lower_case(vars["_source"]);
}
// source was checked either via x509 or dns before
// so it is 'safe' to do this
register_target(source);
// deliver FIXME same code above
if (!vars["_target"]) {
target = find_object(NET_PATH "root");
} else {
target = find_psyc_object(parse_uniform(vars["_target"]));
}
PT(("target is %O\n", target))
// FIXME: net/entity can not yet deal with 0 method
if (objectp(target))
target->msg(source, method || "", body, vars);
else {
// FIXME: proper croak back to sender here
P0(("target %O not found???\n", target))
}
}
}
::dispatch(header_vars, varops, method, body);
}