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 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 }
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 }