This file is indexed.

/usr/share/gocode/src/github.com/google/cups-connector/gcp/http.go is in google-cloud-print-connector 0.0~git20151105.24.1902938-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
Copyright 2015 Google Inc. All rights reserved.

Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file or at
https://developers.google.com/open-source/licenses/bsd
*/

package gcp

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"github.com/google/cups-connector/lib"

	"golang.org/x/oauth2"
)

/*
glibc < 2.20 and OSX 10.10 have problems when C.getaddrinfo is called many
times concurrently. When the connector shares more than about 230 printers, and
GCP is called once per printer in concurrent goroutines, http.Client.Do starts
to fail with a lookup error.

This solution, a semaphore, limits the quantity of concurrent HTTP requests,
which also limits the quantity of concurrent calls to net.LookupHost (which
calls C.getaddrinfo()).

I would rather wait for the Go compiler to solve this problem than make this a
configurable option, hence this long-winded comment.

https://github.com/golang/go/issues/3575
https://github.com/golang/go/issues/6336
*/
var lock *lib.Semaphore = lib.NewSemaphore(100)

// newClient creates an instance of http.Client, wrapped with OAuth credentials.
func newClient(oauthClientID, oauthClientSecret, oauthAuthURL, oauthTokenURL, refreshToken string, scopes ...string) (*http.Client, error) {
	config := oauth2.Config{
		ClientID:     oauthClientID,
		ClientSecret: oauthClientSecret,
		Endpoint: oauth2.Endpoint{
			AuthURL:  oauthAuthURL,
			TokenURL: oauthTokenURL,
		},
		RedirectURL: RedirectURL,
		Scopes:      scopes,
	}

	token := oauth2.Token{RefreshToken: refreshToken}
	client := config.Client(oauth2.NoContext, &token)

	return client, nil
}

// getWithRetry calls get() and retries once on HTTP failure
// (response code != 200).
func getWithRetry(hc *http.Client, url string) (*http.Response, error) {
	response, err := get(hc, url)
	if response != nil && response.StatusCode == http.StatusOK {
		return response, err
	}

	return get(hc, url)
}

// get GETs a URL. Returns the response object (not body), in case the body
// is very large.
//
// The caller must close the returned Response.Body object if err == nil.
func get(hc *http.Client, url string) (*http.Response, error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	request.Header.Set("X-CloudPrint-Proxy", lib.ShortName)

	lock.Acquire()
	response, err := hc.Do(request)
	lock.Release()
	if err != nil {
		return nil, fmt.Errorf("GET failure: %s", err)
	}
	if response.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("GET HTTP-level failure: %s %s", url, response.Status)
	}

	return response, nil
}

// postWithRetry calls post() and retries once on HTTP failure
// (response code != 200).
func postWithRetry(hc *http.Client, url string, form url.Values) ([]byte, uint, int, error) {
	responseBody, gcpErrorCode, httpStatusCode, err := post(hc, url, form)
	if responseBody != nil && httpStatusCode == http.StatusOK {
		return responseBody, gcpErrorCode, httpStatusCode, err
	}

	return post(hc, url, form)
}

// post POSTs to a URL. Returns the body of the response.
//
// Returns the response body, GCP error code, HTTP status, and error.
// None of the returned fields is guaranteed to be non-zero.
func post(hc *http.Client, url string, form url.Values) ([]byte, uint, int, error) {
	requestBody := strings.NewReader(form.Encode())
	request, err := http.NewRequest("POST", url, requestBody)
	if err != nil {
		return nil, 0, 0, err
	}
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Set("X-CloudPrint-Proxy", lib.ShortName)

	lock.Acquire()
	response, err := hc.Do(request)
	lock.Release()
	if err != nil {
		return nil, 0, 0, fmt.Errorf("POST failure: %s", err)
	}

	defer response.Body.Close()
	responseBody, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, 0, response.StatusCode, err
	}

	if response.StatusCode != http.StatusOK {
		return responseBody, 0, response.StatusCode, fmt.Errorf("/%s POST HTTP-level failure: %s", url, response.Status)
	}

	var responseStatus struct {
		Success   bool
		Message   string
		ErrorCode uint
	}
	if err = json.Unmarshal(responseBody, &responseStatus); err != nil {
		return responseBody, 0, response.StatusCode, err
	}
	if !responseStatus.Success {
		return responseBody, responseStatus.ErrorCode, response.StatusCode, fmt.Errorf(
			"%s call failed: %s", url, responseStatus.Message)
	}

	return responseBody, responseStatus.ErrorCode, response.StatusCode, nil
}