Example #1
0
func (cw *streamWriter) run() {
	var msgc chan raftpb.Message
	var heartbeatc <-chan time.Time
	var t streamType
	var enc encoder
	var flusher http.Flusher
	tickc := time.Tick(ConnReadTimeout / 3)

	for {
		select {
		case <-heartbeatc:
			start := time.Now()
			if err := enc.encode(linkHeartbeatMessage); err != nil {
				reportSentFailure(string(t), linkHeartbeatMessage)

				cw.status.deactivate(failureType{source: t.String(), action: "heartbeat"}, err.Error())
				cw.close()
				heartbeatc, msgc = nil, nil
				continue
			}
			flusher.Flush()
			reportSentDuration(string(t), linkHeartbeatMessage, time.Since(start))
		case m := <-msgc:
			start := time.Now()
			if err := enc.encode(m); err != nil {
				reportSentFailure(string(t), m)

				cw.status.deactivate(failureType{source: t.String(), action: "write"}, err.Error())
				cw.close()
				heartbeatc, msgc = nil, nil
				cw.r.ReportUnreachable(m.To)
				continue
			}
			flusher.Flush()
			reportSentDuration(string(t), m, time.Since(start))
		case conn := <-cw.connc:
			cw.close()
			t = conn.t
			switch conn.t {
			case streamTypeMsgAppV2:
				enc = newMsgAppV2Encoder(conn.Writer, cw.fs)
			case streamTypeMessage:
				enc = &messageEncoder{w: conn.Writer}
			default:
				plog.Panicf("unhandled stream type %s", conn.t)
			}
			flusher = conn.Flusher
			cw.mu.Lock()
			cw.status.activate()
			cw.closer = conn.Closer
			cw.working = true
			cw.mu.Unlock()
			heartbeatc, msgc = tickc, cw.msgc
		case <-cw.stopc:
			cw.close()
			close(cw.done)
			return
		}
	}
}
Example #2
0
func (*messageWriter) writeNewMessage(newMessage *messages.MessageOutput, w *http.ResponseWriter, flusher http.Flusher) {
	_, err := fmt.Fprintf(*w, "id: %d\n", newMessage.Id)
	if err != nil {
		log.Printf("Error while pushing: %v", err)
	}
	fmt.Fprintf(*w, "event: %s\n", "msg")
	fmt.Fprintf(*w, "data: %s\n\n", newMessage.Data)
	flusher.Flush()
}
Example #3
0
func flushLoop(f http.Flusher, interval time.Duration, done <-chan struct{}) {
	for {
		select {
		case <-time.After(interval):
			f.Flush()
		case <-done:
			return
		}
	}
}
Example #4
0
//write a string and flush it to the http Flushwriter
func writeStringAndFlush(w http.ResponseWriter, flusher http.Flusher, line string) error {

	_, err := w.Write([]byte(line))

	if err != nil {
		return err
	}

	flusher.Flush()

	return nil
}
Example #5
0
func (b *Broker) sendEvents(w http.ResponseWriter, f http.Flusher, client chan string) {
	for {
		ev, open := <-client

		if !open {
			break
		}

		fmt.Fprintf(w, "data: Event: %s\n\n", ev)
		f.Flush()
	}
}
Example #6
0
func consumerHandler(w http.ResponseWriter, r *http.Request, es *eventSource) {
	if r.Header.Get("Accept") != "text/event-stream" {
		http.Error(w, "eventsource: should accept text/event-stream", http.StatusNotAcceptable)
		return
	}

	var (
		fl  http.Flusher
		con *consumer
		id  int
		err error
		ok  bool
	)

	id, err = lastEventId(r)
	if err != nil {
		http.Error(w, "eventsource: bad last-event-id header", http.StatusBadRequest)
		return
	}

	fl, ok = w.(http.Flusher)
	if !ok {
		http.Error(w, "eventsouce: response does not implement http.Flusher", http.StatusInternalServerError)
		return
	}

	h := w.Header()
	h.Set("Content-Type", "text/event-stream")
	h.Set("Cache-Control", "no-cache")
	h.Set("Connection", "keep-alive")

	con = es.Subscribe(id)
	defer es.Unsubscribe(con)

	for {
		select {
		case b := <-con.ch:
			if _, err := w.Write(b); err == nil {
				fl.Flush()
			} else {
				log.Print(err)
				return
			}
		case <-con.quit:
			close(con.ch)
			close(con.quit)
			return
		}
	}
}
Example #7
0
func (server *Server) sendEvent(w http.ResponseWriter, f http.Flusher, event es.Event) bool {
	_, err := fmt.Fprintf(w, "event: %s\n", event.Event)
	if nil != err {
		return false
	}
	if "" != event.Data {
		_, err = fmt.Fprintf(w, "data: %s\n", event.Data)
		if nil != err {
			return false
		}
	}
	_, err = fmt.Fprint(w, "\n")
	if nil != err {
		return false
	}
	f.Flush()
	return true
}
Example #8
0
func (cw *streamWriter) run() {
	var msgc chan raftpb.Message
	var heartbeatc <-chan time.Time
	var t streamType
	var msgAppTerm uint64
	var enc encoder
	var flusher http.Flusher
	tickc := time.Tick(ConnReadTimeout / 3)

	for {
		select {
		case <-heartbeatc:
			start := time.Now()
			if err := enc.encode(linkHeartbeatMessage); err != nil {
				reportSentFailure(string(t), linkHeartbeatMessage)

				cw.status.deactivate(failureType{source: t.String(), action: "heartbeat"}, err.Error())
				cw.close()
				heartbeatc, msgc = nil, nil
				continue
			}
			flusher.Flush()
			reportSentDuration(string(t), linkHeartbeatMessage, time.Since(start))
		case m := <-msgc:
			if t == streamTypeMsgApp && m.Term != msgAppTerm {
				// TODO: reasonable retry logic
				if m.Term > msgAppTerm {
					cw.close()
					heartbeatc, msgc = nil, nil
					// TODO: report to raft at peer level
					cw.r.ReportUnreachable(m.To)
				}
				continue
			}
			start := time.Now()
			if err := enc.encode(m); err != nil {
				reportSentFailure(string(t), m)

				cw.status.deactivate(failureType{source: t.String(), action: "write"}, err.Error())
				cw.close()
				heartbeatc, msgc = nil, nil
				cw.r.ReportUnreachable(m.To)
				continue
			}
			flusher.Flush()
			reportSentDuration(string(t), m, time.Since(start))
		case conn := <-cw.connc:
			cw.close()
			t = conn.t
			switch conn.t {
			case streamTypeMsgApp:
				var err error
				msgAppTerm, err = strconv.ParseUint(conn.termStr, 10, 64)
				if err != nil {
					plog.Panicf("could not parse term %s to uint (%v)", conn.termStr, err)
				}
				enc = &msgAppEncoder{w: conn.Writer, fs: cw.fs}
			case streamTypeMsgAppV2:
				enc = newMsgAppV2Encoder(conn.Writer, cw.fs)
			case streamTypeMessage:
				enc = &messageEncoder{w: conn.Writer}
			default:
				plog.Panicf("unhandled stream type %s", conn.t)
			}
			flusher = conn.Flusher
			cw.mu.Lock()
			cw.status.activate()
			cw.closer = conn.Closer
			cw.working = true
			cw.mu.Unlock()
			heartbeatc, msgc = tickc, cw.msgc
		case <-cw.stopc:
			cw.close()
			close(cw.done)
			return
		}
	}
}
Example #9
0
func (cw *streamWriter) run() {
	var (
		msgc       chan raftpb.Message
		heartbeatc <-chan time.Time
		t          streamType
		enc        encoder
		flusher    http.Flusher
		batched    int
	)
	tickc := time.Tick(ConnReadTimeout / 3)
	unflushed := 0

	plog.Infof("started streaming with peer %s (writer)", cw.peerID)

	for {
		select {
		case <-heartbeatc:
			err := enc.encode(linkHeartbeatMessage)
			unflushed += linkHeartbeatMessage.Size()
			if err == nil {
				flusher.Flush()
				batched = 0
				sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
				unflushed = 0
				continue
			}

			cw.status.deactivate(failureType{source: t.String(), action: "heartbeat"}, err.Error())

			cw.close()
			plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
			heartbeatc, msgc = nil, nil

		case m := <-msgc:
			err := enc.encode(m)
			if err == nil {
				unflushed += m.Size()

				if len(msgc) == 0 || batched > streamBufSize/2 {
					flusher.Flush()
					sentBytes.WithLabelValues(cw.peerID.String()).Add(float64(unflushed))
					unflushed = 0
					batched = 0
				} else {
					batched++
				}

				continue
			}

			cw.status.deactivate(failureType{source: t.String(), action: "write"}, err.Error())
			cw.close()
			plog.Warningf("lost the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
			heartbeatc, msgc = nil, nil
			cw.r.ReportUnreachable(m.To)

		case conn := <-cw.connc:
			if cw.close() {
				plog.Warningf("closed an existing TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
			}
			t = conn.t
			switch conn.t {
			case streamTypeMsgAppV2:
				enc = newMsgAppV2Encoder(conn.Writer, cw.fs)
			case streamTypeMessage:
				enc = &messageEncoder{w: conn.Writer}
			default:
				plog.Panicf("unhandled stream type %s", conn.t)
			}
			flusher = conn.Flusher
			unflushed = 0
			cw.mu.Lock()
			cw.status.activate()
			cw.closer = conn.Closer
			cw.working = true
			cw.mu.Unlock()
			plog.Infof("established a TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
			heartbeatc, msgc = tickc, cw.msgc
		case <-cw.stopc:
			if cw.close() {
				plog.Infof("closed the TCP streaming connection with peer %s (%s writer)", cw.peerID, t)
			}
			close(cw.done)
			plog.Infof("stopped streaming with peer %s (writer)", cw.peerID)
			return
		}
	}
}
Example #10
0
func (*messageWriter) writeTimeout(w http.ResponseWriter, flusher http.Flusher) {
	fmt.Fprintf(w, "event: %s\n", "timeout")
	fmt.Fprintf(w, "data: %s\n\n", "30s")
	flusher.Flush()
}
Example #11
0
func Sync(mfuser, mfpass, ssuser, sspass string, o io.Writer) bool {

	useflush := false
	var flusher http.Flusher

	if strings.Contains(reflect.TypeOf(o).String(), "http") {
		flusher = o.(http.Flusher)
		useflush = true
	}

	// sendspace api key	4R6XNCX3EA
	// mediafire api key	5v1vtcl1k8285gtbpc891jtijjxnit5v1cgopla8
	// mediafire app id		47574

	mfapi := "5v1vtcl1k8285gtbpc891jtijjxnit5v1cgopla8"
	mfapp := "47574"
	ssapi := "4R6XNCX3EA"

	// create channels for goroutines
	c := make(chan string)
	f := make(chan string)
	numfilestosync := 0

	// sign in to Mediafire and get a file path list
	mfsessionkey, err := MfGetSessionToken(mfapp, mfapi, mfuser, mfpass)
	if err != nil {
		fmt.Fprintln(o, err)
		return false
	}
	go func() {
		MfFindFolders(mfsessionkey, "myfiles", "/", 0)
		c <- "Mediafire file list ok"
	}()

	// sign in to Sendspace and get a file path list
	sstoken, err := SsGetToken(ssapi)
	if err != nil {
		fmt.Fprintln(o, err)
		return false
	}
	sssessionkey, err := SsLogin(sstoken, ssuser, sspass)
	if err != nil {
		fmt.Fprintln(o, err)
		return false
	}
	go func() {
		SsFindFolders(sssessionkey, "0", "/")
		c <- "Sendspace file list ok"
	}()

	// wait for both file path lists before going further
	for i := 0; i < 2; i++ {
		msg := <-c
		fmt.Fprintln(o, msg)
		if useflush {
			flusher.Flush()
		}
	}

	// copy Sendspace data to the Mediafire structs, if exists. don't care about the rest
	for _, s := range SsPaths {
		for i, m := range MfPaths {
			if s.Path == m.Path {
				MfPaths[i].SsD = s.Descriptor
				MfPaths[i].SsP = s.Parent
			}
		}
	}

	// create folder tree on Sendspace as it is on Mediafire
	for i, m := range MfPaths {
		// (m.SsD == "") <==> folder does not exist on Sendspace
		if m.SsD == "" && isFolderPath(m.Path) {
			SsMkFolder(m.Filename, getSsD(MfPaths, m.Parent), sssessionkey, i, m.Path)
			fmt.Fprintln(o, m.Path+" -- CREATED")
		} else if isFolderPath(m.Path) {
			fmt.Fprintln(o, m.Path+" -- exists")
		}
		if useflush {
			flusher.Flush()
		}
	}

	// create files
	for _, m := range MfPaths {

		if !isFolderPath(m.Path) {

			numfilestosync += 1
			go func(m MfPath) {

				// (m.SsD == "") <==> file does not exist on Sendspace
				if m.SsD == "" {
					fmt.Fprintln(o, m.Path+" -- SYNCING")
					pr, pw := io.Pipe()

					go func() {
						// get a download link & download
						dlink := MfGetDownloadlink(mfsessionkey, m.Descriptor)
						dload, err := http.Get(dlink)
						if err != nil {
							log.Fatal(err)
						}

						// copy from download to pipe
						_, err = io.Copy(pw, dload.Body)
						if err != nil {
							log.Fatal(err)
						}

						//fmt.Fprintln(m.Path + " DOWLOADED")
						dload.Body.Close()
						pw.Close()
						c <- m.Filename + " downloaded"
					}()

					go func() {
						// get upload info for the file
						uq := SsGetUploadInfo(sssessionkey)

						urlToCall, err := url.Parse(uq.Res.Upload.Url)
						if err != nil {
							log.Fatal(err)
						}

						urlParams := urlToCall.Query()
						urlParams.Add("folder_id", getSsD(MfPaths, m.Parent))
						urlParams.Add("userfile", m.Filename)
						urlToCall.RawQuery = urlParams.Encode()
						// have to do string concat as urlParams.Add encodes % => %25 and extra info fails then
						callUrl := urlToCall.String() + "&extra_info=" + uq.Res.Upload.Extra

						// create a writer for the upload
						bodyBuf := &bytes.Buffer{}
						bodyWriter := multipart.NewWriter(bodyBuf)
						fileWriter, err := bodyWriter.CreateFormFile("userfile", m.Filename)
						if err != nil {
							log.Fatal(err)
						}

						// iocopy from the pipe
						_, err = io.Copy(fileWriter, pr)
						if err != nil {
							log.Fatal(err)
						}

						contentType := bodyWriter.FormDataContentType()
						bodyWriter.Close()
						pr.Close()

						resp, err := http.Post(callUrl, contentType, bodyBuf)
						defer resp.Body.Close()
						if err != nil {
							log.Fatal(err)
						}

						resp_body, err := ioutil.ReadAll(resp.Body)
						if err != nil {
							log.Fatal(err)
						}

						if strings.Contains(string(resp_body), "fail") {
							fmt.Fprintln(o, string(resp_body))
							return
						} else {
							//fmt.Fprintln(m.Path + " UPLOADED")
						}
						c <- m.Filename + " uploaded"
					}()

					// wait for both download & upload routines to complete
					for i := 0; i < 2; i++ {
						_ = <-c
					}

					// signal sync channel
					f <- m.Path + " -- DONE"

				} else {
					f <- m.Path + " -- exists"
				}

			}(m)
		}
	}

	// wait for all file syncs/exists to complete and print
	for j := 0; j < numfilestosync; j++ {
		msg := <-f
		fmt.Fprintln(o, msg)
		if useflush {
			flusher.Flush()
		}
	}

	fmt.Fprintln(o, "Sync complete!")
	return true
}
Example #12
0
func (cw *streamWriter) run() {
	var msgc chan raftpb.Message
	var heartbeatc <-chan time.Time
	var t streamType
	var msgAppTerm uint64
	var enc encoder
	var flusher http.Flusher
	tickc := time.Tick(ConnReadTimeout / 3)

	for {
		select {
		case <-heartbeatc:
			start := time.Now()
			if err := enc.encode(linkHeartbeatMessage); err != nil {
				reportSentFailure(string(t), linkHeartbeatMessage)

				log.Printf("rafthttp: failed to heartbeat on stream %s due to %v. waiting for a new stream to be established.", t, err)
				cw.resetCloser()
				heartbeatc, msgc = nil, nil
				continue
			}
			flusher.Flush()
			reportSentDuration(string(t), linkHeartbeatMessage, time.Since(start))
		case m := <-msgc:
			if t == streamTypeMsgApp && m.Term != msgAppTerm {
				// TODO: reasonable retry logic
				if m.Term > msgAppTerm {
					cw.resetCloser()
					heartbeatc, msgc = nil, nil
					// TODO: report to raft at peer level
					cw.r.ReportUnreachable(m.To)
				}
				continue
			}
			start := time.Now()
			if err := enc.encode(m); err != nil {
				reportSentFailure(string(t), m)

				log.Printf("rafthttp: failed to send message on stream %s due to %v. waiting for a new stream to be established.", t, err)
				cw.resetCloser()
				heartbeatc, msgc = nil, nil
				cw.r.ReportUnreachable(m.To)
				continue
			}
			flusher.Flush()
			reportSentDuration(string(t), m, time.Since(start))
		case conn := <-cw.connc:
			cw.resetCloser()
			t = conn.t
			switch conn.t {
			case streamTypeMsgApp:
				var err error
				msgAppTerm, err = strconv.ParseUint(conn.termStr, 10, 64)
				if err != nil {
					log.Panicf("rafthttp: unexpected parse term %s error: %v", conn.termStr, err)
				}
				enc = &msgAppEncoder{w: conn.Writer, fs: cw.fs}
			case streamTypeMessage:
				enc = &messageEncoder{w: conn.Writer}
			default:
				log.Panicf("rafthttp: unhandled stream type %s", conn.t)
			}
			flusher = conn.Flusher
			cw.mu.Lock()
			cw.closer = conn.Closer
			cw.working = true
			cw.mu.Unlock()
			heartbeatc, msgc = tickc, cw.msgc
		case <-cw.stopc:
			cw.resetCloser()
			close(cw.done)
			return
		}
	}
}