11using System ;
2+ using System . IO ;
23using System . Net ;
34using System . Net . Sockets ;
45using System . Runtime . InteropServices ;
@@ -79,7 +80,7 @@ struct COPYDATASTRUCT
7980 static readonly IntPtr AGENT_COPYDATA_ID = new IntPtr ( 0x804e50ba ) ;
8081
8182 // Send ssh-agent query to Pageant, ssh-agent and Pageant use same messages
82- static byte [ ] Query ( byte [ ] buf )
83+ static byte [ ] Query ( byte [ ] buf , int buflen )
8384 {
8485 var hwnd = FindWindowByCaption ( IntPtr . Zero , "Pageant" ) ;
8586
@@ -89,17 +90,17 @@ static byte[] Query(byte[] buf)
8990
9091 var sharedMemory = MapViewOfFile ( fileMap , FileMapAccess . FileMapWrite , 0 , 0 , UIntPtr . Zero ) ;
9192
92- Marshal . Copy ( buf , 0 , sharedMemory , buf . Length ) ;
93+ Marshal . Copy ( buf , 0 , sharedMemory , buflen ) ;
9394
9495 var cds = new COPYDATASTRUCT ( ) ;
9596 cds . dwData = AGENT_COPYDATA_ID ;
9697 cds . cbData = mapName . Length + 1 ;
97- var foo = Encoding . UTF8 . GetBytes ( mapName ) ;
98- var bar = new byte [ foo . Length + 1 ] ;
99- foo . CopyTo ( bar , 0 ) ;
100- bar [ bar . Length - 1 ] = 0 ;
101- var gch = GCHandle . Alloc ( bar ) ;
102- cds . lpData = Marshal . UnsafeAddrOfPinnedArrayElement ( bar , 0 ) ;
98+ var mapNameBytes = Encoding . UTF8 . GetBytes ( mapName ) ;
99+ var mapNameBytesZero = new byte [ mapNameBytes . Length + 1 ] ;
100+ mapNameBytes . CopyTo ( mapNameBytesZero , 0 ) ;
101+ mapNameBytesZero [ mapNameBytesZero . Length - 1 ] = 0 ;
102+ var gch = GCHandle . Alloc ( mapNameBytesZero ) ;
103+ cds . lpData = Marshal . UnsafeAddrOfPinnedArrayElement ( mapNameBytesZero , 0 ) ;
103104 var data = Marshal . AllocHGlobal ( Marshal . SizeOf ( cds ) ) ;
104105 Marshal . StructureToPtr ( cds , data , false ) ;
105106 var rcode = SendMessage ( hwnd , WM_COPYDATA , IntPtr . Zero , data ) ;
@@ -117,21 +118,98 @@ static byte[] Query(byte[] buf)
117118 return ret ;
118119 }
119120
121+ private static void Callback ( Task < Socket > t , object state )
122+ {
123+ var client = t . Result ;
124+ client . ReceiveTimeout = 1000 ;
125+ client . SendTimeout = 1000 ;
126+
127+ try
128+ {
129+ ServiceSocket ( client ) ;
130+ }
131+ catch ( TimeoutException )
132+ {
133+ // Ignore timeouts, those should not explode our stuff
134+ }
135+ catch ( SocketException e )
136+ {
137+ // Other socket errors can happen and shouldn't kill the app
138+ Console . Error . WriteLine ( e ) ;
139+ }
140+
141+ client . Dispose ( ) ;
142+ }
143+
144+ private static bool ReadUntil ( Socket client , byte [ ] buf , int buflen , int offset = 0 )
145+ {
146+ int i ;
147+ while ( ( i = client . Receive ( buf , offset , buflen - offset , SocketFlags . None ) ) != 0 )
148+ {
149+ offset += i ;
150+ if ( offset >= buflen )
151+ {
152+ return true ;
153+ }
154+ }
155+ return false ;
156+ }
157+
158+ private static void ServiceSocket ( Socket client )
159+ {
160+ var lenBytes = new byte [ 4 ] ; // uint32
161+
162+ while ( true )
163+ {
164+ // Read length as uint32 (4 bytes)
165+ if ( ! ReadUntil ( client , lenBytes , lenBytes . Length ) )
166+ {
167+ break ;
168+ }
169+ var len = ( lenBytes [ 0 ] << 24 ) |
170+ ( lenBytes [ 1 ] << 16 ) |
171+ ( lenBytes [ 2 ] << 8 ) |
172+ ( lenBytes [ 3 ] ) ;
173+
174+ // Read actual data and copy length to the start of it
175+ var bytes = new byte [ 4 + len ] ;
176+ lenBytes . CopyTo ( bytes , 0 ) ;
177+ if ( ! ReadUntil ( client , bytes , bytes . Length , 4 ) )
178+ {
179+ break ;
180+ }
181+
182+ var msg = Query ( bytes , bytes . Length ) ;
183+ client . Send ( msg , 0 , msg . Length , SocketFlags . None ) ;
184+ }
185+ }
186+
120187 static void Main ( string [ ] args )
121188 {
122- var outstream = Console . OpenStandardOutput ( ) ;
123- var instream = Console . OpenStandardInput ( ) ;
189+ var socketPath = @".\ssh-agent.sock" ;
124190
125- int i ;
191+ if ( args . Length == 1 )
192+ socketPath = args [ 0 ] ;
193+ else if ( args . Length != 0 )
194+ {
195+ Console . WriteLine ( @"wsl-ssh-agent.exe <path: .\ssh-agent.sock>" ) ;
196+ return ;
197+ }
198+
199+ File . Delete ( socketPath ) ;
200+ var server = new Socket ( AddressFamily . Unix , SocketType . Stream , ProtocolType . IP ) ;
201+ server . Bind ( new UnixEndPoint ( socketPath ) ) ;
202+ server . Listen ( 5 ) ;
126203
127- // Buffer for reading data
128- var bytes = new Byte [ AGENT_MAX_MSGLEN ] ;
204+ Console . WriteLine ( @"Listening on {0}" , socketPath ) ;
129205
130- // Loop to receive all the data sent by the client .
131- while ( ( i = instream . Read ( bytes , 0 , bytes . Length ) ) != 0 )
206+ // Enter the listening loop .
207+ while ( true )
132208 {
133- var msg = Query ( bytes ) ;
134- outstream . Write ( msg , 0 , msg . Length ) ;
209+ var t = server . AcceptAsync ( ) ;
210+ t . ContinueWith ( Callback , null ) ;
211+ t . Wait ( ) ;
135212 }
136213 }
137214}
215+
0 commit comments