Ver Fonte

xml препроцессинг, разбиение кучи элементов на отдельные пакеты

kpmy há 10 anos atrás
pai
commit
dababffb1e
5 ficheiros alterados com 133 adições e 22 exclusões
  1. 8 3
      c2s/stream/stream.go
  2. 81 0
      c2s/stream/xml.go
  3. 18 5
      client/main.go
  4. 2 2
      entity/entity.go
  5. 24 12
      entity/xmpp-stanza.go

+ 8 - 3
c2s/stream/stream.go

@@ -74,7 +74,7 @@ func (x *xmppStream) Write(b *bytes.Buffer) (err error) {
 }
 
 func (x *xmppStream) Ring(fn func(*bytes.Buffer) *bytes.Buffer, timeout time.Duration) {
-	log.Println("ring")
+	log.Println("wait")
 	timed := make(chan bool)
 	if timeout > 0 {
 		go func() {
@@ -140,10 +140,15 @@ func Dial(_s Stream) (err error) {
 							if n > 0 && err == nil {
 								data := make([]byte, n)
 								copy(data, buf)
-								log.Println("IN", len(data), adler32.Checksum(data))
+								log.Println("PRE", len(data), adler32.Checksum(data))
 								log.Println(string(data))
 								log.Println()
-								stream.data <- pack{data: data, hash: adler32.Checksum(data)}
+								for data := range spl1t(data) {
+									log.Println("IN", len(data), adler32.Checksum(data))
+									log.Println(string(data))
+									log.Println()
+									stream.data <- pack{data: data, hash: adler32.Checksum(data)}
+								}
 							}
 						}
 					}(x)

+ 81 - 0
c2s/stream/xml.go

@@ -0,0 +1,81 @@
+package stream
+
+import (
+	"bytes"
+	"encoding/xml"
+	"github.com/kpmy/ypk/halt"
+	"io"
+	"log"
+	"reflect"
+)
+
+func spl1t(bunch []byte) (ret chan []byte) {
+	ret = make(chan []byte)
+	go func() {
+		d := xml.NewDecoder(bytes.NewReader(bunch))
+		d.Strict = false
+		var (
+			_t  xml.Token
+			err error
+			buf *bytes.Buffer
+			e   *xml.Encoder
+		)
+		init := func() {
+			buf = bytes.NewBuffer(nil)
+			e = xml.NewEncoder(buf)
+		}
+		flush := func() {
+			e.Flush()
+			if buf.Len() > 0 {
+				ret <- buf.Bytes()
+			}
+			init()
+		}
+		join := func(n xml.Name) (ret string) {
+			if n.Space != "" {
+				ret = n.Space + ":"
+			}
+			ret = ret + n.Local
+			return
+		}
+		depth := 0
+		init()
+		for stop := false; !stop && err == nil; {
+			if _t, err = d.RawToken(); err == nil {
+				switch t := _t.(type) {
+				case xml.ProcInst:
+					e.EncodeToken(t.Copy())
+				case xml.StartElement:
+					tt := t.Copy()
+					tt.Name = xml.Name{Local: join(t.Name)}
+					var tmp []xml.Attr
+					for _, a := range tt.Attr {
+						a.Name = xml.Name{Local: join(a.Name)}
+						tmp = append(tmp, a)
+					}
+					tt.Attr = tmp
+					e.EncodeToken(tt)
+					depth++
+				case xml.EndElement:
+					tt := t
+					tt.Name = xml.Name{Local: join(t.Name)}
+					e.EncodeToken(tt)
+					depth--
+					if depth == 0 {
+						flush()
+					}
+				case xml.CharData:
+					e.EncodeToken(t)
+				default:
+					halt.As(100, reflect.TypeOf(t))
+				}
+			} else if err == io.EOF {
+				flush()
+			} else {
+				log.Println(err)
+			}
+		}
+		close(ret)
+	}()
+	return
+}

+ 18 - 5
client/main.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"flag"
 	"log"
+	"strings"
 	"xep/c2s/actors"
 	"xep/c2s/actors/steps"
 	"xep/c2s/stream"
@@ -24,9 +25,18 @@ func init() {
 	log.SetFlags(0)
 }
 
-func conv(fn func(entity.Entity) entity.Entity) func(*bytes.Buffer) *bytes.Buffer {
+func conv(fn func(entity.Entity)) func(*bytes.Buffer) *bytes.Buffer {
 	return func(in *bytes.Buffer) (out *bytes.Buffer) {
-
+		if _e, err := entity.Consume(in); err == nil {
+			switch e := _e.(type) {
+			case *entity.Message:
+				fn(e)
+			}
+		} else {
+			log.Println("ERROR", err)
+			log.Println(string(in.Bytes()))
+			log.Println()
+		}
 		return
 	}
 }
@@ -51,9 +61,12 @@ func main() {
 			actors.With(st).Do(func(st stream.Stream) error {
 				actors.With(st).Do(steps.PresenceTo("golang@conference.jabber.ru/xep")).Run()
 				for {
-					st.Ring(conv(func(entity.Entity) entity.Entity {
-
-						return nil
+					st.Ring(conv(func(_e entity.Entity) {
+						switch e := _e.(type) {
+						case *entity.Message:
+							log.Println(strings.TrimPrefix(e.From, "golang@conference.jabber.ru/"))
+							log.Println(e.Body)
+						}
 					}), 0)
 				}
 			}).Run()

+ 2 - 2
entity/entity.go

@@ -5,7 +5,6 @@ import (
 	"encoding/xml"
 	"errors"
 	"fmt"
-	"github.com/kpmy/ypk/halt"
 	"io"
 	"strings"
 	"xep/units"
@@ -42,7 +41,6 @@ func (x *dumb) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error)
 		d.DecodeElement(x.x, &start)
 	} else {
 		err = errors.New(fmt.Sprint("unknown entity ", start.Name))
-		halt.As(100, start.Name)
 	}
 	return
 }
@@ -77,4 +75,6 @@ func init() {
 	ns[xml.Name{Space: "urn:ietf:params:xml:ns:xmpp-sasl", Local: "success"}] = func(*bytes.Buffer) Entity { return &Success{} }
 
 	ns[xml.Name{Local: "iq"}] = func(*bytes.Buffer) Entity { return &Iq{} }
+
+	ns[xml.Name{Local: "message"}] = func(*bytes.Buffer) Entity { return &Message{} }
 }

+ 24 - 12
entity/xmpp-stanza.go

@@ -3,33 +3,36 @@ package entity
 import (
 	"encoding/xml"
 	"github.com/kpmy/ypk/fn"
-	"github.com/kpmy/ypk/halt"
+	//	"github.com/kpmy/ypk/halt"
 	"math/rand"
-	"reflect"
+	//	"reflect"
 	"strconv"
 )
 
-type Type string
+type IqType string
 
 const (
-	SET    Type = "set"
-	RESULT Type = "result"
+	SET    IqType = "set"
+	RESULT IqType = "result"
 )
 
-type Stanza interface {
-}
+type MessageType string
+
+const (
+	GROUPCHAT MessageType = "groupchat"
+)
 
 type Iq struct {
 	XMLName xml.Name
 	Id      string      `xml:"id,attr,omitempty"`
-	Type    Type        `xml:"type,attr"`
+	Type    IqType      `xml:"type,attr"`
 	Inner   interface{} `xml:"iq"`
 	dumbProducer
 }
 
 func (i *Iq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
 	i.Id = getAttr(&start, "id")
-	i.Type = Type(getAttr(&start, "type"))
+	i.Type = IqType(getAttr(&start, "type"))
 	var _t xml.Token
 	for stop := false; !stop && err == nil; {
 		_t, err = d.Token()
@@ -41,12 +44,12 @@ func (i *Iq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
 			if !fn.IsNil(i.Inner) {
 				d.DecodeElement(i.Inner, &t)
 			} else {
-				halt.As(100, t.Name)
+				//halt.As(100, t.Name)
 			}
 		case xml.EndElement:
 			stop = t.Name == start.Name
 		default:
-			halt.As(100, reflect.TypeOf(t))
+			//halt.As(100, reflect.TypeOf(t))
 		}
 	}
 	return
@@ -54,7 +57,7 @@ func (i *Iq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
 
 var iq = Iq{XMLName: xml.Name{Local: "iq"}}
 
-func IQ(typ Type, user interface{}) *Iq {
+func IQ(typ IqType, user interface{}) *Iq {
 	i := &Iq{}
 	*i = iq
 	i.Type = typ
@@ -70,6 +73,15 @@ type Presence struct {
 
 var PresencePrototype = Presence{XMLName: xml.Name{Local: "presence"}}
 
+type Message struct {
+	XMLName xml.Name
+	dumbProducer
+	Body string `xml:"body,omitempty"`
+	From string `xml:"from,attr,omitempty"`
+}
+
+var MessagePrototype = Message{XMLName: xml.Name{Local: "message"}}
+
 var us map[xml.Name]func() interface{}
 
 func init() {