Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
geronimo
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sand
geronimo
Commits
5a64ce6b
Commit
5a64ce6b
authored
Aug 01, 2018
by
Daniel Kertesz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more names refactoring
parent
7419c895
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
117 additions
and
129 deletions
+117
-129
channels.go
channels.go
+7
-7
client.go
client/client.go
+26
-33
config.go
config.go
+2
-0
handlers.go
handlers.go
+39
-39
replies.go
replies.go
+5
-5
server.go
server.go
+38
-45
No files found.
channels.go
View file @
5a64ce6b
...
...
@@ -15,7 +15,7 @@ type Channel struct {
TopicTime
time
.
Time
Password
string
BanList
[]
Hostmask
Members
map
[
client
.
GUID
]
*
client
.
Client
Members
map
[
client
.
GUID
]
*
client
.
User
Privileges
map
[
client
.
GUID
]
utils
.
Flags
Modes
utils
.
Flags
}
...
...
@@ -25,7 +25,7 @@ func NewChannel(name string) *Channel {
Name
:
name
,
Modes
:
utils
.
NewChannelFlags
(),
Created
:
time
.
Now
(),
Members
:
make
(
map
[
client
.
GUID
]
*
client
.
Client
),
Members
:
make
(
map
[
client
.
GUID
]
*
client
.
User
),
Privileges
:
make
(
map
[
client
.
GUID
]
utils
.
Flags
),
}
...
...
@@ -49,7 +49,7 @@ func (ch *Channel) SerializeChanModes(includePassword bool) string {
return
rv
}
func
(
ch
*
Channel
)
addMember
(
cli
*
client
.
Client
)
{
func
(
ch
*
Channel
)
addMember
(
cli
*
client
.
User
)
{
var
isFounder
bool
=
false
if
len
(
ch
.
Members
)
==
0
{
...
...
@@ -65,7 +65,7 @@ func (ch *Channel) addMember(cli *client.Client) {
cli
.
AddChannel
(
ch
.
Name
)
}
func
(
ch
*
Channel
)
removeMember
(
cli
*
client
.
Client
)
{
func
(
ch
*
Channel
)
removeMember
(
cli
*
client
.
User
)
{
if
_
,
ok
:=
ch
.
Members
[
cli
.
GUID
()];
ok
{
delete
(
ch
.
Members
,
cli
.
GUID
())
}
...
...
@@ -76,12 +76,12 @@ func (ch *Channel) removeMember(cli *client.Client) {
cli
.
RemoveChannel
(
ch
.
Name
)
}
func
(
ch
*
Channel
)
hasClient
(
cli
*
client
.
Client
)
bool
{
func
(
ch
*
Channel
)
hasClient
(
cli
*
client
.
User
)
bool
{
_
,
ok
:=
ch
.
Members
[
cli
.
GUID
()]
return
ok
}
func
(
ch
*
Channel
)
isVoice
(
cli
*
client
.
Client
)
bool
{
func
(
ch
*
Channel
)
isVoice
(
cli
*
client
.
User
)
bool
{
if
flags
,
ok
:=
ch
.
Privileges
[
cli
.
GUID
()];
ok
{
return
flags
.
Has
(
utils
.
CHAN_VOICE
)
}
...
...
@@ -90,7 +90,7 @@ func (ch *Channel) isVoice(cli *client.Client) bool {
return
false
}
func
(
ch
*
Channel
)
isOp
(
cli
*
client
.
Client
)
bool
{
func
(
ch
*
Channel
)
isOp
(
cli
*
client
.
User
)
bool
{
if
flags
,
ok
:=
ch
.
Privileges
[
cli
.
GUID
()];
ok
{
return
flags
.
Has
(
utils
.
CHAN_OP
)
}
...
...
client/client.go
View file @
5a64ce6b
...
...
@@ -17,10 +17,6 @@ const (
// maximum number of lines in a client queue before... we do something.
ClientWriteQueue
=
256
// ClientEvent event types
CONNECTED
=
iota
DISCONNECTED
// Connection statuses
PRE_REGISTRATION
=
iota
CAP_NEGOTIATION
...
...
@@ -30,18 +26,15 @@ const (
type
GUID
string
type
ClientMessage
struct
{
C
*
Client
M
*
message
.
Message
}
type
ClientEvent
struct
{
C
*
Client
Type
int
type
UserEvent
struct
{
User
*
User
Connected
bool
Disconnected
bool
Message
*
message
.
Message
}
//
Client
is any IRC client connection
type
Client
struct
{
//
User
is any IRC client connection
type
User
struct
{
conn
net
.
Conn
// this must be buffered!
...
...
@@ -67,11 +60,11 @@ type Client struct {
log
*
log
.
Entry
}
func
(
c
*
Client
)
String
()
string
{
func
(
c
*
User
)
String
()
string
{
return
fmt
.
Sprintf
(
"<Client(nick=%q, ident=%q, host=%q, realname=%q)>"
,
c
.
Nick
,
c
.
Ident
,
c
.
Host
,
c
.
Realname
)
}
func
New
(
conn
net
.
Conn
)
(
*
Client
,
error
)
{
func
New
(
conn
net
.
Conn
)
(
*
User
,
error
)
{
id
:=
uuid
.
NewV4
()
now
:=
time
.
Now
()
...
...
@@ -93,7 +86,7 @@ func New(conn net.Conn) (*Client, error) {
remoteHost
=
names
[
0
]
}
c
:=
&
Client
{
c
:=
&
User
{
// It's common practice to set the nickname as "*" before the client registers
Nick
:
"*"
,
LoginTime
:
now
,
...
...
@@ -111,39 +104,39 @@ func New(conn net.Conn) (*Client, error) {
}
// Hostmask returns the hostmask for a user, in the format "ident!user@hostname"
func
(
c
*
Client
)
Hostmask
()
string
{
func
(
c
*
User
)
Hostmask
()
string
{
return
fmt
.
Sprintf
(
"%s!%s@%s"
,
c
.
Nick
,
c
.
Ident
,
c
.
Host
)
}
func
(
c
*
Client
)
IsRegistered
()
bool
{
func
(
c
*
User
)
IsRegistered
()
bool
{
return
c
.
State
>=
REGISTERED
}
func
(
c
*
Client
)
IsAway
()
bool
{
func
(
c
*
User
)
IsAway
()
bool
{
return
c
.
Flags
.
Has
(
utils
.
USER_AWAY
)
}
func
(
c
*
Client
)
SetAway
(
message
string
)
{
func
(
c
*
User
)
SetAway
(
message
string
)
{
c
.
awayReason
=
message
c
.
Flags
.
Set
(
utils
.
USER_AWAY
)
}
func
(
c
*
Client
)
ClearAway
()
{
func
(
c
*
User
)
ClearAway
()
{
c
.
awayReason
=
""
c
.
Flags
.
Unset
(
utils
.
USER_AWAY
)
}
func
(
c
*
Client
)
AwayReason
()
string
{
func
(
c
*
User
)
AwayReason
()
string
{
return
c
.
awayReason
}
func
(
c
*
Client
)
UpdateLastMessage
()
{
func
(
c
*
User
)
UpdateLastMessage
()
{
c
.
LastMessage
=
time
.
Now
()
}
// Reader reads from the client socket, parse each line as "IRC message" and write the message to
// the processing channel (inChan).
func
(
c
*
Client
)
Reader
(
inChan
chan
<-
ClientMessage
,
cliChan
chan
<-
Client
Event
)
{
func
(
c
*
User
)
Reader
(
userEvents
chan
<-
User
Event
)
{
scanner
:=
bufio
.
NewScanner
(
c
.
conn
)
for
scanner
.
Scan
()
{
...
...
@@ -154,7 +147,7 @@ func (c *Client) Reader(inChan chan<- ClientMessage, cliChan chan<- ClientEvent)
if
err
!=
nil
{
panic
(
err
)
}
inChan
<-
ClientMessage
{
c
,
msg
}
userEvents
<-
UserEvent
{
User
:
c
,
Message
:
msg
}
}
if
err
:=
scanner
.
Err
();
err
!=
nil
{
...
...
@@ -162,14 +155,14 @@ func (c *Client) Reader(inChan chan<- ClientMessage, cliChan chan<- ClientEvent)
}
// see http://www.tapirgames.com/blog/golang-channel-closing
cliChan
<-
ClientEvent
{
C
:
c
,
Type
:
DISCONNECTED
}
userEvents
<-
UserEvent
{
User
:
c
,
Disconnected
:
true
}
c
.
log
.
Debug
(
"Exiting Reader"
)
c
.
exitWriter
()
}
// TODO: find a way to send writes to a client and then close the connection; this will be used to
// send error messages and then terminate the client session.
func
(
c
*
Client
)
Writer
()
{
func
(
c
*
User
)
Writer
()
{
for
line
:=
range
c
.
Out
{
c
.
log
.
Debugf
(
">> %s"
,
line
)
payload
:=
[]
byte
(
line
+
"
\r\n
"
)
...
...
@@ -189,24 +182,24 @@ func (c *Client) Writer() {
}
// exitWriter closes the output channel, shutting down the goroutine that runs WriteResponse()
func
(
c
*
Client
)
exitWriter
()
{
func
(
c
*
User
)
exitWriter
()
{
close
(
c
.
Out
)
}
func
(
c
*
Client
)
CloseConnection
()
error
{
func
(
c
*
User
)
CloseConnection
()
error
{
c
.
log
.
Info
(
"Server closing connection for client"
)
return
c
.
conn
.
Close
()
}
func
(
c
*
Client
)
GUID
()
GUID
{
func
(
c
*
User
)
GUID
()
GUID
{
return
GUID
(
c
.
Id
.
String
())
}
func
(
c
*
Client
)
AddChannel
(
name
string
)
{
func
(
c
*
User
)
AddChannel
(
name
string
)
{
c
.
Channels
=
append
(
c
.
Channels
,
name
)
}
func
(
c
*
Client
)
RemoveChannel
(
name
string
)
{
func
(
c
*
User
)
RemoveChannel
(
name
string
)
{
rv
:=
make
([]
string
,
0
,
len
(
c
.
Channels
))
for
_
,
c
:=
range
c
.
Channels
{
if
c
!=
name
{
...
...
config.go
View file @
5a64ce6b
...
...
@@ -39,6 +39,8 @@ type ListenConfig struct {
Key
string
`yaml:"key"`
// Proxy enable HA-PROXY support.
Proxy
bool
`yaml:"proxy"`
// Server enable connections from other servers
Server
bool
`yaml:"server"`
}
type
AdminConfig
struct
{
...
...
handlers.go
View file @
5a64ce6b
This diff is collapsed.
Click to expand it.
replies.go
View file @
5a64ce6b
...
...
@@ -8,27 +8,27 @@ import (
)
// 461 ERR_NEEDMOREPARAMS
func
(
s
*
Server
)
replyNeedMoreParams
(
cli
*
client
.
Client
,
command
string
)
{
func
(
s
*
Server
)
replyNeedMoreParams
(
cli
*
client
.
User
,
command
string
)
{
s
.
send
(
cli
,
message
.
NewMessage
(
"461"
,
[]
string
{
cli
.
Nick
,
command
},
"Not enough parameters"
))
}
// 403 ERR_NOSUCHCHANNEL
func
(
s
*
Server
)
replyNoSuchChannel
(
cli
*
client
.
Client
,
name
string
)
{
func
(
s
*
Server
)
replyNoSuchChannel
(
cli
*
client
.
User
,
name
string
)
{
s
.
send
(
cli
,
message
.
NewMessage
(
"403"
,
[]
string
{
cli
.
Nick
,
name
},
"No such channel"
))
}
//411 ERR_NORECIPIENT
func
(
s
*
Server
)
replyNoRecipient
(
cli
*
client
.
Client
,
command
string
)
{
func
(
s
*
Server
)
replyNoRecipient
(
cli
*
client
.
User
,
command
string
)
{
s
.
send
(
cli
,
message
.
NewMessage
(
"411"
,
[]
string
{
cli
.
Nick
},
fmt
.
Sprintf
(
"No recipient given (%s)"
,
command
)))
}
// 401 ERR_NOSUCHNICK
func
(
s
*
Server
)
replyNoSuchNick
(
cli
*
client
.
Client
,
nick
string
)
{
func
(
s
*
Server
)
replyNoSuchNick
(
cli
*
client
.
User
,
nick
string
)
{
s
.
send
(
cli
,
message
.
NewMessage
(
"401"
,
[]
string
{
cli
.
Nick
,
nick
},
"No such nick/channel"
))
}
// 315 RPL_ENDOFWHO
func
(
srv
*
Server
)
replyWhoEnd
(
cli
*
client
.
Client
,
name
string
)
{
func
(
srv
*
Server
)
replyWhoEnd
(
cli
*
client
.
User
,
name
string
)
{
resp
:=
message
.
NewMessage
(
"315"
,
[]
string
{
cli
.
Nick
,
name
},
"End of /WHO list"
)
srv
.
send
(
cli
,
resp
)
}
server.go
View file @
5a64ce6b
...
...
@@ -59,8 +59,8 @@ type Server struct {
handlers
map
[
string
]
ircCmdHandler
channels
map
[
string
]
*
Channel
clients
map
[
uuid
.
UUID
]
*
client
.
Client
// ID -> client
nicknames
map
[
string
]
uuid
.
UUID
// nickname -> ID
clients
map
[
uuid
.
UUID
]
*
client
.
User
// ID -> client
nicknames
map
[
string
]
uuid
.
UUID
// nickname -> ID
ExitChan
chan
bool
config
*
Config
...
...
@@ -84,7 +84,7 @@ func NewServer(config *Config) *Server {
startTime
:
time
.
Now
(),
handlers
:
make
(
map
[
string
]
ircCmdHandler
),
channels
:
make
(
map
[
string
]
*
Channel
),
clients
:
make
(
map
[
uuid
.
UUID
]
*
client
.
Client
),
clients
:
make
(
map
[
uuid
.
UUID
]
*
client
.
User
),
nicknames
:
make
(
map
[
string
]
uuid
.
UUID
),
ExitChan
:
make
(
chan
bool
,
1
),
...
...
@@ -134,20 +134,17 @@ func (srv *Server) StartServer() {
log
.
Debug
(
"Starting main loop"
)
// inChan is used to fan-in messages from all the connected clients
inChan
:=
make
(
chan
client
.
ClientMessage
)
// cliChan is used to process client related events (new connections and lost connections)
cliChan
:=
make
(
chan
client
.
ClientEvent
)
userEvents
:=
make
(
chan
client
.
UserEvent
)
for
_
,
lconf
:=
range
srv
.
config
.
Listen
{
log
.
Infof
(
"Starting IRC server on: %s (TLS: %v, Proxy: %v)"
,
lconf
.
Address
,
lconf
.
TLS
,
lconf
.
Proxy
)
go
srv
.
listen
(
lconf
,
inChan
,
cliChan
)
go
srv
.
listen
(
lconf
,
userEvents
)
}
go
srv
.
mainLoop
(
inChan
,
cliChan
)
go
srv
.
mainLoop
(
userEvents
)
}
func
(
srv
*
Server
)
listen
(
lconf
*
ListenConfig
,
inChan
chan
<-
client
.
ClientMessage
,
cliChan
chan
<-
client
.
Client
Event
)
{
func
(
srv
*
Server
)
listen
(
lconf
*
ListenConfig
,
userEvents
chan
<-
client
.
User
Event
)
{
listener
,
err
:=
net
.
Listen
(
"tcp"
,
lconf
.
Address
)
if
err
!=
nil
{
panic
(
err
)
...
...
@@ -175,21 +172,21 @@ func (srv *Server) listen(lconf *ListenConfig, inChan chan<- client.ClientMessag
})
.
Info
(
"New client connection"
)
// Each new client is handled in its own goroutine to allow DNS resolution without blocking the listening goroutine (this one)
go
srv
.
newClientConnection
(
conn
,
inChan
,
cliChan
)
go
srv
.
newClientConnection
(
conn
,
userEvents
)
}
}
// newClientConnection handles new client connections; it needs to be a goroutine because it does DNS resolution.
// TODO: start a goroutine that will kill this connection if it doesn't transition to the "registered" state in X seconds.
func
(
srv
*
Server
)
newClientConnection
(
conn
net
.
Conn
,
inChan
chan
<-
client
.
ClientMessage
,
cliChan
chan
<-
client
.
Client
Event
)
{
func
(
srv
*
Server
)
newClientConnection
(
conn
net
.
Conn
,
userEvents
chan
<-
client
.
User
Event
)
{
cli
,
err
:=
client
.
New
(
conn
)
if
err
!=
nil
{
log
.
Errorf
(
"Error creating client object: %s"
,
err
.
Error
())
conn
.
Close
()
return
}
cliChan
<-
client
.
ClientEvent
{
C
:
cli
,
Type
:
client
.
CONNECTED
}
go
cli
.
Reader
(
inChan
,
cliChan
)
userEvents
<-
client
.
UserEvent
{
User
:
cli
,
Connected
:
true
}
go
cli
.
Reader
(
userEvents
)
go
cli
.
Writer
()
}
...
...
@@ -197,37 +194,33 @@ func (srv *Server) newClientConnection(conn net.Conn, inChan chan<- client.Clien
// incoming commands from 'inChan'. It also handles new IRC (network) connections.
// NOTE:
// the server handles incoming messages sequentially.
func
(
srv
*
Server
)
mainLoop
(
inChan
<-
chan
client
.
ClientMessage
,
cliChan
<-
chan
client
.
Client
Event
)
{
func
(
srv
*
Server
)
mainLoop
(
userEvents
<-
chan
client
.
User
Event
)
{
for
{
select
{
case
climsg
:=
<-
inChan
:
if
!
climsg
.
C
.
IsRegistered
()
||
climsg
.
C
.
Nick
==
""
||
climsg
.
C
.
Ident
==
""
{
if
!
isPreRegCommand
(
climsg
.
M
.
Command
)
{
log
.
Warnf
(
"Client %q attempted a command before being registered"
,
climsg
.
C
)
resp
:=
message
.
NewMessage
(
"451"
,
[]
string
{},
"You have not registered"
)
srv
.
send
(
climsg
.
C
,
resp
)
continue
case
event
:=
<-
userEvents
:
if
event
.
Connected
{
srv
.
addNewClient
(
event
.
User
)
}
else
if
event
.
Disconnected
{
srv
.
removeClient
(
event
.
User
)
}
else
{
if
!
event
.
User
.
IsRegistered
()
||
event
.
User
.
Nick
==
""
||
event
.
User
.
Ident
==
""
{
if
!
isPreRegCommand
(
event
.
Message
.
Command
)
{
log
.
Warnf
(
"Client %q attempted a command before being registered"
,
event
.
User
)
resp
:=
message
.
NewMessage
(
"451"
,
[]
string
{},
"You have not registered"
)
srv
.
send
(
event
.
User
,
resp
)
continue
}
}
}
if
handler
,
ok
:=
srv
.
handlers
[
climsg
.
M
.
Command
];
ok
{
if
climsg
.
M
.
Command
!=
"PING"
{
log
.
Infof
(
"Handling command '%s' with args: %q, %q"
,
climsg
.
M
.
Command
,
climsg
.
M
.
Args
,
climsg
.
M
.
Trailing
)
if
handler
,
ok
:=
srv
.
handlers
[
event
.
Message
.
Command
];
ok
{
if
event
.
Message
.
Command
!=
"PING"
{
log
.
Infof
(
"Handling command '%s' with args: %q, %q"
,
event
.
Message
.
Command
,
event
.
Message
.
Args
,
event
.
Message
.
Trailing
)
}
handler
(
event
.
User
,
event
.
Message
)
}
else
{
log
.
Warnf
(
"handler not found for command %s (%q)"
,
event
.
Message
.
Command
,
event
.
Message
.
Args
)
}
handler
(
climsg
.
C
,
climsg
.
M
)
}
else
{
log
.
Warnf
(
"handler not found for command %s (%q)"
,
climsg
.
M
.
Command
,
climsg
.
M
.
Args
)
}
case
event
:=
<-
cliChan
:
if
event
.
Type
==
client
.
CONNECTED
{
srv
.
addNewClient
(
event
.
C
)
}
else
if
event
.
Type
==
client
.
DISCONNECTED
{
srv
.
removeClient
(
event
.
C
)
}
else
{
log
.
Errorf
(
"Unknown event type: %q"
,
event
)
}
case
<-
srv
.
ExitChan
:
log
.
Info
(
"Quitting server (ExitChan triggered)"
)
return
...
...
@@ -236,7 +229,7 @@ func (srv *Server) mainLoop(inChan <-chan client.ClientMessage, cliChan <-chan c
}
// send send a Response to a client. It inserts the Source prefix when needed.
func
(
s
*
Server
)
send
(
cli
*
client
.
Client
,
msg
*
message
.
Message
)
{
func
(
s
*
Server
)
send
(
cli
*
client
.
User
,
msg
*
message
.
Message
)
{
t
:=
[]
string
{}
if
msg
.
Source
!=
""
{
t
=
append
(
t
,
":"
+
msg
.
Source
)
...
...
@@ -265,14 +258,14 @@ func (s *Server) send(cli *client.Client, msg *message.Message) {
}
// addNewClient is called when a new client connects
func
(
srv
*
Server
)
addNewClient
(
cli
*
client
.
Client
)
{
func
(
srv
*
Server
)
addNewClient
(
cli
*
client
.
User
)
{
log
.
Debugf
(
"Adding client: %v"
,
cli
.
Id
.
String
())
srv
.
clients
[
cli
.
Id
]
=
cli
metrics
.
ClientsConnected
.
Inc
()
}
// removeClient is called when a client is no longer connected
func
(
srv
*
Server
)
removeClient
(
cli
*
client
.
Client
)
{
func
(
srv
*
Server
)
removeClient
(
cli
*
client
.
User
)
{
log
.
Debugf
(
"Removing client: %v"
,
cli
.
Id
.
String
())
for
_
,
channel
:=
range
srv
.
channels
{
...
...
@@ -306,7 +299,7 @@ on them automatically upon joining the network, the server SHOULD send the clien
the client sent it the MOTD command, i.e. it must send either the successful Message of the Day
numerics or the ERR_NOMOTD numeric. */
func
(
srv
*
Server
)
registerClient
(
cli
*
client
.
Client
)
{
func
(
srv
*
Server
)
registerClient
(
cli
*
client
.
User
)
{
if
cli
.
Ident
==
""
||
cli
.
Nick
==
""
||
cli
.
IsRegistered
()
||
cli
.
State
==
client
.
CAP_NEGOTIATION
{
return
}
...
...
@@ -388,7 +381,7 @@ func (srv *Server) getChannel(name string) (*Channel, error) {
return
nil
,
fmt
.
Errorf
(
"Channel %s does not exists"
,
name
)
}
func
(
srv
*
Server
)
createChannel
(
name
string
,
founder
*
client
.
Client
)
(
*
Channel
,
error
)
{
func
(
srv
*
Server
)
createChannel
(
name
string
,
founder
*
client
.
User
)
(
*
Channel
,
error
)
{
ch
,
err
:=
srv
.
getChannel
(
name
)
if
err
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Channel %q already exists"
,
name
)
...
...
@@ -403,7 +396,7 @@ func (srv *Server) createChannel(name string, founder *client.Client) (*Channel,
return
ch
,
nil
}
func
(
srv
*
Server
)
getClient
(
nickname
string
)
(
*
client
.
Client
,
error
)
{
func
(
srv
*
Server
)
getClient
(
nickname
string
)
(
*
client
.
User
,
error
)
{
lNickname
:=
strings
.
ToLower
(
nickname
)
id
,
ok
:=
srv
.
nicknames
[
lNickname
]
if
!
ok
{
...
...
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