Example #1
0
// ParseEvent parse s into an Event struct.
// The input must be single event line, stripped of the "000 " prefix.
func ParseEvent(s []byte) (Event, error) {
	var e Event
	cmd := ssmp.NewCommand(s)
	from, err := ssmp.IdField(cmd)
	if err != nil {
		return e, ErrInvalidEvent
	}
	e.From = from
	ev, err := ssmp.VerbField(cmd)
	if err != nil {
		return e, ErrInvalidEvent
	}
	fields := events[string(ev)]
	if fields == 0 {
		return e, ErrInvalidEvent
	}
	e.Name = ev
	if fields == noFields {
		return e, nil
	}
	if (fields & fieldTo) != 0 {
		to, err := ssmp.IdField(cmd)
		if err != nil {
			return e, ErrInvalidEvent
		}
		e.To = to
	}
	if (fields & fieldOption) != 0 {
		payload, err := ssmp.OptionField(cmd)
		if err != nil {
			return e, ErrInvalidEvent
		}
		e.Payload = payload
	} else if (fields & fieldPayload) != 0 {
		payload, err := ssmp.PayloadField(cmd)
		if err != nil {
			return e, ErrInvalidEvent
		}
		e.Payload = payload
	}
	return e, nil
}
Example #2
0
// NewConnection creates a SSMP connection out of a streaming netwrok connection.
//
// This method blocks until either a first message is received or a 10s timeout
// elapses.
//
// Each accepted connection spawns a goroutine continuously reading from the
// underlying network connection and triggering the Dispatcher. The caller must
// keep track of the returned Connection and call the Close method to stop the
// read goroutine and close the udnerlying netwrok connection.
//
// errInvalidLogin is returned if the first message is not a well-formed LOGIN
// request.
// errUnauthorized is returned if the authenticator doesn't accept the provided
// credentials.
func NewConnection(c net.Conn, a Authenticator, d *Dispatcher) (*Connection, error) {
	r := bufio.NewReaderSize(c, 1024)
	c.SetReadDeadline(time.Now().Add(10 * time.Second))
	l, err := r.ReadSlice('\n')
	if err != nil {
		return nil, err
	}
	// strip LF delimiter
	l = l[0 : len(l)-1]

	cmd := ssmp.NewCommand(l)
	verb, err := ssmp.VerbField(cmd)
	if err != nil || !ssmp.Equal(verb, ssmp.LOGIN) {
		return nil, ErrInvalidLogin
	}
	user, err := ssmp.IdField(cmd)
	if err != nil {
		return nil, ErrInvalidLogin
	}
	scheme, err := ssmp.IdField(cmd)
	if err != nil {
		return nil, ErrInvalidLogin
	}
	cred := cmd.Trailing()
	if !a.Auth(c, user, scheme, cred) {
		return nil, ErrUnauthorized
	}
	cc := &Connection{
		c:    c,
		r:    r,
		User: string(user),
	}
	go cc.readLoop(d)
	cc.Write(respOk)
	return cc, nil
}