Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision 55b1e690c595ac6b027cf4bd1465c6676214bb50)
+++ protocols/msn/msn.c	(revision efbc154f93aeee89877378e8433a035f0a8febb2)
@@ -38,4 +38,5 @@
 	set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc );
 	set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc );
+	set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc );
 }
 
Index: protocols/msn/msn.h
===================================================================
--- protocols/msn/msn.h	(revision 55b1e690c595ac6b027cf4bd1465c6676214bb50)
+++ protocols/msn/msn.h	(revision efbc154f93aeee89877378e8433a035f0a8febb2)
@@ -31,4 +31,5 @@
 #define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r"
 #define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r"
+#define SB_KEEPALIVE_MESSAGE "\r\r\rDONT HANG UP ON ME!\r\r\r"
 
 #ifdef DEBUG_MSN
@@ -53,4 +54,8 @@
                            "TypingUser: %s\r\n" \
                            "\r\n\r\n"
+
+#define SB_KEEPALIVE_HEADERS "MIME-Version: 1.0\r\n" \
+                             "Content-Type: text/x-ping\r\n" \
+                             "\r\n\r\n"
 
 #define PROFILE_URL "http://members.msn.com/"
@@ -83,4 +88,5 @@
 	gint inp;
 	struct msn_handler_data *handler;
+	gint keepalive;
 	
 	int trId;
@@ -180,4 +186,6 @@
 gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond );
 int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m );
+void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial );
+void msn_sb_stop_keepalives( struct msn_switchboard *sb );
 
 #endif //_MSN_H
Index: protocols/msn/ns.c
===================================================================
--- protocols/msn/ns.c	(revision 55b1e690c595ac6b027cf4bd1465c6676214bb50)
+++ protocols/msn/ns.c	(revision efbc154f93aeee89877378e8433a035f0a8febb2)
@@ -422,6 +422,10 @@
 	else if( strcmp( cmd[0], "FLN" ) == 0 )
 	{
-		if( cmd[1] )
-			imcb_buddy_status( ic, cmd[1], 0, NULL, NULL );
+		if( cmd[1] == NULL )
+			return 1;
+		
+		imcb_buddy_status( ic, cmd[1], 0, NULL, NULL );
+		
+		msn_sb_start_keepalives( msn_sb_by_handle( ic, cmd[1] ), TRUE );
 	}
 	else if( strcmp( cmd[0], "NLN" ) == 0 )
@@ -449,4 +453,6 @@
 		                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),
 		                   st->name, NULL );
+		
+		msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) );
 	}
 	else if( strcmp( cmd[0], "RNG" ) == 0 )
Index: protocols/msn/sb.c
===================================================================
--- protocols/msn/sb.c	(revision 55b1e690c595ac6b027cf4bd1465c6676214bb50)
+++ protocols/msn/sb.c	(revision efbc154f93aeee89877378e8433a035f0a8febb2)
@@ -168,5 +168,16 @@
 		
 		/* Build the message. Convert LF to CR-LF for normal messages. */
-		if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) != 0 )
+		if( strcmp( text, TYPING_NOTIFICATION_MESSAGE ) == 0 )
+		{
+			i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
+			buf = g_new0( char, i );
+			i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
+		}
+		else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 )
+		{
+			buf = g_strdup( SB_KEEPALIVE_HEADERS );
+			i = strlen( buf );
+		}
+		else
 		{
 			buf = g_new0( char, sizeof( MSN_MESSAGE_HEADERS ) + strlen( text ) * 2 + 1 );
@@ -182,10 +193,4 @@
 			}
 		}
-		else
-		{
-			i = strlen( MSN_TYPING_HEADERS ) + strlen( sb->ic->acc->user );
-			buf = g_new0( char, i );
-			i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );
-		}
 		
 		/* Build the final packet (MSG command + the message). */
@@ -250,4 +255,5 @@
 	
 	msn_msgq_purge( ic, &sb->msgq );
+	msn_sb_stop_keepalives( sb );
 	
 	if( sb->key ) g_free( sb->key );
@@ -471,4 +477,6 @@
 		
 		sb->ready = 1;
+		
+		msn_sb_start_keepalives( sb, FALSE );
 	}
 	else if( strcmp( cmd[0], "CAL" ) == 0 )
@@ -520,4 +528,6 @@
 			}
 			
+			msn_sb_start_keepalives( sb, FALSE );
+			
 			return( st );
 		}
@@ -581,4 +591,6 @@
 		if( sb->who )
 		{
+			msn_sb_stop_keepalives( sb );
+			
 			/* This is a single-person chat, and the other person is leaving. */
 			g_free( sb->who );
@@ -764,2 +776,32 @@
 	return( 1 );
 }
+
+static gboolean msn_sb_keepalive( gpointer data, gint source, b_input_condition cond )
+{
+	struct msn_switchboard *sb = data;
+	return sb->ready && msn_sb_sendmessage( sb, SB_KEEPALIVE_MESSAGE );
+}
+
+void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial )
+{
+	struct buddy *b;
+	
+	if( sb && sb->who && sb->keepalive == 0 &&
+	    ( b = imcb_find_buddy( sb->ic, sb->who ) ) && !b->present &&
+	    set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) )
+	{
+		if( initial )
+			msn_sb_keepalive( sb, 0, 0 );
+		
+		sb->keepalive = b_timeout_add( 20000, msn_sb_keepalive, sb );
+	}
+}
+
+void msn_sb_stop_keepalives( struct msn_switchboard *sb )
+{
+	if( sb && sb->keepalive > 0 )
+	{
+		b_event_remove( sb->keepalive );
+		sb->keepalive = 0;
+	}
+}
