2017-11-22 06:11:40 +00:00
package libnmdc
2017-11-23 05:23:39 +00:00
import (
"strings"
)
type adcState int
const (
adcStateProtocol adcState = 0
adcStateIdentify adcState = 1
adcStateVerify adcState = 2
adcStateNormal adcState = 3
adcStateData adcState = 4
)
2017-11-22 06:11:40 +00:00
type AdcProtocol struct {
2017-11-23 05:23:39 +00:00
hc * HubConnection
state adcState
sid string
supports map [ string ] struct { }
2017-11-22 06:11:40 +00:00
}
2017-11-22 07:02:11 +00:00
func NewAdcProtocol ( hc * HubConnection ) Protocol {
2017-11-23 05:23:39 +00:00
proto := AdcProtocol {
hc : hc ,
state : adcStateProtocol ,
supports : make ( map [ string ] struct { } ) ,
}
2017-11-22 06:11:40 +00:00
2017-11-22 07:02:21 +00:00
// Start logging in
hc . SayRaw ( "HSUP ADBASE ADTIGR\n" )
2017-11-22 06:22:13 +00:00
2017-11-22 06:11:40 +00:00
return & proto
}
func ( this * AdcProtocol ) ProcessCommand ( msg string ) {
this . hc . processEvent ( HubEvent { EventType : EVENT_DEBUG_MESSAGE , Message : msg } )
2017-11-23 05:23:39 +00:00
if len ( msg ) == 0 {
return
}
parts := strings . Split ( msg , " " )
switch parts [ 0 ] {
case "ISUP" :
if ! ( this . state == adcStateProtocol || this . state == adcStateNormal ) {
this . malformed ( parts )
return
}
for _ , supportflag := range parts [ 1 : ] {
if len ( supportflag ) < 2 {
this . malformed ( parts )
return
}
if supportflag [ 0 : 2 ] == "AD" {
this . supports [ supportflag [ 2 : ] ] = struct { } { }
} else if supportflag [ 0 : 2 ] == "RM" {
delete ( this . supports , supportflag [ 2 : ] )
} else {
this . malformed ( parts )
return
}
}
if this . state == adcStateProtocol {
this . state = adcStateIdentify
}
case "ISID" :
if this . state != adcStateIdentify {
this . malformed ( parts )
return
}
this . sid = parts [ 1 ]
case "IINF" :
flags := make ( map [ string ] string )
for _ , flag := range parts [ 1 : ] {
if len ( flag ) < 2 {
this . malformed ( parts )
return
}
flags [ flag [ 0 : 2 ] ] = flag [ 2 : ]
}
// Possibilities: User MyINFO (Normal state), or, hub telling information about itself (Identify->Normal state)
if ( this . state == adcStateIdentify || this . state == adcStateVerify ) && flags [ "CT" ] == "32" {
// Hub telling information about itself
this . handleInfo ( flags )
// Transition to state VERIFY and send our own info
this . hc . SayRaw ( "BINF " + this . escape ( this . sid ) + " GARBAGE" ) // FIXME send a real info string
this . state = adcStateVerify
} else if this . state == adcStateNormal {
// OK
this . handleInfo ( flags )
} else {
this . malformed ( parts )
return
}
case "IGPA" :
//
default :
this . malformed ( parts )
}
}
func ( this * AdcProtocol ) handleInfo ( flags map [ string ] string ) {
if flags [ "CT" ] == "32" {
// IINF DEADCH++\sTest\shub VE2.12.1\s(r"[unknown]")\sRelease HI1 NIADCH++ APADCH++ CT32
// AP: extension 3.24 "Application and version separation in INF"
// HI:
// Hub properties updated
hubName , ok := flags [ "DE" ]
if ok {
this . hc . HubName = this . unescape ( hubName )
this . hc . processEvent ( HubEvent { EventType : EVENT_HUBNAME_CHANGED , Nick : this . hc . HubName } )
}
} else {
// User MyINFO
// TODO
}
}
func ( this * AdcProtocol ) enterNormalState ( ) {
this . state = adcStateNormal
this . hc . processEvent ( HubEvent { EventType : EVENT_CONNECTION_STATE_CHANGED , StateChange : CONNECTIONSTATE_CONNECTED } )
this . hc . State = CONNECTIONSTATE_CONNECTED
}
func ( this * AdcProtocol ) malformed ( parts [ ] string ) {
this . hc . processEvent ( HubEvent { EventType : EVENT_DEBUG_MESSAGE , Message : "Ignoring malformed, unhandled, or out-of-state protocol command '" + parts [ 0 ] + "'" } )
}
func ( this * AdcProtocol ) escape ( plaintext string ) string {
// The string "\s" escapes space, "\n" newline and "\\" backslash. This version of the protocol reserves all other escapes for future use; any message containing unknown escapes must be discarded.
v1 := strings . Replace ( plaintext , ` \ ` , ` \\ ` , - 1 )
v2 := strings . Replace ( v1 , "\n" , ` \n ` , - 1 )
return strings . Replace ( v2 , " " , ` \s ` , - 1 )
}
func ( this * AdcProtocol ) unescape ( encoded string ) string {
v1 := strings . Replace ( encoded , ` \s ` , " " , - 1 )
v2 := strings . Replace ( v1 , ` \n ` , "\n" , - 1 )
return strings . Replace ( v2 , ` \\ ` , ` \ ` , - 1 )
2017-11-22 06:11:40 +00:00
}
func ( this * AdcProtocol ) SayPublic ( msg string ) {
}
func ( this * AdcProtocol ) SayPrivate ( user , message string ) {
}
func ( this * AdcProtocol ) ProtoMessageSeparator ( ) string {
return "\n"
}