@@ -21,6 +21,7 @@ import (
2121 "github.com/yomorun/yomo/pkg/frame-codec/y3codec"
2222 yquic "github.com/yomorun/yomo/pkg/listener/quic"
2323 pkgtls "github.com/yomorun/yomo/pkg/tls"
24+ "github.com/yomorun/yomo/pkg/version"
2425 oteltrace "go.opentelemetry.io/otel/trace"
2526)
2627
@@ -152,7 +153,22 @@ func (s *Server) Serve(ctx context.Context, conn net.PacketConn) error {
152153 }
153154}
154155
155- func (s * Server ) handshake (fconn frame.Conn ) (bool , router.Route , * Connection ) {
156+ func (s * Server ) handleFrameConn (fconn frame.Conn , logger * slog.Logger ) {
157+ route , conn , err := s .handshake (fconn )
158+ if err != nil {
159+ logger .Error ("handshake failed" , "err" , err )
160+ return
161+ }
162+
163+ s .connHandler (conn , route ) // s.handleConnRoute(conn, route) with middlewares
164+
165+ if conn .ClientType () == ClientTypeStreamFunction {
166+ _ = route .Remove (conn .ID ())
167+ }
168+ _ = s .connector .Remove (conn .ID ())
169+ }
170+
171+ func (s * Server ) handshake (fconn frame.Conn ) (router.Route , * Connection , error ) {
156172 var gerr error
157173
158174 defer func () {
@@ -166,7 +182,7 @@ func (s *Server) handshake(fconn frame.Conn) (bool, router.Route, *Connection) {
166182 first , err := fconn .ReadFrame ()
167183 if err != nil {
168184 gerr = err
169- return false , nil , nil
185+ return nil , nil , gerr
170186 }
171187 switch first .Type () {
172188 case frame .TypeHandshakeFrame :
@@ -175,17 +191,17 @@ func (s *Server) handshake(fconn frame.Conn) (bool, router.Route, *Connection) {
175191 conn , err := s .handleHandshakeFrame (fconn , hf )
176192 if err != nil {
177193 gerr = err
178- return false , nil , conn
194+ return nil , conn , gerr
179195 }
180196
181197 route , err := s .addSfnToRoute (hf , conn .Metadata ())
182198 if err != nil {
183199 gerr = err
184200 }
185- return true , route , conn
201+ return route , conn , gerr
186202 default :
187203 gerr = fmt .Errorf ("yomo: handshake read unexpected frame, read: %s" , first .Type ().String ())
188- return false , nil , nil
204+ return nil , nil , gerr
189205 }
190206}
191207
@@ -216,22 +232,8 @@ func (s *Server) handleConnRoute(conn *Connection, route router.Route) {
216232 }
217233}
218234
219- func (s * Server ) handleFrameConn (fconn frame.Conn , logger * slog.Logger ) {
220- ok , route , conn := s .handshake (fconn )
221- if ! ok {
222- logger .Error ("handshake failed" )
223- return
224- }
225-
226- s .connHandler (conn , route ) // s.handleConnRoute(conn, route) with middlewares
227-
228- if conn .ClientType () == ClientTypeStreamFunction {
229- _ = route .Remove (conn .ID ())
230- }
231- _ = s .connector .Remove (conn .ID ())
232- }
233-
234235func (s * Server ) handleHandshakeFrame (fconn frame.Conn , hf * frame.HandshakeFrame ) (* Connection , error ) {
236+ // 1. authentication
235237 md , ok := auth .Authenticate (s .opts .auths , hf )
236238
237239 if ! ok {
@@ -243,6 +245,11 @@ func (s *Server) handleHandshakeFrame(fconn frame.Conn, hf *frame.HandshakeFrame
243245 return nil , fmt .Errorf ("authentication failed: client credential type is %s" , hf .AuthName )
244246 }
245247
248+ // 2. version negotiation
249+ if err := negotiateVersion (hf .Version , Version ); err != nil {
250+ return nil , err
251+ }
252+
246253 conn := newConnection (hf .Name , hf .ID , ClientType (hf .ClientType ), md , hf .ObserveDataTags , fconn , s .logger )
247254
248255 return conn , s .connector .Store (hf .ID , conn )
@@ -263,6 +270,25 @@ func (s *Server) addSfnToRoute(hf *frame.HandshakeFrame, md metadata.M) (router.
263270 return route , nil
264271}
265272
273+ func negotiateVersion (cVersion , sVersion string ) error {
274+ cv , err := version .Parse (cVersion )
275+ if err != nil {
276+ return err
277+ }
278+
279+ sv , err := version .Parse (sVersion )
280+ if err != nil {
281+ return err
282+ }
283+
284+ // If the Major and Minor versions are equal, the server can serve the client.
285+ if cv .Major == sv .Major && cv .Minor == sv .Minor {
286+ return nil
287+ }
288+
289+ return fmt .Errorf ("yomo: version negotiation failed, client=%s, server=%s" , cVersion , sVersion )
290+ }
291+
266292func (s * Server ) handleFrame (c * Context ) {
267293 // routing data frame.
268294 if err := s .routingDataFrame (c ); err != nil {
0 commit comments