mirror of
https://github.com/originalmk/archat-server.git
synced 2025-01-18 08:19:17 +00:00
Finished basic connection initation
This commit is contained in:
parent
67eda0d069
commit
b23e8c00a6
@ -3,8 +3,9 @@ package client
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"slices"
|
||||
@ -13,11 +14,18 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/gorilla/websocket"
|
||||
"krzyzanowski.dev/archat/common"
|
||||
cm "krzyzanowski.dev/archat/common"
|
||||
)
|
||||
|
||||
type InitiationInfo struct {
|
||||
otherSideNick string
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
conn *websocket.Conn
|
||||
// Assumption: size of 1 is enough, because first response read will be response for the last request
|
||||
@ -25,7 +33,7 @@ type Context struct {
|
||||
resFromServer chan cm.RFrame
|
||||
reqFromServer chan cm.RFrame
|
||||
rToServer chan cm.RFrame
|
||||
initiations []*cm.Initiation
|
||||
initiations []InitiationInfo
|
||||
initiationsLock sync.RWMutex
|
||||
}
|
||||
|
||||
@ -58,6 +66,8 @@ handleNext:
|
||||
res, err = cliCtx.handleStartChatB(reqFrame)
|
||||
} else if reqFrame.ID == cm.StartChatDReqID {
|
||||
res, err = cliCtx.handleStartChatD(reqFrame)
|
||||
} else if reqFrame.ID == cm.StartChatFinishReqID {
|
||||
res, err = cliCtx.handleChatStartFinish(reqFrame)
|
||||
} else {
|
||||
logger.Warn("can't handle it!")
|
||||
}
|
||||
@ -103,10 +113,8 @@ func (cliCtx *Context) handleStartChatB(reqFrame cm.RFrame) (res cm.Response, er
|
||||
"decide if you want to accept the chat", startChatBReq.Nickname)
|
||||
|
||||
cliCtx.initiationsLock.Lock()
|
||||
cliCtx.initiations = append(cliCtx.initiations, &cm.Initiation{
|
||||
AbANick: startChatBReq.Nickname,
|
||||
AbBNick: "",
|
||||
Stage: cm.InitiationStageB,
|
||||
cliCtx.initiations = append(cliCtx.initiations, InitiationInfo{
|
||||
otherSideNick: startChatBReq.Nickname,
|
||||
})
|
||||
cliCtx.initiationsLock.Unlock()
|
||||
|
||||
@ -126,16 +134,45 @@ func (cliCtx *Context) handleStartChatD(reqFrame cm.RFrame) (res cm.Response, er
|
||||
startChatDReq.Nickname, startChatDReq.PunchCode)
|
||||
logger.Warn("handleStartChatD not implemented yet")
|
||||
|
||||
idx := slices.IndexFunc(cliCtx.initiations, func(i *cm.Initiation) bool {
|
||||
return i.AbBNick == startChatDReq.Nickname
|
||||
idx := slices.IndexFunc(cliCtx.initiations, func(i InitiationInfo) bool {
|
||||
return i.otherSideNick == startChatDReq.Nickname
|
||||
})
|
||||
|
||||
if idx == -1 {
|
||||
logger.Error("there is no initation related to chatstartd's nickname, ignoring")
|
||||
logger.Error("there is no initation related to chatstartd's nickname, ignoring",
|
||||
"nickname", startChatDReq.Nickname)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
cliCtx.initiations[idx].Stage = cm.InitiationStageD
|
||||
conn, err := net.Dial("udp", ":8081")
|
||||
if err != nil {
|
||||
logger.Error("error udp dialing for punch", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(conn)
|
||||
err = enc.Encode(cm.PunchRequest{PunchCode: startChatDReq.PunchCode})
|
||||
|
||||
if err != nil {
|
||||
logger.Error("error sending punch request data", "err", err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
logger.Debug("punch request sent!")
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ctx *Context) handleChatStartFinish(reqFrame common.RFrame) (res common.Response, err error) {
|
||||
startChatFinishReq, err := common.RequestFromFrame[common.StartChatFinishRequest](reqFrame)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger.Info("got chat finish info!",
|
||||
"nick", startChatFinishReq.OtherSideNickname,
|
||||
"addr", startChatFinishReq.OtherSideAddress)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@ -288,8 +325,8 @@ func sendStartChatC(ctx *Context, nick string) {
|
||||
ctx.initiationsLock.Lock()
|
||||
defer ctx.initiationsLock.Unlock()
|
||||
|
||||
idx := slices.IndexFunc(ctx.initiations, func(i *cm.Initiation) bool {
|
||||
return i.AbANick == nick
|
||||
idx := slices.IndexFunc(ctx.initiations, func(i InitiationInfo) bool {
|
||||
return i.otherSideNick == nick
|
||||
})
|
||||
|
||||
if idx == -1 {
|
||||
@ -304,8 +341,6 @@ func sendStartChatC(ctx *Context, nick string) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.initiations[idx].Stage = cm.InitiationStageC
|
||||
|
||||
logger.Debug("request sent, no wait for response")
|
||||
}
|
||||
|
||||
@ -399,12 +434,18 @@ func RunClient() {
|
||||
}
|
||||
|
||||
sendStartChatA(cliCtx, cmdArgs[0])
|
||||
|
||||
cliCtx.initiationsLock.Lock()
|
||||
cliCtx.initiations = append(cliCtx.initiations, InitiationInfo{
|
||||
otherSideNick: cmdArgs[0],
|
||||
})
|
||||
cliCtx.initiationsLock.Unlock()
|
||||
} else if cmdName == "initations" {
|
||||
logger.Info("displaying all initations...")
|
||||
|
||||
cliCtx.initiationsLock.RLock()
|
||||
for _, i := range cliCtx.initiations {
|
||||
logger.Debugf("from %s, stage: %d", i.AbANick, i.Stage)
|
||||
logger.Debugf("with %s", i.otherSideNick)
|
||||
}
|
||||
cliCtx.initiationsLock.RUnlock()
|
||||
} else if cmdName == "startchatc" {
|
||||
|
@ -17,6 +17,7 @@ const (
|
||||
StartChatBReqID = 5
|
||||
StartChatCReqID = 6
|
||||
StartChatDReqID = 7
|
||||
StartChatFinishReqID = 8
|
||||
)
|
||||
|
||||
// Requests & responses subtypes
|
||||
@ -181,12 +182,23 @@ func (StartChatDRequest) ID() int {
|
||||
return StartChatDReqID
|
||||
}
|
||||
|
||||
type StartChatFinishRequest struct {
|
||||
OtherSideNickname string `json:"otherSideNickname"`
|
||||
OtherSideAddress string `json:"otherSideAddress"`
|
||||
}
|
||||
|
||||
func (StartChatFinishRequest) ID() int {
|
||||
return StartChatFinishReqID
|
||||
}
|
||||
|
||||
type Initiation struct {
|
||||
AbANick string
|
||||
AbBNick string
|
||||
Stage int
|
||||
AbAPunchCode string
|
||||
AbBPunchCode string
|
||||
AbAAddress string
|
||||
AbBAddress string
|
||||
}
|
||||
|
||||
const (
|
||||
@ -195,3 +207,11 @@ const (
|
||||
InitiationStageC = 3
|
||||
InitiationStageD = 4
|
||||
)
|
||||
|
||||
type PunchRequest struct {
|
||||
PunchCode string `json:"punchCode"`
|
||||
}
|
||||
|
||||
type PunchResponse struct {
|
||||
IPAddr int32 `json:"ipAddr"`
|
||||
}
|
||||
|
108
server/server.go
108
server/server.go
@ -5,6 +5,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
@ -614,6 +615,89 @@ func (ctx *Context) wsapiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (srvCtx *Context) handleUDP(data []byte, addr net.Addr) {
|
||||
var punchReq common.PunchRequest
|
||||
err := json.Unmarshal(data, &punchReq)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("error unmarshalling punch request", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debugf("got punch request %+v", punchReq)
|
||||
|
||||
srvCtx.initiationsLock.Lock()
|
||||
defer srvCtx.initiationsLock.Unlock()
|
||||
|
||||
idx := slices.IndexFunc(srvCtx.initiations, func(i *common.Initiation) bool {
|
||||
return i.AbAPunchCode == punchReq.PunchCode ||
|
||||
i.AbBPunchCode == punchReq.PunchCode
|
||||
})
|
||||
|
||||
if idx == -1 {
|
||||
logger.Debugf("haven't found initiation for the request")
|
||||
return
|
||||
}
|
||||
|
||||
matchedInitation := srvCtx.initiations[idx]
|
||||
logger.Debugf("matched initiation %+v", matchedInitation)
|
||||
|
||||
if matchedInitation.AbAPunchCode == punchReq.PunchCode {
|
||||
matchedInitation.AbAAddress = addr.String()
|
||||
} else {
|
||||
matchedInitation.AbBAddress = addr.String()
|
||||
}
|
||||
|
||||
if matchedInitation.AbAAddress == "" || matchedInitation.AbBAddress == "" {
|
||||
// does not have two addresses can't do anything yet
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debugf("finished completing initiation %+v", matchedInitation)
|
||||
logger.Debug("now sending peers their addresses")
|
||||
|
||||
srvCtx.peersListLock.Lock()
|
||||
defer srvCtx.peersListLock.Unlock()
|
||||
|
||||
abA, err := srvCtx.getCtxByNick(matchedInitation.AbANick)
|
||||
|
||||
if err != nil {
|
||||
logger.Debug("could not finish punching, abA not found",
|
||||
"err", err)
|
||||
return
|
||||
}
|
||||
|
||||
abB, err := srvCtx.getCtxByNick(matchedInitation.AbBNick)
|
||||
|
||||
if err != nil {
|
||||
logger.Debug("could not finish punching, abB not found",
|
||||
"err", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = abA.sendRequest(common.StartChatFinishRequest{
|
||||
OtherSideNickname: matchedInitation.AbBNick,
|
||||
OtherSideAddress: matchedInitation.AbBAddress,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Debug("could not send start chat finish request to abA, aborting",
|
||||
"err", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = abB.sendRequest(common.StartChatFinishRequest{
|
||||
OtherSideNickname: matchedInitation.AbANick,
|
||||
OtherSideAddress: matchedInitation.AbAAddress,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Debug("could not send start chat finish request to abB, aborting",
|
||||
"err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func RunServer() {
|
||||
srvCtx := NewContext()
|
||||
|
||||
@ -625,10 +709,30 @@ func RunServer() {
|
||||
}()
|
||||
|
||||
http.HandleFunc("/wsapi", srvCtx.wsapiHandler)
|
||||
logger.Info("Starting server...")
|
||||
logger.Info("Starting websocket server...")
|
||||
go func() {
|
||||
err := http.ListenAndServe(":8080", nil)
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
logger.Info("Starting punching server...")
|
||||
listener, err := net.ListenPacket("udp", ":8081")
|
||||
if err != nil {
|
||||
logger.Error("could not create listener for punching server", err)
|
||||
}
|
||||
|
||||
for {
|
||||
data := make([]byte, 65536)
|
||||
n, punchAddr, err := listener.ReadFrom(data)
|
||||
if err != nil {
|
||||
logger.Error("error reading from punching server", err)
|
||||
continue
|
||||
}
|
||||
|
||||
data = data[:n]
|
||||
logger.Debugf("got message: %+v", data)
|
||||
srvCtx.handleUDP(data, punchAddr)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user