summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2012-04-15 17:50:04 +0200
committerYorhel <git@yorhel.nl>2012-04-15 17:50:04 +0200
commit2eedc86d7c7f7afefc4e2da0de188be6fc9a3e2b (patch)
tree23481f7364d10a1bd1e90a90faf4d0d876985949
parent8a698dbcb6dd15c4581c8b145b333c2a4f2eb740 (diff)
Added (simple) ADC login sequence + chat command
Yay! Globster can now be used for sending spam messages to a hub!
-rw-r--r--design14
-rw-r--r--src/globster/adc/handle.go6
-rw-r--r--src/globster/adc/types.go10
-rw-r--r--src/globster/hub/hub.go55
-rw-r--r--src/globster/userlist/list.go41
5 files changed, 115 insertions, 11 deletions
diff --git a/design b/design
index dbe5cae..6a049f7 100644
--- a/design
+++ b/design
@@ -38,9 +38,12 @@ Hub:
< hub $name connect $addr
< hub $name disconnect
< hub $name info
- Replies with hub information
+ Replies with hub information (TODO)
+ < hub $name chat $user $message
+ $user=$id of the userlist, wildcard for mainchat
< userlist $name Changed "" $data
+ (TODO)
> hub $name Created
> hub $name Closed
@@ -66,17 +69,20 @@ UserList:
> userlist $hub Deleted $id
$hub = $name of the corresponding Hub session
- $id = This client: ""
- ADC: SID (FourCC string)
- NMDC: hex(raw_nick)
+ $id = Local user: ""
+ ADC: SID (FourCC string)
+ NMDC: hex(raw_nick)
$gid = The GID field ("global ID")
$data = map with information on the user
$old, $new = $data, only containing the fields that changed
$field = refers to the keys in $data, not present = all
+ TODO: Let 'get' and 'getid' return arrays rather than maps.
+
Fields (used in $data):
Name Username (UTF-8)
CID ADC: CID (base32 string), NMDC: Empty
+ PID ADC: PID (base32 string), NMDC: Empty (Only for the local user)
TID Temp. ID = $id (read only)
GID Global ID. ADC: CID, NMDC: $id (read only)
Desc Description
diff --git a/src/globster/adc/handle.go b/src/globster/adc/handle.go
index 669b4c5..f044268 100644
--- a/src/globster/adc/handle.go
+++ b/src/globster/adc/handle.go
@@ -10,7 +10,7 @@ var (
type HubHandler interface {
AdcSUP(ad, rm []string) error
- AdcSID(string) error
+ AdcSID(FourCC) error
}
// Assumes the message has been received from a hub. This function performs
@@ -38,7 +38,7 @@ func HandleHub(m *Message, state State, h HubHandler) error {
switch m.Header.Command() {
case SUP:
f := func(a []Arg) []string {
- r := make([]string, 0, len(a))
+ r := make([]string, len(a))
for i, v := range a {
if v.FourCC() == 0 {
return nil
@@ -57,7 +57,7 @@ func HandleHub(m *Message, state State, h HubHandler) error {
if !m.PosArgs[0].IsSID() {
return ErrInvalidArg
}
- return h.AdcSID(string(m.PosArgs[0]))
+ return h.AdcSID(m.PosArgs[0].FourCC())
}
return nil
diff --git a/src/globster/adc/types.go b/src/globster/adc/types.go
index 83f9491..ad74d85 100644
--- a/src/globster/adc/types.go
+++ b/src/globster/adc/types.go
@@ -105,6 +105,16 @@ func (m *Message) AddPos(s string) *Message {
return m
}
+func (m *Message) SetSrc(s FourCC) *Message {
+ m.Src = s
+ return m
+}
+
+func (m *Message) SetDest(s FourCC) *Message {
+ m.Dest = s
+ return m
+}
+
func (m *Message) AddNamed(n, s string) *Message {
if m.NamedArgs == nil {
m.NamedArgs = make(map[[2]byte][]Arg)
diff --git a/src/globster/hub/hub.go b/src/globster/hub/hub.go
index 6ee6237..34be864 100644
--- a/src/globster/hub/hub.go
+++ b/src/globster/hub/hub.go
@@ -22,7 +22,7 @@ type hub struct {
connCh <-chan interface{}
// ADC info (only useful if conn != nil)
state adc.State
- mysid string
+ mysid adc.FourCC
}
func newHub(node *tanja.Node, name string) *hub {
@@ -118,6 +118,7 @@ func (s *hub) Tdisconnect(m *tanja.Message, r ...tanja.Element) {
}(s.rd)
s.rd = nil
}
+ s.state = adc.InvalidState
} else {
m.Close()
@@ -128,6 +129,26 @@ func (s *hub) Tdisconnect(m *tanja.Message, r ...tanja.Element) {
}
}
+func (s *hub) Tchat(user tanja.Element, me bool, msg string) {
+ if s.state != adc.NORMAL {
+ return
+ }
+ var cmd *adc.Message
+ if user.WC() {
+ cmd = adc.NewMessage('B', adc.MSG)
+ } else if adc.Arg(user.String()).IsSID() {
+ // TODO: type = E?
+ cmd = adc.NewMessage('D', adc.MSG).SetDest(adc.Arg(user.String()).FourCC())
+ } else {
+ return
+ }
+ cmd.SetSrc(s.mysid).AddPos(msg)
+ if me {
+ cmd.AddNamed("ME", "1")
+ }
+ s.wr.Write(cmd)
+}
+
func (s *hub) connected(r interface{}) {
s.connCh = nil
if e, ok := r.(error); ok {
@@ -179,9 +200,39 @@ func (s *hub) AdcSUP(ad []string, rm []string) error {
return nil
}
-func (s *hub) AdcSID(sid string) error {
+func (s *hub) AdcSID(sid adc.FourCC) error {
s.mysid = sid
s.state = adc.IDENTIFY
+
+ // Send our initial INF
+ res := s.ses.Send(true, "userlist", s.name, "get", "",
+ "PID", "CID", "Name", "Client", "IP4", "Slots", "ShareSize", "ShareFiles",
+ "HubsNorm", "HubsReg", "HubsOp", "Desc", "EMail")
+ nfo := <-res.Chan()
+ res.Close()
+ if nfo == nil {
+ return errors.New("No local user info")
+ }
+ n := nfo[0].Map()
+ s.wr.Write(adc.NewMessage('B', adc.INF).SetSrc(s.mysid).
+ AddNamed("NI", n["Name"].String()).
+ AddNamed("ID", n["CID"].String()).
+ AddNamed("PD", n["PID"].String()).
+ AddNamed("I4", n["IP4"].String()).
+ AddNamed("U4", "").
+ AddNamed("SU", "").
+ AddNamed("SL", n["Slots"].String()).
+ AddNamed("SF", n["ShareFiles"].String()).
+ AddNamed("SS", n["ShareSize"].String()).
+ AddNamed("HN", n["HubsNorm"].String()).
+ AddNamed("HR", n["HubsReg"].String()).
+ AddNamed("HO", n["HubsOp"].String()).
+ AddNamed("EM", n["EMail"].String()).
+ AddNamed("DE", n["Desc"].String()).
+ AddNamed("VE", n["Client"].String()))
+
+ // TODO: We're not actually in the NORMAL yet, but this works for debugging purposes.
+ s.state = adc.NORMAL
return nil
}
diff --git a/src/globster/userlist/list.go b/src/globster/userlist/list.go
index d0af549..6639b5c 100644
--- a/src/globster/userlist/list.go
+++ b/src/globster/userlist/list.go
@@ -11,11 +11,12 @@ import "blicky.net/tanja"
type user map[string]tanja.Element
var elNil = tanja.El(nil)
-var fieldDefs map[string]tanja.Element = map[string]tanja.Element{
+var fieldDefs = map[string]tanja.Element{
"Name": tanja.El(""),
"CID": tanja.El(""),
"TID": elNil, // set on creation
"GID": elNil, // virtual
+ "PID": tanja.El(""),
"Desc": tanja.El(""),
"EMail": tanja.El(""),
"Client": tanja.El(""),
@@ -32,6 +33,31 @@ var fieldDefs map[string]tanja.Element = map[string]tanja.Element{
"HubsNorm": tanja.El(0),
}
+// "Default" local user.
+// TODO: Make this configurable? Or at least generate a unique PID/name.
+// TODO: Auto-update hub counters? Or let the application do this?
+var defLocal = map[string]tanja.Element{
+ "Name": tanja.El("Globster"),
+ "CID": tanja.El("EQZPAA3CIHGN7YFFY2M2AK6N72SLLDFUETPZB7A"),
+ "TID": tanja.El(""),
+ "GID": elNil,
+ "PID": tanja.El("OZRFSIKSO2LKURJRKPL2C2ST2FVFFS5MCYYSVQI"),
+ "Desc": tanja.El(""),
+ "EMail": tanja.El(""),
+ "Client": tanja.El("globster 0.0"),
+ "Upload": tanja.El(""),
+ "Download": tanja.El(0),
+ "ShareSize": tanja.El(0),
+ "ShareFiles": tanja.El(0),
+ "KeyPrint": tanja.El(""),
+ "IP4": tanja.El("0.0.0.0"),
+ "Slots": tanja.El(1),
+ "AutoSlots": tanja.El(0),
+ "HubsOp": tanja.El(0),
+ "HubsReg": tanja.El(0),
+ "HubsNorm": tanja.El(1),
+}
+
// Assumes the field exists
func (u user) get(field string) tanja.Element {
// GID is the only "virtual" field
@@ -78,6 +104,15 @@ type hub struct {
func newHub(node *tanja.Node, name string) *hub {
s := &hub{node.Session(), name, make(map[string]*user), make(map[string]*user), 0}
+
+ // Create a local user (copy from defUser)
+ d := newUser("")
+ for k, v := range defLocal {
+ (*d)[k] = v
+ }
+ s.userTID[""] = d
+ s.userGID[(*d)["userCID"].String()] = d
+
s.ses.RegRPC(s, func(s string) tanja.Tuple {
if s[0] != 'T' {
return nil
@@ -135,6 +170,8 @@ func (s *hub) Tgetid(m *tanja.Message, id string, fields ...tanja.Element) {
m.Replyt(u.getFields(flds))
}
+// TODO: For the local user: If PID is set, update CID as well (or at least
+// validate it).
func (s *hub) Tset(id string, data map[string]tanja.Element) {
// Get or create user entry
u := s.userTID[id]
@@ -148,7 +185,7 @@ func (s *hub) Tset(id string, data map[string]tanja.Element) {
new := make(map[string]tanja.Element)
for k, v := range data {
- if fieldDefs[k] == elNil {
+ if fieldDefs[k] == elNil || (id != "" && k == "PID") {
continue
}
// All elements are scalar types and must be representable as a string,