func createAttachment(stream *spdystream.Stream) (*os.File, error) { if stream.IsFinished() { return nil, fmt.Errorf("stream already finished") } socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0) if socketErr != nil { return nil, socketErr } pipe := os.NewFile(uintptr(socketFds[1]), "") defer pipe.Close() conn, connErr := net.FileConn(pipe) if connErr != nil { return nil, connErr } go func() { io.Copy(conn, stream) conn.Close() }() go func() { io.Copy(stream, conn) }() return os.NewFile(uintptr(socketFds[0]), ""), nil }
func (s *StreamSession) getStreamChan(stream *spdystream.Stream) chan *spdystream.Stream { if stream == nil { return s.streamChan } streamChan, ok := s.subStreamChans[stream.String()] if ok { return streamChan } return s.streamChan }
func (l *ListenSession) getStreamChan(stream *spdystream.Stream) chan *spdystream.Stream { if stream == nil { return l.streamChan } l.streamLock.RLock() defer l.streamLock.RUnlock() streamChan, ok := l.subStreamChans[stream.String()] if ok { return streamChan } return l.streamChan }
func (s *Server) getStreamChan(stream *spdystream.Stream) chan *spdystream.Stream { if stream == nil { return s.streamChan } s.streamLock.RLock() defer s.streamLock.RUnlock() streamChan, ok := s.subStreamChans[stream.String()] if ok { return streamChan } return s.streamChan }
// newSpdyStream is the internal new stream handler used by spdystream.Connection.Serve. // It calls connection's newStreamHandler, giving it the opportunity to accept or reject // the stream. If newStreamHandler returns an error, the stream is rejected. If not, the // stream is accepted and registered with the connection. func (c *connection) newSpdyStream(stream *spdystream.Stream) { err := c.newStreamHandler(stream) rejectStream := (err != nil) if rejectStream { glog.Warningf("Stream rejected: %v", err) stream.Reset() return } c.registerStream(stream) stream.SendReply(http.Header{}, rejectStream) }
func createStreamMessage(stream *spdystream.Stream, mode int, streamChans streamChanProvider, ret libchan.Sender) (*libchan.Message, error) { dataString := stream.Headers()["Data"] if len(dataString) != 1 { if len(dataString) == 0 { return nil, fmt.Errorf("Stream(%s) is missing data header", stream) } else { return nil, fmt.Errorf("Stream(%s) has multiple data headers", stream) } } data, decodeErr := base64.URLEncoding.DecodeString(dataString[0]) if decodeErr != nil { return nil, decodeErr } var attach *os.File if !stream.IsFinished() { socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0) if socketErr != nil { return nil, socketErr } attach = os.NewFile(uintptr(socketFds[0]), "") conn, connErr := net.FileConn(os.NewFile(uintptr(socketFds[1]), "")) if connErr != nil { return nil, connErr } go func() { io.Copy(conn, stream) }() go func() { io.Copy(stream, conn) }() } retSender := ret if retSender == nil || libchan.RetPipe.Equals(retSender) { retSender = &StreamSender{stream: stream, streamChans: streamChans} } if mode&libchan.Ret == 0 { retSender.Close() } return &libchan.Message{ Data: data, Fd: attach, Ret: retSender, }, nil }
// newSpdyStream is the internal new stream handler used by spdystream.Connection.Serve. // It calls connection's newStreamHandler, giving it the opportunity to accept or reject // the stream. If newStreamHandler returns an error, the stream is rejected. If not, the // stream is accepted and registered with the connection. func (c *connection) newSpdyStream(stream *spdystream.Stream) { replySent := make(chan struct{}) err := c.newStreamHandler(stream, replySent) rejectStream := (err != nil) if rejectStream { glog.Warningf("Stream rejected: %v", err) stream.Reset() return } c.registerStream(stream) stream.SendReply(http.Header{}, rejectStream) close(replySent) }
func (p *spdyStreamProvider) newStreamHandler(stream *spdystream.Stream) { s := &spdyStream{ stream: stream, } returnHeaders := http.Header{} var finish bool select { case <-p.closeChan: returnHeaders.Set(":status", "502") finish = true case p.listenChan <- s: returnHeaders.Set(":status", "200") } stream.SendReply(returnHeaders, finish) }
func (s *Transport) newStreamHandler(stream *spdystream.Stream) { referenceIDString := stream.Headers().Get("libchan-ref") parentIDString := stream.Headers().Get("libchan-parent-ref") returnHeaders := http.Header{} finish := false referenceID, parseErr := strconv.ParseUint(referenceIDString, 10, 64) if parseErr != nil { returnHeaders.Set("status", "400") finish = true } else { if parentIDString == "" { byteStream := &byteStream{ referenceID: referenceID, stream: stream, session: s, } s.byteStreamC.L.Lock() s.byteStreams[referenceID] = byteStream s.byteStreamC.Broadcast() s.byteStreamC.L.Unlock() returnHeaders.Set("status", "200") } else { parentID, parseErr := strconv.ParseUint(parentIDString, 10, 64) if parseErr != nil { returnHeaders.Set("status", "400") finish = true } else { c := &channel{ referenceID: referenceID, parentID: parentID, stream: stream, session: s, } s.channelC.L.Lock() s.channels[referenceID] = c s.channelC.Broadcast() s.channelC.L.Unlock() if parentID == 0 { c.direction = inbound s.receiverChan <- c } returnHeaders.Set("status", "200") } } } stream.SendReply(returnHeaders, finish) }
func (s *Server) addStreamChan(stream *spdystream.Stream, streamChan chan *spdystream.Stream) { s.streamLock.Lock() s.subStreamChans[stream.String()] = streamChan s.streamLock.Unlock() }
func (s *Server) streamHandler(stream *spdystream.Stream) { streamChan := s.getStreamChan(stream.Parent()) streamChan <- stream }
func createStreamMessage(stream *spdystream.Stream, mode int, streamChans streamChanProvider, ret beam.Sender) (*beam.Message, error) { verbString := stream.Headers()["Verb"] if len(verbString) != 1 { if len(verbString) == 0 { return nil, fmt.Errorf("Stream(%s) is missing verb header", stream) } else { return nil, fmt.Errorf("Stream(%s) has multiple verb headers", stream) } } verb, verbOk := verbs[verbString[0]] if !verbOk { return nil, fmt.Errorf("Unknown verb: %s", verbString[0]) } var args []string argString := stream.Headers()["Args"] if len(argString) > 1 { return nil, fmt.Errorf("Stream(%s) has multiple args headers", stream) } if len(argString) == 1 { var err error args, err = decodeArgs(argString[0]) if err != nil { return nil, err } } var attach *os.File if !stream.IsFinished() { socketFds, socketErr := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.FD_CLOEXEC, 0) if socketErr != nil { return nil, socketErr } attach = os.NewFile(uintptr(socketFds[0]), "") conn, connErr := net.FileConn(os.NewFile(uintptr(socketFds[1]), "")) if connErr != nil { return nil, connErr } go func() { io.Copy(conn, stream) }() go func() { io.Copy(stream, conn) }() } retSender := ret if retSender == nil || beam.RetPipe.Equals(retSender) { retSender = &StreamSender{stream: stream, streamChans: streamChans} } if mode&beam.Ret == 0 { retSender.Close() } return &beam.Message{ Verb: verb, Args: args, Att: attach, Ret: retSender, }, nil }
func (l *ListenSession) streamHandler(stream *spdystream.Stream) { // TODO authorize stream stream.SendReply(http.Header{}, false) streamChan := l.getStreamChan(stream.Parent()) streamChan <- stream }
func (l *ListenSession) addStreamChan(stream *spdystream.Stream, streamChan chan *spdystream.Stream) { l.streamLock.Lock() l.subStreamChans[stream.String()] = streamChan l.streamLock.Unlock() }
func (l *ListenSession) streamHandler(stream *spdystream.Stream) { streamChan := l.getStreamChan(stream.Parent()) streamChan <- stream }
func (s *StreamSession) newStreamHandler(stream *spdystream.Stream) { stream.SendReply(http.Header{}, false) streamChan := s.getStreamChan(stream.Parent()) streamChan <- stream }
func (s *StreamSession) newStreamHandler(stream *spdystream.Stream) { streamChan := s.getStreamChan(stream.Parent()) streamChan <- stream }
func (s *StreamSession) addStreamChan(stream *spdystream.Stream, streamChan chan *spdystream.Stream) { s.subStreamChans[stream.String()] = streamChan }