Example #1
0
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
		},
	}
}
Example #2
0
// 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
}
Example #3
0
// 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
}
Example #4
0
// 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[:])
}
Example #5
0
// 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
}
Example #6
0
// 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
}