blob: ebf799eecf053770e56bf98ad134ebad0a3d1547 [file] [log] [blame]
package wspr
import (
"bytes"
"fmt"
"path/filepath"
"runtime"
"veyron/services/wsprd/lib"
"veyron2/verror"
"veyron2/vlog"
"veyron2/vom"
"github.com/gorilla/websocket"
)
// Wraps a response to the proxy client and adds a message type.
type response struct {
Type lib.ResponseType
Message interface{}
}
// Implements clientWriter interface for sending messages over websockets.
type websocketWriter struct {
wsp *websocketPipe
logger vlog.Logger
id int64
}
func (w *websocketWriter) Send(messageType lib.ResponseType, data interface{}) error {
var buf bytes.Buffer
if err := vom.ObjToJSON(&buf, vom.ValueOf(response{Type: messageType, Message: data})); err != nil {
w.logger.Error("Failed to marshal with", err)
return err
}
var buf2 bytes.Buffer
if err := vom.ObjToJSON(&buf2, vom.ValueOf(websocketMessage{Id: w.id, Data: buf.String()})); err != nil {
w.logger.Error("Failed to write the message", err)
return err
}
w.wsp.writeQueue <- wsMessage{messageType: websocket.TextMessage, buf: buf2.Bytes()}
return nil
}
func (w *websocketWriter) Error(err error) {
verr := verror.ToStandard(err)
// Also log the error but write internal errors at a more severe log level
var logLevel vlog.Level = 2
logErr := fmt.Sprintf("%v", verr)
// We want to look at the stack three frames up to find where the error actually
// occurred. (caller -> websocketErrorResponse/sendError -> generateErrorMessage).
if _, file, line, ok := runtime.Caller(3); ok {
logErr = fmt.Sprintf("%s:%d: %s", filepath.Base(file), line, logErr)
}
if verror.Is(verr, verror.Internal) {
logLevel = 2
}
w.logger.VI(logLevel).Info(logErr)
var errMsg = verror.Standard{
ID: verr.ErrorID(),
Msg: verr.Error(),
}
w.Send(lib.ResponseError, errMsg)
}