github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/igm/sockjs-go.v2/sockjs/websocket.go (about)

     1  package sockjs
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"github.com/insionng/yougam/libraries/gorilla/websocket"
     9  )
    10  
    11  // WebSocketReadBufSize is a parameter that is used for WebSocket Upgrader.
    12  // https://yougam/libraries/gorilla/websocket/blob/master/server.go#L230
    13  var WebSocketReadBufSize = 4096
    14  
    15  // WebSocketWriteBufSize is a parameter that is used for WebSocket Upgrader
    16  // https://yougam/libraries/gorilla/websocket/blob/master/server.go#L230
    17  var WebSocketWriteBufSize = 4096
    18  
    19  func (h *handler) sockjsWebsocket(rw http.ResponseWriter, req *http.Request) {
    20  	conn, err := websocket.Upgrade(rw, req, nil, WebSocketReadBufSize, WebSocketWriteBufSize)
    21  	if _, ok := err.(websocket.HandshakeError); ok {
    22  		http.Error(rw, `Can "Upgrade" only to "WebSocket".`, http.StatusBadRequest)
    23  		return
    24  	} else if err != nil {
    25  		rw.WriteHeader(http.StatusInternalServerError)
    26  		return
    27  	}
    28  	sessID, _ := h.parseSessionID(req.URL)
    29  	sess := newSession(req, sessID, h.options.DisconnectDelay, h.options.HeartbeatDelay)
    30  	if h.handlerFunc != nil {
    31  		go h.handlerFunc(sess)
    32  	}
    33  
    34  	receiver := newWsReceiver(conn)
    35  	sess.attachReceiver(receiver)
    36  	readCloseCh := make(chan struct{})
    37  	go func() {
    38  		var d []string
    39  		for {
    40  			err := conn.ReadJSON(&d)
    41  			if err != nil {
    42  				close(readCloseCh)
    43  				return
    44  			}
    45  			sess.accept(d...)
    46  		}
    47  	}()
    48  
    49  	select {
    50  	case <-readCloseCh:
    51  	case <-receiver.doneNotify():
    52  	}
    53  	sess.close()
    54  	conn.Close()
    55  }
    56  
    57  type wsReceiver struct {
    58  	conn    *websocket.Conn
    59  	closeCh chan struct{}
    60  }
    61  
    62  func newWsReceiver(conn *websocket.Conn) *wsReceiver {
    63  	return &wsReceiver{
    64  		conn:    conn,
    65  		closeCh: make(chan struct{}),
    66  	}
    67  }
    68  
    69  func (w *wsReceiver) sendBulk(messages ...string) {
    70  	if len(messages) > 0 {
    71  		w.sendFrame(fmt.Sprintf("a[%s]", strings.Join(transform(messages, quote), ",")))
    72  	}
    73  }
    74  
    75  func (w *wsReceiver) sendFrame(frame string) {
    76  	if err := w.conn.WriteMessage(websocket.TextMessage, []byte(frame)); err != nil {
    77  		w.close()
    78  	}
    79  }
    80  
    81  func (w *wsReceiver) close() {
    82  	select {
    83  	case <-w.closeCh: // already closed
    84  	default:
    85  		close(w.closeCh)
    86  	}
    87  }
    88  func (w *wsReceiver) canSend() bool {
    89  	select {
    90  	case <-w.closeCh: // already closed
    91  		return false
    92  	default:
    93  		return true
    94  	}
    95  }
    96  func (w *wsReceiver) doneNotify() <-chan struct{}        { return w.closeCh }
    97  func (w *wsReceiver) interruptedNotify() <-chan struct{} { return nil }