shithub: rd

Download patch

ref: b71205289556e1c0baa4e68d46846c52ab675a1a
parent: 0beacde9afd629a61994d1eac8a084ddc4f357f7
author: Yaroslav Kolomiiets <yarikos@gmail.com>
date: Fri Mar 25 09:18:54 EDT 2016

fix freeze on connection to an existing session on 2008 server

--- a/dat.h
+++ b/dat.h
@@ -225,10 +225,10 @@
 
 void	activating(Rdp*,Share*);
 void	deactivating(Rdp*,Share*);
+void	finalhandshake(Rdp*);
 void	scanimgupdate(Rdp*,Share*);
 void	scancmap(Rdp*,Share*);
 void	scanorders(Rdp*,Share*);
-
 
 struct Imgupd {
 	int	x;
--- a/mcs.c
+++ b/mcs.c
@@ -325,7 +325,7 @@
 	PLONG(p+16, 0x409);	// keyboardLayout=us
 	PLONG(p+20, 2600); 	// clientBuild
 	memset(p+24, 32, 0);	// clientName[32]
-	toutf16(p+24, 32, sysname, strlen(sysname));	
+	toutf16(p+24, 32, sysname, strlen(sysname)+1);
 	PSHORT(p+54, 0);		// zero-terminateclientName
 	PLONG(p+56, 4);	// keyboardType: 4="IBM enhanced (101-key or 102-key)"
 	PLONG(p+60, 0);	// keyboardSubType
--- a/rd.c
+++ b/rd.c
@@ -224,7 +224,7 @@
 readnet(Rdp* c)
 {
 	Msg r;
-	
+
 	for(;;){
 		if(readmsg(c, &r) <= 0)
 			return;
@@ -238,6 +238,11 @@
 		case Aupdate:
 			scanupdates(c, &r);
 			break;
+		case 0:
+			fprint(2, "unsupported PDU\n");
+			break;
+		default:
+			fprint(2, "r.type %d is not expected\n", r.type);
 		}
 	}
 }
@@ -258,9 +263,16 @@
 			sysfatal("scanupdates: %r");
 
 		switch(u.type){
+		default:
+			if(u.type != 0)
+				fprint(2, "scanupdates: unhandled %d\n", u.type);
+			break;
 		case ShDeactivate:
 			deactivating(c, &u);
 			break;
+		case ShActivate:	// server may engage capability re-exchange
+			activating(c, &u);
+			break;
 		case ShEinfo:
 			c->hupreason = u.err;
 			break;
@@ -276,45 +288,10 @@
 		case ShUwarp:
 			warpmouse(u.x, u.y);
 			break;
+		case Aflow:
+			break;
 		}
 	}
-}
-
-/* 2.2.1.13.1 Server Demand Active PDU */
-void
-activating(Rdp* c, Share* as)
-{
-	Caps rcaps;
-
-	if(getcaps(&rcaps, as->data, as->ndata) < 0)
-		sysfatal("getcaps: %r");
-	if(!rcaps.canrefresh)
-		sysfatal("server can not Refresh Rect PDU");
-	if(!rcaps.cansupress)
-		sysfatal("server can not Suppress Output PDU");
-	if(!rcaps.bitmap)
-		sysfatal("server concealed their Bitmap Capabilities");
-
-	switch(rcaps.depth){
-	default:	sysfatal("Unsupported server color depth: %uhd\n", rcaps.depth);
-	case 8:	c->chan = CMAP8; break;
-	case 15:	c->chan = RGB15; break;
-	case 16:	c->chan = RGB16; break;
-	case 24:	c->chan = RGB24; break;
-	case 32:	c->chan = XRGB32; break;
-	}
-	c->depth = rcaps.depth;
-	c->xsz = rcaps.xsz;
-	c->ysz = rcaps.ysz;
-	c->srvchan = as->source;
-	c->shareid = as->shareid;
-	c->active = 1;
-}
-
-void
-deactivating(Rdp* c, Share*)
-{
-	c->active = 0;
 }
 
 /* 2.2.9.1.1.3.1.2.1 Bitmap Update Data (TS_UPDATE_BITMAP_DATA) */
--- a/rpc.c
+++ b/rpc.c
@@ -158,7 +158,6 @@
 		case Mclosing:
 			werrstr("Disconnect Provider Ultimatum");
 			return -1;
-		case Aflow:
 		case Ldone:
 			break;
 		case Lneedlicense:
@@ -169,27 +168,97 @@
 			if(r.getshare(&u, r.data, r.ndata) < 0)
 				return -1;
 			switch(u.type){
-			case ShEinfo:
+			default:
+				fprint(2, "handshake: unhandled %d\n", u.type);
+				break;
+			case ShEinfo:	/* do we really expect this here? */
 				c->hupreason = u.err;
 				break;
 			case ShActivate:
 				activating(c, &u);
-				confirmactive(c);
-				passinput(c, 0, InputSync, 0, 0, 0);
-				assync(c);
-				asctl(c, CAcooperate);
-				asctl(c, CAreqctl);
-				asfontls(c);
+				return 0;
+			}
+		}
+	}
+}
+
+/* 2.2.1.13.1 Server Demand Active PDU */
+void
+activating(Rdp* c, Share* as)
+{
+	Caps rcaps;
+
+	if(getcaps(&rcaps, as->data, as->ndata) < 0)
+		sysfatal("getcaps: %r");
+	if(!rcaps.canrefresh)
+		sysfatal("server can not Refresh Rect PDU");
+	if(!rcaps.cansupress)
+		sysfatal("server can not Suppress Output PDU");
+	if(!rcaps.bitmap)
+		sysfatal("server concealed their Bitmap Capabilities");
+
+	switch(rcaps.depth){
+	default:	sysfatal("Unsupported server color depth: %uhd\n", rcaps.depth);
+	case 8:	c->chan = CMAP8; break;
+	case 15:	c->chan = RGB15; break;
+	case 16:	c->chan = RGB16; break;
+	case 24:	c->chan = RGB24; break;
+	case 32:	c->chan = XRGB32; break;
+	}
+	c->depth = rcaps.depth;
+	c->xsz = rcaps.xsz;
+	c->ysz = rcaps.ysz;
+	c->srvchan = as->source;
+	c->shareid = as->shareid;
+	c->active = 1;
+
+	confirmactive(c);
+	finalhandshake(c);
+
+	passinput(c, 0, InputSync, 0, 0, 0);
+}
+
+void
+deactivating(Rdp* c, Share*)
+{
+	c->active = 0;
+}
+
+void
+finalhandshake(Rdp* c)
+{
+	Msg r;
+	Share u;
+
+	assync(c);
+	asctl(c, CAcooperate);
+	asctl(c, CAreqctl);
+	asfontls(c);
+
+	for(;;){
+		if(readmsg(c, &r) <= 0)
+			sysfatal("activating: readmsg: %r");
+		switch(r.type){
+		default:
+			fprint(2, "activating: unhandled PDU type %d\n", u.type);
+			break;
+		case Mclosing:
+			fprint(2, "disconnecting early");
+			return;
+		case Aupdate:
+			if(r.getshare(&u, r.data, r.ndata) < 0)
+				sysfatal("activating: r.getshare: %r");
+			switch(u.type){
+			default:
+				fprint(2, "activating: unhandled ASPDU type %d\n", u.type);
 				break;
-			case ShDeactivate:
-				deactivating(c, &u);
-				break;
 			case ShSync:
 			case ShCtl:
+				/* responses to the assync(). asctl() calls above */
 				break;
 			case ShFmap:
-				return 0;
-				break;
+				/* finalized - we're good */
+				return;
 			}
 		}
 	}