dispatch/server/websocket_handler.go

396 lines
7.9 KiB
Go
Raw Normal View History

package server
2015-01-17 01:37:21 +00:00
import (
"log"
"net"
"net/http"
"strings"
2015-01-17 01:37:21 +00:00
2016-03-01 00:51:26 +00:00
"github.com/gorilla/websocket"
"github.com/khlieng/dispatch/storage"
2015-01-17 01:37:21 +00:00
)
2015-06-16 22:46:58 +00:00
type wsHandler struct {
ws *wsConn
state *State
addr net.Addr
2015-06-16 22:46:58 +00:00
handlers map[string]func([]byte)
}
2015-06-05 22:34:13 +00:00
func newWSHandler(conn *websocket.Conn, state *State, r *http.Request) *wsHandler {
2015-06-16 22:46:58 +00:00
h := &wsHandler{
ws: newWSConn(conn),
state: state,
addr: conn.RemoteAddr(),
}
h.init(r)
h.initHandlers()
2015-06-16 22:46:58 +00:00
return h
}
2015-01-17 01:37:21 +00:00
2015-06-16 22:46:58 +00:00
func (h *wsHandler) run() {
defer h.ws.close()
go h.ws.send()
go h.ws.recv()
2015-01-17 01:37:21 +00:00
for {
2015-06-16 22:46:58 +00:00
req, ok := <-h.ws.in
2015-06-05 22:34:13 +00:00
if !ok {
if h.state != nil {
h.state.deleteWS(h.addr.String())
2015-01-17 01:37:21 +00:00
}
return
}
2015-06-16 22:46:58 +00:00
h.dispatchRequest(req)
}
}
2015-01-17 01:37:21 +00:00
2015-06-16 22:46:58 +00:00
func (h *wsHandler) dispatchRequest(req WSRequest) {
if handler, ok := h.handlers[req.Type]; ok {
handler(req.Data)
}
}
2015-01-17 01:37:21 +00:00
func (h *wsHandler) init(r *http.Request) {
2020-06-15 08:58:51 +00:00
if r.Header.Get("X-Forwarded-For") != "" {
ip := net.ParseIP(r.Header.Get("X-Forwarded-For"))
if ip != nil {
h.addr.(*net.TCPAddr).IP = ip
}
}
h.state.setWS(h.addr.String(), h.ws)
h.state.user.SetLastIP(addrToIPBytes(h.addr))
2020-05-17 01:55:46 +00:00
if r.TLS != nil {
h.state.Set("scheme", "https")
} else {
h.state.Set("scheme", "http")
}
h.state.Set("host", r.Host)
2015-01-17 01:37:21 +00:00
log.Println(h.addr, "[State] User ID:", h.state.user.ID, "|",
h.state.numIRC(), "IRC connections |",
h.state.numWS(), "WebSocket connections")
2015-01-17 01:37:21 +00:00
2020-06-15 08:58:51 +00:00
go h.sendData(r)
}
2020-06-15 08:58:51 +00:00
func (h *wsHandler) sendData(r *http.Request) {
tab, err := tabFromRequest(r)
if err != nil {
log.Println(err)
}
2015-01-17 01:37:21 +00:00
2020-06-15 08:58:51 +00:00
h.state.lock.Lock()
for _, network := range h.state.networks {
for _, channel := range network.ChannelNames() {
if network.Host == tab.Network && channel == tab.Name {
// Userlist and messages for this channel gets embedded in the index page
continue
}
if users := network.Client().ChannelUsers(channel); len(users) > 0 {
h.state.sendJSON("users", Userlist{
Network: network.Host,
Channel: channel,
Users: users,
})
}
2020-06-15 08:58:51 +00:00
h.state.sendLastMessages(network.Host, channel, 50)
}
2015-06-16 22:46:58 +00:00
}
2020-06-15 08:58:51 +00:00
h.state.lock.Unlock()
2020-06-15 08:58:51 +00:00
openDMs, err := h.state.user.OpenDMs()
if err != nil {
log.Println(err)
}
for _, openDM := range openDMs {
2020-06-15 08:58:51 +00:00
if openDM.Network == tab.Network && openDM.Name == tab.Name {
continue
}
2020-06-15 08:58:51 +00:00
h.state.sendLastMessages(openDM.Network, openDM.Name, 50)
}
2015-06-16 22:46:58 +00:00
}
2015-01-17 01:37:21 +00:00
2015-06-16 22:46:58 +00:00
func (h *wsHandler) connect(b []byte) {
2020-06-15 08:58:51 +00:00
var network storage.Network
network.UnmarshalJSON(b)
2015-01-17 01:37:21 +00:00
2020-06-15 08:58:51 +00:00
network.Host = strings.ToLower(network.Host)
2019-01-23 06:34:39 +00:00
2020-06-15 08:58:51 +00:00
if _, ok := h.state.network(network.Host); !ok {
log.Println(h.addr, "[IRC] Add server", network.Host)
2015-01-17 01:37:21 +00:00
2020-06-15 08:58:51 +00:00
connectIRC(&network, h.state, addrToIPBytes(h.addr))
2020-06-15 08:58:51 +00:00
go network.Save()
2015-06-16 22:46:58 +00:00
} else {
2020-06-15 08:58:51 +00:00
log.Println(h.addr, "[IRC]", network.Host, "already added")
2015-06-16 22:46:58 +00:00
}
}
func (h *wsHandler) reconnect(b []byte) {
var data ReconnectSettings
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok && !i.Connected() {
2020-05-23 07:42:20 +00:00
if i.Config.TLS {
i.Config.TLSConfig.InsecureSkipVerify = data.SkipVerify
}
i.Reconnect()
}
}
2015-06-16 22:46:58 +00:00
func (h *wsHandler) join(b []byte) {
var data Join
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2015-01-17 01:37:21 +00:00
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2015-06-16 22:46:58 +00:00
i.Join(data.Channels...)
}
}
2015-01-17 01:37:21 +00:00
2015-06-16 22:46:58 +00:00
func (h *wsHandler) part(b []byte) {
var data Part
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2015-02-04 01:43:49 +00:00
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2015-06-16 22:46:58 +00:00
i.Part(data.Channels...)
}
2020-06-15 08:58:51 +00:00
go func() {
if network, ok := h.state.network(data.Network); ok {
network.RemoveChannels(data.Channels...)
}
for _, channel := range data.Channels {
h.state.user.RemoveChannel(data.Network, channel)
}
}()
2015-06-16 22:46:58 +00:00
}
2015-02-04 01:43:49 +00:00
2015-06-16 22:46:58 +00:00
func (h *wsHandler) quit(b []byte) {
var data Quit
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2015-02-04 01:43:49 +00:00
2020-06-15 08:58:51 +00:00
log.Println(h.addr, "[IRC] Remove server", data.Network)
if i, ok := h.state.client(data.Network); ok {
h.state.deleteNetwork(data.Network)
2017-07-03 05:35:38 +00:00
i.Quit()
2015-06-16 22:46:58 +00:00
}
2017-07-03 05:35:38 +00:00
2020-06-15 08:58:51 +00:00
go h.state.user.RemoveNetwork(data.Network)
2015-06-16 22:46:58 +00:00
}
func (h *wsHandler) message(b []byte) {
var data Message
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
i.Privmsg(data.To, data.Content)
2017-04-20 03:32:22 +00:00
go h.state.user.LogMessage(&storage.Message{
2020-06-15 08:58:51 +00:00
Network: data.Network,
From: i.GetNick(),
To: data.To,
Content: data.Content,
})
2015-06-16 22:46:58 +00:00
}
}
2015-06-16 22:46:58 +00:00
func (h *wsHandler) nick(b []byte) {
var data Nick
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2015-06-16 22:46:58 +00:00
i.Nick(data.New)
}
}
func (h *wsHandler) topic(b []byte) {
var data Topic
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
i.Topic(data.Channel, data.Topic)
}
}
2015-06-16 22:46:58 +00:00
func (h *wsHandler) invite(b []byte) {
var data Invite
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2015-06-16 22:46:58 +00:00
i.Invite(data.User, data.Channel)
}
}
2015-06-16 22:46:58 +00:00
func (h *wsHandler) kick(b []byte) {
var data Invite
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2015-06-16 22:46:58 +00:00
i.Kick(data.Channel, data.User)
}
}
2015-06-16 22:46:58 +00:00
func (h *wsHandler) whois(b []byte) {
var data Whois
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2015-02-21 12:06:05 +00:00
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2015-06-16 22:46:58 +00:00
i.Whois(data.User)
}
}
2015-02-21 12:06:05 +00:00
2015-06-16 22:46:58 +00:00
func (h *wsHandler) away(b []byte) {
var data Away
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2015-02-21 12:06:05 +00:00
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2015-06-16 22:46:58 +00:00
i.Away(data.Message)
}
}
2016-01-27 19:48:47 +00:00
func (h *wsHandler) raw(b []byte) {
var data Raw
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2016-01-27 19:48:47 +00:00
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok {
2016-01-27 19:48:47 +00:00
i.Write(data.Message)
}
}
2015-06-16 22:46:58 +00:00
func (h *wsHandler) search(b []byte) {
go func() {
var data SearchRequest
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
results, err := h.state.user.SearchMessages(data.Network, data.Channel, data.Phrase)
2015-06-16 22:46:58 +00:00
if err != nil {
log.Println(err)
return
}
h.state.sendJSON("search", SearchResult{
2020-06-15 08:58:51 +00:00
Network: data.Network,
2015-06-16 22:46:58 +00:00
Channel: data.Channel,
Results: results,
})
}()
}
2016-01-11 20:04:57 +00:00
func (h *wsHandler) cert(b []byte) {
var data ClientCert
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2016-01-11 20:04:57 +00:00
2018-10-10 19:23:42 +00:00
err := h.state.user.SetCertificate([]byte(data.Cert), []byte(data.Key))
2016-01-11 20:04:57 +00:00
if err != nil {
h.state.sendJSON("cert_fail", Error{Message: err.Error()})
2016-01-11 20:04:57 +00:00
return
}
h.state.sendJSON("cert_success", nil)
2016-01-11 20:04:57 +00:00
}
2017-05-02 21:21:25 +00:00
func (h *wsHandler) fetchMessages(b []byte) {
var data FetchMessages
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2017-05-02 21:21:25 +00:00
2020-06-15 08:58:51 +00:00
h.state.sendMessages(data.Network, data.Channel, 200, data.Next)
2017-05-02 21:21:25 +00:00
}
2020-06-15 08:58:51 +00:00
func (h *wsHandler) setNetworkName(b []byte) {
var data NetworkName
2018-05-25 21:54:36 +00:00
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
if isValidNetworkName(data.Name) {
if network, ok := h.state.network(data.Network); ok {
network.SetName(data.Name)
go network.Save()
}
}
}
2018-10-15 06:56:17 +00:00
func (h *wsHandler) setSettings(b []byte) {
err := h.state.user.UnmarshalClientSettingsJSON(b)
if err != nil {
log.Println(err)
}
}
2019-01-23 06:34:39 +00:00
func (h *wsHandler) channelSearch(b []byte) {
var data ChannelSearch
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
index, needsUpdate := channelIndexes.Get(data.Network)
2019-01-23 06:34:39 +00:00
if index != nil {
n := 10
if data.Start > 0 {
n = 50
}
h.state.sendJSON("channel_search", ChannelSearchResult{
2020-05-03 07:05:16 +00:00
ChannelSearch: data,
Results: index.SearchN(data.Q, data.Start, n),
2019-01-23 06:34:39 +00:00
})
}
2020-06-15 08:58:51 +00:00
if i, ok := h.state.client(data.Network); ok && needsUpdate {
h.state.Set("update_chanlist_"+data.Network, true)
2019-01-23 06:34:39 +00:00
i.List()
}
}
func (h *wsHandler) openDM(b []byte) {
var data Tab
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
h.state.sendLastMessages(data.Network, data.Name, 50)
h.state.user.AddOpenDM(data.Network, data.Name)
}
func (h *wsHandler) closeDM(b []byte) {
var data Tab
data.UnmarshalJSON(b)
2020-06-15 08:58:51 +00:00
h.state.user.RemoveOpenDM(data.Network, data.Name)
}
2015-06-16 22:46:58 +00:00
func (h *wsHandler) initHandlers() {
h.handlers = map[string]func([]byte){
2020-06-15 08:58:51 +00:00
"connect": h.connect,
"reconnect": h.reconnect,
"join": h.join,
"part": h.part,
"quit": h.quit,
"message": h.message,
"nick": h.nick,
"topic": h.topic,
"invite": h.invite,
"kick": h.kick,
"whois": h.whois,
"away": h.away,
"raw": h.raw,
"search": h.search,
"cert": h.cert,
"fetch_messages": h.fetchMessages,
"set_network_name": h.setNetworkName,
"settings_set": h.setSettings,
"channel_search": h.channelSearch,
"open_dm": h.openDM,
"close_dm": h.closeDM,
2015-01-17 01:37:21 +00:00
}
}
2020-06-15 08:58:51 +00:00
func isValidNetworkName(name string) bool {
return strings.TrimSpace(name) != ""
}