1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -12,3 +12,4 @@ | |||||||
|  |  | ||||||
| # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 | ||||||
| .glide/ | .glide/ | ||||||
|  | examples/examples | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								channeltype_string.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								channeltype_string.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | // Code generated by "stringer -type=ChannelType"; DO NOT EDIT. | ||||||
|  |  | ||||||
|  | package spice | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  |  | ||||||
|  | const _ChannelType_name = "RedChannelMainRedChannelDisplayRedChannelInputsRedChannelCursorRedChannelPlaybackRedChannelRecord" | ||||||
|  |  | ||||||
|  | var _ChannelType_index = [...]uint8{0, 14, 31, 47, 63, 81, 97} | ||||||
|  |  | ||||||
|  | func (i ChannelType) String() string { | ||||||
|  | 	i -= 1 | ||||||
|  | 	if i >= ChannelType(len(_ChannelType_index)-1) { | ||||||
|  | 		return fmt.Sprintf("ChannelType(%d)", i+1) | ||||||
|  | 	} | ||||||
|  | 	return _ChannelType_name[_ChannelType_index[i]:_ChannelType_index[i+1]] | ||||||
|  | } | ||||||
							
								
								
									
										85
									
								
								conn.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								conn.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | package spice | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"crypto/rand" | ||||||
|  | 	"crypto/rsa" | ||||||
|  | 	"crypto/sha1" | ||||||
|  | 	"crypto/x509" | ||||||
|  | 	"encoding/binary" | ||||||
|  | 	"fmt" | ||||||
|  | 	"net" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Conn struct { | ||||||
|  | 	conn        net.Conn | ||||||
|  | 	commonCAPS  []Compatibily | ||||||
|  | 	channelCAPS []Compatibily | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Conn) Close() error { | ||||||
|  | 	return c.conn.Close() | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Connect(conn net.Conn) (*Conn, error) { | ||||||
|  | 	var req RedLinkMess | ||||||
|  | 	var res RedLinkReply | ||||||
|  |  | ||||||
|  | 	req.Magick = RedMagick | ||||||
|  | 	req.VersionMajor = RedVersionMajor | ||||||
|  | 	req.VersionMinor = RedVersionMinor | ||||||
|  | 	req.Size = 18 | ||||||
|  | 	req.ConnectionID = 0 | ||||||
|  | 	req.ChannelType = RedChannelMain | ||||||
|  | 	req.ChannelID = 0 | ||||||
|  | 	req.CommonCAPSNum = 0 | ||||||
|  | 	req.ChannelCAPSNum = 0 | ||||||
|  | 	req.CAPSOffset = 0 | ||||||
|  |  | ||||||
|  | 	if err := binary.Write(conn, binary.LittleEndian, req); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := binary.Read(conn, binary.LittleEndian, &res); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	c := &Conn{conn: conn} | ||||||
|  |  | ||||||
|  | 	var caps Compatibily | ||||||
|  |  | ||||||
|  | 	for i := uint32(0); i < res.CommonCAPSNum; i++ { | ||||||
|  | 		if err := binary.Read(conn, binary.LittleEndian, &caps); err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		c.commonCAPS = append(c.commonCAPS, caps) | ||||||
|  | 	} | ||||||
|  | 	for i := uint32(0); i < res.ChannelCAPSNum; i++ { | ||||||
|  | 		if err := binary.Read(conn, binary.LittleEndian, &caps); err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		c.channelCAPS = append(c.channelCAPS, caps) | ||||||
|  | 	} | ||||||
|  | 	cert, err := x509.ParsePKIXPublicKey(res.Pubkey[:]) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	rng := rand.Reader | ||||||
|  | 	crypted, err := rsa.EncryptOAEP(sha1.New(), rng, cert.(*rsa.PublicKey), []byte("test"), []byte("")) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err := binary.Write(conn, binary.LittleEndian, crypted); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var result LinkResult | ||||||
|  | 	if err := binary.Read(conn, binary.LittleEndian, &result); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if Error(result) != RedErrorOK { | ||||||
|  | 		return nil, fmt.Errorf("failed to auth, code: %s", Error(result)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return c, nil | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								error_string.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								error_string.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // Code generated by "stringer -type=Error"; DO NOT EDIT. | ||||||
|  |  | ||||||
|  | package spice | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  |  | ||||||
|  | const _Error_name = "RedErrorOKRedErrorErrorRedErrorInvalidMagickRedErrorInvalidDataRedErrorVersionMismatchRedErrorNeedSecuredRedErrorNeedUnsecuredRedErrorPermissionDeniedRedErrorBadConnectionIDRedErrorChannelNotAvailable" | ||||||
|  |  | ||||||
|  | var _Error_index = [...]uint8{0, 10, 23, 44, 63, 86, 105, 126, 150, 173, 200} | ||||||
|  |  | ||||||
|  | func (i Error) String() string { | ||||||
|  | 	if i >= Error(len(_Error_index)-1) { | ||||||
|  | 		return fmt.Sprintf("Error(%d)", i) | ||||||
|  | 	} | ||||||
|  | 	return _Error_name[_Error_index[i]:_Error_index[i+1]] | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								examples/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								examples/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | package main | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net" | ||||||
|  |  | ||||||
|  | 	spice "github.com/vtolstov/go-spice" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func main() { | ||||||
|  | 	conn, err := net.Dial("tcp", "127.0.0.1:6789") | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sp, err := spice.Connect(conn) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	defer sp.Close() | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								info_string.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								info_string.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // Code generated by "stringer -type=Info"; DO NOT EDIT. | ||||||
|  |  | ||||||
|  | package spice | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  |  | ||||||
|  | const _Info_name = "RedInfoGeneral" | ||||||
|  |  | ||||||
|  | var _Info_index = [...]uint8{0, 14} | ||||||
|  |  | ||||||
|  | func (i Info) String() string { | ||||||
|  | 	if i >= Info(len(_Info_index)-1) { | ||||||
|  | 		return fmt.Sprintf("Info(%d)", i) | ||||||
|  | 	} | ||||||
|  | 	return _Info_name[_Info_index[i]:_Info_index[i+1]] | ||||||
|  | } | ||||||
							
								
								
									
										84
									
								
								messages.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								messages.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | |||||||
|  | package spice | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  |  | ||||||
|  | type RedLinkMess struct { | ||||||
|  | 	Magick         uint32 | ||||||
|  | 	VersionMajor   uint32 | ||||||
|  | 	VersionMinor   uint32 | ||||||
|  | 	Size           uint32 | ||||||
|  | 	ConnectionID   uint32 | ||||||
|  | 	ChannelType    ChannelType | ||||||
|  | 	ChannelID      uint8 | ||||||
|  | 	CommonCAPSNum  uint32 | ||||||
|  | 	ChannelCAPSNum uint32 | ||||||
|  | 	CAPSOffset     uint32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (msg *RedLinkMess) String() string { | ||||||
|  | 	return fmt.Sprintf("%v", msg) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type RedLinkReply struct { | ||||||
|  | 	Magick         uint32 | ||||||
|  | 	VersionMajor   uint32 | ||||||
|  | 	VersionMinor   uint32 | ||||||
|  | 	Size           uint32 | ||||||
|  | 	Error          Error | ||||||
|  | 	Pubkey         [RedTicketPubkeyBytes]byte | ||||||
|  | 	CommonCAPSNum  uint32 | ||||||
|  | 	ChannelCAPSNum uint32 | ||||||
|  | 	CAPSOffset     uint32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (msg *RedLinkReply) String() string { | ||||||
|  | 	return fmt.Sprintf("Magic:0x%x, Major: %d, Minor: %d, Size: %d, Error: %s Pubkey: %v, CommonCAPSNum: %d, ChannelCAPSNum: %d, CAPSOffset: %d", msg.Magick, msg.VersionMajor, msg.VersionMinor, msg.Size, msg.Error, msg.Pubkey, msg.CommonCAPSNum, msg.ChannelCAPSNum, msg.CAPSOffset) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type LinkResult uint32 | ||||||
|  |  | ||||||
|  | type RedDataHeader struct { | ||||||
|  | 	Serial  uint64 | ||||||
|  | 	Type    MessageType | ||||||
|  | 	Size    uint32 | ||||||
|  | 	SubList uint32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type RedSubMessageList struct { | ||||||
|  | 	Size        uint16 | ||||||
|  | 	SubMessages []uint32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type RedSubMessage struct { | ||||||
|  | 	Type uint16 | ||||||
|  | 	Size uint32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type MessageType uint16 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	_ MessageType = iota | ||||||
|  |  | ||||||
|  | 	RedMigrateMsgType | ||||||
|  | 	RedMigrateDataMsgType | ||||||
|  | 	RedSetAckMsgType | ||||||
|  | 	RedPingMsgType | ||||||
|  | 	RedWaitForChannelsMsgType | ||||||
|  | 	RedDisconnectingMsgType | ||||||
|  | 	RedNotifyMsgType | ||||||
|  |  | ||||||
|  | 	RedFirstAvailMessageMsgType = 101 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	_ MessageType = iota | ||||||
|  |  | ||||||
|  | 	RedcAckSyncMsgType | ||||||
|  | 	RedcAckMsgType | ||||||
|  | 	RedcPongMsgType | ||||||
|  | 	RedcMigrateFlushMarkMsgType | ||||||
|  | 	RedcMigrateDataMsgType | ||||||
|  | 	RedcDisconnectingMsgType | ||||||
|  |  | ||||||
|  | 	RedcFirstAvailMessagemsgType = 101 | ||||||
|  | ) | ||||||
							
								
								
									
										63
									
								
								spice.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								spice.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | package spice | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	RedMagick = 1363428690 // "REDQ" in uint32 LittleEndian | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	RedVersionMajor uint32 = 0x2 | ||||||
|  | 	RedVersionMinor uint32 = 0x2 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Compatibily uint32 | ||||||
|  |  | ||||||
|  | //go:generate stringer -type=ChannelType | ||||||
|  |  | ||||||
|  | type ChannelType uint8 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	_                          = iota | ||||||
|  | 	RedChannelMain ChannelType = iota | ||||||
|  | 	RedChannelDisplay | ||||||
|  | 	RedChannelInputs | ||||||
|  | 	RedChannelCursor | ||||||
|  | 	RedChannelPlayback | ||||||
|  | 	RedChannelRecord | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | //go:generate stringer -type=Error | ||||||
|  |  | ||||||
|  | type Error uint32 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	RedErrorOK Error = iota | ||||||
|  | 	RedErrorError | ||||||
|  | 	RedErrorInvalidMagick | ||||||
|  | 	RedErrorInvalidData | ||||||
|  | 	RedErrorVersionMismatch | ||||||
|  | 	RedErrorNeedSecured | ||||||
|  | 	RedErrorNeedUnsecured | ||||||
|  | 	RedErrorPermissionDenied | ||||||
|  | 	RedErrorBadConnectionID | ||||||
|  | 	RedErrorChannelNotAvailable | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | //go:generate stringer -type=Warn | ||||||
|  |  | ||||||
|  | type Warn uint32 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	RedWarnGeneral Warn = iota | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | //go:generate stringer -type=Info | ||||||
|  |  | ||||||
|  | type Info uint32 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	RedInfoGeneral Info = iota | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	RedTicketPubkeyBytes = 162 | ||||||
|  | ) | ||||||
							
								
								
									
										16
									
								
								warn_string.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								warn_string.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // Code generated by "stringer -type=Warn"; DO NOT EDIT. | ||||||
|  |  | ||||||
|  | package spice | ||||||
|  |  | ||||||
|  | import "fmt" | ||||||
|  |  | ||||||
|  | const _Warn_name = "RedWarnGeneral" | ||||||
|  |  | ||||||
|  | var _Warn_index = [...]uint8{0, 14} | ||||||
|  |  | ||||||
|  | func (i Warn) String() string { | ||||||
|  | 	if i >= Warn(len(_Warn_index)-1) { | ||||||
|  | 		return fmt.Sprintf("Warn(%d)", i) | ||||||
|  | 	} | ||||||
|  | 	return _Warn_name[_Warn_index[i]:_Warn_index[i+1]] | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user