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