Browse Source

Add Notice helpers

Rod Hynes 11 years ago
parent
commit
1c6707f274
2 changed files with 76 additions and 50 deletions
  1. 76 0
      psiphon/notice.go
  2. 0 50
      psiphon/utils.go

+ 76 - 0
psiphon/notice.go

@@ -20,6 +20,7 @@
 package psiphon
 
 import (
+	"bytes"
 	"encoding/json"
 	"fmt"
 	"io"
@@ -157,3 +158,78 @@ func NoticeHomepage(url string) {
 func NoticeTunnels(count int) {
 	outputNotice("Tunnels", false, "count", count)
 }
+
+type noticeObject struct {
+	NoticeType string          `json:"noticeType"`
+	Data       json.RawMessage `json:"data"`
+	Timestamp  string          `json:"timestamp"`
+}
+
+// GetNoticeTunnels receives a JSON encoded object and attempts to parse it as a Notice.
+// When the object is a Notice of type Tunnels, the count payload is returned.
+func GetNoticeTunnels(notice []byte) (count int, ok bool) {
+	var object noticeObject
+	if json.Unmarshal(notice, &object) != nil {
+		return 0, false
+	}
+	if object.NoticeType != "Tunnels" {
+		return 0, false
+	}
+	type tunnelsPayload struct {
+		Count int `json:"count"`
+	}
+	var payload tunnelsPayload
+	if json.Unmarshal(object.Data, &payload) != nil {
+		return 0, false
+	}
+	return payload.Count, true
+}
+
+// NoticeReceiver consumes a notice input stream and invokes a callback function
+// for each discrete JSON notice object byte sequence.
+type NoticeReceiver struct {
+	mutex    sync.Mutex
+	buffer   []byte
+	callback func([]byte)
+}
+
+// NewNoticeReceiver initializes a new NoticeReceiver
+func NewNoticeReceiver(callback func([]byte)) *NoticeReceiver {
+	return &NoticeReceiver{callback: callback}
+}
+
+// Write implements io.Writer.
+func (receiver *NoticeReceiver) Write(p []byte) (n int, err error) {
+	receiver.mutex.Lock()
+	defer receiver.mutex.Unlock()
+
+	receiver.buffer = append(receiver.buffer, p...)
+
+	index := bytes.Index(receiver.buffer, []byte("\n"))
+	if index == -1 {
+		return len(p), nil
+	}
+
+	notice := receiver.buffer[:index]
+	receiver.buffer = receiver.buffer[index+1:]
+
+	receiver.callback(notice)
+
+	return len(p), nil
+}
+
+// NewNoticeConsoleRewriter consumes JSON-format notice input and parses each
+// notice and rewrites in a more human-readable format more suitable for
+// console output. The data payload field is left as JSON.
+func NewNoticeConsoleRewriter(writer io.Writer) *NoticeReceiver {
+	return NewNoticeReceiver(func(notice []byte) {
+		var object noticeObject
+		_ = json.Unmarshal(notice, &object)
+		fmt.Fprintf(
+			writer,
+			"%s %s %s\n",
+			object.Timestamp,
+			object.NoticeType,
+			string(object.Data))
+	})
+}

+ 0 - 50
psiphon/utils.go

@@ -20,19 +20,14 @@
 package psiphon
 
 import (
-	"bytes"
 	"crypto/rand"
 	"crypto/x509"
 	"encoding/base64"
-	"encoding/json"
 	"errors"
 	"fmt"
-	"io"
 	"math/big"
-	"os"
 	"runtime"
 	"strings"
-	"sync"
 	"time"
 )
 
@@ -150,48 +145,3 @@ func ContextError(err error) error {
 func IsNetworkBindError(err error) bool {
 	return strings.Contains(err.Error(), "bind: address already in use")
 }
-
-// NoticeConsoleRewriter consumes JOSN-format notice input and parses each
-// notice and rewrites in a more human-readable format more suitable for
-// console output. The data payload field is left as JSON.
-type NoticeConsoleRewriter struct {
-	mutex  sync.Mutex
-	writer io.Writer
-	buffer []byte
-}
-
-// NewNoticeConsoleRewriter initializes a new NoticeConsoleRewriter
-func NewNoticeConsoleRewriter(writer io.Writer) *NoticeConsoleRewriter {
-	return &NoticeConsoleRewriter{writer: writer}
-}
-
-// Write implements io.Writer.
-func (rewriter *NoticeConsoleRewriter) Write(p []byte) (n int, err error) {
-	rewriter.mutex.Lock()
-	defer rewriter.mutex.Unlock()
-
-	rewriter.buffer = append(rewriter.buffer, p...)
-
-	index := bytes.Index(rewriter.buffer, []byte("\n"))
-	if index == -1 {
-		return len(p), nil
-	}
-	line := rewriter.buffer[:index]
-	rewriter.buffer = rewriter.buffer[index+1:]
-
-	type NoticeObject struct {
-		NoticeType string          `json:"noticeType"`
-		Data       json.RawMessage `json:"data"`
-		Timestamp  string          `json:"timestamp"`
-	}
-
-	var noticeObject NoticeObject
-	_ = json.Unmarshal(line, &noticeObject)
-	fmt.Fprintf(os.Stderr,
-		"%s %s %s\n",
-		noticeObject.Timestamp,
-		noticeObject.NoticeType,
-		string(noticeObject.Data))
-
-	return len(p), nil
-}