wip: 0.2.5
还未实现 rtc 握手
This commit is contained in:
parent
013670b78f
commit
b8645a68ed
@ -72,18 +72,18 @@ interface Bubble {
|
|||||||
interface WSMessage {
|
interface WSMessage {
|
||||||
body: Client;
|
body: Client;
|
||||||
time: number;
|
time: number;
|
||||||
type: "enter" | "leave" | "offer" | "answer"
|
type: "register" | "enter" | "leave" | "offer" | "answer"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Client {
|
interface Client {
|
||||||
client_type: 'desktop' | 'mobile' | 'tablet';
|
client_type: 'desktop' | 'mobile' | 'tablet';
|
||||||
app_type: 'web';
|
app_type: 'web';
|
||||||
room: string;
|
|
||||||
ip: number;
|
ip: number;
|
||||||
name: string;
|
name: string;
|
||||||
id: string;
|
id: string;
|
||||||
register_at: string;
|
register_at: string;
|
||||||
offer: RTCSessionDescription;
|
offer: RTCSessionDescription;
|
||||||
|
candidate: RTCIceCandidateInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Store {
|
interface Store {
|
||||||
@ -184,19 +184,26 @@ export const LocalSharing: React.FC = () => {
|
|||||||
return bubbles;
|
return bubbles;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateClients = async (room?: string) => {
|
const updateClients = async () => {
|
||||||
const res = await fetch(`/api/ulocal/clients?room=${room ? room : rtcStore.client?.room}`)
|
setTimeout(async () => {
|
||||||
const jes = await res.json() as Resp<Client[]>
|
const res = await fetch(`/api/ulocal/clients`)
|
||||||
console.log('[D] update clients called, resp =', jes)
|
const jes = await res.json() as Resp<Client[]>
|
||||||
setRTCStore(val => {
|
setRTCStore(val => {
|
||||||
return {...val, clients: jes.data}
|
return {...val, clients: jes.data}
|
||||||
})
|
})
|
||||||
|
}, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleWSEvent = async (e: MessageEvent) => {
|
const handleWSEvent = async (e: MessageEvent) => {
|
||||||
const msg = JSON.parse(e.data) as WSMessage
|
const msg = JSON.parse(e.data) as WSMessage
|
||||||
console.log('[D] ws event msg =', msg)
|
console.log('[D] ws event msg =', msg)
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
|
case "register":
|
||||||
|
const reg_resp = JSON.parse(e.data) as { body: Client }
|
||||||
|
setRTCStore(val => {
|
||||||
|
return {...val, client: reg_resp.body}
|
||||||
|
})
|
||||||
|
break
|
||||||
case "enter":
|
case "enter":
|
||||||
await updateClients()
|
await updateClients()
|
||||||
break
|
break
|
||||||
@ -204,89 +211,119 @@ export const LocalSharing: React.FC = () => {
|
|||||||
await updateClients()
|
await updateClients()
|
||||||
break
|
break
|
||||||
case "offer":
|
case "offer":
|
||||||
console.log('[D] rtc =', rtcStore.rtc)
|
const res_offer = JSON.parse(e.data) as {
|
||||||
const offer = JSON.parse(e.data) as { offer: RTCSessionDescriptionInit, id: number, room: string }
|
offer: RTCSessionDescriptionInit,
|
||||||
console.log('[D] offer =', offer)
|
id: number,
|
||||||
await rtcStore.rtc?.setRemoteDescription(offer.offer)
|
candidate: RTCIceCandidateInit
|
||||||
|
}
|
||||||
|
console.log('[D] offer res =', res_offer)
|
||||||
|
await rtcStore.rtc?.setRemoteDescription(res_offer.offer)
|
||||||
const answer = await rtcStore.rtc?.createAnswer()
|
const answer = await rtcStore.rtc?.createAnswer()
|
||||||
await rtcStore.rtc?.setLocalDescription(answer)
|
await rtcStore.rtc?.setLocalDescription(answer)
|
||||||
console.log('[D] answer =', answer)
|
await fetch('/api/ulocal/answer', {
|
||||||
await fetch("/api/ulocal/answer", {
|
method: 'POST',
|
||||||
method: "POST",
|
|
||||||
headers: {"Content-Type": "application/json"},
|
headers: {"Content-Type": "application/json"},
|
||||||
body: JSON.stringify({id: offer.id, room: offer.room, answer: answer})
|
body: JSON.stringify({id: rtcStore.client?.id, answer: answer})
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case "answer":
|
case "answer":
|
||||||
// const _answer = JSON.parse(e.data) as { answer: RTCSessionDescriptionInit, id: number, room: string }
|
const res_answer = JSON.parse(e.data) as { answer: RTCSessionDescriptionInit, id: number }
|
||||||
// await rtcStore.rtc?.setRemoteDescription(_answer.answer)
|
await rtcStore.rtc?.setRemoteDescription(res_answer.answer)
|
||||||
// break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const fn = async () => {
|
||||||
|
// // const rtc = new RTCPeerConnection({iceServers: [{urls: "stun:stun.qq.com:3478"}]})
|
||||||
|
// const rtc = new RTCPeerConnection({})
|
||||||
|
// rtc.onconnectionstatechange = () => {
|
||||||
|
// console.log('rtc connection state =', rtc.connectionState)
|
||||||
|
// }
|
||||||
|
// const dataChannel = rtc.createDataChannel('fileTransfer', {ordered: true});
|
||||||
|
// setupDataChannel(dataChannel);
|
||||||
|
// const waitCandidate = (): Promise<RTCIceCandidate | null> => {
|
||||||
|
// return new Promise<RTCIceCandidate | null>(resolve => {
|
||||||
|
// rtc.onicecandidate = (e) => {
|
||||||
|
// resolve(e.candidate)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// const waitNegotiation = (): Promise<void> => {
|
||||||
|
// return new Promise<void>(resolve => {
|
||||||
|
// rtc.onnegotiationneeded = async () => {
|
||||||
|
// const _offer = await rtc.createOffer()
|
||||||
|
// await rtc.setLocalDescription(_offer)
|
||||||
|
// resolve()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// await waitNegotiation()
|
||||||
|
// const candidate: RTCIceCandidate | null = await waitCandidate();
|
||||||
|
//
|
||||||
|
// const res = await fetch("/api/ulocal/register", {
|
||||||
|
// method: "POST",
|
||||||
|
// headers: {"Content-Type": "application/json"},
|
||||||
|
// body: JSON.stringify({candidate: candidate})
|
||||||
|
// })
|
||||||
|
// const jes = await res.json() as Resp<Client>;
|
||||||
|
//
|
||||||
|
// console.log('[D] register resp =', jes)
|
||||||
|
//
|
||||||
|
// if (!jes.data.id) {
|
||||||
|
// message.error("注册失败")
|
||||||
|
// throw new Error("register failed")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// setRTCStore(val => {
|
||||||
|
// return {
|
||||||
|
// ...val,
|
||||||
|
// client: jes.data,
|
||||||
|
// candidate: candidate,
|
||||||
|
// offer: rtc.localDescription,
|
||||||
|
// rtc: rtc,
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// const api = `${window.location.protocol === 'https' ? 'wss' : 'ws'}://${window.location.host}/api/ulocal/ws?id=${jes.data.id}`
|
||||||
|
// console.log('[D] websocket url =', api)
|
||||||
|
// connect(api, {fn: handleWSEvent})
|
||||||
|
//
|
||||||
|
// await updateClients()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn()
|
||||||
|
//
|
||||||
|
// return () => close();
|
||||||
|
// }, []
|
||||||
|
// );
|
||||||
|
|
||||||
|
// 气泡点击处理
|
||||||
|
const handleBubbleClick = async (bubble: Bubble) => {
|
||||||
|
const offer = await rtcStore.rtc?.createOffer()
|
||||||
|
await rtcStore.rtc?.setLocalDescription(offer)
|
||||||
|
// await fetch('/api/ulocal/offer', {
|
||||||
|
// method: 'POST',
|
||||||
|
// headers: {"Content-Type": "application/json"},
|
||||||
|
// body: JSON.stringify({
|
||||||
|
// id: bubble.id,
|
||||||
|
// offer: rtcStore.offer,
|
||||||
|
// candidate: rtcStore.candidate,
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fn = async () => {
|
const fn = async () => {
|
||||||
|
connect("/api/ulocal/ws", {fn: handleWSEvent})
|
||||||
|
await updateClients()
|
||||||
const rtc = new RTCPeerConnection({iceServers: [{urls: "stun:stun.qq.com:3478"}]})
|
const rtc = new RTCPeerConnection({iceServers: [{urls: "stun:stun.qq.com:3478"}]})
|
||||||
const dataChannel = rtc.createDataChannel('fileTransfer', {ordered: true});
|
setRTCStore(val => {return {...val, rtc: rtc}})
|
||||||
setupDataChannel(dataChannel);
|
};
|
||||||
const waitCandidate = new Promise<RTCIceCandidate | null>(resolve => {
|
|
||||||
rtc.onicecandidate = (e) => {
|
|
||||||
resolve(e.candidate)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const waitNegotiationneeded = new Promise<void>(resolve => {
|
|
||||||
rtc.onnegotiationneeded = async () => {
|
|
||||||
const _offer = await rtc.createOffer()
|
|
||||||
await rtc.setLocalDescription(_offer)
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
await waitNegotiationneeded
|
|
||||||
const candidate: RTCIceCandidate | null = await waitCandidate;
|
|
||||||
if (!candidate) throw new Error("candidate is null")
|
|
||||||
|
|
||||||
const res = await fetch("/api/ulocal/register", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {"Content-Type": "application/json"},
|
|
||||||
body: JSON.stringify({candidate: candidate, offer: rtc.localDescription})
|
|
||||||
})
|
|
||||||
const jes = await res.json() as Resp<Client>;
|
|
||||||
|
|
||||||
if (!jes.data.id) {
|
|
||||||
message.error("注册失败")
|
|
||||||
throw new Error("register failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
setRTCStore(val => {
|
|
||||||
return {...val, client: jes.data, candidate: candidate, offer: rtc.localDescription, rtc: rtc, ch: dataChannel}
|
|
||||||
})
|
|
||||||
|
|
||||||
const api = `${window.location.protocol === 'https' ? 'wss' : 'ws'}://${window.location.host}/api/ulocal/ws?id=${jes.data.id}`
|
|
||||||
//console.log('[D] websocket url =', api)
|
|
||||||
connect(api, {fn: handleWSEvent})
|
|
||||||
|
|
||||||
await updateClients(jes.data.room)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn()
|
fn()
|
||||||
|
}, [])
|
||||||
return () => close();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// 气泡点击处理
|
|
||||||
const handleBubbleClick = async (id: string) => {
|
|
||||||
await fetch('/api/ulocal/offer', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {"Content-Type": "application/json"},
|
|
||||||
body: JSON.stringify({room: rtcStore.client?.room, id: id, offer: rtcStore.offer})
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
rtcStore.ch?.send("hello, world")
|
|
||||||
}, 1000)
|
|
||||||
};
|
|
||||||
|
|
||||||
return <div className={classes.container}>
|
return <div className={classes.container}>
|
||||||
<CloudBackground/>
|
<CloudBackground/>
|
||||||
@ -305,7 +342,7 @@ export const LocalSharing: React.FC = () => {
|
|||||||
`${Math.random() * 0.5}s,
|
`${Math.random() * 0.5}s,
|
||||||
${0.5 + Math.random() * 2}s`
|
${0.5 + Math.random() * 2}s`
|
||||||
}}
|
}}
|
||||||
onClick={() => handleBubbleClick(bubble.id)}
|
onClick={() => handleBubbleClick(bubble)}
|
||||||
>
|
>
|
||||||
{bubble.name}
|
{bubble.name}
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,7 +25,6 @@ func Start(ctx context.Context) <-chan struct{} {
|
|||||||
|
|
||||||
{
|
{
|
||||||
api := app.Group("/api/ulocal")
|
api := app.Group("/api/ulocal")
|
||||||
api.Post("/register", handler.LocalRegister())
|
|
||||||
api.Post("/offer", handler.LocalOffer())
|
api.Post("/offer", handler.LocalOffer())
|
||||||
api.Post("/answer", handler.LocalAnswer())
|
api.Post("/answer", handler.LocalAnswer())
|
||||||
api.Get("/clients", handler.LocalClients())
|
api.Get("/clients", handler.LocalClients())
|
||||||
|
@ -55,12 +55,9 @@ type roomClient struct {
|
|||||||
ClientType RoomClientType `json:"client_type"`
|
ClientType RoomClientType `json:"client_type"`
|
||||||
AppType RoomAppType `json:"app_type"`
|
AppType RoomAppType `json:"app_type"`
|
||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
Room string `json:"room"`
|
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
RegisterAt time.Time `json:"register_at"`
|
RegisterAt time.Time `json:"register_at"`
|
||||||
Offer *RoomOffer `json:"offer"`
|
|
||||||
Candidate *RoomCandidate `json:"candidate"`
|
|
||||||
msgChan chan any
|
msgChan chan any
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,42 +127,25 @@ func (rc *roomClient) start(ctx context.Context) {
|
|||||||
|
|
||||||
type roomController struct {
|
type roomController struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
rooms map[string]map[string]*roomClient // map[room_id(remote-IP)][Id]
|
//rooms map[string]map[string]*roomClient // map[room_id(remote-IP)][Id]
|
||||||
notReadies map[string]*roomClient
|
clients map[string]*roomClient
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
RoomController = &roomController{
|
RoomController = &roomController{
|
||||||
rooms: make(map[string]map[string]*roomClient),
|
clients: make(map[string]*roomClient),
|
||||||
notReadies: make(map[string]*roomClient),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (rc *roomController) Start(ctx context.Context) {
|
func (rc *roomController) Start(ctx context.Context) {
|
||||||
rc.ctx = ctx
|
rc.ctx = ctx
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(1 * time.Minute)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-rc.ctx.Done():
|
|
||||||
return
|
|
||||||
case now := <-ticker.C:
|
|
||||||
for _, nrc := range rc.notReadies {
|
|
||||||
if now.Sub(nrc.RegisterAt).Minutes() > 1 {
|
|
||||||
rc.Lock()
|
|
||||||
delete(rc.notReadies, nrc.Id)
|
|
||||||
rc.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *roomController) Register(ip, userAgent string, candidate *RoomCandidate, offer *RoomOffer) *roomClient {
|
func (rc *roomController) Register(conn *websocket.Conn, ip, userAgent string) *roomClient {
|
||||||
nrc := &roomClient{
|
nrc := &roomClient{
|
||||||
controller: rc,
|
controller: rc,
|
||||||
|
conn: conn,
|
||||||
ClientType: ClientTypeDesktop,
|
ClientType: ClientTypeDesktop,
|
||||||
AppType: RoomAppTypeWeb,
|
AppType: RoomAppTypeWeb,
|
||||||
IP: ip,
|
IP: ip,
|
||||||
@ -173,8 +153,6 @@ func (rc *roomController) Register(ip, userAgent string, candidate *RoomCandidat
|
|||||||
Name: tool.RandomName(),
|
Name: tool.RandomName(),
|
||||||
msgChan: make(chan any, 1),
|
msgChan: make(chan any, 1),
|
||||||
RegisterAt: time.Now(),
|
RegisterAt: time.Now(),
|
||||||
Candidate: candidate,
|
|
||||||
Offer: offer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ua := useragent.Parse(userAgent)
|
ua := useragent.Parse(userAgent)
|
||||||
@ -185,121 +163,71 @@ func (rc *roomController) Register(ip, userAgent string, candidate *RoomCandidat
|
|||||||
nrc.ClientType = ClientTypeTablet
|
nrc.ClientType = ClientTypeTablet
|
||||||
}
|
}
|
||||||
|
|
||||||
key := "local"
|
log.Debug("controller.room: registry client, IP = %s, Id = %s, Name = %s", nrc.IP, nrc.Id, nrc.Name)
|
||||||
if !tool.IsPrivateIP(ip) {
|
|
||||||
key = ip
|
|
||||||
}
|
|
||||||
|
|
||||||
nrc.Room = key
|
nrc.start(rc.ctx)
|
||||||
|
|
||||||
|
nrc.msgChan <- map[string]any{"type": "register", "time": time.Now().UnixMilli(), "body": nrc}
|
||||||
|
rc.Broadcast(map[string]any{"type": "enter", "time": time.Now().UnixMilli(), "body": nrc})
|
||||||
|
|
||||||
rc.Lock()
|
rc.Lock()
|
||||||
|
rc.clients[nrc.Id] = nrc
|
||||||
log.Debug("controller.room: registry client, IP = %s(%s), Id = %s, Name = %s", key, nrc.IP, nrc.Id, nrc.Name)
|
|
||||||
rc.notReadies[nrc.Id] = nrc
|
|
||||||
if _, ok := rc.rooms[nrc.Room]; !ok {
|
|
||||||
rc.rooms[nrc.Room] = make(map[string]*roomClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
rc.Unlock()
|
rc.Unlock()
|
||||||
|
|
||||||
return nrc
|
return nrc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *roomController) Enter(conn *websocket.Conn, id string) {
|
func (rc *roomController) List() []*roomClient {
|
||||||
client, ok := rc.notReadies[id]
|
|
||||||
if !ok {
|
|
||||||
log.Warn("controller.room: entry room id not exist, id = %s", id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rc.Lock()
|
|
||||||
|
|
||||||
if _, ok = rc.rooms[client.Room]; !ok {
|
|
||||||
log.Warn("controller.room: entry room not exist, room = %s, id = %s, name = %s", client.Room, id, client.Name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rc.rooms[client.Room][id] = client
|
|
||||||
client.conn = conn
|
|
||||||
|
|
||||||
rc.Unlock()
|
|
||||||
|
|
||||||
client.start(rc.ctx)
|
|
||||||
|
|
||||||
rc.Broadcast(client.Room, map[string]any{"type": RoomMessageTypeEnter, "time": time.Now().UnixMilli(), "body": client})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *roomController) List(room string) []*roomClient {
|
|
||||||
log.Debug("controller.room: list room = %s", room)
|
|
||||||
clientList := make([]*roomClient, 0)
|
clientList := make([]*roomClient, 0)
|
||||||
|
|
||||||
clients, ok := rc.rooms[room]
|
for _, client := range rc.clients {
|
||||||
if !ok {
|
|
||||||
return clientList
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, client := range clients {
|
|
||||||
clientList = append(clientList, client)
|
clientList = append(clientList, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
return clientList
|
return clientList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *roomController) Broadcast(room string, msg any) {
|
func (rc *roomController) Broadcast(msg any) {
|
||||||
for _, client := range rc.rooms[room] {
|
for _, client := range rc.clients {
|
||||||
select {
|
select {
|
||||||
case client.msgChan <- msg:
|
case client.msgChan <- msg:
|
||||||
case <-time.After(2 * time.Second):
|
case <-time.After(2 * time.Second):
|
||||||
log.Warn("RoomController: broadcast timeout, room = %s, client Id = %s, IP = %s", room, client.Id, client.IP)
|
log.Warn("RoomController: broadcast timeout, client Id = %s, IP = %s", client.Id, client.IP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *roomController) Unregister(client *roomClient) {
|
func (rc *roomController) Unregister(client *roomClient) {
|
||||||
key := "local"
|
log.Debug("controller.room: unregister client, IP = %s, Id = %s, Name = %s", client.IP, client.Id, client.Name)
|
||||||
if !tool.IsPrivateIP(client.IP) {
|
|
||||||
key = client.IP
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("controller.room: unregister client, IP = %s(%s), Id = %s, Name = %s", client.IP, key, client.Id, client.Name)
|
|
||||||
|
|
||||||
rc.Lock()
|
rc.Lock()
|
||||||
delete(rc.rooms[key], client.Id)
|
delete(rc.clients, client.Id)
|
||||||
rc.Unlock()
|
rc.Unlock()
|
||||||
|
|
||||||
rc.Broadcast(key, map[string]any{"type": RoomMessageTypeLeave, "time": time.Now().UnixMilli(), "body": client})
|
rc.Broadcast(map[string]any{"type": RoomMessageTypeLeave, "time": time.Now().UnixMilli(), "body": client})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *roomController) Offer(room, id string, offer *RoomOffer) {
|
func (rc *roomController) Offer(id string, offer *RoomOffer, candidate *RoomCandidate) {
|
||||||
if _, ok := rc.rooms[room]; !ok {
|
if _, ok := rc.clients[id]; !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := rc.rooms[room][id]; !ok {
|
rc.clients[id].msgChan <- map[string]any{
|
||||||
return
|
"type": "offer",
|
||||||
}
|
"id": id,
|
||||||
|
"offer": offer,
|
||||||
rc.rooms[room][id].msgChan <- map[string]any{
|
"candidate": candidate,
|
||||||
"type": "offer",
|
|
||||||
"id": id,
|
|
||||||
"room": room,
|
|
||||||
"offer": offer,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *roomController) Answer(room, id string, answer *RoomOffer) {
|
func (rc *roomController) Answer(id string, answer *RoomOffer) {
|
||||||
if _, ok := rc.rooms[room]; !ok {
|
if _, ok := rc.clients[id]; !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := rc.rooms[room][id]; !ok {
|
rc.clients[id].msgChan <- map[string]any{
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rc.rooms[room][id].msgChan <- map[string]any{
|
|
||||||
"type": "answer",
|
"type": "answer",
|
||||||
"id": id,
|
"id": id,
|
||||||
"room": room,
|
|
||||||
"answer": answer,
|
"answer": answer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,38 +9,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LocalRegister() nf.HandlerFunc {
|
|
||||||
return func(c *nf.Ctx) error {
|
|
||||||
type Req struct {
|
|
||||||
Candidate *controller.RoomCandidate `json:"candidate"`
|
|
||||||
Offer *controller.RoomOffer `json:"offer"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
req = new(Req)
|
|
||||||
ip = c.IP(true)
|
|
||||||
ua = c.Get("User-Agent")
|
|
||||||
)
|
|
||||||
|
|
||||||
if err = c.BodyParser(req); err != nil {
|
|
||||||
return c.Status(http.StatusBadRequest).JSON(map[string]interface{}{"msg": err.Error()})
|
|
||||||
}
|
|
||||||
|
|
||||||
client := controller.RoomController.Register(ip, ua, req.Candidate, req.Offer)
|
|
||||||
|
|
||||||
return resp.Resp200(c, client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func LocalClients() nf.HandlerFunc {
|
func LocalClients() nf.HandlerFunc {
|
||||||
return func(c *nf.Ctx) error {
|
return func(c *nf.Ctx) error {
|
||||||
room := c.Query("room")
|
list := controller.RoomController.List()
|
||||||
if room == "" {
|
|
||||||
return c.Status(http.StatusBadRequest).JSON(map[string]string{"err": "room can't be empty"})
|
|
||||||
}
|
|
||||||
|
|
||||||
list := controller.RoomController.List(room)
|
|
||||||
|
|
||||||
return resp.Resp200(c, list)
|
return resp.Resp200(c, list)
|
||||||
}
|
}
|
||||||
@ -56,12 +27,10 @@ func LocalWS() nf.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return func(c *nf.Ctx) error {
|
return func(c *nf.Ctx) error {
|
||||||
|
var (
|
||||||
id := c.Query("id")
|
ip = c.IP(true)
|
||||||
|
ua = c.Get("User-Agent")
|
||||||
if id == "" {
|
)
|
||||||
return c.Status(http.StatusBadRequest).JSON(map[string]string{"error": "id is empty"})
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,7 +38,7 @@ func LocalWS() nf.HandlerFunc {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.RoomController.Enter(conn, id)
|
controller.RoomController.Register(conn, ip, ua)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -78,9 +47,9 @@ func LocalWS() nf.HandlerFunc {
|
|||||||
func LocalOffer() nf.HandlerFunc {
|
func LocalOffer() nf.HandlerFunc {
|
||||||
return func(c *nf.Ctx) error {
|
return func(c *nf.Ctx) error {
|
||||||
type Req struct {
|
type Req struct {
|
||||||
Room string `json:"room"`
|
Id string `json:"id"`
|
||||||
Id string `json:"id"`
|
Offer *controller.RoomOffer `json:"offer"`
|
||||||
Offer *controller.RoomOffer `json:"offer"`
|
Candidate *controller.RoomCandidate `json:"candidate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -92,7 +61,7 @@ func LocalOffer() nf.HandlerFunc {
|
|||||||
return c.Status(http.StatusBadRequest).JSON(map[string]string{"err": err.Error()})
|
return c.Status(http.StatusBadRequest).JSON(map[string]string{"err": err.Error()})
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.RoomController.Offer(req.Room, req.Id, req.Offer)
|
controller.RoomController.Offer(req.Id, req.Offer, req.Candidate)
|
||||||
|
|
||||||
return resp.Resp200(c, req.Offer)
|
return resp.Resp200(c, req.Offer)
|
||||||
}
|
}
|
||||||
@ -101,7 +70,6 @@ func LocalOffer() nf.HandlerFunc {
|
|||||||
func LocalAnswer() nf.HandlerFunc {
|
func LocalAnswer() nf.HandlerFunc {
|
||||||
return func(c *nf.Ctx) error {
|
return func(c *nf.Ctx) error {
|
||||||
type Req struct {
|
type Req struct {
|
||||||
Room string `json:"room"`
|
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Answer *controller.RoomOffer `json:"answer"`
|
Answer *controller.RoomOffer `json:"answer"`
|
||||||
}
|
}
|
||||||
@ -115,7 +83,7 @@ func LocalAnswer() nf.HandlerFunc {
|
|||||||
return c.Status(http.StatusBadRequest).JSON(map[string]string{"err": err.Error()})
|
return c.Status(http.StatusBadRequest).JSON(map[string]string{"err": err.Error()})
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.RoomController.Answer(req.Room, req.Id, req.Answer)
|
controller.RoomController.Answer(req.Id, req.Answer)
|
||||||
|
|
||||||
return resp.Resp200(c, req)
|
return resp.Resp200(c, req)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user