github.com/marineam/etcd@v0.1.2-0.20130821182615-9b7109b46686/transporter.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/tls"
     6  	"encoding/json"
     7  	"fmt"
     8  	"github.com/coreos/go-raft"
     9  	"io"
    10  	"net"
    11  	"net/http"
    12  )
    13  
    14  // Transporter layer for communication between raft nodes
    15  type transporter struct {
    16  	client *http.Client
    17  }
    18  
    19  // Create transporter using by raft server
    20  // Create http or https transporter based on
    21  // whether the user give the server cert and key
    22  func newTransporter(scheme string, tlsConf tls.Config) transporter {
    23  	t := transporter{}
    24  
    25  	tr := &http.Transport{
    26  		Dial: dialTimeout,
    27  	}
    28  
    29  	if scheme == "https" {
    30  		tr.TLSClientConfig = &tlsConf
    31  		tr.DisableCompression = true
    32  	}
    33  
    34  	t.client = &http.Client{Transport: tr}
    35  
    36  	return t
    37  }
    38  
    39  // Dial with timeout
    40  func dialTimeout(network, addr string) (net.Conn, error) {
    41  	return net.DialTimeout(network, addr, HTTPTimeout)
    42  }
    43  
    44  // Sends AppendEntries RPCs to a peer when the server is the leader.
    45  func (t transporter) SendAppendEntriesRequest(server *raft.Server, peer *raft.Peer, req *raft.AppendEntriesRequest) *raft.AppendEntriesResponse {
    46  	var aersp *raft.AppendEntriesResponse
    47  	var b bytes.Buffer
    48  	json.NewEncoder(&b).Encode(req)
    49  
    50  	u, _ := nameToRaftURL(peer.Name)
    51  	debugf("Send LogEntries to %s ", u)
    52  
    53  	resp, err := t.Post(fmt.Sprintf("%s/log/append", u), &b)
    54  
    55  	if err != nil {
    56  		debugf("Cannot send AppendEntriesRequest to %s: %s", u, err)
    57  	}
    58  
    59  	if resp != nil {
    60  		defer resp.Body.Close()
    61  		aersp = &raft.AppendEntriesResponse{}
    62  		if err := json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF {
    63  			return aersp
    64  		}
    65  
    66  	}
    67  
    68  	return aersp
    69  }
    70  
    71  // Sends RequestVote RPCs to a peer when the server is the candidate.
    72  func (t transporter) SendVoteRequest(server *raft.Server, peer *raft.Peer, req *raft.RequestVoteRequest) *raft.RequestVoteResponse {
    73  	var rvrsp *raft.RequestVoteResponse
    74  	var b bytes.Buffer
    75  	json.NewEncoder(&b).Encode(req)
    76  
    77  	u, _ := nameToRaftURL(peer.Name)
    78  	debugf("Send Vote to %s", u)
    79  
    80  	resp, err := t.Post(fmt.Sprintf("%s/vote", u), &b)
    81  
    82  	if err != nil {
    83  		debugf("Cannot send VoteRequest to %s : %s", u, err)
    84  	}
    85  
    86  	if resp != nil {
    87  		defer resp.Body.Close()
    88  		rvrsp := &raft.RequestVoteResponse{}
    89  		if err := json.NewDecoder(resp.Body).Decode(&rvrsp); err == nil || err == io.EOF {
    90  			return rvrsp
    91  		}
    92  
    93  	}
    94  	return rvrsp
    95  }
    96  
    97  // Sends SnapshotRequest RPCs to a peer when the server is the candidate.
    98  func (t transporter) SendSnapshotRequest(server *raft.Server, peer *raft.Peer, req *raft.SnapshotRequest) *raft.SnapshotResponse {
    99  	var aersp *raft.SnapshotResponse
   100  	var b bytes.Buffer
   101  	json.NewEncoder(&b).Encode(req)
   102  
   103  	u, _ := nameToRaftURL(peer.Name)
   104  	debugf("Send Snapshot to %s [Last Term: %d, LastIndex %d]", u,
   105  		req.LastTerm, req.LastIndex)
   106  
   107  	resp, err := t.Post(fmt.Sprintf("%s/snapshot", u), &b)
   108  
   109  	if err != nil {
   110  		debugf("Cannot send SendSnapshotRequest to %s : %s", u, err)
   111  	}
   112  
   113  	if resp != nil {
   114  		defer resp.Body.Close()
   115  		aersp = &raft.SnapshotResponse{}
   116  		if err = json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF {
   117  
   118  			return aersp
   119  		}
   120  	}
   121  
   122  	return aersp
   123  }
   124  
   125  // Sends SnapshotRecoveryRequest RPCs to a peer when the server is the candidate.
   126  func (t transporter) SendSnapshotRecoveryRequest(server *raft.Server, peer *raft.Peer, req *raft.SnapshotRecoveryRequest) *raft.SnapshotRecoveryResponse {
   127  	var aersp *raft.SnapshotRecoveryResponse
   128  	var b bytes.Buffer
   129  	json.NewEncoder(&b).Encode(req)
   130  
   131  	u, _ := nameToRaftURL(peer.Name)
   132  	debugf("Send SnapshotRecovery to %s [Last Term: %d, LastIndex %d]", u,
   133  		req.LastTerm, req.LastIndex)
   134  
   135  	resp, err := t.Post(fmt.Sprintf("%s/snapshotRecovery", u), &b)
   136  
   137  	if err != nil {
   138  		debugf("Cannot send SendSnapshotRecoveryRequest to %s : %s", u, err)
   139  	}
   140  
   141  	if resp != nil {
   142  		defer resp.Body.Close()
   143  		aersp = &raft.SnapshotRecoveryResponse{}
   144  		if err = json.NewDecoder(resp.Body).Decode(&aersp); err == nil || err == io.EOF {
   145  			return aersp
   146  		}
   147  	}
   148  
   149  	return aersp
   150  }
   151  
   152  // Send server side POST request
   153  func (t transporter) Post(path string, body io.Reader) (*http.Response, error) {
   154  	return t.client.Post(path, "application/json", body)
   155  }
   156  
   157  // Send server side GET request
   158  func (t transporter) Get(path string) (*http.Response, error) {
   159  	return t.client.Get(path)
   160  }