github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+incompatible/private/constellation/node.go (about) 1 package constellation 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "github.com/tv42/httpunix" 10 "io" 11 "io/ioutil" 12 "net/http" 13 "os" 14 "os/exec" 15 "strings" 16 "time" 17 ) 18 19 func launchNode(cfgPath string) (*exec.Cmd, error) { 20 cmd := exec.Command("constellation-node", cfgPath) 21 stderr, err := cmd.StderrPipe() 22 if err != nil { 23 return nil, err 24 } 25 go io.Copy(os.Stderr, stderr) 26 if err := cmd.Start(); err != nil { 27 return nil, err 28 } 29 time.Sleep(100 * time.Millisecond) 30 return cmd, nil 31 } 32 33 func unixTransport(socketPath string) *httpunix.Transport { 34 t := &httpunix.Transport{ 35 DialTimeout: 1 * time.Second, 36 RequestTimeout: 5 * time.Second, 37 ResponseHeaderTimeout: 5 * time.Second, 38 } 39 t.RegisterLocation("c", socketPath) 40 return t 41 } 42 43 func unixClient(socketPath string) *http.Client { 44 return &http.Client{ 45 Transport: unixTransport(socketPath), 46 } 47 } 48 49 func RunNode(socketPath string) error { 50 c := unixClient(socketPath) 51 res, err := c.Get("http+unix://c/upcheck") 52 if err != nil { 53 return err 54 } 55 if res.StatusCode == 200 { 56 return nil 57 } 58 return errors.New("Constellation Node API did not respond to upcheck request") 59 } 60 61 type Client struct { 62 httpClient *http.Client 63 } 64 65 func (c *Client) doJson(path string, apiReq interface{}) (*http.Response, error) { 66 buf := new(bytes.Buffer) 67 err := json.NewEncoder(buf).Encode(apiReq) 68 if err != nil { 69 return nil, err 70 } 71 req, err := http.NewRequest("POST", "http+unix://c/"+path, buf) 72 if err != nil { 73 return nil, err 74 } 75 req.Header.Set("Content-Type", "application/json") 76 res, err := c.httpClient.Do(req) 77 if err == nil && res.StatusCode != 200 { 78 return nil, fmt.Errorf("Non-200 status code: %+v", res) 79 } 80 return res, err 81 } 82 83 func (c *Client) SendPayload(pl []byte, b64From string, b64To []string) ([]byte, error) { 84 buf := bytes.NewBuffer(pl) 85 req, err := http.NewRequest("POST", "http+unix://c/sendraw", buf) 86 if err != nil { 87 return nil, err 88 } 89 if b64From != "" { 90 req.Header.Set("c11n-from", b64From) 91 } 92 req.Header.Set("c11n-to", strings.Join(b64To, ",")) 93 req.Header.Set("Content-Type", "application/octet-stream") 94 res, err := c.httpClient.Do(req) 95 if err == nil && res.StatusCode != 200 { 96 return nil, fmt.Errorf("Non-200 status code: %+v", res) 97 } 98 defer res.Body.Close() 99 return ioutil.ReadAll(base64.NewDecoder(base64.StdEncoding, res.Body)) 100 } 101 102 func (c *Client) ReceivePayload(key []byte) ([]byte, error) { 103 req, err := http.NewRequest("GET", "http+unix://c/receiveraw", nil) 104 if err != nil { 105 return nil, err 106 } 107 req.Header.Set("c11n-key", base64.StdEncoding.EncodeToString(key)) 108 res, err := c.httpClient.Do(req) 109 if err == nil && res.StatusCode != 200 { 110 return nil, fmt.Errorf("Non-200 status code: %+v", res) 111 } 112 defer res.Body.Close() 113 return ioutil.ReadAll(res.Body) 114 } 115 116 func NewClient(socketPath string) (*Client, error) { 117 return &Client{ 118 httpClient: unixClient(socketPath), 119 }, nil 120 }