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
ef89c4a8
Commit
ef89c4a8
authored
Oct 02, 2022
by
Chunchi Che
Committed by
GitHub
Oct 02, 2022
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9 from DarkNeos/dev
Dev
parents
4d91f8af
bb7863da
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
104 additions
and
33 deletions
+104
-33
DarkNeos/transform.go
DarkNeos/transform.go
+43
-9
proxy.go
proxy.go
+45
-24
util/context.go
util/context.go
+16
-0
No files found.
DarkNeos/transform.go
View file @
ef89c4a8
...
...
@@ -10,13 +10,14 @@ import (
"unicode/utf16"
"github.com/sktt1ryze/ygopro-proxy/DarkNeos/ygopropb"
util
"github.com/sktt1ryze/ygopro-proxy/util"
"google.golang.org/protobuf/proto"
)
const
FILLING_TOKEN
uint16
=
0xcccc
const
UTF16_BUFFER_MAX_LEN
int
=
20
const
PACKET_MIN_LEN
int
=
3
const
COMPONENT
=
"[transform]"
const
(
ProtobufToRawBuf
=
1
RawBufToProtobuf
=
2
...
...
@@ -26,8 +27,9 @@ const (
CtosProtoPlayerInfo
=
16
CtosProtoJoinGame
=
18
StocJoinGame
=
18
StocChat
=
25
StocJoinGame
=
18
StocChat
=
25
StocHsPlayerEnter
=
32
)
type
YgoPacket
struct
{
...
...
@@ -64,7 +66,7 @@ func packetToBuffer(pkt YgoPacket) []byte {
return
buf
}
func
bufferToPacket
(
p
[]
byte
)
(
YgoPacket
,
error
)
{
func
bufferToPacket
(
p
[]
byte
,
ctx
*
util
.
Context
)
(
YgoPacket
,
error
)
{
if
len
(
p
)
<
PACKET_MIN_LEN
{
return
YgoPacket
{},
errors
.
New
(
fmt
.
Sprintf
(
"Packet len too short, len=%d"
,
len
(
p
)))
}
...
...
@@ -72,6 +74,17 @@ func bufferToPacket(p []byte) (YgoPacket, error) {
// todo: impl Reader/Writer for buffer
packet_len
:=
binary
.
LittleEndian
.
Uint16
(
p
)
proto
:=
p
[
2
]
if
len
(
p
)
<
int
(
packet_len
+
2
)
{
log
.
Printf
(
COMPONENT
+
`Unmatched packet size, proto=%d, buffer_length=%d, packet_len=%d, infa_read_len=%d
Use the buffer length.\n`
,
proto
,
len
(
p
),
packet_len
,
ctx
.
InfaReadBufferLen
,
)
packet_len
=
uint16
(
len
(
p
)
-
2
)
}
exdata
:=
p
[
3
:
packet_len
+
2
]
return
YgoPacket
{
...
...
@@ -81,7 +94,7 @@ func bufferToPacket(p []byte) (YgoPacket, error) {
},
nil
}
func
Transform
(
src
[]
byte
,
tranformType
int
)
([]
byte
,
error
)
{
func
Transform
(
src
[]
byte
,
tranformType
int
,
ctx
*
util
.
Context
)
([]
byte
,
error
)
{
if
tranformType
==
ProtobufToRawBuf
{
message
:=
&
ygopropb
.
YgoCtosMsg
{}
err
:=
proto
.
Unmarshal
(
src
,
message
)
...
...
@@ -96,13 +109,13 @@ func Transform(src []byte, tranformType int) ([]byte, error) {
case
*
(
ygopropb
.
YgoCtosMsg_CtosJoinGame
)
:
packet
=
(
*
pCtosJoinGame
)(
message
.
GetCtosJoinGame
())
.
Pb2Packet
()
default
:
return
nil
,
errors
.
New
(
"Unhandled YgoCtosMsg type"
)
return
nil
,
errors
.
New
(
COMPONENT
+
"Unhandled YgoCtosMsg type"
)
}
return
packetToBuffer
(
packet
),
nil
}
else
if
tranformType
==
RawBufToProtobuf
{
packet
,
err
:=
bufferToPacket
(
src
)
packet
,
err
:=
bufferToPacket
(
src
,
ctx
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -113,13 +126,15 @@ func Transform(src []byte, tranformType int) ([]byte, error) {
pb
=
pStocChat
{}
.
Packet2Pb
(
packet
)
case
StocJoinGame
:
pb
=
pStocJoinGame
{}
.
Packet2Pb
(
packet
)
case
StocHsPlayerEnter
:
pb
=
pStocHsPlayerEnter
{}
.
Packet2Pb
(
packet
)
default
:
return
nil
,
errors
.
New
(
fmt
.
Sprintf
(
"Unhandled YgoStocMsg type, proto=%d"
,
packet
.
Proto
))
return
nil
,
errors
.
New
(
fmt
.
Sprintf
(
COMPONENT
+
"Unhandled YgoStocMsg type, proto=%d"
,
packet
.
Proto
))
}
return
proto
.
Marshal
(
&
pb
)
}
else
{
return
nil
,
errors
.
New
(
"Unknown tranformType"
)
return
nil
,
errors
.
New
(
COMPONENT
+
"Unknown tranformType"
)
}
}
...
...
@@ -233,6 +248,25 @@ func (_ pStocJoinGame) Packet2Pb(pkt YgoPacket) ygopropb.YgoStocMsg {
}
}
type
pStocHsPlayerEnter
struct
{}
func
(
_
pStocHsPlayerEnter
)
Packet2Pb
(
pkt
YgoPacket
)
ygopropb
.
YgoStocMsg
{
name_max
:=
UTF16_BUFFER_MAX_LEN
*
2
name
:=
utf16BufferToStr
(
pkt
.
Exdata
[
:
name_max
])
pos
:=
pkt
.
Exdata
[
name_max
]
msg
:=
ygopropb
.
YgoStocMsg_StocHsPlayerEnter
{
StocHsPlayerEnter
:
&
ygopropb
.
StocHsPlayerEnter
{
Name
:
name
,
Pos
:
int32
(
pos
),
},
}
return
ygopropb
.
YgoStocMsg
{
Msg
:
&
msg
,
}
}
// +++++ Util Functions +++++
func
strToUtf16Buffer
(
s
string
)
[]
uint16
{
...
...
proxy.go
View file @
ef89c4a8
package
main
import
(
"
bufio
"
"
encoding/binary
"
"io"
"log"
"net"
...
...
@@ -10,6 +10,7 @@ import (
"github.com/gorilla/websocket"
darkneos
"github.com/sktt1ryze/ygopro-proxy/DarkNeos"
util
"github.com/sktt1ryze/ygopro-proxy/util"
)
const
TARGET_PORT
=
":8000"
...
...
@@ -17,14 +18,19 @@ const PROXY_PORT = ":3344"
const
CHANNEL_SIZE
=
0x1000
const
BUFFER_SIZE
=
0x1000
const
TIME_OUT
=
5
const
COMPONENT
=
"[proxy]"
var
upgrader
=
websocket
.
Upgrader
{
ReadBufferSize
:
0x1000
,
WriteBufferSize
:
0x1000
,
}
// todo: create Context
func
ygoEndpoint
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
defer
log
.
Println
(
"ygoEndpoint finished"
)
defer
log
.
Println
(
COMPONENT
+
"ygoEndpoint finished"
)
ctx
:=
util
.
NewContext
()
upgrader
.
CheckOrigin
=
wsChecker
...
...
@@ -32,15 +38,17 @@ func ygoEndpoint(w http.ResponseWriter, r *http.Request) {
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
ctx
.
WsConnected
=
true
log
.
Println
(
"Connection to ws://localhost"
+
TARGET_PORT
+
" [websocket] succeeded!"
)
log
.
Println
(
COMPONENT
+
"Connection to ws://localhost"
+
TARGET_PORT
+
" [websocket] succeeded!"
)
tcp
,
err
:=
net
.
Dial
(
"tcp"
,
"127.0.0.1"
+
PROXY_PORT
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
ctx
.
TcpConnected
=
true
log
.
Println
(
"Connection to "
+
"12.0.0.1"
+
PROXY_PORT
+
" [tcp] succeeded!"
)
log
.
Println
(
COMPONENT
+
"Connection to "
+
"12.0.0.1"
+
PROXY_PORT
+
" [tcp] succeeded!"
)
wsCh
:=
make
(
chan
[]
byte
,
CHANNEL_SIZE
)
tcpCh
:=
make
(
chan
[]
byte
,
CHANNEL_SIZE
)
...
...
@@ -55,8 +63,8 @@ func ygoEndpoint(w http.ResponseWriter, r *http.Request) {
close
(
tcpStopCh
)
}()
go
wsProxy
(
ws
,
wsCh
,
wsStopCh
)
go
tcpProxy
(
tcp
,
tcpCh
,
tcpStopCh
)
go
wsProxy
(
ws
,
wsCh
,
wsStopCh
,
ctx
)
go
tcpProxy
(
tcp
,
tcpCh
,
tcpStopCh
,
ctx
)
for
{
select
{
...
...
@@ -82,15 +90,15 @@ func ygoEndpoint(w http.ResponseWriter, r *http.Request) {
}
}
// todo:
generic
func
wsProxy
(
ws
*
websocket
.
Conn
,
Ch
chan
<-
[]
byte
,
stopCh
<-
chan
bool
)
{
// todo:
use interface
func
wsProxy
(
ws
*
websocket
.
Conn
,
Ch
chan
<-
[]
byte
,
stopCh
<-
chan
bool
,
ctx
util
.
Context
)
{
defer
ws
.
Close
()
defer
close
(
Ch
)
for
{
select
{
case
_
,
ok
:=
<-
stopCh
:
log
.
Println
(
"wsProxy recv stop singal, exit. channel closed: "
,
ok
)
log
.
Println
(
COMPONENT
+
"wsProxy recv stop singal, exit. channel closed: "
,
ok
)
return
default
:
// if err := ws.SetReadDeadline(time.Now().Add(time.Second * TIME_OUT)); err != nil {
...
...
@@ -107,13 +115,14 @@ func wsProxy(ws *websocket.Conn, Ch chan<- []byte, stopCh <-chan bool) {
log
.
Println
(
err
)
return
}
ctx
.
InfaReadBufferLen
=
len
(
buffer
)
if
messageType
==
websocket
.
CloseMessage
{
log
.
Println
(
"Websocket closed"
)
log
.
Println
(
COMPONENT
+
"Websocket closed"
)
return
}
buffer
,
err
=
darkneos
.
Transform
(
buffer
,
darkneos
.
ProtobufToRawBuf
)
buffer
,
err
=
darkneos
.
Transform
(
buffer
,
darkneos
.
ProtobufToRawBuf
,
&
ctx
)
if
err
!=
nil
{
log
.
Println
(
err
)
return
...
...
@@ -124,17 +133,15 @@ func wsProxy(ws *websocket.Conn, Ch chan<- []byte, stopCh <-chan bool) {
}
}
func
tcpProxy
(
tcp
net
.
Conn
,
Ch
chan
<-
[]
byte
,
stopCh
<-
chan
bool
)
{
func
tcpProxy
(
tcp
net
.
Conn
,
Ch
chan
<-
[]
byte
,
stopCh
<-
chan
bool
,
ctx
util
.
Context
)
{
const
PACKET_LEN_PENDING
=
2
defer
tcp
.
Close
()
defer
close
(
Ch
)
reader
:=
bufio
.
NewReader
(
tcp
)
buffer
:=
make
([]
byte
,
BUFFER_SIZE
)
for
{
select
{
case
_
,
ok
:=
<-
stopCh
:
log
.
Println
(
"tcpProxy recv stop singal, exit. channel closed: "
,
ok
)
log
.
Println
(
COMPONENT
+
"tcpProxy recv stop singal, exit. channel closed: "
,
ok
)
return
default
:
if
err
:=
tcp
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
time
.
Second
*
TIME_OUT
));
err
!=
nil
{
...
...
@@ -142,12 +149,8 @@ func tcpProxy(tcp net.Conn, Ch chan<- []byte, stopCh <-chan bool) {
return
}
_
,
err
:=
reader
.
Read
(
buffer
)
if
err
!=
nil
{
if
err
==
io
.
EOF
{
continue
}
guardBuf
:=
make
([]
byte
,
PACKET_LEN_PENDING
)
if
_
,
err
:=
tcp
.
Read
(
guardBuf
);
err
!=
nil
{
if
err
,
ok
:=
err
.
(
net
.
Error
);
ok
&&
err
.
Timeout
()
{
continue
}
...
...
@@ -156,13 +159,29 @@ func tcpProxy(tcp net.Conn, Ch chan<- []byte, stopCh <-chan bool) {
return
}
buffer
,
err
=
darkneos
.
Transform
(
buffer
,
darkneos
.
RawBufToProtobuf
)
packet_len
:=
int
(
binary
.
LittleEndian
.
Uint16
(
guardBuf
))
ctx
.
InfaReadBufferLen
=
PACKET_LEN_PENDING
buffer
:=
make
([]
byte
,
packet_len
+
PACKET_LEN_PENDING
)
copy
(
buffer
,
guardBuf
)
if
packet_len
>
0
{
n
,
err
:=
io
.
ReadAtLeast
(
tcp
,
buffer
[
PACKET_LEN_PENDING
:
],
packet_len
)
if
err
!=
nil
&&
err
!=
io
.
EOF
{
log
.
Println
(
err
)
return
}
ctx
.
InfaReadBufferLen
+=
n
}
newBuffer
,
err
:=
darkneos
.
Transform
(
buffer
,
darkneos
.
RawBufToProtobuf
,
&
ctx
)
if
err
!=
nil
{
log
.
Println
(
err
)
return
}
Ch
<-
b
uffer
Ch
<-
newB
uffer
}
}
}
...
...
@@ -178,5 +197,7 @@ func main() {
setupRoutes
()
log
.
Println
(
COMPONENT
+
"start listening on ws://localhost:"
+
TARGET_PORT
)
log
.
Fatal
(
http
.
ListenAndServe
(
TARGET_PORT
,
nil
))
}
util/context.go
0 → 100644
View file @
ef89c4a8
package
util
type
Context
struct
{
ContextId
int64
WsConnected
bool
TcpConnected
bool
InfaReadBufferLen
int
}
func
NewContext
()
Context
{
return
Context
{
ContextId
:
0
,
// todo
WsConnected
:
false
,
TcpConnected
:
false
,
}
}
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