xmpp/layer3.go
author Chris Jones <chris@cjones.org>
Sat, 09 Nov 2013 12:09:37 -0700
changeset 178 ccfebbd9f49b
parent 163 3f891f7fe817
permissions -rw-r--r--
Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     1
// This layer of the XMPP protocol reads XMLish structures and
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     2
// responds to them. It negotiates TLS and authentication.
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     3
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     4
package xmpp
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     5
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     6
import (
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     7
	"encoding/xml"
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
     8
	"fmt"
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
     9
	"log"
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    10
)
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    11
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    12
// Callback to handle a stanza with a particular id.
144
9d7fdb1d2fc1 Renamed HandleStanza to SetCallback.
Chris Jones <christian.jones@sri.com>
parents: 143
diff changeset
    13
type callback struct {
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    14
	id string
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    15
	f  func(Stanza)
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    16
}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    17
147
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    18
// Receive XMPP stanzas from the client and send them on to the
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    19
// remote. Don't allow the client to send us any stanzas until
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    20
// negotiation has completed.  This loop is paused until resource
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    21
// binding is complete. Otherwise the app might inject something
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    22
// inappropriate into our negotiations with the server. The control
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    23
// channel controls this loop's activity.
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    24
func sendStream(sendXml chan<- interface{}, recvXmpp <-chan Stanza,
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    25
	status <-chan Status) {
147
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    26
	defer close(sendXml)
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    27
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    28
	var input <-chan Stanza
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    29
	for {
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    30
		select {
162
7b5586a5e109 Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents: 153
diff changeset
    31
		case stat, ok := <-status:
7b5586a5e109 Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents: 153
diff changeset
    32
			if !ok {
7b5586a5e109 Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents: 153
diff changeset
    33
				return
7b5586a5e109 Added a Close() function and fixed a couple of shutdown bugs.
Chris Jones <chris@cjones.org>
parents: 153
diff changeset
    34
			}
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    35
			switch stat {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    36
			default:
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    37
				input = nil
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    38
			case StatusRunning:
147
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    39
				input = recvXmpp
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    40
			}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    41
		case x, ok := <-input:
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    42
			if !ok {
148
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
    43
				return
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    44
			}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    45
			if x == nil {
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
    46
				if Debug {
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
    47
					log.Println("Won't send nil stanza")
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
    48
				}
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    49
				continue
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    50
			}
147
d7679d991b17 Function renames and improved doc.
Chris Jones <christian.jones@sri.com>
parents: 146
diff changeset
    51
			sendXml <- x
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    52
		}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    53
	}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    54
}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    55
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    56
// Receive XMLish structures, handle all the stream-related ones, and
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    57
// send XMPP stanzas on to the client once the connection is running.
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    58
func (cl *Client) recvStream(recvXml <-chan interface{}, sendXmpp chan<- Stanza,
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    59
	status <-chan Status) {
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    60
	defer close(sendXmpp)
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    61
	defer cl.statmgr.close()
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    62
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    63
	handlers := make(map[string]func(Stanza))
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    64
	doSend := false
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    65
	for {
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    66
		select {
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    67
		case stat := <-status:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    68
			switch stat {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    69
			default:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    70
				doSend = false
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    71
			case StatusRunning:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    72
				doSend = true
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    73
			}
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    74
		case h := <-cl.handlers:
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    75
			handlers[h.id] = h.f
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    76
		case x, ok := <-recvXml:
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    77
			if !ok {
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    78
				return
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    79
			}
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    80
			switch obj := x.(type) {
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    81
			case *stream:
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    82
				// Do nothing.
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    83
			case *streamError:
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
    84
				cl.setError(fmt.Errorf("%#v", obj))
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
    85
				return
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    86
			case *Features:
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    87
				cl.handleFeatures(obj)
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    88
			case *starttls:
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    89
				cl.handleTls(obj)
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    90
			case *auth:
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    91
				cl.handleSasl(obj)
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    92
			case Stanza:
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    93
				id := obj.GetHeader().Id
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    94
				if handlers[id] != nil {
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    95
					f := handlers[id]
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    96
					delete(handlers, id)
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    97
					f(obj)
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
    98
				}
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
    99
				if doSend {
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   100
					sendXmpp <- obj
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   101
				}
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   102
			default:
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   103
				if Debug {
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   104
					log.Printf("Unrecognized input: %T %#v",
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   105
						x, x)
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   106
				}
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   107
			}
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   108
		}
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   109
	}
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   110
}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   111
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   112
func (cl *Client) handleFeatures(fe *Features) {
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   113
	cl.Features = fe
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   114
	if fe.Starttls != nil {
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   115
		start := &starttls{XMLName: xml.Name{Space: NsTLS,
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   116
			Local: "starttls"}}
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   117
		cl.sendRaw <- start
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   118
		return
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   119
	}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   120
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   121
	if len(fe.Mechanisms.Mechanism) > 0 {
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   122
		cl.chooseSasl(fe)
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   123
		return
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   124
	}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   125
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   126
	if fe.Bind != nil {
149
22c96a9ab289 Removed an unused parameter.
Chris Jones <christian.jones@sri.com>
parents: 148
diff changeset
   127
		cl.bind()
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   128
		return
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   129
	}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   130
}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   131
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   132
func (cl *Client) handleTls(t *starttls) {
148
b1b4900eee5b Made layers 1 and 3 more modular, shrinking the surface area of the coupling between them.
Chris Jones <christian.jones@sri.com>
parents: 147
diff changeset
   133
	cl.layer1.startTls(&cl.tlsConfig)
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   134
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
   135
	cl.setStatus(StatusConnectedTls)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
   136
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   137
	// Now re-send the initial handshake message to start the new
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   138
	// session.
178
ccfebbd9f49b Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Chris Jones <chris@cjones.org>
parents: 163
diff changeset
   139
	cl.sendRaw <- &stream{To: cl.Jid.Domain(), Version: XMPPVersion}
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   140
}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   141
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   142
// Send a request to bind a resource. RFC 3920, section 7.
149
22c96a9ab289 Removed an unused parameter.
Chris Jones <christian.jones@sri.com>
parents: 148
diff changeset
   143
func (cl *Client) bind() {
178
ccfebbd9f49b Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Chris Jones <chris@cjones.org>
parents: 163
diff changeset
   144
	res := cl.Jid.Resource()
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   145
	bindReq := &bindIq{}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   146
	if res != "" {
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   147
		bindReq.Resource = &res
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   148
	}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   149
	msg := &Iq{Header: Header{Type: "set", Id: NextId(),
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   150
		Nested: []interface{}{bindReq}}}
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
   151
	f := func(st Stanza) {
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   152
		iq, ok := st.(*Iq)
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   153
		if !ok {
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   154
			cl.setError(fmt.Errorf("non-iq response to bind %#v",
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   155
				st))
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   156
			return
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   157
		}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   158
		if iq.Type == "error" {
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   159
			cl.setError(fmt.Errorf("Resource binding failed"))
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   160
			return
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   161
		}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   162
		var bindRepl *bindIq
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   163
		for _, ele := range iq.Nested {
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   164
			if b, ok := ele.(*bindIq); ok {
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   165
				bindRepl = b
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   166
				break
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   167
			}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   168
		}
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   169
		if bindRepl == nil {
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   170
			cl.setError(fmt.Errorf("Bad bind reply: %#v", iq))
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   171
			return
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   172
		}
178
ccfebbd9f49b Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Chris Jones <chris@cjones.org>
parents: 163
diff changeset
   173
		jid := bindRepl.Jid
ccfebbd9f49b Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Chris Jones <chris@cjones.org>
parents: 163
diff changeset
   174
		if jid == nil || *jid == "" {
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   175
			cl.setError(fmt.Errorf("empty resource in bind %#v",
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   176
				iq))
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   177
			return
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   178
		}
178
ccfebbd9f49b Changed the JID type to be an alias of string, rather than a struct. This allows it to be used as a key in a map, among other benefits.
Chris Jones <chris@cjones.org>
parents: 163
diff changeset
   179
		cl.Jid = JID(*jid)
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
   180
		cl.setStatus(StatusBound)
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   181
	}
144
9d7fdb1d2fc1 Renamed HandleStanza to SetCallback.
Chris Jones <christian.jones@sri.com>
parents: 143
diff changeset
   182
	cl.SetCallback(msg.Id, f)
163
3f891f7fe817 Removed the weirdo logging facility. There's now a Debug variable which can be set which replaces the former debug log. NewClient() will return an error if something goes wrong setting up the connection.
Chris Jones <chris@cjones.org>
parents: 162
diff changeset
   183
	cl.sendRaw <- msg
143
62166e57800e Split stream.go into layer1, layer2, layer3, and sasl.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   184
}
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   185
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   186
// Register a callback to handle the next XMPP stanza (iq, message, or
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   187
// presence) with a given id. The provided function will not be called
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   188
// more than once. If it returns false, the stanza will not be made
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   189
// available on the normal Client.Recv channel. The callback must not
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   190
// read from that channel, as deliveries on it cannot proceed until
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   191
// the handler returns true or false.
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents: 150
diff changeset
   192
func (cl *Client) SetCallback(id string, f func(Stanza)) {
150
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   193
	h := &callback{id: id, f: f}
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   194
	cl.handlers <- h
fa7f6ff10c67 Code reorder and doc cleanup.
Chris Jones <christian.jones@sri.com>
parents: 149
diff changeset
   195
}