func newSocketTransport(c context.Context) *http.Transport { return &http.Transport{ Dial: func(net, addr string) (net.Conn, error) { c, err := socket.Dial(c, net, addr) if c != nil && err == nil { c.SetDeadline(time.Now().Add(1 * time.Hour)) } return c, err }, } }
// NewConn returns a new Redigo connection for the given net connection. func NewConn(appEngineContext context.Context, netConn *socket.Conn, network, address string, readTimeout, writeTimeout time.Duration) (Conn, error) { appEngineSocketConn, err := socket.Dial(appEngineContext, network, address) if err != nil { return nil, err } return &conn{ conn: appEngineSocketConn, bw: bufio.NewWriter(appEngineSocketConn), // br: bufio.NewReader(appEngineSocketConn), readTimeout: readTimeout, writeTimeout: writeTimeout, }, nil }
// Dial connects to the Redis server at address on the named network. func (d *xDialer) Dial(appEngineContext context.Context, network, address string) (Conn, error) { appEngineSocketConn, err := socket.Dial(appEngineContext, network, address) if err != nil { return nil, err } return &conn{ conn: appEngineSocketConn, bw: bufio.NewWriter(appEngineSocketConn), br: bufio.NewReader(appEngineSocketConn), readTimeout: d.ReadTimeout, writeTimeout: d.WriteTimeout, }, nil }
// LookupCNAME does a CNAME lookup on the specified host func LookupCNAME(ctx context.Context, host string) (cname string, err error) { conn, err := socket.Dial(ctx, "udp", nextDNSServer()) if err != nil { return "", err } defer conn.Close() q := packCNAME(host) _, err = conn.Write(q) if err != nil { return "", err } var in [512]byte _, err = conn.Read(in[:]) if err != nil { return "", err } return parseCNAMEAnswer(in[:]) }
// Connect establishes a connection to a Cassandra node. // You must also call the Serve method before you can execute any queries. func Connect(addr string, cfg ConnConfig, errorHandler ConnErrorHandler) (*Conn, error) { // var ( // err error // conn net.Conn // ) // dialer := &net.Dialer{ // Timeout: cfg.Timeout, // } // if cfg.tlsConfig != nil { // // the TLS config is safe to be reused by connections but it must not // // be modified after being used. // conn, err = tls.DialWithDialer(dialer, "tcp", addr, cfg.tlsConfig) // } else { conn, err := socket.Dial(cfg.contextOfAppEngine, "tcp", addr) // } if err != nil { return nil, err } // going to default to proto 2 if cfg.ProtoVersion < protoVersion1 || cfg.ProtoVersion > protoVersion3 { log.Printf("unsupported protocol version: %d using 2\n", cfg.ProtoVersion) cfg.ProtoVersion = 2 } headerSize := 8 maxStreams := 128 if cfg.ProtoVersion > protoVersion2 { maxStreams = 32768 headerSize = 9 } if cfg.NumStreams <= 0 || cfg.NumStreams >= maxStreams { cfg.NumStreams = maxStreams } else { cfg.NumStreams++ } c := &Conn{ conn: conn, r: bufio.NewReader(conn), uniq: make(chan int, cfg.NumStreams), calls: make([]callReq, cfg.NumStreams), timeout: cfg.Timeout, version: uint8(cfg.ProtoVersion), addr: conn.RemoteAddr().String(), errorHandler: errorHandler, compressor: cfg.Compressor, auth: cfg.Authenticator, headerBuf: make([]byte, headerSize), quit: make(chan struct{}), } if cfg.Keepalive > 0 { c.setKeepalive(cfg.Keepalive) } // reserve stream 0 incase cassandra returns an error on it without us sending // a request. for i := 1; i < cfg.NumStreams; i++ { c.calls[i].resp = make(chan error) c.uniq <- i } go c.serve() if err := c.startup(&cfg); err != nil { conn.Close() return nil, err } c.started = true return c, nil }
// ConnectAndWrite establishes the connection to Apple and handles the // transmission of your push notification, as well as waiting for a reply. // // In lieu of a timeout (which would be available in Go 1.1) // we use a timeout channel pattern instead. We start two goroutines, // one of which just sleeps for TimeoutSeconds seconds, while the other // waits for a response from the Apple servers. // // Whichever channel puts data on first is the "winner". As such, it's // possible to get a false positive if Apple takes a long time to respond. // It's probably not a deal-breaker, but something to be aware of. func (client *Client) ConnectAndWrite(context context.Context, resp *PushNotificationResponse, payload []byte) (err error) { var cert tls.Certificate if len(client.CertificateBase64) == 0 && len(client.KeyBase64) == 0 { // The user did not specify raw block contents, so check the filesystem. cert, err = tls.LoadX509KeyPair(client.CertificateFile, client.KeyFile) } else { // The user provided the raw block contents, so use that. cert, err = tls.X509KeyPair([]byte(client.CertificateBase64), []byte(client.KeyBase64)) } if err != nil { return err } gatewayParts := strings.Split(client.Gateway, ":") conf := &tls.Config{ Certificates: []tls.Certificate{cert}, ServerName: gatewayParts[0], } conn, err := socket.Dial(context, "tcp", client.Gateway) if err != nil { return err } defer conn.Close() tlsConn := tls.Client(conn, conf) err = tlsConn.Handshake() if err != nil { return err } defer tlsConn.Close() _, err = tlsConn.Write(payload) if err != nil { return err } // Create one channel that will serve to handle // timeouts when the notification succeeds. timeoutChannel := make(chan bool, 1) go func() { time.Sleep(time.Second * TimeoutSeconds) timeoutChannel <- true }() // This channel will contain the binary response // from Apple in the event of a failure. responseChannel := make(chan []byte, 1) go func() { buffer := make([]byte, 6, 6) tlsConn.Read(buffer) responseChannel <- buffer }() // First one back wins! // The data structure for an APN response is as follows: // // command -> 1 byte // status -> 1 byte // identifier -> 4 bytes // // The first byte will always be set to 8. select { case r := <-responseChannel: resp.Success = false resp.AppleResponse = ApplePushResponses[r[1]] err = errors.New(resp.AppleResponse) case <-timeoutChannel: resp.Success = true } return err }