package constellation import ( "bytes" "encoding/base64" "encoding/json" "errors" "fmt" "github.com/tv42/httpunix" "io" "io/ioutil" "net/http" "os" "os/exec" "strings" "time" ) func launchNode(cfgPath string) (*exec.Cmd, error) { cmd := exec.Command("constellation-node", cfgPath) stderr, err := cmd.StderrPipe() if err != nil { return nil, err } go io.Copy(os.Stderr, stderr) if err := cmd.Start(); err != nil { return nil, err } time.Sleep(100 * time.Millisecond) return cmd, nil } func unixTransport(socketPath string) *httpunix.Transport { t := &httpunix.Transport{ DialTimeout: 1 * time.Second, RequestTimeout: 5 * time.Second, ResponseHeaderTimeout: 5 * time.Second, } t.RegisterLocation("c", socketPath) return t } func unixClient(socketPath string) *http.Client { return &http.Client{ Transport: unixTransport(socketPath), } } func RunNode(socketPath string) error { c := unixClient(socketPath) res, err := c.Get("http+unix://c/upcheck") if err != nil { return err } if res.StatusCode == 200 { return nil } return errors.New("Constellation Node API did not respond to upcheck request") } type Client struct { httpClient *http.Client } func (c *Client) doJson(path string, apiReq interface{}) (*http.Response, error) { buf := new(bytes.Buffer) err := json.NewEncoder(buf).Encode(apiReq) if err != nil { return nil, err } req, err := http.NewRequest("POST", "http+unix://c/"+path, buf) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") res, err := c.httpClient.Do(req) if err == nil && res.StatusCode != 200 { return nil, fmt.Errorf("Non-200 status code: %+v", res) } return res, err } func (c *Client) SendPayload(pl []byte, b64From string, b64To []string) ([]byte, error) { buf := bytes.NewBuffer(pl) req, err := http.NewRequest("POST", "http+unix://c/sendraw", buf) if err != nil { return nil, err } if b64From != "" { req.Header.Set("c11n-from", b64From) } req.Header.Set("c11n-to", strings.Join(b64To, ",")) req.Header.Set("Content-Type", "application/octet-stream") res, err := c.httpClient.Do(req) if err == nil && res.StatusCode != 200 { return nil, fmt.Errorf("Non-200 status code: %+v", res) } defer res.Body.Close() return ioutil.ReadAll(res.Body) } func (c *Client) ReceivePayload(key []byte) ([]byte, error) { req, err := http.NewRequest("GET", "http+unix://c/receiveraw", nil) if err != nil { return nil, err } req.Header.Set("c11n-key", base64.StdEncoding.EncodeToString(key)) res, err := c.httpClient.Do(req) if err == nil && res.StatusCode != 200 { return nil, fmt.Errorf("Non-200 status code: %+v", res) } defer res.Body.Close() return ioutil.ReadAll(res.Body) } func NewClient(socketPath string) (*Client, error) { return &Client{ httpClient: unixClient(socketPath), }, nil }