Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro-proxy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
ygopro-proxy
Commits
6f2ba85e
Commit
6f2ba85e
authored
Sep 12, 2022
by
Chunchi Che
Committed by
GitHub
Sep 12, 2022
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3 from DarkNeos/dev
Dev
parents
e4d56fc9
6368e27a
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
448 additions
and
142 deletions
+448
-142
DarkNeos/transform.go
DarkNeos/transform.go
+216
-0
DarkNeos/ygoprobuffer/ctos.go
DarkNeos/ygoprobuffer/ctos.go
+7
-0
DarkNeos/ygopropb/ygopro.pb.go
DarkNeos/ygopropb/ygopro.pb.go
+179
-120
go.mod
go.mod
+5
-1
go.sum
go.sum
+9
-0
proxy.go
proxy.go
+20
-12
ygopro.proto
ygopro.proto
+12
-9
No files found.
DarkNeos/transform.go
0 → 100644
View file @
6f2ba85e
package
darkneos
import
(
"encoding/binary"
"errors"
"fmt"
"unicode/utf16"
"github.com/sktt1ryze/ygopro-proxy/DarkNeos/ygopropb"
"google.golang.org/protobuf/proto"
)
const
FILLING_TOKEN
uint16
=
0xcccc
const
UTF16_BUFFER_MAX_LEN
int
=
20
const
PACKET_MIN_LEN
int
=
3
const
(
ProtobufToRawBuf
=
1
RawBufToProtobuf
=
2
)
const
(
CtosProtoPlayerInfo
=
16
CtosProtoJoinGame
=
18
StocChat
=
25
)
type
YgoPacket
struct
{
PacketLen
uint16
Proto
uint8
Exdata
[]
byte
}
func
packetToBuffer
(
pkt
YgoPacket
)
[]
byte
{
buf
:=
make
([]
byte
,
0
)
// packet len
buf
=
append
(
buf
,
byte
(
pkt
.
PacketLen
),
byte
(
pkt
.
PacketLen
>>
8
))
// proto
buf
=
append
(
buf
,
byte
(
pkt
.
Proto
))
// exdata
for
_
,
v
:=
range
pkt
.
Exdata
{
buf
=
append
(
buf
,
v
)
}
return
buf
}
func
bufferToPacket
(
p
[]
byte
)
(
YgoPacket
,
error
)
{
if
len
(
p
)
<
PACKET_MIN_LEN
{
return
YgoPacket
{},
errors
.
New
(
fmt
.
Sprintf
(
"Packet len too short, len=%d"
,
len
(
p
)))
}
// todo: impl Reader/Writer for buffer
packet_len
:=
binary
.
LittleEndian
.
Uint16
(
p
)
proto
:=
p
[
2
]
exdata
:=
p
[
3
:
packet_len
+
2
]
return
YgoPacket
{
PacketLen
:
packet_len
,
Proto
:
proto
,
Exdata
:
exdata
,
},
nil
}
func
Transform
(
src
[]
byte
,
tranformType
int
)
([]
byte
,
error
)
{
if
tranformType
==
ProtobufToRawBuf
{
message
:=
&
ygopropb
.
YgoCtosMsg
{}
err
:=
proto
.
Unmarshal
(
src
,
message
)
if
err
!=
nil
{
return
nil
,
err
}
var
packet
YgoPacket
switch
message
.
Msg
.
(
type
)
{
case
*
(
ygopropb
.
YgoCtosMsg_CtosPlayerInfo
)
:
packet
=
transformPlayerInfo
(
message
.
GetCtosPlayerInfo
())
case
*
(
ygopropb
.
YgoCtosMsg_CtosJoinGame
)
:
packet
=
transformJoinGame
(
message
.
GetCtosJoinGame
())
default
:
return
nil
,
errors
.
New
(
"Unhandled YgoCtosMsg type"
)
}
return
packetToBuffer
(
packet
),
nil
}
else
if
tranformType
==
RawBufToProtobuf
{
packet
,
err
:=
bufferToPacket
(
src
)
if
err
!=
nil
{
return
nil
,
err
}
var
pb
ygopropb
.
YgoStocMsg
switch
packet
.
Proto
{
case
StocChat
:
msg
:=
transformChat
(
packet
)
pb
=
ygopropb
.
YgoStocMsg
{
Msg
:
&
msg
,
}
default
:
return
nil
,
errors
.
New
(
"Unhandled YgoStocMsg type"
)
}
return
proto
.
Marshal
(
&
pb
)
}
else
{
return
nil
,
errors
.
New
(
"Unknown tranformType"
)
}
}
// todo: use interface
// +++++ Client To Server +++++
// @Name: [20]uint16
func
transformPlayerInfo
(
pb
*
ygopropb
.
CtosPlayerInfo
)
YgoPacket
{
buf
:=
strToUtf16Buffer
(
pb
.
Name
)
exdata
:=
uint16BufToByteBuf
(
buf
)
return
YgoPacket
{
PacketLen
:
uint16
(
len
(
exdata
))
+
1
,
Proto
:
CtosProtoPlayerInfo
,
Exdata
:
exdata
,
}
}
// @Version: uint16
// @Gameid: uint32
// @Passwd: [20]uint16
func
transformJoinGame
(
pb
*
ygopropb
.
CtosJoinGame
)
YgoPacket
{
exdata
:=
make
([]
byte
,
0
)
version
:=
uint16
(
pb
.
Version
)
exdata
=
append
(
exdata
,
byte
(
version
),
byte
(
version
>>
8
),
0
,
0
)
exdata
=
append
(
exdata
,
byte
(
pb
.
Gameid
),
byte
(
pb
.
Gameid
>>
8
),
byte
(
pb
.
Gameid
>>
16
),
byte
(
pb
.
Gameid
>>
24
))
for
_
,
v
:=
range
uint16BufToByteBuf
(
strToUtf16Buffer
(
pb
.
Passwd
))
{
exdata
=
append
(
exdata
,
v
)
}
return
YgoPacket
{
PacketLen
:
uint16
(
len
(
exdata
))
+
1
,
Proto
:
CtosProtoJoinGame
,
Exdata
:
exdata
,
}
}
// +++++ Server To Client +++++
// @player: uint16
// @message: []uint16
func
transformChat
(
pkt
YgoPacket
)
ygopropb
.
YgoStocMsg_StocChat
{
player
:=
int32
(
binary
.
LittleEndian
.
Uint16
(
pkt
.
Exdata
))
message
:=
utf16BufferToStr
(
pkt
.
Exdata
[
2
:
])
return
ygopropb
.
YgoStocMsg_StocChat
{
StocChat
:
&
ygopropb
.
StocChat
{
Player
:
player
,
Msg
:
message
,
},
}
}
// +++++ Util Functions +++++
func
strToUtf16Buffer
(
s
string
)
[]
uint16
{
b
:=
make
([]
uint16
,
UTF16_BUFFER_MAX_LEN
,
UTF16_BUFFER_MAX_LEN
)
for
i
:=
range
b
{
b
[
i
]
=
FILLING_TOKEN
}
s_utf16
:=
utf16
.
Encode
([]
rune
(
s
))
// todo: optimize
for
i
,
v
:=
range
s_utf16
{
if
i
<
UTF16_BUFFER_MAX_LEN
{
b
[
i
]
=
v
if
i
==
len
(
s_utf16
)
-
1
&&
i
<
len
(
b
)
-
1
{
b
[
i
+
1
]
=
0
}
}
else
{
break
}
}
return
b
}
func
utf16BufferToStr
(
p
[]
byte
)
string
{
v
:=
chunkBytesToUint16s
(
p
)
return
string
(
utf16
.
Decode
(
v
))
}
func
uint16BufToByteBuf
(
u16_b
[]
uint16
)
[]
byte
{
b
:=
make
([]
byte
,
0
,
len
(
u16_b
)
*
2
)
for
_
,
v
:=
range
u16_b
{
// little endian
b
=
append
(
b
,
byte
(
v
),
byte
(
v
>>
8
))
}
return
b
}
func
chunkBytesToUint16s
(
items
[]
byte
)
[]
uint16
{
const
chunkSize
=
2
var
chunks
[]
uint16
for
chunkSize
<
len
(
items
)
{
items
,
chunks
=
items
[
chunkSize
:
],
append
(
chunks
,
binary
.
LittleEndian
.
Uint16
(
items
))
}
return
chunks
}
DarkNeos/ygoprobuffer/ctos.go
0 → 100644
View file @
6f2ba85e
package
ygoprobuffer
const
PLAYER_NAME_MAX_LEN
int
=
20
type
CtosPlayerInfo
struct
{
Name
[
PLAYER_NAME_MAX_LEN
]
uint16
}
DarkNeos/ygopropb/ygopro.pb.go
View file @
6f2ba85e
This diff is collapsed.
Click to expand it.
go.mod
View file @
6f2ba85e
...
@@ -2,4 +2,8 @@ module github.com/sktt1ryze/ygopro-proxy
...
@@ -2,4 +2,8 @@ module github.com/sktt1ryze/ygopro-proxy
go 1.17
go 1.17
require github.com/gorilla/websocket v1.5.0 // indirect
require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
)
go.sum
View file @
6f2ba85e
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
proxy.go
View file @
6f2ba85e
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"sync"
"sync"
"github.com/gorilla/websocket"
"github.com/gorilla/websocket"
darkneos
"github.com/sktt1ryze/ygopro-proxy/DarkNeos"
)
)
const
TARGET_PORT
=
":8000"
const
TARGET_PORT
=
":8000"
...
@@ -50,10 +51,12 @@ func ygoEndpoint(w http.ResponseWriter, r *http.Request) {
...
@@ -50,10 +51,12 @@ func ygoEndpoint(w http.ResponseWriter, r *http.Request) {
}
}
func
wsProxy
(
ws
*
websocket
.
Conn
,
tcp
*
net
.
Conn
,
wg
*
sync
.
WaitGroup
)
{
func
wsProxy
(
ws
*
websocket
.
Conn
,
tcp
*
net
.
Conn
,
wg
*
sync
.
WaitGroup
)
{
writer
:=
bufio
.
NewWriter
(
*
tcp
)
for
{
for
{
messageType
,
buf
,
err
:=
ws
.
ReadMessage
()
messageType
,
buf
fer
,
err
:=
ws
.
ReadMessage
()
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Fatal
(
"websocket read message error: "
,
err
)
log
.
Println
(
"websocket read message error: "
,
err
)
break
break
}
}
...
@@ -62,10 +65,11 @@ func wsProxy(ws *websocket.Conn, tcp *net.Conn, wg *sync.WaitGroup) {
...
@@ -62,10 +65,11 @@ func wsProxy(ws *websocket.Conn, tcp *net.Conn, wg *sync.WaitGroup) {
break
break
}
}
log
.
Println
(
"websocket to tcp: "
+
string
(
buf
))
buffer
,
err
=
darkneos
.
Transform
(
buffer
,
darkneos
.
ProtobufToRawBuf
)
if
err
!=
nil
{
writer
:=
bufio
.
NewWriter
(
*
tcp
)
log
.
Fatal
(
err
)
buffer
:=
make
([]
byte
,
BUFFER_SIZE
)
break
}
_
,
err
=
writer
.
Write
(
buffer
)
_
,
err
=
writer
.
Write
(
buffer
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -78,23 +82,27 @@ func wsProxy(ws *websocket.Conn, tcp *net.Conn, wg *sync.WaitGroup) {
...
@@ -78,23 +82,27 @@ func wsProxy(ws *websocket.Conn, tcp *net.Conn, wg *sync.WaitGroup) {
}
}
func
tcpProxy
(
tcp
*
net
.
Conn
,
ws
*
websocket
.
Conn
,
wg
*
sync
.
WaitGroup
)
{
func
tcpProxy
(
tcp
*
net
.
Conn
,
ws
*
websocket
.
Conn
,
wg
*
sync
.
WaitGroup
)
{
for
{
reader
:=
bufio
.
NewReader
(
*
tcp
)
reader
:=
bufio
.
NewReader
(
*
tcp
)
buffer
:=
make
([]
byte
,
BUFFER_SIZE
)
buffer
:=
make
([]
byte
,
BUFFER_SIZE
)
for
{
_
,
err
:=
reader
.
Read
(
buffer
)
_
,
err
:=
reader
.
Read
(
buffer
)
if
err
!=
nil
{
if
err
!=
nil
{
if
err
==
io
.
EOF
{
if
err
==
io
.
EOF
{
continue
continue
}
}
log
.
Fatal
(
"tcp read message error: "
,
err
)
log
.
Println
(
"tcp read message error: "
,
err
)
break
break
}
}
log
.
Println
(
"tcp to websocket: "
+
string
(
buffer
))
buffer
,
err
=
darkneos
.
Transform
(
buffer
,
darkneos
.
RawBufToProtobuf
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
break
}
err
=
ws
.
WriteMessage
(
websocket
.
TextMessage
,
buffer
)
// temporary TextMessage, should be BinaryMessage in ygopro
err
=
ws
.
WriteMessage
(
websocket
.
BinaryMessage
,
buffer
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Fatal
(
"tcp send message error: "
,
err
)
log
.
Fatal
(
"tcp send message error: "
,
err
)
break
break
...
...
ygopro.proto
View file @
6f2ba85e
...
@@ -4,19 +4,22 @@ package ygopro;
...
@@ -4,19 +4,22 @@ package ygopro;
option
go_package
=
"DarkNeos/ygopropb"
;
option
go_package
=
"DarkNeos/ygopropb"
;
message
YgoCtosMsg
{
message
YgoCtosMsg
{
int32
proto
=
1
;
oneof
msg
{
oneof
msg
{
CtosPlayerInfo
ctos_player_info
=
2
;
CtosPlayerInfo
ctos_player_info
=
1
;
CtosJoinGame
ctos_join_game
=
3
;
CtosJoinGame
ctos_join_game
=
2
;
CtosUpdateDeck
ctos_update_deck
=
4
;
CtosUpdateDeck
ctos_update_deck
=
3
;
StocJoinGame
stoc_join_game
=
101
;
StocChat
stoc_chat
=
102
;
StocHsPlayerEnter
stoc_hs_player_enter
=
103
;
StocTypeChange
stoc_type_change
=
104
;
}
}
}
}
message
YgoStocMsg
{
oneof
msg
{
StocJoinGame
stoc_join_game
=
1
;
StocChat
stoc_chat
=
2
;
StocHsPlayerEnter
stoc_hs_player_enter
=
3
;
StocTypeChange
stoc_type_change
=
4
;
}
}
// ----- CTOS -----
// ----- CTOS -----
message
CtosPlayerInfo
{
message
CtosPlayerInfo
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment