From b3a307095b1e5444563be1ffd12484d233463aa7 Mon Sep 17 00:00:00 2001
From: "psyc://psyced.org/~lynX" <@>
Date: Sat, 30 Jan 2010 23:39:47 +0100
Subject: [PATCH 1/3] handle dialback timeouts.. thx fip
---
CHANGESTODO | 13 +++++++++++++
world/default/de/plain.textdb | 3 +++
world/default/en/plain.textdb | 3 +++
world/net/jabber/active.c | 2 ++
4 files changed, 21 insertions(+)
diff --git a/CHANGESTODO b/CHANGESTODO
index 4273972..3226ab6 100644
--- a/CHANGESTODO
+++ b/CHANGESTODO
@@ -86,6 +86,15 @@ ________________________________________________________________________
? should /load inform that errors go to the console?
- the ~0 bug
+ i found a reliable way to reproduce this ~0 uni problem
+ - start psyced
+ - connect with a native psyc client
+ - kill psyced while the client is connected
+ - start psyced again
+ - connect with native psyc client
+ it will give you this ~0 uni then
+ until you connect with a telnet client
+ but it works again after you connect & disconnect w/ a telnet client
________________________________________________________________________
:_group psyc://psyced.org/@welcome
:_source_identification psyc://xxx.no-ip.org/~xxx
@@ -3976,3 +3985,7 @@ usercmd
be negative, like -5.
user
- psyc client _examine was falling thru to _HTML output, added return;
+=== 201001 ============================================================
+jabber/active
++ handle dialback timeouts, thx fip
+
diff --git a/world/default/de/plain.textdb b/world/default/de/plain.textdb
index f35a39d..e938f9c 100644
--- a/world/default/de/plain.textdb
+++ b/world/default/de/plain.textdb
@@ -843,6 +843,9 @@ _failure_unsuccessful_delivery_resolve
_failure_unsuccessful_delivery_self
|Die Adresse [_host] zeigt auf [_source_origin], ist dort aber nicht vorgesehen.
+_failure_unsuccessful_delivery_timeout_dialback
+|Konnte kein XMPP dialback zu [_host] herstellen um [_method_relay] an [_source] auszuliefern.
+
_failure_unavailable_service
|Solch ein Dienst wird hier derzeit nicht angeboten.
diff --git a/world/default/en/plain.textdb b/world/default/en/plain.textdb
index 1faa626..0d570fb 100644
--- a/world/default/en/plain.textdb
+++ b/world/default/en/plain.textdb
@@ -664,6 +664,9 @@ _failure_unsuccessful_delivery_resolve
_failure_unsuccessful_delivery_self
|The [_host] address points to [_source_origin] which however wasn't instructed to handle that.
+_failure_unsuccessful_delivery_timeout_dialback
+|Could not establish an XMPP dialback to [_host] to deliver a [_method_relay] to [_source].
+
_failure_unavailable_service_version
|Requesting version from [_nick_target] is not possible.
diff --git a/world/net/jabber/active.c b/world/net/jabber/active.c
index 0d3dea2..e28b068 100644
--- a/world/net/jabber/active.c
+++ b/world/net/jabber/active.c
@@ -72,6 +72,7 @@ start_dialback() {
dialback_outgoing = 1;
emit(sprintf("%s",
hostname, source_host, key));
+ call_out(120, #'connect_failure, "_timeout_dialback", "no dialback response received, timeout");
}
process_dialback_queue() {
@@ -364,6 +365,7 @@ jabberMsg(XMLNode node) {
* we are originating server and are informed of the result
*/
dialback_outgoing = 0;
+ remove_call_out(#'connect_failure);
if (node["@type"] == "valid") {
#ifdef LOG_XMPP_AUTH
D0( log_file("XMPP_AUTH", "\n%O auth dialback", ME); )
From 4084c8312b7a98a9fd04b9a09243881b3aae68f2 Mon Sep 17 00:00:00 2001
From: "psyc://psyced.org/~lynX" <@>
Date: Sun, 31 Jan 2010 06:27:33 +0100
Subject: [PATCH 2/3] outgoing mail queue for psyced
---
world/net/smtp/outgoing.c | 355 ++++++++++++++++++++++++++++++++++++++
world/net/smtp/user.c | 6 +
2 files changed, 361 insertions(+)
create mode 100644 world/net/smtp/outgoing.c
create mode 100644 world/net/smtp/user.c
diff --git a/world/net/smtp/outgoing.c b/world/net/smtp/outgoing.c
new file mode 100644
index 0000000..c297775
--- /dev/null
+++ b/world/net/smtp/outgoing.c
@@ -0,0 +1,355 @@
+// outgoing mail queue for psyced.
+
+// i *could* rewrite this to use net/spool.c
+// but then i'd have such a mess in my room
+
+#include
+#include
+virtual inherit NET_PATH "output";
+
+#define MAX_SPOOL 23
+#define SPOOL_FILE DATA_PATH "mail_queue"
+
+#if defined(DEBUG) && DEBUG > 1
+# define QUEUE_POLL_TIME 9
+# define COLLECT_TIME 15
+# define CONNECT_RETRY 99
+#else
+# define QUEUE_POLL_TIME 33
+# define COLLECT_TIME 60 * 2
+# define CONNECT_RETRY 60 * 7
+#endif
+
+#ifndef DEFAULT_MAIL_SENDER
+# define DEFAULT_MAIL_SENDER "psyc-daemon@" SERVER_HOST
+#endif
+#ifndef DEFAULT_MAIL_SENDER_NAME
+# define DEFAULT_MAIL_SENDER_NAME "PSYC server on " SERVER_HOST
+#endif
+#ifndef DEFAULT_MAIL_SUBJECT
+# define DEFAULT_MAIL_SUBJECT "Messages for [_target]"
+#endif
+
+#ifndef SMTP_RELAY
+# define SMTP_RELAY "127.0.0.1"
+#endif
+
+#define S_OFF 0
+#define S_CONN 101
+#define S_READY 102
+#define S_SOML 103
+#define S_FROM 104
+#define S_TO 105
+#define S_DATA 106
+#define S_MESS 107
+#define S_DONE 108
+
+#define FILE_FORMAT 0
+#define Q_SOURCE 0
+#define Q_METHOD 1
+#define Q_DATA 2
+#define Q_VARS 3
+#define Q_TARGET 4
+#define Q_URL_LOGIN 5
+//#define Q_SENDER 99
+
+mapping spool;
+int time_of_connect_attempt;
+int file_format;
+
+#ifdef Q_SENDER
+static string sndr;
+#else
+# define sndr DEFAULT_MAIL_SENDER
+#endif
+static string rcpt, target;
+static int state;
+
+#ifdef OFFLINE
+# define mwrite(TEXT) D(TEXT)
+#else
+# if defined(DEBUG) && DEBUG > 1
+mwrite(str) { log_file("SENDMAIL", str); emit(str); }
+# else
+# define mwrite(TEXT) emit(TEXT)
+# endif
+#endif
+
+reset(a) {
+// if (a) {
+#ifndef OFFLINE
+ P2(("RESET: saving mail queue into "+ SPOOL_FILE +"\n"))
+ save_object(SPOOL_FILE);
+#endif
+// return;
+// }
+}
+
+create() {
+ sTextPath (DEFAULT_LAYOUT, DEFLANG, "smtp");
+
+ unless (spool) {
+ restore_object(SPOOL_FILE);
+ if (file_format != FILE_FORMAT) spool = 0;
+ }
+ D2( if (spool) log_file("SENDMAIL", "*** Restored spool %O\n",
+ spool && m_indices(spool) ); )
+ file_format = FILE_FORMAT;
+ if (spool) qjack(1);
+}
+
+load() { return ME; }
+
+static connect() {
+#ifndef OFFLINE
+ if (interactive()) return 1;
+ // could this be using net/connect?
+ if (time() > time_of_connect_attempt + CONNECT_RETRY) {
+ int res;
+
+ time_of_connect_attempt = time();
+ save_object(SPOOL_FILE);
+ D1( D("SMTP: attempting connect to "+SMTP_RELAY+"\n"); )
+ if (res = net_connect(SMTP_RELAY, 25)) {
+ D0(D("SMTP connect error #"+ res
+ +" to " SMTP_RELAY ".\n");)
+ log_file("SENDMAIL", "*** No connect ("+res+") at "+
+ ctime(time())+"\n");
+ return 0;
+ }
+ state=S_CONN;
+ return 1;
+ }
+ return 0;
+#endif
+}
+
+// called from smtp_sendmsg()
+// this doesn't support the user's aliases, but doing so pretty
+// much means a major architectural change.. or a dirty ->aliasresolve()
+enqueue(target, method, data, vars, source, rcpt, urllogin) {
+ int i = 0;
+
+ // gets checked in /set and mailto:
+#ifdef BRAIN
+ // but we check again since brain has old user files
+ // with unchecked adresses
+ unless (rcpt = legal_mailto(rcpt)) return 0;
+#endif
+ PT(("smtp/enqueue: from %O to %O (%O)\n", source, target, rcpt))
+ unless (spool) {
+ spool = ([]);
+ call_out("qjack", COLLECT_TIME, 1);
+ }
+ if (spool[rcpt]) {
+ i = spool[rcpt][1]++;
+ if (i >= MAX_SPOOL) return 0;
+ spool[rcpt][i] = ({
+ source, method, data, vars, target, urllogin });
+ } else {
+ spool[rcpt] = allocate(MAX_SPOOL);
+ spool[rcpt][1] = 3;
+ if (objectp(target)) target = psyc_name(target);
+ spool[rcpt][2] = ({
+ source, method, data, vars, target, urllogin });
+ }
+ spool[rcpt][0] = COLLECT_TIME + time();
+ return connect();
+}
+
+qjack(arg) {
+ unless (spool) return;
+ if (arg) call_out("qjack", QUEUE_POLL_TIME, arg+1);
+
+#ifndef OFFLINE
+ unless (interactive()) return connect();
+ D2( D("jacking Q: "+ state + ", idle "+ query_idle(ME) + "\n"); )
+ unless (state == S_READY) return 0;
+#endif
+ foreach(rcpt : spool) {
+ if (spool[rcpt][0] < time()) {
+#ifdef OFFLINE
+ rendermsg(rcpt);
+ done();
+#else
+ target = spool[rcpt][2][Q_TARGET];
+// if (objectp(target)) target = psyc_name(target);
+# ifdef Q_SENDER
+ // do we want them to downgrade communication to email?
+ sndr = spool[rcpt][2][Q_SENDER];
+ unless (sndr) sndr = DEFAULT_MAIL_SENDER;
+# endif
+ mwrite("SOML FROM: <"+sndr+">\n");
+ state = S_SOML;
+#endif
+ return 1;
+ }
+ }
+ D2( D("nothing ready yet\n"); )
+}
+
+static done() {
+ unless (spool) return;
+ m_delete(spool, rcpt);
+ if (sizeof(spool) == 0) spool = 0;
+#ifndef OFFLINE
+ D2( save_object(SPOOL_FILE); )
+#endif
+}
+
+static abort(code, msg) {
+ done(); // we cannot risk to have this person block outgoing mail
+#ifdef PRO_PATH
+ sendmsg(query_monitor_unl(), "_error_transaction_mail_monitor",
+ "Received [_code_smtp] '[_text_smtp]' while delivering to [_recipient_mailto] ([_recipient]).", ([
+ "_code_smtp": code, "_text_smtp": msg,
+ "_recipient_mailto" : "mailto:"+rcpt,
+ "_recipient" : target ]) );
+#endif
+ mwrite("QUIT\n"); // restart mailer connection (not necessary?)
+ state=S_DONE;
+}
+
+parse(str) {
+ int code;
+ string msg;
+
+ input_to(#'parse);
+ if (str) {
+ D2( log_file("SENDMAIL", "« "+ str+"\n"); )
+ if (sscanf(str, "%d%t%s", code, msg) !=2)
+ sscanf(str, "%d",code);
+ }
+ if (!code) code=250; // is this smart?
+
+ switch(state) {
+ case S_CONN:
+ state=S_READY;
+ mwrite("HELO " SERVER_HOST "\n");
+ break;
+ case S_READY:
+ if (code!=250) abort(code, msg);
+ else qjack(0);
+ break;
+ case S_SOML:
+ if (code!=250) {
+ P3(("SOML to %O returns %s\n", query_ip_number(), str))
+ state = S_FROM;
+ mwrite("MAIL FROM: <"+sndr+">\n");
+ break;
+ }
+ // else we were successful, so let's fall thru
+ P0(("Yoohoo! %O is a mailer who understands SOML!\n",
+ query_ip_number()))
+ case S_FROM:
+ state=S_TO;
+ if (code!=250) abort(code, msg);
+ else mwrite("RCPT TO: <"+rcpt+">\n");
+ break;
+ case S_TO:
+ state=S_DATA;
+ if (code!=250) abort(code, msg);
+ else mwrite("DATA\n");
+ break;
+ case S_DATA:
+ state=S_MESS;
+ if (code!=354) abort(code, msg);
+ else rendermsg(rcpt);
+ break;
+ case S_MESS:
+ state=S_READY;
+ if (code!=250) abort(code, msg);
+ done();
+ break;
+ case S_DONE:
+ // 221 2.0.0 fly.symlynX.com closing connection
+ state=S_OFF;
+ break;
+ case S_OFF:
+ remove_interactive(ME);
+ D2(D("SMTP had to force connection close: "+str+"\n");)
+ break;
+ default:
+ D2(D("SMTP should not get here: "+state+"\n");)
+ }
+}
+
+w(string mc, string data, mapping vars, mixed source) {
+ string output, nick = 0;
+ string template = T(mc, "");
+
+ // source can be 0
+ if (stringp(source) && mappingp(vars)) nick = psyctext(
+ T("_MISC_identification_remote",
+ "<[_source]> [_nick]"), ([
+ "_source":source,
+ "_nick": (vars["_nick_verbatim"] || vars["_nick"])
+ ]));
+ output = psyctext( template, vars, data, source, nick );
+ P3(("SMTP:w(%O,%O,%O,%O) - %O\n", mc,data,vars,source, template))
+ if (template == "") output += abbrev("_prefix", mc) ? " " : "\n";
+ return output;
+}
+
+// TODO: to be formally correct all umlauts in the header would have to
+// be escaped with that ugly embedded encoding trick. do we care?
+rendermsg(rcpt) {
+ string m, t2;
+ int i, l, o, t;
+
+ mwrite("From: " DEFAULT_MAIL_SENDER " ("
+ DEFAULT_MAIL_SENDER_NAME ")\n");
+ l = spool[rcpt][1];
+ if (l > MAX_SPOOL) {
+ o = l - MAX_SPOOL;
+ mwrite("X-Amount-Messages-Omitted: "+ o +"\n");
+ l = MAX_SPOOL;
+ }
+ for (i=2; iqName()+"\n");
+//write("Reply-To: "+sndr+"."+lower_case(CHATNAME)+"@"+SMTP_RELAY+"\n");
+
+ if (o) m += w("_warning_omitted_messages",
+ "[_amount_messages_omitted] messages omitted.",
+ ([ "_amount_messages_omitted" : o ]) );
+#ifndef _flag_disable_mail_signature
+ m += "\n--\n"+ w( "_info_mail_signature", "Reply by E-Mail is not possible. Please log in:\n[_URL_login]",
+ ([ "_URL_login": (t2 || DEFAULT_URL_LOGIN) ]) ) + "\n";
+#endif
+ t2 = "Content-Type: text/plain; charset=" SYSTEM_CHARSET "\n"
+#ifndef SEND_FIRST_MSG_AS_SUBJECT
+ "Subject: "+ w("_info_mail_subject", DEFAULT_MAIL_SUBJECT,
+ ([ "_target": target || rcpt || ME ]) ) +
+#endif
+ "Content-Length: "+( strlen(m) )+"\n"
+ "\n"+ m +".\n";
+ mwrite(t2);
+}
+
+logon() { input_to(#'parse); }
+
diff --git a/world/net/smtp/user.c b/world/net/smtp/user.c
new file mode 100644
index 0000000..706d12f
--- /dev/null
+++ b/world/net/smtp/user.c
@@ -0,0 +1,6 @@
+#include
+#include
+
+qScheme() { return "smtp"; }
+
+// useless object for now
From 69c1a1e2f5f3fb02036e2196e680a63760a784ea Mon Sep 17 00:00:00 2001
From: "psyc://psyced.org/~lynX" <@>
Date: Sun, 31 Jan 2010 06:35:49 +0100
Subject: [PATCH 3/3] smtp_sendmsg()
---
world/net/library.i | 15 +++++++++++++++
world/net/smtp/outgoing.c | 9 +++++++--
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/world/net/library.i b/world/net/library.i
index a82aab0..89bfe40 100644
--- a/world/net/library.i
+++ b/world/net/library.i
@@ -621,6 +621,21 @@ int greater_user(object a, object b) { return file_name(a) > file_name(b); }
object* sorted_users() { return sort_array(users(), #'greater_user; }
#endif
+volatile mixed mailer;
+
+// simple SMTP interface.. used from person:logAppend - why target?
+// assumes that mailto: rcpt has already been checked with legal_mailto() !
+int smtp_sendmsg(string target, string method, string data,
+ mapping vars, string source, string rcpt, string loginurl) {
+#ifdef SMTP_PATH
+ unless (mailer) mailer = SMTP_PATH "outgoing" -> load();
+ return mailer -> enqueue(target, method, data, vars, source, rcpt,
+ loginurl);
+#else
+ return 0;
+#endif
+}
+
int xmpp_sendmsg(mixed target, string mc, mixed data, mapping vars,
mixed source, array(mixed) u, int showingLog, string otarget) {
string tmp;
diff --git a/world/net/smtp/outgoing.c b/world/net/smtp/outgoing.c
index c297775..e2c08c3 100644
--- a/world/net/smtp/outgoing.c
+++ b/world/net/smtp/outgoing.c
@@ -86,8 +86,11 @@ reset(a) {
}
create() {
+#ifdef DEFAULT_LAYOUT
sTextPath (DEFAULT_LAYOUT, DEFLANG, "smtp");
-
+#else
+ sTextPath (0, 0, "smtp");
+#endif
unless (spool) {
restore_object(SPOOL_FILE);
if (file_format != FILE_FORMAT) spool = 0;
@@ -337,9 +340,11 @@ rendermsg(rcpt) {
if (o) m += w("_warning_omitted_messages",
"[_amount_messages_omitted] messages omitted.",
([ "_amount_messages_omitted" : o ]) );
-#ifndef _flag_disable_mail_signature
+#ifdef DEFAULT_URL_LOGIN
+# ifndef _flag_disable_mail_signature
m += "\n--\n"+ w( "_info_mail_signature", "Reply by E-Mail is not possible. Please log in:\n[_URL_login]",
([ "_URL_login": (t2 || DEFAULT_URL_LOGIN) ]) ) + "\n";
+# endif
#endif
t2 = "Content-Type: text/plain; charset=" SYSTEM_CHARSET "\n"
#ifndef SEND_FIRST_MSG_AS_SUBJECT