mirror of
https://github.com/screego/server.git
synced 2026-11-02 20:12:06 +08:00
* User1 connects with IPv6 * User2 connects with IPv4 (without any support for IPv6) * User1 asks via STUN for his address, and receives a IPv6 address back * User2 asks via STUN for his address, and receives a IPv4 address back * User2 cannot connect to User1 IPv6 address After this fix: User1 asks both for his IPv4 and IPv6 addresses. See #56
147 lines
3.5 KiB
Go
147 lines
3.5 KiB
Go
package ws
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"sort"
|
|
|
|
"github.com/rs/xid"
|
|
"github.com/screego/server/config"
|
|
"github.com/screego/server/util"
|
|
"github.com/screego/server/ws/outgoing"
|
|
)
|
|
|
|
type ConnectionMode string
|
|
|
|
const (
|
|
ConnectionLocal ConnectionMode = "local"
|
|
ConnectionSTUN ConnectionMode = "stun"
|
|
ConnectionTURN ConnectionMode = config.AuthModeTurn
|
|
)
|
|
|
|
type Room struct {
|
|
ID string
|
|
CloseOnOwnerLeave bool
|
|
Mode ConnectionMode
|
|
Users map[xid.ID]*User
|
|
Sessions map[xid.ID]*RoomSession
|
|
}
|
|
|
|
const (
|
|
CloseOwnerLeft = "Owner Left"
|
|
CloseDone = "Read End"
|
|
)
|
|
|
|
func (r *Room) newSession(host, client xid.ID, rooms *Rooms) {
|
|
id := xid.New()
|
|
r.Sessions[id] = &RoomSession{
|
|
Host: host,
|
|
Client: client,
|
|
}
|
|
sessionCreatedTotal.Inc()
|
|
|
|
iceHost := []outgoing.ICEServer{}
|
|
iceClient := []outgoing.ICEServer{}
|
|
switch r.Mode {
|
|
case ConnectionLocal:
|
|
case ConnectionSTUN:
|
|
iceHost = []outgoing.ICEServer{{URLs: rooms.addresses("stun", false)}}
|
|
iceClient = []outgoing.ICEServer{{URLs: rooms.addresses("stun", false)}}
|
|
case ConnectionTURN:
|
|
hostPW := util.RandString(20)
|
|
clientPW := util.RandString(20)
|
|
hostName := id.String() + "host"
|
|
rooms.turnServer.Allow(hostName, hostPW, r.Users[host].Addr)
|
|
clientName := id.String() + "client"
|
|
rooms.turnServer.Allow(clientName, clientPW, r.Users[client].Addr)
|
|
iceHost = []outgoing.ICEServer{{
|
|
URLs: rooms.addresses("turn", true),
|
|
Credential: hostPW,
|
|
Username: hostName,
|
|
}}
|
|
iceClient = []outgoing.ICEServer{{
|
|
URLs: rooms.addresses("turn", true),
|
|
Credential: clientPW,
|
|
Username: clientName,
|
|
}}
|
|
|
|
}
|
|
r.Users[host].Write <- outgoing.HostSession{Peer: client, ID: id, ICEServers: iceHost}
|
|
r.Users[client].Write <- outgoing.ClientSession{Peer: host, ID: id, ICEServers: iceClient}
|
|
}
|
|
|
|
func (r *Rooms) addresses(prefix string, tcp bool) (result []string) {
|
|
if r.config.ExternalIPV4 != nil {
|
|
result = append(result, fmt.Sprintf("%s:%s:%s", prefix, r.config.ExternalIPV4.String(), r.turnServer.Port))
|
|
if tcp {
|
|
result = append(result, fmt.Sprintf("%s:%s:%s?transport=tcp", prefix, r.config.ExternalIPV4.String(), r.turnServer.Port))
|
|
}
|
|
}
|
|
if r.config.ExternalIPV6 != nil {
|
|
result = append(result, fmt.Sprintf("%s:[%s]:%s", prefix, r.config.ExternalIPV6.String(), r.turnServer.Port))
|
|
if tcp {
|
|
result = append(result, fmt.Sprintf("%s:[%s]:%s?transport=tcp", prefix, r.config.ExternalIPV6.String(), r.turnServer.Port))
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (r *Room) closeSession(rooms *Rooms, id xid.ID) {
|
|
if r.Mode == ConnectionTURN {
|
|
rooms.turnServer.Disallow(id.String() + "host")
|
|
rooms.turnServer.Disallow(id.String() + "client")
|
|
}
|
|
delete(r.Sessions, id)
|
|
sessionClosedTotal.Inc()
|
|
}
|
|
|
|
type RoomSession struct {
|
|
Host xid.ID
|
|
Client xid.ID
|
|
}
|
|
|
|
func (r *Room) notifyInfoChanged() {
|
|
for _, current := range r.Users {
|
|
users := []outgoing.User{}
|
|
for _, user := range r.Users {
|
|
users = append(users, outgoing.User{
|
|
ID: user.ID,
|
|
Name: user.Name,
|
|
Streaming: user.Streaming,
|
|
You: current == user,
|
|
Owner: user.Owner,
|
|
})
|
|
}
|
|
|
|
sort.Slice(users, func(i, j int) bool {
|
|
left := users[i]
|
|
right := users[j]
|
|
|
|
if left.Owner != right.Owner {
|
|
return left.Owner
|
|
}
|
|
|
|
if left.Streaming != right.Streaming {
|
|
return left.Streaming
|
|
}
|
|
|
|
return left.Name < right.Name
|
|
})
|
|
|
|
current.Write <- outgoing.Room{
|
|
ID: r.ID,
|
|
Users: users,
|
|
}
|
|
}
|
|
}
|
|
|
|
type User struct {
|
|
ID xid.ID
|
|
Addr net.IP
|
|
Name string
|
|
Streaming bool
|
|
Owner bool
|
|
Write chan<- outgoing.Message
|
|
Close chan<- string
|
|
}
|