19 Commits

Author SHA1 Message Date
21847db9fd readme 2017-02-11 13:56:08 +13:00
b8122710f5 patch a crash on incomplete supplied UserIP2 2017-02-11 13:55:20 +13:00
f8c0fc54d8 Added tag release-0.13 for changeset 3ee0f4ea5142 2017-02-09 19:31:24 +13:00
4490444d1c readme 2017-02-09 19:31:19 +13:00
c5f655ff78 doc: update TODO 2017-02-09 19:28:58 +13:00
4415109174 support UserIP2 extension 2017-02-09 19:28:37 +13:00
0adc13ddfa move our is-connected one half roundtrip sooner 2017-02-09 19:19:17 +13:00
59c56fea1b doc: todo 2017-02-09 19:15:53 +13:00
7f8f98aa5a add ChatOnly to our $Supports 2017-02-08 19:30:53 +13:00
8536cb0a5c implement QuickList, save a network roundtrip on supported hubs (ptokax) 2017-02-08 19:22:07 +13:00
553ec20850 fix not emitting EVENT_USER_UPDATED_INFO on recieved MyINFO (!) 2017-02-08 18:58:14 +13:00
a403dac461 declare NoHello support (since our MyINFO handler will add unknown users) 2017-02-08 18:58:03 +13:00
59a37b975c more idiomatic error handling 2017-02-08 18:57:49 +13:00
a4e7d876cc Added tag release-0.12 for changeset 22b156a6fc2f 2017-02-05 22:37:24 +13:00
7c3069eabb readme 2017-02-05 22:35:18 +13:00
3cc31323ad more fine-grained locking around user map (fixes deadlock if callee uses Users() in response to processEvent) 2017-02-05 19:06:17 +13:00
7f898dff32 display a system message and disconnect if we're asked for a password but don't have one 2017-02-05 17:12:59 +13:00
58c1151278 readme for 0.11 2016-11-29 20:18:17 +13:00
d1c549f1f2 Added tag release-0.11 for changeset 5149ffe70ea8 2016-11-29 20:13:14 +13:00
5 changed files with 112 additions and 23 deletions

View File

@@ -13,3 +13,6 @@ cb86f3a40115cc46f450c0c83fd9b9d3b740e820 libnmdc-r6
b0e57a5fcffdf4102d669db51a3648ddf66a0792 libnmdc-r8 b0e57a5fcffdf4102d669db51a3648ddf66a0792 libnmdc-r8
e7c2c71ef24b386add728fad35fff4a996fccbac libnmdc-r9 e7c2c71ef24b386add728fad35fff4a996fccbac libnmdc-r9
3ecc037cf2d7080572fe87c2e39ecd153fb0e947 libnmdc-r10 3ecc037cf2d7080572fe87c2e39ecd153fb0e947 libnmdc-r10
5149ffe70ea8475e480b682345b31aa45a3352db release-0.11
22b156a6fc2f6161765317f4ec9ab3731a26e0e2 release-0.12
3ee0f4ea5142d66079a9500bdcd48a53bdcf362f release-0.13

View File

@@ -28,6 +28,8 @@ type HubConnection struct {
connValid bool connValid bool
sentOurHello bool sentOurHello bool
autoReconnect bool autoReconnect bool
supports map[string]struct{}
} }
// Thread-safe user accessor. // Thread-safe user accessor.
@@ -67,10 +69,11 @@ func (this *HubConnection) UserCount() int {
func (this *HubConnection) userJoined_NameOnly(nick string) { func (this *HubConnection) userJoined_NameOnly(nick string) {
if !this.UserExists(nick) { if !this.UserExists(nick) {
this.userLock.Lock()
defer this.userLock.Unlock()
this.userLock.Lock()
this.users[nick] = *NewUserInfo(nick) this.users[nick] = *NewUserInfo(nick)
this.userLock.Unlock() // Don't lock over a processEvent boundary
this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: nick}) this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: nick})
} }
} }
@@ -78,14 +81,14 @@ func (this *HubConnection) userJoined_NameOnly(nick string) {
func (this *HubConnection) userJoined_Full(uinf *UserInfo) { func (this *HubConnection) userJoined_Full(uinf *UserInfo) {
// n.b. also called when we get a replacement MyINFO for someone // n.b. also called when we get a replacement MyINFO for someone
this.userLock.Lock() this.userLock.Lock()
defer this.userLock.Unlock()
_, userExisted := this.users[uinf.Nick] // don't use UserExists as it would deadlock the mutex _, userExisted := this.users[uinf.Nick] // don't use UserExists as it would deadlock the mutex
this.users[uinf.Nick] = *uinf this.users[uinf.Nick] = *uinf
this.userLock.Unlock() // Don't lock over a processEvent boundary
if !userExisted { if !userExisted {
this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: uinf.Nick}) this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: uinf.Nick})
} else {
this.processEvent(HubEvent{EventType: EVENT_USER_UPDATED_INFO, Nick: uinf.Nick})
} }
} }
@@ -132,9 +135,8 @@ func (this *HubConnection) processProtocolMessage(message string) {
switch commandParts[0] { switch commandParts[0] {
case "$Lock": case "$Lock":
this.SayRaw("$Supports NoGetINFO UserCommand UserIP2|" + this.SayRaw("$Supports NoHello NoGetINFO UserCommand UserIP2 QuickList ChatOnly|" +
"$Key " + unlock([]byte(commandParts[1])) + "|" + "$Key " + unlock([]byte(commandParts[1])) + "|")
"$ValidateNick " + Escape(this.Hco.Self.Nick) + "|")
this.sentOurHello = false this.sentOurHello = false
case "$Hello": case "$Hello":
@@ -167,26 +169,32 @@ func (this *HubConnection) processProtocolMessage(message string) {
this.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Incorrect password."}) this.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Incorrect password."})
case "$GetPass": case "$GetPass":
if len(this.Hco.NickPassword) == 0 {
// We've got a problem. MyPass with no arguments is a syntax error with no message = instant close
// Just drop the connection
this.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "This account is passworded."})
this.Disconnect()
} else {
this.SayRaw("$MyPass " + Escape(this.Hco.NickPassword) + "|") this.SayRaw("$MyPass " + Escape(this.Hco.NickPassword) + "|")
}
case "$Quit": case "$Quit":
func() {
this.userLock.Lock() this.userLock.Lock()
defer this.userLock.Unlock()
delete(this.users, commandParts[1]) delete(this.users, commandParts[1])
}() this.userLock.Unlock() // Don't lock over a processEvent boundary
this.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: commandParts[1]}) this.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: commandParts[1]})
case "$MyINFO": case "$MyINFO":
u := UserInfo{} u := UserInfo{}
err := u.fromMyINFO(commandParts[1]) err := u.fromMyINFO(commandParts[1])
if err == nil { if err != nil {
this.userJoined_Full(&u)
} else {
this.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: err.Error()}) this.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: err.Error()})
return
} }
this.userJoined_Full(&u)
case "$NickList": case "$NickList":
nicklist := strings.Split(commandParts[1], "$$") nicklist := strings.Split(commandParts[1], "$$")
for _, nick := range nicklist { for _, nick := range nicklist {
@@ -237,11 +245,39 @@ func (this *HubConnection) processProtocolMessage(message string) {
} }
case "$UserIP": case "$UserIP":
// Final message in PtokaX connection handshake - trigger connection callback. this.userLock.Lock()
// This might not be the case for other hubsofts, though
if this.State != CONNECTIONSTATE_CONNECTED { pairs := strings.Split(commandParts[1], "$$")
this.processEvent(HubEvent{EventType: EVENT_CONNECTION_STATE_CHANGED, StateChange: CONNECTIONSTATE_CONNECTED}) notifyOfUpdate := make([]string, 0, len(pairs))
this.State = CONNECTIONSTATE_CONNECTED
nextIPPair:
for _, pair := range pairs {
parts := strings.SplitN(pair, " ", 2)
if len(parts) != 2 {
// ????
continue nextIPPair
}
ip2nick := parts[0]
ip2addr := parts[1]
uinfo, ok := this.users[ip2nick]
if !ok {
this.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Recieved IP '" + ip2addr + "' for unknown user '" + ip2nick + "'"})
continue nextIPPair
}
if uinfo.IPAddress != ip2addr {
uinfo.IPAddress = ip2addr
notifyOfUpdate = append(notifyOfUpdate, ip2nick)
this.users[ip2nick] = uinfo
}
}
this.userLock.Unlock()
for _, nick := range notifyOfUpdate {
this.processEvent(HubEvent{EventType: EVENT_USER_UPDATED_INFO, Nick: nick})
} }
case "$ForceMove": case "$ForceMove":
@@ -269,8 +305,34 @@ func (this *HubConnection) processProtocolMessage(message string) {
this.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Malformed usercommand '" + commandParts[1] + "'"}) this.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Malformed usercommand '" + commandParts[1] + "'"})
} }
// IGNORABLE COMMANDS
case "$Supports": case "$Supports":
this.supports = make(map[string]struct{})
for _, s := range strings.Split(commandParts[1], " ") {
this.supports[s] = struct{}{}
}
if !this.sentOurHello {
// Need to log in.
// If the hub supports QuickList, we can skip one network roundtrip
if _, ok := this.supports["QuickList"]; ok {
this.SayInfo()
this.SayRaw("$GetNickList|")
} else {
this.SayRaw("$ValidateNick " + Escape(this.Hco.Self.Nick) + "|")
}
// This also counts as the end of the handshake from our POV. Consider
// ourselves logged in
this.sentOurHello = true
if this.State != CONNECTIONSTATE_CONNECTED {
this.processEvent(HubEvent{EventType: EVENT_CONNECTION_STATE_CHANGED, StateChange: CONNECTIONSTATE_CONNECTED})
this.State = CONNECTIONSTATE_CONNECTED
}
}
// IGNORABLE COMMANDS
case "$HubTopic": case "$HubTopic":
case "$Search": case "$Search":
case "$ConnectToMe": case "$ConnectToMe":

1
TODO.txt Normal file
View File

@@ -0,0 +1 @@
- Implement ZPipe ($ZOn)

View File

@@ -24,6 +24,7 @@ type UserInfo struct {
HubsRegistered uint64 HubsRegistered uint64
HubsOperator uint64 HubsOperator uint64
IsOperator bool IsOperator bool
IPAddress string
} }
var rx_myinfo *regexp.Regexp var rx_myinfo *regexp.Regexp

View File

@@ -9,6 +9,28 @@ Tags: nmdc
=CHANGELOG= =CHANGELOG=
2017-02-09 0.14
- Fix an issue with crashing on malformed IP addresses supplied by the hub
2017-02-09 0.13
- Feature: Implement UserIP2 extension, to retrieve IP addresses of other users
- Enhancement: Implement QuickList extension (reduce one network roundtrip during initial connection)
- Enhancement: Implement NoHello extension (faster connection performance)
- Enhancement: Implement ChatOnly extension
- Fix an issue with not notifying client on all MyINFO updates
2017-02-05 0.12
- Fix an issue with mutex deadlock when accessing user information from a callback
- Fix an issue with silent disconnection if a password was required but not present
2016-11-29 0.11
- BREAKING: Remove some exported methods
- BREAKING: Fix an issue with missing sufficient parameters in the synchronous API
- Enhancement: Improve output under godoc
- Fix an issue with special characters appearing in recieved private messages
- Fix an issue with parsing active/passive connection modes
- Fix an issue with errors appearing on stdout
2016-10-08 r10 2016-10-08 r10
- Feature: Support `$UserCommand` - Feature: Support `$UserCommand`