stream.go
author Chris Jones <chris@cjones.org>
Mon, 26 Dec 2011 18:07:14 -0700
changeset 10 f38b0ee7b1c1
child 11 48be1ae93fd4
permissions -rw-r--r--
Added TLS negotiation.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     1
// Copyright 2011 The Go Authors.  All rights reserved.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     2
// Use of this source code is governed by a BSD-style
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     3
// license that can be found in the LICENSE file.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     4
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     5
// This file contains the three layers of processing for the
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     6
// communication with the server: transport (where TLS happens), XML
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     7
// (where strings are converted to go structures), and Stream (where
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     8
// we respond to XMPP events on behalf of the library client).
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
     9
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    10
package xmpp
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    11
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    12
import (
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    13
	"crypto/tls"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    14
	"io"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    15
	"log"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    16
	"net"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    17
	"os"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    18
	"time"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    19
	"xml"
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    20
)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    21
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    22
func (cl *Client) readTransport(w io.Writer) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    23
	defer tryClose(cl.socket, w)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    24
	cl.socket.SetReadTimeout(1e8)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    25
	p := make([]byte, 1024)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    26
	for {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    27
		if cl.socket == nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    28
			cl.waitForSocket()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    29
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    30
		nr, err := cl.socket.Read(p)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    31
		if nr == 0 {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    32
			if errno, ok := err.(*net.OpError) ; ok {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    33
				if errno.Timeout() {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    34
					continue
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    35
				}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    36
			}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    37
			log.Printf("read: %s", err.String())
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    38
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    39
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    40
		nw, err := w.Write(p[:nr])
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    41
		if nw < nr {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    42
			log.Println("read: %s", err.String())
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    43
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    44
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    45
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    46
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    47
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    48
func (cl *Client) writeTransport(r io.Reader) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    49
	defer tryClose(r, cl.socket)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    50
	p := make([]byte, 1024)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    51
	for {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    52
		nr, err := r.Read(p)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    53
		if nr == 0 {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    54
			log.Printf("write: %s", err.String())
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    55
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    56
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    57
		nw, err := cl.socket.Write(p[:nr])
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    58
		if nw < nr {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    59
			log.Println("write: %s", err.String())
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    60
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    61
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    62
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    63
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    64
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    65
func readXml(r io.Reader, ch chan<- interface{}) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    66
	if debug {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    67
		pr, pw := io.Pipe()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    68
		go tee(r, pw, "S: ")
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    69
		r = pr
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    70
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    71
	defer tryClose(r, ch)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    72
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    73
	p := xml.NewParser(r)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    74
	for {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    75
		// Sniff the next token on the stream.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    76
		t, err := p.Token()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    77
		if t == nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    78
			if err != os.EOF {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    79
				log.Printf("read: %v", err)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    80
			}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    81
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    82
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    83
		var se xml.StartElement
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    84
		var ok bool
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    85
		if se, ok = t.(xml.StartElement) ; !ok {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    86
			continue
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    87
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    88
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    89
		// Allocate the appropriate structure for this token.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    90
		var obj interface{}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    91
		switch se.Name.Space + " " + se.Name.Local {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    92
		case nsStream + " stream":
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    93
			st, err := parseStream(se)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    94
			if err != nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    95
				log.Printf("unmarshal stream: %v",
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    96
					err)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    97
				break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    98
			}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
    99
			ch <- st
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   100
			continue
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   101
		case "stream error", nsStream + " error":
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   102
			obj = &StreamError{}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   103
		case nsStream + " features":
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   104
			obj = &Features{}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   105
		case nsTLS + " proceed", nsTLS + " failure":
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   106
			obj = &starttls{}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   107
		default:
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   108
			obj = &Unrecognized{}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   109
			log.Printf("Ignoring unrecognized: %s %s\n",
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   110
				se.Name.Space, se.Name.Local)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   111
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   112
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   113
		// Read the complete XML stanza.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   114
		err = p.Unmarshal(obj, &se)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   115
		if err != nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   116
			log.Printf("unmarshal: %v", err)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   117
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   118
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   119
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   120
		// Put it on the channel.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   121
		ch <- obj
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   122
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   123
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   124
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   125
func writeXml(w io.Writer, ch <-chan interface{}) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   126
	if debug {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   127
		pr, pw := io.Pipe()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   128
		go tee(pr, w, "C: ")
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   129
		w = pw
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   130
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   131
	defer tryClose(w, ch)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   132
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   133
	for obj := range ch {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   134
		err := xml.Marshal(w, obj)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   135
		if err != nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   136
			log.Printf("write: %v", err)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   137
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   138
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   139
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   140
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   141
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   142
func writeText(w io.Writer, ch <-chan *string) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   143
	if debug {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   144
		pr, pw := io.Pipe()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   145
		go tee(pr, w, "C: ")
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   146
		w = pw
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   147
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   148
	defer tryClose(w, ch)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   149
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   150
	for str := range ch {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   151
		_, err := w.Write([]byte(*str))
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   152
		if err != nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   153
			log.Printf("writeStr: %v", err)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   154
			break
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   155
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   156
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   157
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   158
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   159
func (cl *Client) readStream(srvIn <-chan interface{}, srvOut, cliOut chan<- interface{}) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   160
	defer tryClose(srvIn, cliOut)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   161
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   162
	for x := range srvIn {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   163
		switch obj := x.(type) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   164
		case *Stream:
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   165
			handleStream(obj)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   166
		case *Features:
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   167
			handleFeatures(obj, srvOut)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   168
		case *starttls:
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   169
			cl.handleTls(obj)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   170
		default:
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   171
			cliOut <- x
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   172
		}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   173
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   174
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   175
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   176
func writeStream(srvOut chan<- interface{}, cliIn <-chan interface{}) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   177
	defer tryClose(srvOut, cliIn)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   178
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   179
	for x := range cliIn {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   180
		srvOut <- x
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   181
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   182
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   183
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   184
func handleStream(ss *Stream) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   185
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   186
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   187
func handleFeatures(fe *Features, srvOut chan<- interface{}) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   188
	if fe.Starttls != nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   189
		start := &starttls{XMLName: xml.Name{Space: nsTLS,
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   190
			Local: "starttls"}}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   191
		srvOut <- start
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   192
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   193
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   194
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   195
// readTransport() is running concurrently. We need to stop it,
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   196
// negotiate TLS, then start it again. It calls waitForSocket() in
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   197
// its inner loop; see below.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   198
func (cl *Client) handleTls(t *starttls) {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   199
	tcp := cl.socket
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   200
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   201
	// Set the socket to nil, and wait for the reader routine to
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   202
	// signal that it's paused.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   203
	cl.socket = nil
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   204
	cl.socketSync.Add(1)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   205
	cl.socketSync.Wait()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   206
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   207
	// Negotiate TLS with the server.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   208
	tls := tls.Client(tcp, nil)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   209
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   210
	// Make the TLS connection available to the reader, and wait
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   211
	// for it to signal that it's working again.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   212
	cl.socketSync.Add(1)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   213
	cl.socket = tls
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   214
	cl.socketSync.Wait()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   215
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   216
	// Reset the read timeout on the (underlying) socket so the
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   217
	// reader doesn't get woken up unnecessarily.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   218
	tcp.SetReadTimeout(0)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   219
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   220
	log.Println("TLS negotiation succeeded.")
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   221
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   222
	// Now re-send the initial handshake message to start the new
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   223
	// session.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   224
	hsOut := &Stream{To: cl.Jid.Domain, Version: Version}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   225
	cl.xmlOut <- hsOut
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   226
}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   227
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   228
// Synchronize with handleTls(). Called from readTransport() when
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   229
// cl.socket is nil.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   230
func (cl *Client) waitForSocket() {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   231
	// Signal that we've stopped reading from the socket.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   232
	cl.socketSync.Done()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   233
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   234
	// Wait until the socket is available again.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   235
	for cl.socket == nil {
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   236
		time.Sleep(1e8)
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   237
	}
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   238
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   239
	// Signal that we're going back to the read loop.
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   240
	cl.socketSync.Done()
f38b0ee7b1c1 Added TLS negotiation.
Chris Jones <chris@cjones.org>
parents:
diff changeset
   241
}