diff --git a/lib/modules/Protocols.pmod/LysKOM.pmod/ASync.pmod b/lib/modules/Protocols.pmod/LysKOM.pmod/ASync.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..6062d4e66c1589b372d313a54248530206188fe5
--- /dev/null
+++ b/lib/modules/Protocols.pmod/LysKOM.pmod/ASync.pmod
@@ -0,0 +1,126 @@
+import .ProtocolTypes;
+
+/* 0 async-new-text-old */
+array decode_0(array what)
+{
+   return ({ (int) what[0], 
+	     TextStatOld(@what[1..]) });
+}
+
+/* 5 async-new-name */
+array decode_5(array what)
+{
+   return ({ (int) what[0], 
+	     what[1],
+	     what[2] });
+}
+
+/* 6 async-i-am-on */
+array decode_6(array what)
+{
+   return ({ WhoInfo(@what) });
+}
+
+/* 7 async-sync-db */
+array decode_7(array what)
+{
+   return ({ });
+}
+
+/* 8 async-leave-conf */
+array decode_8(array what)
+{
+   return ({ (int)what[0] });
+}
+
+/* 9 async-login */
+array decode_9(array what)
+{
+   return ({ (int)what[0],
+             (int)what[1] });
+}
+
+/* 10 async-broadcast */
+array decode_10(array what)
+{
+   return ({ (int)what[0],
+             what[1] });
+}
+
+/* 11 async-rejected-connection */
+array decode_11(array what)
+{
+   return ({ });
+}
+
+/* 12 async-send-message */
+array decode_12(array what)
+{
+   return ({ (int)what[0],
+	     (int)what[1],
+             what[2] });
+}
+
+/* 13 async-async-logout */
+array decode_13(array what)
+{
+   return ({ (int)what[0],
+             (int)what[1] });
+}
+
+/* 14 async-deleted-text */
+array decode_14(array what)
+{
+   return ({ (int)what[0],
+             TextStat(@what[1..]) });
+}
+
+/* 15 async-new-text */
+array decode_15(array what)
+{
+   return ({ (int)what[0],
+             TextStat(@what[1..]) });
+}
+
+/* 16 async-new-recipient */
+array decode_16(array what)
+{
+   return ({ (int)what[0],
+	     (int)what[1],
+             (array(int))what[3] });
+}
+
+/* 17 async-sub-recipient */
+array decode_17(array what)
+{
+   return ({ (int)what[0],
+	     (int)what[1],
+             (array(int))what[3] });
+}
+
+/* 18 async-new-membership */
+array decode_18(array what)
+{
+   return ({ (int)what[0],
+	     (int)what[1] });
+}
+
+mapping name2no=
+([
+   "async-async-logout":13,
+   "async-broadcast":10,
+   "async-deleted-text":14,
+   "async-deleted-text":14,
+   "async-i-am-on":6,
+   "async-leave-conf":8,
+   "async-login":9,
+   "async-new-membership":18,
+   "async-new-name":5,
+   "async-new-recipient":16,
+   "async-new-text":15,
+   "async-new-text-old":0,
+   "async-rejected-connection":11,
+   "async-send-message":12,
+   "async-sub-recipient":17,
+   "async-sync-db":7,
+]);
diff --git a/lib/modules/Protocols.pmod/LysKOM.pmod/Helper.pmod b/lib/modules/Protocols.pmod/LysKOM.pmod/Helper.pmod
index cca32b8e11c423f2ca6fe34f287d09212b785d8b..68370fb8a2889f46ae65a714e8d4b5f7c4996790 100644
--- a/lib/modules/Protocols.pmod/LysKOM.pmod/Helper.pmod
+++ b/lib/modules/Protocols.pmod/LysKOM.pmod/Helper.pmod
@@ -56,6 +56,7 @@ class LysKOMError
 	 case 0: return "Protocols.LysKOM: ["+no+"] "+name+"\n";
 	 case 1: return __backtrace;
       }
+      return ::`[](z);
    }
 }
 
diff --git a/lib/modules/Protocols.pmod/LysKOM.pmod/Raw.pike b/lib/modules/Protocols.pmod/LysKOM.pmod/Raw.pike
index acc1932591d500bc9d5e7b0e916f3910b73ef7da..9740d2e735000d63b1ff1b3572031caf369afb65 100644
--- a/lib/modules/Protocols.pmod/LysKOM.pmod/Raw.pike
+++ b/lib/modules/Protocols.pmod/LysKOM.pmod/Raw.pike
@@ -31,7 +31,7 @@ mapping(int:function(string:void)) async=([]);
 int ref=1;
 
 /* asynchronous messages callback list */
-mapping(int:function(string:void)) async_callbacks=([]);
+mapping(int:array(function(string:void))) async_callbacks=([]);
 
 /* max number of outstanding requests */
 int max_out_req=4;
@@ -347,11 +347,6 @@ void create(string server,void|int port,void|string whoami)
    return;
 }
 
-void set_async_callbacks(mapping(int:function(string:void)) m)
-{
-   async_callbacks=m;
-}
-
 array(array(mixed)|int) try_parse(string what)
 {
    array res=({});
@@ -473,10 +468,6 @@ array(array(mixed)|int) try_parse(string what)
    return ({0,0}); // incomplete
 }
 
-void got_async_message(array what)
-{
-   // werror("got async: %O\n",what);
-}
 
 void got_reply(int ref,object|array what)
 {
@@ -499,3 +490,41 @@ void delete_async(int ref)
 {
    m_delete(async,ref);
 }
+
+void add_async_callback(string which, function what, int dont_update)
+{
+   int no=.ASync.name2no[which];
+   
+   if (!no && zero_type(.ASync.name2no[which]))
+      throw(LysKOMError( -1,"LysKOM: unsupported async",
+			 sprintf("There is no supported async call named %O",
+				 which) ));
+
+   if (!async_callbacks[no]) async_callbacks[no]=({what});
+   else async_callbacks[no]+=({what});
+}
+
+void remove_async_callback(string which, function what, void|int dont_update)
+{
+   int no=.ASync.name2no[which];
+   
+   if (!no && zero_type(.ASync.name2no[which]))
+      throw(LysKOMError( -1,"LysKOM: unsupported async",
+			 sprintf("There is no supported async call named %O",
+				 which) ));
+
+   async_callbacks[no]-=({what});
+}
+
+array active_asyncs()
+{
+   foreach (indices(async_callbacks),int z)
+      if (async_callbacks[z]==({})) m_delete(async_callbacks,z);
+   return indices(async_callbacks);
+}
+
+void got_async_message(array what)
+{
+   if (async_callbacks[(int)what[1]])
+      async_callbacks[(int)what[1]](@.ASync["decode_"+what[1]](what[2..]));
+}
diff --git a/lib/modules/Protocols.pmod/LysKOM.pmod/Request.pmod b/lib/modules/Protocols.pmod/LysKOM.pmod/Request.pmod
index 2044f0308f704dfccfa87a674417901b697518f7..0eb2ec86be5ade6d36d9bde0e523c3bf9d0b6e9e 100644
--- a/lib/modules/Protocols.pmod/LysKOM.pmod/Request.pmod
+++ b/lib/modules/Protocols.pmod/LysKOM.pmod/Request.pmod
@@ -1,4 +1,4 @@
-//  $Id: Request.pmod,v 1.3 1999/07/19 13:46:45 mirar Exp $
+//  $Id: Request.pmod,v 1.4 1999/07/19 16:03:51 mirar Exp $
 //! module Protocols
 //! submodule LysKOM
 //! submodule Request
@@ -261,9 +261,9 @@ class Create_person_old
                H(passwd)});
    }
 
-   string reply(array what)
+   int reply(array what)
    {
-      return what[0]; /* HOLLERITH */
+      return (int)what[0]; /* Pers-no */
    }
 
    void failure(object error)
diff --git a/lib/modules/Protocols.pmod/LysKOM.pmod/Session.pike b/lib/modules/Protocols.pmod/LysKOM.pmod/Session.pike
index 4423cf555ab51f866ce06a7cca176a21f93b151d..23ebf0f966c8b303d1fa8d06ba0738ad4513c5c3 100644
--- a/lib/modules/Protocols.pmod/LysKOM.pmod/Session.pike
+++ b/lib/modules/Protocols.pmod/LysKOM.pmod/Session.pike
@@ -1,4 +1,4 @@
-//  $Id: Session.pike,v 1.5 1999/07/04 08:18:39 hubbe Exp $
+//  $Id: Session.pike,v 1.6 1999/07/19 16:03:54 mirar Exp $
 //! module Protocols
 //! submodule LysKOM
 //! class Session
@@ -16,7 +16,7 @@ object user; // logged in as this Person
 
 string server;
 
-int protlevel; // level <10 protocol
+int protlevel; // protocol level
 
 mapping(int:object) _text=([]);
 mapping(int:object) _person=([]);
@@ -30,6 +30,7 @@ mapping(int:object) _conference=([]);
 //!	options is a mapping of options,
 //!	<data_description type=mapping>
 //!	<elem name=login type="int|string">login as this person number<br>(get number from name)</elem>
+//!	<elem name=create type="string"><br>create a new person and login with it</elem>
 //!	<elem name=password type=string>send this login password</elem>
 //!	<elem name=invisible type="int(0..1)">if set, login invisible</elem>
 //!	<elem>advanced</elem>
@@ -56,9 +57,72 @@ void create(object|string _server,void|mapping options)
    con=Connection(_server,options);
    user=(options && options->login)?person(options->login):0;
    protlevel=con->protocol_level;
-   werror("protocol_level is %d\n",protlevel);
+
+   /* setup async stuff */
+   con->con->add_async_callback("async-new-name",async_new_name);
+   con->con->add_async_callback("async-leave-conf",async_leave_conf);
+
+   if (protlevel>=10)
+   {
+      con->con->add_async_callback("async-deleted-text",async_deleted_text);
+      con->con->add_async_callback("async-new-text",async_new_text);
+      con->con->add_async_callback("async-new-recipient",async_new_recipient);
+      con->con->add_async_callback("async-sub-recipient",async_sub_recipient);
+      con->con->add_async_callback("async-new-membership",
+				   async_new_membership);
+   }
+   else
+   {
+      con->con->add_async_callback("async-new-text-old",async_new_text_old);
+   }
+
+   con->accept_async(con->con->active_asyncs());
+
+   /* create person if wanted */
+
+   if (options->create)
+      create_person(options->create,options->password);
 }
 
+/** async callbacks from raw session **/
+
+void async_new_name()
+{
+}
+
+void async_leave_conf()
+{
+}
+
+void async_deleted_text()
+{
+}
+
+void async_new_text()
+{
+}
+
+void async_new_recipient(int textno,int confno,array misc)
+{
+   if (_text[textno]) _text[textno]->update_misc(MiscInfo(misc));
+   // if (_conference[confno]) _conference[confno]->new_texts();
+}
+
+void async_sub_recipient(int textno,int confno,array misc)
+{
+   if (_text[textno]) _text[textno]->update_misc(MiscInfo(misc));
+   // if (_conference[confno]) _conference[confno]->sub_text(textno);
+}
+
+void async_new_membership()
+{
+}
+
+void async_new_text_old()
+{
+}
+
+/** classes *********************/
 
 class MiscInfo
 {
@@ -316,6 +380,11 @@ class Text
    FETCHERC2b(stat,object,_stat,get_text_stat,@({no}),
 	      (_misc=MiscInfo(res->misc_info),res))
 
+   void update_misc(MiscInfo m)
+   {
+      _misc=m;
+   }
+
    mixed `[](string what)
    {
       switch (what)
@@ -578,26 +647,39 @@ array(ProtocolTypes.ConfZInfo) try_complete_person(string orig)
    return con->lookup_z_name(orig,1,0);
 }
 
-//! method login(int user_no,string password)
-//! method login(int user_no,string password,int invisible)
+//! method object login(int user_no,string password)
+//! method object login(int user_no,string password,int invisible)
 //!	Performs a login. Returns 1 on success or throws a lyskom error.
+//! returns the called object
 
-int(1..1) login(int user_no,string password,
-		void|int invisible)
+object login(int user_no,string password,
+	     void|int invisible)
 {
    con->login(user_no,password,invisible);
    user=person(user_no);
-   return 1;
+   return this_object();
+}
+
+//! method object create_person(string name,string password)
+//!	Create a person, which will be logged in.
+//! returns the new person object
+
+object create_person(string name,string password)
+{
+   if (!stringp(name)||!stringp(password))
+      error("bad types to create_person call\n");
+   return user=person(con->create_person_old(name,password));
 }
 
-//! method logout()
+//! method object logout()
 //!	Logouts from the server.
+//! returns the called object
 
-int(1..1) logout()
+object logout()
 {
    if (con) 
       con->logout();
-   return 1;
+   return this_object();
 }
 
 //! method object create_text(string subject,string body,mapping options)