@@ -17,6 +17,11 @@ import (
1717
1818const cERROR_PIPE_NOT_CONNECTED syscall.Errno = 233
1919
20+ const WSAECONNREFUSED syscall.Errno = 10061
21+ const WSAENETUNREACH syscall.Errno = 10051
22+ const WSAETIMEDOUT syscall.Errno = 10060
23+ const ERROR_CONNECTION_REFUSED syscall.Errno = 1225
24+
2025var (
2126 poll = flag .Bool ("p" , false , "poll until the the named pipe exists" )
2227 closeWrite = flag .Bool ("s" , false , "send a 0-byte message to the pipe after EOF on stdin" )
@@ -30,60 +35,46 @@ func dialPipe(p string, poll bool) (*overlappedFile, error) {
3035 if err != nil {
3136 return nil , err
3237 }
33- for {
34- h , err := windows .CreateFile (& p16 [0 ], windows .GENERIC_READ | windows .GENERIC_WRITE , 0 , nil , windows .OPEN_EXISTING , windows .FILE_FLAG_OVERLAPPED , 0 )
35- if err == nil {
36- return newOverlappedFile (h ), nil
37- }
38- if poll && os .IsNotExist (err ) {
39- time .Sleep (200 * time .Millisecond )
40- continue
41- }
42- return nil , & os.PathError {Path : p , Op : "open" , Err : err }
38+
39+ h , err := windows .CreateFile (& p16 [0 ], windows .GENERIC_READ | windows .GENERIC_WRITE , 0 , nil , windows .OPEN_EXISTING , windows .FILE_FLAG_OVERLAPPED , 0 )
40+ if err == nil {
41+ return newOverlappedFile (h ), nil
4342 }
43+
44+ return nil , err
4445}
4546
4647func dialPort (p int , poll bool ) (* overlappedFile , error ) {
4748 if p < 0 || p > 65535 {
4849 return nil , errors .New ("Invalid port value" )
4950 }
5051
51- for {
52- h , err := windows .Socket (windows .AF_INET , windows .SOCK_STREAM , 0 )
53- if err != nil {
54- return nil , err
55- }
56-
57- // Create a SockaddrInet4 for connecting to
58- sa := & windows.SockaddrInet4 {Addr : [4 ]byte {0x7F , 0x00 , 0x00 , 0x01 }, Port : p }
59- if err != nil {
60- return nil , err
61- }
62-
63- // Bind to a randomly assigned port
64- err = windows .Bind (h , & windows.SockaddrInet4 {})
65- if err != nil {
66- return nil , err
67- }
68-
69- conn := newOverlappedFile (h )
52+ h , err := windows .Socket (windows .AF_INET , windows .SOCK_STREAM , 0 )
53+ if err != nil {
54+ return nil , err
55+ }
7056
71- _ , err = conn .asyncIo (func (h windows.Handle , n * uint32 , o * windows.Overlapped ) error {
72- return windows .ConnectEx (h , sa , nil , 0 , nil , o )
73- })
74- err = os .NewSyscallError ("connectEx" , err )
57+ // Create a SockaddrInet4 for connecting to
58+ sa := & windows.SockaddrInet4 {Addr : [4 ]byte {0x7F , 0x00 , 0x00 , 0x01 }, Port : p }
7559
76- if err == nil {
77- return conn , nil
78- }
60+ // Bind to a randomly assigned local port
61+ err = windows .Bind (h , & windows.SockaddrInet4 {})
62+ if err != nil {
63+ return nil , err
64+ }
7965
80- if poll && os .IsNotExist (err ) {
81- time .Sleep (200 * time .Millisecond )
82- continue
83- }
66+ // Wrap our socket up to be properly handled
67+ conn := newOverlappedFile (h )
8468
85- return nil , err
69+ // Connect to the LibAssuan socket using overlapped ConnectEx operation
70+ _ , err = conn .asyncIo (func (h windows.Handle , n * uint32 , o * windows.Overlapped ) error {
71+ return windows .ConnectEx (h , sa , nil , 0 , nil , o )
72+ })
73+ if err == nil {
74+ return conn , nil
8675 }
76+
77+ return nil , err
8778}
8879
8980func underlyingError (err error ) error {
@@ -105,44 +96,73 @@ func main() {
10596 log .Println ("connecting to" , args [0 ])
10697 }
10798
108- conn , err := dialPipe (args [0 ], * poll )
109- if err != nil {
110- log .Fatalln (err )
111- }
99+ var conn * overlappedFile
100+ var err error
112101
113- if ! strings .HasPrefix ("//./" , args [0 ]) {
114- tmp := make ([]byte , 22 ) // 5 bytes for ascii port number, 1 for newline, 16 for nonce
102+ // Loop only if we're polling the named pipe or socket
103+ for {
104+ conn , err = dialPipe (args [0 ], * poll )
115105
116- var port int
117- nonce := make ([]byte , 16 )
106+ if * poll && os .IsNotExist (err ) {
107+ time .Sleep (200 * time .Millisecond )
108+ continue
109+ }
118110
119- // Check if file is a LibAssuane socket
120- _ , err := conn .Read (tmp )
121111 if err != nil {
122- log .Fatalln ("Could not open socket" , err )
112+ err = & os.PathError {Path : args [0 ], Op : "open" , Err : err }
113+ log .Fatalln (err )
123114 }
124115
125- for i , c := range tmp {
126- // Find the new line
127- if c == 0x0A {
128- port , _ = strconv .Atoi (string (tmp [:i ]))
129- copy (nonce , tmp [i + 1 :])
116+ // Not a named pipe, so attempt to read contents and connect to a TCP port for LibAssaaun
117+ if ! strings .HasPrefix ("//./" , args [0 ]) {
118+ tmp := make ([]byte , 22 ) // 5 bytes for ascii port number, 1 for newline, 16 for nonce
119+
120+ var port int
121+ var nonce [16 ]byte
122+
123+ _ , err := conn .Read (tmp )
124+ if err != nil {
125+ log .Fatalln ("Could not open file" , err )
126+ }
127+
128+ for i , c := range tmp {
129+ // Find the new line
130+ if c == 0x0A {
131+ port , err = strconv .Atoi (string (tmp [:i ]))
132+ if err != nil {
133+ log .Fatalln (err )
134+ }
135+
136+ copy (nonce [:], tmp [i + 1 :])
130137
131- if * verbose {
132- log .Printf ("Port: %d, Nonce: %X" , port , nonce )
138+ if * verbose {
139+ log .Printf ("Port: %d, Nonce: %X" , port , nonce )
140+ }
141+ break
133142 }
134- break
135143 }
136- }
137144
138- _ = conn .Close ()
145+ _ = conn .Close ()
139146
140- conn , err = dialPort (port , * poll )
147+ conn , err = dialPort (port , * poll )
141148
142- _ , err = conn .Write (nonce )
143- if err != nil {
144- log .Fatal (err )
149+ if * poll && (err == WSAETIMEDOUT || err == WSAECONNREFUSED || err == WSAENETUNREACH || err == ERROR_CONNECTION_REFUSED ) {
150+ time .Sleep (200 * time .Millisecond )
151+ continue
152+ }
153+
154+ err = os .NewSyscallError ("ConnectEx" , err )
155+
156+ if err != nil {
157+ log .Fatal (err )
158+ }
159+
160+ _ , err = conn .Write (nonce [:])
161+ if err != nil {
162+ log .Fatal (err )
163+ }
145164 }
165+ break
146166 }
147167
148168 if * verbose {
0 commit comments