github.com/amitbet/vnc2video@v0.0.0-20190616012314-9d50b9dab1d9/handlers.go (about)

     1  package vnc2video
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"github.com/amitbet/vnc2video/logger"
     7  )
     8  
     9  // Handler represents handler of handshake
    10  type Handler interface {
    11  	Handle(Conn) error
    12  }
    13  
    14  // ProtoVersionLength protocol version length
    15  const ProtoVersionLength = 12
    16  
    17  const (
    18  	// ProtoVersionUnknown unknown version
    19  	ProtoVersionUnknown = ""
    20  	// ProtoVersion33 sets if proto 003.003
    21  	ProtoVersion33 = "RFB 003.003\n"
    22  	// ProtoVersion38 sets if proto 003.008
    23  	ProtoVersion38 = "RFB 003.008\n"
    24  	// ProtoVersion37 sets if proto 003.007
    25  	ProtoVersion37 = "RFB 003.007\n"
    26  )
    27  
    28  // ParseProtoVersion parse protocol version
    29  func ParseProtoVersion(pv []byte) (uint, uint, error) {
    30  	var major, minor uint
    31  
    32  	if len(pv) < ProtoVersionLength {
    33  		return 0, 0, fmt.Errorf("ProtocolVersion message too short (%v < %v)", len(pv), ProtoVersionLength)
    34  	}
    35  
    36  	l, err := fmt.Sscanf(string(pv), "RFB %d.%d\n", &major, &minor)
    37  	if l != 2 {
    38  		return 0, 0, fmt.Errorf("error parsing protocol version")
    39  	}
    40  	if err != nil {
    41  		return 0, 0, err
    42  	}
    43  
    44  	return major, minor, nil
    45  }
    46  
    47  // DefaultClientVersionHandler represents default handler
    48  type DefaultClientVersionHandler struct{}
    49  
    50  // Handle provide version handler for client side
    51  func (*DefaultClientVersionHandler) Handle(c Conn) error {
    52  	var version [ProtoVersionLength]byte
    53  
    54  	if err := binary.Read(c, binary.BigEndian, &version); err != nil {
    55  		return err
    56  	}
    57  
    58  	major, minor, err := ParseProtoVersion(version[:])
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	pv := ProtoVersionUnknown
    64  	if major == 3 {
    65  		if minor >= 8 {
    66  			pv = ProtoVersion38
    67  		} else if minor >= 3 {
    68  			pv = ProtoVersion38
    69  		}
    70  	}
    71  	if pv == ProtoVersionUnknown {
    72  		return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
    73  	}
    74  	c.SetProtoVersion(string(version[:]))
    75  
    76  	if err := binary.Write(c, binary.BigEndian, []byte(pv)); err != nil {
    77  		return err
    78  	}
    79  	return c.Flush()
    80  }
    81  
    82  // DefaultServerVersionHandler represents default server handler
    83  type DefaultServerVersionHandler struct{}
    84  
    85  // Handle provide server version handler
    86  func (*DefaultServerVersionHandler) Handle(c Conn) error {
    87  	var version [ProtoVersionLength]byte
    88  	if err := binary.Write(c, binary.BigEndian, []byte(ProtoVersion38)); err != nil {
    89  		return err
    90  	}
    91  	if err := c.Flush(); err != nil {
    92  		return err
    93  	}
    94  	if err := binary.Read(c, binary.BigEndian, &version); err != nil {
    95  		return err
    96  	}
    97  	major, minor, err := ParseProtoVersion(version[:])
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	pv := ProtoVersionUnknown
   103  	if major == 3 {
   104  		if minor >= 8 {
   105  			pv = ProtoVersion38
   106  		} else if minor >= 3 {
   107  			pv = ProtoVersion33
   108  		}
   109  	}
   110  	if pv == ProtoVersionUnknown {
   111  		return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
   112  	}
   113  
   114  	c.SetProtoVersion(pv)
   115  	return nil
   116  }
   117  
   118  // DefaultClientSecurityHandler used for client security handler
   119  type DefaultClientSecurityHandler struct{}
   120  
   121  // Handle provide client side security handler
   122  func (*DefaultClientSecurityHandler) Handle(c Conn) error {
   123  	cfg := c.Config().(*ClientConfig)
   124  	var numSecurityTypes uint8
   125  	if err := binary.Read(c, binary.BigEndian, &numSecurityTypes); err != nil {
   126  		return err
   127  	}
   128  	secTypes := make([]SecurityType, numSecurityTypes)
   129  	if err := binary.Read(c, binary.BigEndian, &secTypes); err != nil {
   130  		return err
   131  	}
   132  
   133  	var secType SecurityHandler
   134  	for _, st := range cfg.SecurityHandlers {
   135  		for _, sc := range secTypes {
   136  			if st.Type() == sc {
   137  				secType = st
   138  			}
   139  		}
   140  	}
   141  
   142  	if err := binary.Write(c, binary.BigEndian, cfg.SecurityHandlers[0].Type()); err != nil {
   143  		return err
   144  	}
   145  
   146  	if err := c.Flush(); err != nil {
   147  		return err
   148  	}
   149  
   150  	err := secType.Auth(c)
   151  	if err != nil {
   152  		logger.Error("Authentication error: ", err)
   153  		return err
   154  	}
   155  
   156  	var authCode uint32
   157  	if err := binary.Read(c, binary.BigEndian, &authCode); err != nil {
   158  		return err
   159  	}
   160  
   161  	logger.Tracef("authenticating, secType: %d, auth code(0=success): %d", secType.Type(), authCode)
   162  	if authCode == 1 {
   163  		var reasonLength uint32
   164  		if err := binary.Read(c, binary.BigEndian, &reasonLength); err != nil {
   165  			return err
   166  		}
   167  		reasonText := make([]byte, reasonLength)
   168  		if err := binary.Read(c, binary.BigEndian, &reasonText); err != nil {
   169  			return err
   170  		}
   171  		return fmt.Errorf("%s", reasonText)
   172  	}
   173  	c.SetSecurityHandler(secType)
   174  	return nil
   175  }
   176  
   177  // DefaultServerSecurityHandler used for server security handler
   178  type DefaultServerSecurityHandler struct{}
   179  
   180  // Handle provide server side security handler
   181  func (*DefaultServerSecurityHandler) Handle(c Conn) error {
   182  	cfg := c.Config().(*ServerConfig)
   183  	var secType SecurityType
   184  	if c.Protocol() == ProtoVersion37 || c.Protocol() == ProtoVersion38 {
   185  		if err := binary.Write(c, binary.BigEndian, uint8(len(cfg.SecurityHandlers))); err != nil {
   186  			return err
   187  		}
   188  
   189  		for _, sectype := range cfg.SecurityHandlers {
   190  			if err := binary.Write(c, binary.BigEndian, sectype.Type()); err != nil {
   191  				return err
   192  			}
   193  		}
   194  	} else {
   195  		st := uint32(0)
   196  		for _, sectype := range cfg.SecurityHandlers {
   197  			if uint32(sectype.Type()) > st {
   198  				st = uint32(sectype.Type())
   199  				secType = sectype.Type()
   200  			}
   201  		}
   202  		if err := binary.Write(c, binary.BigEndian, st); err != nil {
   203  			return err
   204  		}
   205  	}
   206  	if err := c.Flush(); err != nil {
   207  		return err
   208  	}
   209  
   210  	if c.Protocol() == ProtoVersion38 {
   211  		if err := binary.Read(c, binary.BigEndian, &secType); err != nil {
   212  			return err
   213  		}
   214  	}
   215  	secTypes := make(map[SecurityType]SecurityHandler)
   216  	for _, sType := range cfg.SecurityHandlers {
   217  		secTypes[sType.Type()] = sType
   218  	}
   219  
   220  	sType, ok := secTypes[secType]
   221  	if !ok {
   222  		return fmt.Errorf("security type %d not implemented", secType)
   223  	}
   224  
   225  	var authCode uint32
   226  	authErr := sType.Auth(c)
   227  	if authErr != nil {
   228  		authCode = uint32(1)
   229  	}
   230  
   231  	if err := binary.Write(c, binary.BigEndian, authCode); err != nil {
   232  		return err
   233  	}
   234  
   235  	if authErr == nil {
   236  		if err := c.Flush(); err != nil {
   237  			return err
   238  		}
   239  		c.SetSecurityHandler(sType)
   240  		return nil
   241  	}
   242  
   243  	if c.Protocol() == ProtoVersion38 {
   244  		if err := binary.Write(c, binary.BigEndian, uint32(len(authErr.Error()))); err != nil {
   245  			return err
   246  		}
   247  		if err := binary.Write(c, binary.BigEndian, []byte(authErr.Error())); err != nil {
   248  			return err
   249  		}
   250  		if err := c.Flush(); err != nil {
   251  			return err
   252  		}
   253  	}
   254  	return authErr
   255  }
   256  
   257  // DefaultClientServerInitHandler default client server init handler
   258  type DefaultClientServerInitHandler struct{}
   259  
   260  // Handle provide default server init handler
   261  func (*DefaultClientServerInitHandler) Handle(c Conn) error {
   262  	logger.Trace("starting DefaultClientServerInitHandler")
   263  	var err error
   264  	srvInit := ServerInit{}
   265  
   266  	if err = binary.Read(c, binary.BigEndian, &srvInit.FBWidth); err != nil {
   267  		return err
   268  	}
   269  	if err = binary.Read(c, binary.BigEndian, &srvInit.FBHeight); err != nil {
   270  		return err
   271  	}
   272  	if err = binary.Read(c, binary.BigEndian, &srvInit.PixelFormat); err != nil {
   273  		return err
   274  	}
   275  	if err = binary.Read(c, binary.BigEndian, &srvInit.NameLength); err != nil {
   276  		return err
   277  	}
   278  
   279  	srvInit.NameText = make([]byte, srvInit.NameLength)
   280  	if err = binary.Read(c, binary.BigEndian, &srvInit.NameText); err != nil {
   281  		return err
   282  	}
   283  	logger.Tracef("DefaultClientServerInitHandler got serverInit: %v", srvInit)
   284  	c.SetDesktopName(srvInit.NameText)
   285  	if c.Protocol() == "aten1" {
   286  		c.SetWidth(800)
   287  		c.SetHeight(600)
   288  		c.SetPixelFormat(NewPixelFormatAten())
   289  	} else {
   290  		c.SetWidth(srvInit.FBWidth)
   291  		c.SetHeight(srvInit.FBHeight)
   292  
   293  		//telling the server to use 32bit pixels (with 24 dept, tight standard format)
   294  		pixelMsg := SetPixelFormat{PF: PixelFormat32bit}
   295  		pixelMsg.Write(c)
   296  		c.SetPixelFormat(PixelFormat32bit)
   297  		//c.SetPixelFormat(srvInit.PixelFormat)
   298  	}
   299  	if c.Protocol() == "aten1" {
   300  		ikvm := struct {
   301  			_               [8]byte
   302  			IKVMVideoEnable uint8
   303  			IKVMKMEnable    uint8
   304  			IKVMKickEnable  uint8
   305  			VUSBEnable      uint8
   306  		}{}
   307  		if err = binary.Read(c, binary.BigEndian, &ikvm); err != nil {
   308  			return err
   309  		}
   310  	}
   311  	/*
   312  		caps := struct {
   313  			ServerMessagesNum uint16
   314  			ClientMessagesNum uint16
   315  			EncodingsNum      uint16
   316  			_                 [2]byte
   317  		}{}
   318  		if err := binary.Read(c, binary.BigEndian, &caps); err != nil {
   319  			return err
   320  		}
   321  
   322  		caps.ServerMessagesNum = uint16(1)
   323  		var item [16]byte
   324  		for i := uint16(0); i < caps.ServerMessagesNum; i++ {
   325  			if err := binary.Read(c, binary.BigEndian, &item); err != nil {
   326  				return err
   327  			}
   328  			fmt.Printf("server message cap %s\n", item)
   329  		}
   330  
   331  			for i := uint16(0); i < caps.ClientMessagesNum; i++ {
   332  				if err := binary.Read(c, binary.BigEndian, &item); err != nil {
   333  					return err
   334  				}
   335  				fmt.Printf("client message cap %s\n", item)
   336  			}
   337  			for i := uint16(0); i < caps.EncodingsNum; i++ {
   338  				if err := binary.Read(c, binary.BigEndian, &item); err != nil {
   339  					return err
   340  				}
   341  				fmt.Printf("encoding cap %s\n", item)
   342  			}
   343  		//	var pad [1]byte
   344  		//	if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
   345  		//		return err
   346  		//	}
   347  	}*/
   348  	return nil
   349  }
   350  
   351  // DefaultServerServerInitHandler default server server init handler
   352  type DefaultServerServerInitHandler struct{}
   353  
   354  // Handle provide default server server init handler
   355  func (*DefaultServerServerInitHandler) Handle(c Conn) error {
   356  	if err := binary.Write(c, binary.BigEndian, c.Width()); err != nil {
   357  		return err
   358  	}
   359  	if err := binary.Write(c, binary.BigEndian, c.Height()); err != nil {
   360  		return err
   361  	}
   362  	if err := binary.Write(c, binary.BigEndian, c.PixelFormat()); err != nil {
   363  		return err
   364  	}
   365  	if err := binary.Write(c, binary.BigEndian, uint32(len(c.DesktopName()))); err != nil {
   366  		return err
   367  	}
   368  	if err := binary.Write(c, binary.BigEndian, []byte(c.DesktopName())); err != nil {
   369  		return err
   370  	}
   371  	return c.Flush()
   372  }
   373  
   374  // DefaultClientClientInitHandler default client client init handler
   375  type DefaultClientClientInitHandler struct{}
   376  
   377  // Handle provide default client client init handler
   378  func (*DefaultClientClientInitHandler) Handle(c Conn) error {
   379  	logger.Trace("starting DefaultClientClientInitHandler")
   380  	cfg := c.Config().(*ClientConfig)
   381  	var shared uint8
   382  	if cfg.Exclusive {
   383  		shared = 0
   384  	} else {
   385  		shared = 1
   386  	}
   387  	if err := binary.Write(c, binary.BigEndian, shared); err != nil {
   388  		return err
   389  	}
   390  	logger.Tracef("DefaultClientClientInitHandler sending: shared=%d", shared)
   391  	return c.Flush()
   392  }
   393  
   394  // DefaultServerClientInitHandler default server client init handler
   395  type DefaultServerClientInitHandler struct{}
   396  
   397  // Handle provide default server client init handler
   398  func (*DefaultServerClientInitHandler) Handle(c Conn) error {
   399  	var shared uint8
   400  	if err := binary.Read(c, binary.BigEndian, &shared); err != nil {
   401  		return err
   402  	}
   403  	/* TODO
   404  	if shared != 1 {
   405  		c.SetShared(false)
   406  	}
   407  	*/
   408  	return nil
   409  }