1414package vm
1515
1616import (
17+ "bufio"
1718 "context"
1819 "fmt"
1920 "net"
21+ "strings"
2022 "time"
2123
2224 "github.com/mdlayher/vsock"
@@ -184,14 +186,6 @@ func vsockConnectMsg(port uint32) string {
184186 return fmt .Sprintf ("CONNECT %d\n " , port )
185187}
186188
187- func vsockAckMsg (port uint32 ) string {
188- // The message a guest-side connection will write after accepting a connection from
189- // a host dial. This is not part of the official Firecracker vsock spec, but is
190- // recommended in order to allow the host to verify connections were established
191- // successfully: https://github.com/firecracker-microvm/firecracker/issues/1272#issuecomment-533004066
192- return fmt .Sprintf ("IMALIVE %d\n " , port )
193- }
194-
195189// tryConnect attempts to dial a guest vsock listener at the provided host-side
196190// unix socket and provided guest-listener port.
197191func tryConnect (logger * logrus.Entry , udsPath string , port uint32 ) (net.Conn , error ) {
@@ -215,10 +209,18 @@ func tryConnect(logger *logrus.Entry, udsPath string, port uint32) (net.Conn, er
215209 return nil , vsockConnectMsgError {cause : err }
216210 }
217211
218- err = tryConnRead (conn , vsockAckMsg ( port ) , vsockAckMsgTimeout )
212+ line , err := tryConnReadUntil (conn , '\n' , vsockAckMsgTimeout )
219213 if err != nil {
220214 return nil , vsockAckError {cause : err }
221215 }
216+
217+ // The line would be "OK <assigned_hostside_port>\n", but we don't use the hostside port here.
218+ // https://github.com/firecracker-microvm/firecracker/blob/master/docs/vsock.md#host-initiated-connections
219+ if ! strings .HasPrefix (line , "OK " ) {
220+ return nil , vsockAckError {
221+ cause : errors .Errorf (`expected to read "OK <port>", but instead read %q` , line ),
222+ }
223+ }
222224 return conn , nil
223225}
224226
@@ -240,35 +242,19 @@ func tryAccept(logger *logrus.Entry, listener net.Listener, port uint32) (net.Co
240242 }
241243 }()
242244
243- err = tryConnWrite (conn , vsockAckMsg (port ), vsockAckMsgTimeout )
244- if err != nil {
245- return nil , vsockAckError {cause : err }
246- }
247-
248245 return conn , nil
249246}
250247
251- // tryConnRead will try to do a read from the provided conn, returning an error if
252- // the bytes read does not match what was provided or if the read does not complete
248+ // tryConnReadUntil will try to do a read from the provided conn until the specified
249+ // end character is encounteed. Returning an error if the read does not complete
253250// within the provided timeout. It will reset socket deadlines to none after returning.
254251// It's only intended to be used for connect/ack messages, not general purpose reads
255252// after the vsock connection is established fully.
256- func tryConnRead (conn net.Conn , expectedRead string , timeout time.Duration ) error {
253+ func tryConnReadUntil (conn net.Conn , end byte , timeout time.Duration ) ( string , error ) {
257254 conn .SetDeadline (time .Now ().Add (timeout ))
258255 defer conn .SetDeadline (time.Time {})
259256
260- actualRead := make ([]byte , len (expectedRead ))
261- _ , err := conn .Read (actualRead )
262- if err != nil {
263- return err
264- }
265-
266- if expectedRead != string (actualRead ) {
267- return errors .Errorf ("expected to read %q, but instead read %q" ,
268- expectedRead , string (actualRead ))
269- }
270-
271- return nil
257+ return bufio .NewReaderSize (conn , 32 ).ReadString (end )
272258}
273259
274260// tryConnWrite will try to do a write to the provided conn, returning an error if
0 commit comments