initial import

Signed-off-by: Vasiliy Tolstov <v.tolstov@selfip.ru>
This commit is contained in:
Василий Толстов 2017-07-08 23:23:17 +03:00
parent befe6b8302
commit f3a0197dd9
9 changed files with 319 additions and 0 deletions

1
.gitignore vendored
View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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]]
}