xmpp.go
changeset 5 faef59c8db05
parent 4 a8fbec71a194
child 6 8e425e340ca1
equal deleted inserted replaced
4:a8fbec71a194 5:faef59c8db05
     7 package xmpp
     7 package xmpp
     8 
     8 
     9 import (
     9 import (
    10 	"fmt"
    10 	"fmt"
    11 	"io"
    11 	"io"
       
    12 	"log"
    12 	"net"
    13 	"net"
    13 	"os"
    14 	"os"
       
    15 	"xml"
    14 )
    16 )
    15 
    17 
    16 const (
    18 const (
    17 	serverSrv = "xmpp-server"
    19 	serverSrv = "xmpp-server"
    18 	clientSrv = "xmpp-client"
    20 	clientSrv = "xmpp-client"
    19 )
    21 )
    20 
    22 
    21 // The client in a client-server XMPP connection.
    23 // The client in a client-server XMPP connection.
    22 type Client struct {
    24 type Client struct {
    23 	//In <-chan *Stanza
    25 	In <-chan interface{}
    24 	//Out chan<- *Stanza
    26 	in chan interface{}
       
    27 	Out chan<- interface{}
       
    28 	out chan interface{}
    25 	tcp *net.TCPConn
    29 	tcp *net.TCPConn
    26 }
    30 }
    27 var _ io.Closer = &Client{}
    31 var _ io.Closer = &Client{}
    28 
    32 
    29 // Connect to the appropriate server and authenticate as the given JID
    33 // Connect to the appropriate server and authenticate as the given JID
    56 		return nil, err
    60 		return nil, err
    57 	}
    61 	}
    58 
    62 
    59 	cl := Client{}
    63 	cl := Client{}
    60 	cl.tcp = c
    64 	cl.tcp = c
       
    65 	cl.in = make(chan interface{})
       
    66 	cl.In = cl.in
       
    67 	// TODO Send readXml a reader that we can close when we
       
    68 	// negotiate TLS.
       
    69 	go readXml(cl.tcp, cl.in)
       
    70 	// TODO go writeXml(&cl)
       
    71 
    61 	return &cl, nil
    72 	return &cl, nil
    62 }
    73 }
    63 
    74 
    64 func (c *Client) Close() os.Error {
    75 func (c *Client) Close() os.Error {
    65 	return c.tcp.Close()
    76 	return c.tcp.Close()
    66 }
    77 }
       
    78 
       
    79 func readXml(r io.Reader, ch chan<- interface{}) {
       
    80 	p := xml.NewParser(r)
       
    81 	for {
       
    82 		// Sniff the next token on the stream.
       
    83 		t, err := p.Token()
       
    84 		if t == nil {
       
    85 			if err != os.EOF {
       
    86 				log.Printf("read: %v", err)
       
    87 			}
       
    88 			break
       
    89 		}
       
    90 		var se xml.StartElement
       
    91 		var ok bool
       
    92 		if se, ok = t.(xml.StartElement) ; !ok {
       
    93 			continue
       
    94 		}
       
    95 
       
    96 		// Allocate the appropriate structure for this token.
       
    97 		var obj interface{}
       
    98 		switch se.Name.Space + se.Name.Local {
       
    99 		case "stream stream":
       
   100 			st, err := parseStream(se)
       
   101 			if err != nil {
       
   102 				log.Printf("unmarshal stream: %v",
       
   103 					err)
       
   104 				break
       
   105 			}
       
   106 			ch <- st
       
   107 			continue
       
   108 		case nsStreams + " stream:error":
       
   109 			obj = &StreamError{}
       
   110 		default:
       
   111 			obj = &Unrecognized{}
       
   112 		}
       
   113 
       
   114 		// Read the complete XML stanza.
       
   115 		err = p.Unmarshal(obj, &se)
       
   116 		if err != nil {
       
   117 			log.Printf("unmarshal: %v", err)
       
   118 			break
       
   119 		}
       
   120 
       
   121 		// Put it on the channel.
       
   122 		ch <- obj
       
   123 	}
       
   124 }