github.com/alpe/etcd@v0.1.2-0.20130915230056-09f31af88aeb/transporter.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "crypto/tls" 6 "encoding/json" 7 "fmt" 8 "io" 9 "net" 10 "net/http" 11 "time" 12 13 "github.com/coreos/go-raft" 14 ) 15 16 // Transporter layer for communication between raft nodes 17 type transporter struct { 18 client *http.Client 19 timeout time.Duration 20 } 21 22 // response struct 23 type transporterResponse struct { 24 resp *http.Response 25 err error 26 } 27 28 // Create transporter using by raft server 29 // Create http or https transporter based on 30 // whether the user give the server cert and key 31 func newTransporter(scheme string, tlsConf tls.Config, timeout time.Duration) *transporter { 32 t := transporter{} 33 34 tr := &http.Transport{ 35 Dial: dialTimeout, 36 } 37 38 if scheme == "https" { 39 tr.TLSClientConfig = &tlsConf 40 tr.DisableCompression = true 41 } 42 43 t.client = &http.Client{Transport: tr} 44 t.timeout = timeout 45 46 return &t 47 } 48 49 // Dial with timeout 50 func dialTimeout(network, addr string) (net.Conn, error) { 51 return net.DialTimeout(network, addr, HTTPTimeout) 52 } 53 54 // Sends AppendEntries RPCs to a peer when the server is the leader. 55 func (t *transporter) SendAppendEntriesRequest(server *raft.Server, peer *raft.Peer, req *raft.AppendEntriesRequest) *raft.AppendEntriesResponse { 56 var aersp *raft.AppendEntriesResponse 57 var b bytes.Buffer 58 59 json.NewEncoder(&b).Encode(req) 60 61 size := b.Len() 62 63 r.serverStats.SendAppendReq(size) 64 65 u, _ := nameToRaftURL(peer.Name) 66 67 debugf("Send LogEntries to %s ", u) 68 69 thisPeerStats, ok := r.peersStats[peer.Name] 70 71 start := time.Now() 72 73 resp, err := t.Post(fmt.Sprintf("%s/log/append", u), &b) 74 75 end := time.Now() 76 77 if err != nil { 78 debugf("Cannot send AppendEntriesRequest to %s: %s", u, err) 79 if ok { 80 thisPeerStats.Fail() 81 } 82 } else { 83 if ok { 84 thisPeerStats.Succ(end.Sub(start)) 85 } 86 } 87 88 r.peersStats[peer.Name] = thisPeerStats 89 90 if resp != nil { 91 defer resp.Body.Close() 92 aersp = &raft.AppendEntriesResponse{} 93 if err := json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF { 94 return aersp 95 } 96 97 } 98 99 return aersp 100 } 101 102 // Sends RequestVote RPCs to a peer when the server is the candidate. 103 func (t *transporter) SendVoteRequest(server *raft.Server, peer *raft.Peer, req *raft.RequestVoteRequest) *raft.RequestVoteResponse { 104 var rvrsp *raft.RequestVoteResponse 105 var b bytes.Buffer 106 json.NewEncoder(&b).Encode(req) 107 108 u, _ := nameToRaftURL(peer.Name) 109 debugf("Send Vote to %s", u) 110 111 resp, err := t.Post(fmt.Sprintf("%s/vote", u), &b) 112 113 if err != nil { 114 debugf("Cannot send VoteRequest to %s : %s", u, err) 115 } 116 117 if resp != nil { 118 defer resp.Body.Close() 119 rvrsp := &raft.RequestVoteResponse{} 120 if err := json.NewDecoder(resp.Body).Decode(&rvrsp); err == nil || err == io.EOF { 121 return rvrsp 122 } 123 124 } 125 return rvrsp 126 } 127 128 // Sends SnapshotRequest RPCs to a peer when the server is the candidate. 129 func (t *transporter) SendSnapshotRequest(server *raft.Server, peer *raft.Peer, req *raft.SnapshotRequest) *raft.SnapshotResponse { 130 var aersp *raft.SnapshotResponse 131 var b bytes.Buffer 132 json.NewEncoder(&b).Encode(req) 133 134 u, _ := nameToRaftURL(peer.Name) 135 debugf("Send Snapshot to %s [Last Term: %d, LastIndex %d]", u, 136 req.LastTerm, req.LastIndex) 137 138 resp, err := t.Post(fmt.Sprintf("%s/snapshot", u), &b) 139 140 if err != nil { 141 debugf("Cannot send SendSnapshotRequest to %s : %s", u, err) 142 } 143 144 if resp != nil { 145 defer resp.Body.Close() 146 aersp = &raft.SnapshotResponse{} 147 if err = json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF { 148 149 return aersp 150 } 151 } 152 153 return aersp 154 } 155 156 // Sends SnapshotRecoveryRequest RPCs to a peer when the server is the candidate. 157 func (t *transporter) SendSnapshotRecoveryRequest(server *raft.Server, peer *raft.Peer, req *raft.SnapshotRecoveryRequest) *raft.SnapshotRecoveryResponse { 158 var aersp *raft.SnapshotRecoveryResponse 159 var b bytes.Buffer 160 json.NewEncoder(&b).Encode(req) 161 162 u, _ := nameToRaftURL(peer.Name) 163 debugf("Send SnapshotRecovery to %s [Last Term: %d, LastIndex %d]", u, 164 req.LastTerm, req.LastIndex) 165 166 resp, err := t.Post(fmt.Sprintf("%s/snapshotRecovery", u), &b) 167 168 if err != nil { 169 debugf("Cannot send SendSnapshotRecoveryRequest to %s : %s", u, err) 170 } 171 172 if resp != nil { 173 defer resp.Body.Close() 174 aersp = &raft.SnapshotRecoveryResponse{} 175 if err = json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF { 176 return aersp 177 } 178 } 179 180 return aersp 181 } 182 183 // Send server side POST request 184 func (t *transporter) Post(path string, body io.Reader) (*http.Response, error) { 185 186 c := make(chan *transporterResponse, 1) 187 188 go func() { 189 tr := new(transporterResponse) 190 tr.resp, tr.err = t.client.Post(path, "application/json", body) 191 c <- tr 192 }() 193 194 return t.waitResponse(c) 195 196 } 197 198 // Send server side GET request 199 func (t *transporter) Get(path string) (*http.Response, error) { 200 201 c := make(chan *transporterResponse, 1) 202 203 go func() { 204 tr := new(transporterResponse) 205 tr.resp, tr.err = t.client.Get(path) 206 c <- tr 207 }() 208 209 return t.waitResponse(c) 210 } 211 212 func (t *transporter) waitResponse(responseChan chan *transporterResponse) (*http.Response, error) { 213 214 timeoutChan := time.After(t.timeout) 215 216 select { 217 case <-timeoutChan: 218 return nil, fmt.Errorf("Wait Response Timeout: %v", t.timeout) 219 220 case r := <-responseChan: 221 return r.resp, r.err 222 } 223 224 // for complier 225 return nil, nil 226 }