Exemple #1
0
func (m *MockStompngo) Send(headers stompngo.Headers, message string) error {
	if headers.Value("destination") == "" {
		return fmt.Errorf("No destination header, cannot send.")
	}

	msg := MockStompMessage{len(m.Messages), headers, message}
	m.Messages <- msg

	m.NumMessages++

	return nil
}
// Connect to a STOMP broker, publish some messages and disconnect.
func main() {

	st := time.Now()

	// Standard example connect sequence
	n, conn, e := sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	// *NOTE* application specific functionaltiy starts here!
	sh := stompngo.Headers{"destination", sngecomm.Dest()}
	ll.Printf("%stag:%s connsess:%s destination dest:%s\n",
		exampid, tag, conn.Session(),
		sngecomm.Dest())
	if senv.Persistent() {
		sh = sh.Add("persistent", "true")
	}
	ms := exampid + "message: "
	for i := 1; i <= senv.Nmsgs(); i++ {
		mse := ms + fmt.Sprintf("%d", i)
		ll.Printf("%stag:%s connsess:%s main_sending mse:~%s~\n",
			exampid, tag, conn.Session(),
			mse)
		e := conn.Send(sh, mse)
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
				exampid, tag, conn.Session(),
				e.Error()) // Handle this ......
		}
		ll.Printf("%stag:%s connsess:%s main_send_complete mse:~%s~\n",
			exampid, tag, conn.Session(),
			mse)
		time.Sleep(100 * time.Millisecond)
	}
	// *NOTE* application specific functionaltiy ends here!

	// Standard example disconnect sequence
	e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_disconnect error:%v",
			exampid, tag, conn.Session(),
			e.Error()) // Handle this ......
	}

	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, conn.Session(),
		time.Now().Sub(st))
}
// Send messages to a particular queue
func sender(qn, mc int) {
	ltag := tag + "-sender"

	qns := fmt.Sprintf("%d", qn) // string queue number
	id := stompngo.Uuid()        // A unique sender id
	d := sngecomm.Dest() + "." + qns

	ll.Printf("%stag:%s connsess:%s queue_info id:%v d:%v qnum:%v mc:%v\n",
		exampid, ltag, conn.Session(),
		id, d, qn, mc)
	//
	wh := stompngo.Headers{"destination", d, "senderId", id,
		"qnum", qns} // send Headers
	if senv.Persistent() {
		wh = wh.Add("persistent", "true")
	}
	//
	tmr := time.NewTimer(100 * time.Hour)
	// Send loop
	for i := 1; i <= mc; i++ {
		si := fmt.Sprintf("%d", i)
		sh := append(wh, "msgnum", si)
		// Generate a message to send ...............
		ll.Printf("%stag:%s connsess:%s send_headers id:%v d:%v qnum:%v headers:%v\n",
			exampid, ltag, conn.Session(),
			id, d, qn, sh)
		e := conn.Send(sh, string(sngecomm.Partial()))
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s send_error qnum:%v error:%v",
				exampid, tag, conn.Session(),
				qn, e.Error()) // Handle this ......
		}
		if i == mc {
			break
		}
		if sw {
			dt := time.Duration(sngecomm.ValueBetween(min, max, sf))
			ll.Printf("%stag:%s connsess:%s send_stagger id:%v d:%v qnum:%v stagger:%v\n",
				exampid, ltag, conn.Session(),
				id, d, qn, dt)
			tmr.Reset(dt)
			_ = <-tmr.C
			runtime.Gosched()
		}
	}
	// Sending is done
	ll.Printf("%stag:%s connsess:%s finish_info id:%v d:%v qnum:%v mc:%v\n",
		exampid, ltag, conn.Session(),
		id, d, qn, mc)
	wgs.Done()
}
// Send messages to a particular queue
func sender(conn *stompngo.Connection, qn, nmsgs int) {
	ltag := tag + "-sender"

	qns := fmt.Sprintf("%d", qn) // queue number
	d := sngecomm.Dest() + "." + qns
	ll.Printf("%stag:%s connsess:%s starts qn:%d nmsgs:%d d:%s\n",
		exampid, ltag, conn.Session(),
		qn, nmsgs, d)
	//
	wh := stompngo.Headers{"destination", d,
		"qnum", qns} // send Headers
	if senv.Persistent() {
		wh = wh.Add("persistent", "true")
	}
	//
	tmr := time.NewTimer(100 * time.Hour)
	// Send loop
	for i := 1; i <= nmsgs; i++ {
		si := fmt.Sprintf("%d", i)
		sh := append(wh, "msgnum", si)
		// Generate a message to send ...............
		ll.Printf("%stag:%s connsess:%s message qns:%s si:%s\n",
			exampid, ltag, conn.Session(),
			qns, si)
		e := conn.Send(sh, string(sngecomm.Partial()))
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s send_error qnum:%v error:%v",
				exampid, ltag, conn.Session(),
				qn, e.Error()) // Handle this ......
		}
		if i == nmsgs {
			break
		}
		if sw {
			runtime.Gosched() // yield for this example
			dt := time.Duration(sngecomm.ValueBetween(min, max, sf))
			ll.Printf("%stag:%s connsess:%s send_stagger dt:%v qns:%s\n",
				exampid, ltag, conn.Session(),
				dt, qns)
			tmr.Reset(dt)
			_ = <-tmr.C
		}
	}
	// Sending is done
	ll.Printf("%stag:%s connsess:%s sender_ends qn:%d nmsgs:%d\n",
		exampid, ltag, conn.Session(),
		qn, nmsgs)
	wgs.Done()
}
Exemple #5
0
func main() {
	fmt.Println("Receiver Start...")

	// create a net.Conn, and pass that into Connect
	p := os.Getenv("STOMP_PORT")
	if p == "" {
		p = "61613"
	}
	nc, error := net.Dial("tcp", hap+p)
	if error != nil {
		log.Fatal(error)
	}
	// Connect
	ch := stompngo.Headers{"login", "getter", "passcode", "recv1234"}
	ch = ch.Add("accept-version", "1.0") // 1.0 only
	ch = ch.Add("host", host)
	c, error := stompngo.Connect(nc, ch)
	if error != nil {
		log.Fatal(error)
	}
	for i := 1; i <= mq; i++ {
		qn := fmt.Sprintf("%d", i)
		wg.Add(1)
		go recMessages(c, qname+qn)
	}
	wg.Wait()
	fmt.Println("Receiver done with wait")
	// Disconnect
	nh := stompngo.Headers{}
	error = c.Disconnect(nh)
	if error != nil {
		log.Fatalf("Receiver discerr %v\n", error)
	}
	// Sanity check for spurious errors
	select {
	case v := <-c.MessageData:
		fmt.Printf("Receiver frame2: %s\n", v.Message.Command)
		fmt.Printf("Receiver header2: %v\n", v.Message.Headers)
		fmt.Printf("Receiver data2: %s\n", string(v.Message.Body))
	default:
		fmt.Println("Receiver Nothing to show")
	}
	// Network close
	nc.Close()
	fmt.Println("Receiver done nc.Close()")
	ngor := runtime.NumGoroutine()
	fmt.Printf("Receiver ngor: %v\n", ngor)
	fmt.Println("Receiver End... numq:", mq, "Num received:", numRecv)
}
Exemple #6
0
func (m *Mediator) Send(h stompngo.Headers, b []byte) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	if m.sendHeaders != nil {
		h = h.AddHeaders(m.sendHeaders)
	}

	err := m.conn.Send(h, string(b))

	if err != nil {
		return err
	}

	return nil
}
Exemple #7
0
// Connect to a STOMP broker, send some messages and disconnect.
func main() {

	st := time.Now()

	// Standard example connect sequence
	// Use AMQ port here
	n, conn, e := sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	// Suppress content length here, so JMS will treat this as a 'text' message.
	sh := stompngo.Headers{"destination", "jms.queue.exampleQueue"}
	if os.Getenv("STOMP_NOSCL") != "true" {
		sh = sh.Add("suppress-content-length", "true")
	}
	if senv.Persistent() {
		sh = sh.Add("persistent", "true")
	}
	ms := exampid + " message: "
	for i := 1; i <= nmsgs; i++ {
		mse := ms + fmt.Sprintf("%d", i)
		e := conn.Send(sh, mse)
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s send_error error:%v\n",
				exampid, tag, conn.Session(),
				e.Error()) // Handle this ......
		}
		ll.Printf("%stag:%s connsess:%s send_complete\n",
			exampid, tag, conn.Session())
	}

	// Standard example disconnect sequence
	e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_disconnect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, conn.Session(),
		time.Now().Sub(st))

}
/*
runSender sends all messages to a specified queue.
*/
func runSender(conn *stompngo.Connection, qns string) {
	ltag := tag + "-runsender"

	d := sngecomm.Dest() + "." + qns
	id := stompngo.Uuid() // A unique sender id
	ll.Printf("%stag:%s connsess:%s start id:%s dest:%s\n",
		exampid, ltag, conn.Session(),
		id, d)
	wh := stompngo.Headers{"destination", d, "senderId", id,
		"qnum", qns} // basic send Headers
	if senv.Persistent() {
		wh = wh.Add("persistent", "true")
	}
	tmr := time.NewTimer(100 * time.Hour)
	nmsgs := senv.Nmsgs()
	for mc := 1; mc <= nmsgs; mc++ {
		sh := append(wh, "msgnum", fmt.Sprintf("%d", mc))
		// Generate a message to send ...............
		ll.Printf("%stag:%s  connsess:%s send id:%s qns:%s mc:%d\n",
			exampid, ltag, conn.Session(),
			id, qns, mc)
		e := conn.Send(sh, string(sngecomm.Partial()))
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s send_error qns:%v error:%v",
				exampid, ltag, conn.Session(),
				qns, e.Error()) // Handle this ......
		}
		if mc == nmsgs {
			break
		}
		if sw {
			dt := time.Duration(sngecomm.ValueBetween(min, max, sf))
			ll.Printf("%stag:%s connsess:%s send_stagger dt:%v qns:%s mc:%d\n",
				exampid, ltag, conn.Session(),
				dt, qns, mc)
			tmr.Reset(dt)
			_ = <-tmr.C
			runtime.Gosched()
		}
	}
	ll.Printf("%stag:%s connsess:%s end id:%s dest:%s\n",
		exampid, ltag, conn.Session(),
		id, d)
	//
	wgs.Done()
}
func sendMessages(conn *stompngo.Connection, qnum int, nc net.Conn) {
	ltag := tag + "-sendmessages"

	qns := fmt.Sprintf("%d", qnum) // queue number
	d := sngecomm.Dest() + "." + qns
	ll.Printf("%stag:%s connsess:%s start d:%s qnum:%d\n",
		exampid, ltag, conn.Session(),
		d, qnum)
	wh := stompngo.Headers{"destination", d,
		"qnum", qns} // send Headers
	if senv.Persistent() {
		wh = wh.Add("persistent", "true")
	}
	//
	tmr := time.NewTimer(100 * time.Hour)
	// Send messages
	for mc := 1; mc <= nmsgs; mc++ {
		mcs := fmt.Sprintf("%d", mc)
		sh := append(wh, "msgnum", mcs)
		// Generate a message to send ...............

		ll.Printf("%stag:%s connsess:%s message mc:%d qnum:%d\n",
			exampid, ltag, conn.Session(),
			mc, qnum)
		e := conn.Send(sh, string(sngecomm.Partial()))
		if e != nil {
			ll.Fatalf("%stag:%s connsess:%s send_error qnum:%v error:%v",
				exampid, ltag, conn.Session(),
				qnum, e.Error()) // Handle this ......
		}
		if mc == nmsgs {
			break
		}
		if sw {
			runtime.Gosched() // yield for this example
			dt := time.Duration(sngecomm.ValueBetween(min, max, sf))
			ll.Printf("%stag:%s connsess:%s send_stagger dt:%v qnum:%s mc:%d\n",
				exampid, ltag, conn.Session(),
				dt, qnum, mc)
			tmr.Reset(dt)
			_ = <-tmr.C
		}
	}
}
Exemple #10
0
func main() {
	fmt.Println("Start...")

	// create a net.Conn, and pass that into Connect
	nc, error := net.Dial("tcp", hap+os.Getenv("STOMP_PORT"))
	if error != nil {
		log.Fatal(error)
	}
	// Connect
	ch := stompngo.Headers{"login", "getter", "passcode", "recv1234"}
	ch = ch.Add("accept-version", "1.1")
	ch = ch.Add("host", host)
	c, error := stompngo.Connect(nc, ch)
	if error != nil {
		log.Fatal(error)
	}
	for i := 1; i <= mq; i++ {
		qn := fmt.Sprintf("%d", i)
		wg.Add(1)
		go recMessages(c, qname+qn)
	}
	wg.Wait()
	fmt.Printf("Num received: %d\n", numRecv)
	// Disconnect
	nh := stompngo.Headers{}
	error = c.Disconnect(nh)
	if error != nil {
		log.Fatalf("discerr %v\n", error)
	}
	fmt.Println("done nc.Close()")
	nc.Close()
	ngor := runtime.NumGoroutine()
	fmt.Printf("egor: %v\n", ngor)
	select {
	case v := <-c.MessageData:
		fmt.Printf("frame2: %s\n", v.Message.Command)
		fmt.Printf("header2: %v\n", v.Message.Headers)
		fmt.Printf("data2: %s\n", string(v.Message.Body))
	default:
		fmt.Println("Nothing to show")
	}
	fmt.Println("End... mq:", mq)
}
Exemple #11
0
func recMessages(c *stompngo.Connection, q string, k int) {

	var error error
	ks := fmt.Sprintf("%d", k)

	// Receive phase
	headers := stompngo.Headers{"destination", q}
	sh := headers.Add("id", q)
	//
	log.Println("start subscribe", q)
	sc, error := c.Subscribe(sh)
	log.Println("end subscribe", q)
	if error != nil {
		log.Fatal(error)
	}
	for input := range sc {
		inmsg := input.Message.BodyString()
		if printMsgs {
			log.Println("Receive:", q, " / ", inmsg)
		}
		if inmsg == "***EOF***" {
			break
		}
		if !strings.HasPrefix(inmsg, ks) {
			log.Printf("bad prefix: [%v], [%v], [%v]\n", q, inmsg, ks)
			log.Fatal("bad prefix ....")
		}
		//
		d := time.Duration(getStagger(1e9/10, 1e9/5))
		time.Sleep(d)
	}
	log.Println("quit for", q)
	error = c.Unsubscribe(headers)
	log.Println("end unsubscribe", q)
	if error != nil {
		log.Fatal(error)
	}
	wgrecv.Done()
}
// Handle a subscribe for the different protocol levels.
func HandleSubscribe(c *stompngo.Connection, d, i, a string) <-chan stompngo.MessageData {
	h := stompngo.Headers{"destination", d, "ack", a}
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		// Add required id header
		h = h.Add("id", i)
	case stompngo.SPL_11:
		// Add required id header
		h = h.Add("id", i)
	case stompngo.SPL_10:
		// Nothing else to do here
	default:
		llu.Fatalf("v1:%v v2:%v\n", "subscribe invalid protocol level, should not happen")
	}
	//
	r, e := c.Subscribe(h)
	if e != nil {
		llu.Fatalf("v1:%v v2:%v\n", "subscribe failed", e)
	}
	return r
}
Exemple #13
0
func (m *Mediator) Subscribe(h stompngo.Headers) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	m.subId = stompngo.Uuid()

	m.subHeaders = h.
		Add("id", m.subId)

	var err error
	m.sub, err = m.conn.Subscribe(m.subHeaders)

	return err
}
// Provide connect headers
func ConnectHeaders() stompngo.Headers {
	h := stompngo.Headers{}
	l := senv.Login()
	if l != "" {
		h = h.Add("login", l)
	}
	pc := senv.Passcode()
	if pc != "" {
		h = h.Add("passcode", pc)
	}
	//
	p := senv.Protocol()
	if p != stompngo.SPL_10 { // 1.1 and 1.2
		h = h.Add("accept-version", p).Add("host", senv.Vhost())
		hb := senv.Heartbeats()
		if hb != "" {
			h = h.Add("heart-beat", hb)
		}
	}
	//

	return h
}
// Handle a unsubscribe for the different protocol levels.
func HandleUnsubscribe(c *stompngo.Connection, d, i string) {
	sbh := stompngo.Headers{}
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		sbh = sbh.Add("id", i)
	case stompngo.SPL_11:
		sbh = sbh.Add("id", i)
	case stompngo.SPL_10:
		sbh = sbh.Add("destination", d)
	default:
		llu.Fatalf("v1:%v v2:%v\n", "unsubscribe invalid protocol level, should not happen")
	}
	e := c.Unsubscribe(sbh)
	if e != nil {
		llu.Fatalf("v1:%v v2:%v d:%v\n", "unsubscribe failed", e, d)
	}
	return
}
Exemple #16
0
func New(host, port, user, pass string, connHeaders stompngo.Headers) (*Mediator, error) {
	if host == "" || port == "" || user == "" || pass == "" {
		return nil, fmt.Errorf("one or more values for Mediator initialization are blank")
	}

	m := &Mediator{
		host:      host,
		port:      port,
		user:      user,
		pass:      pass,
		mu:        new(sync.Mutex),
		reconnect: time.Duration(DefaultReconnect),
	}

	m.connHeaders = connHeaders.
		Add("login", m.user).
		Add("passcode", m.pass).
		Add("host", m.host)

	err := m.Connect()
	if err != nil {
		return nil, err
	}

	// Add reconnect to stack for accommodating DNS changes
	go func(m *Mediator) {
		for {
			select {
			case <-time.After(m.reconnect):
				m.Connect()
			}
		}
	}(m)

	return m, nil
}
Exemple #17
0
// Handle a subscribe for the different protocol levels.
func doSubscribe(c *stompngo.Connection, d, id, a string, h stompngo.Headers) <-chan stompngo.MessageData {
	h = h.Add("destination", d).Add("ack", a)
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		// Add required id header
		h = h.Add("id", id)
	case stompngo.SPL_11:
		// Add required id header
		h = h.Add("id", id)
	case stompngo.SPL_10:
		// Nothing else to do here
	default:
		ll.Fatalf("v1:%v\n", "subscribe invalid protocol level, should not happen")
	}
	//
	r, e := c.Subscribe(h)
	if e != nil {
		ll.Fatalf("subscribe failed err:[%v]\n", e)
	}
	return r
}
Exemple #18
0
func runNextQueue(qn int, conn *stompngo.Connection) {

	qns := fmt.Sprintf("%d", qn) // string number of the queue
	conn.SetLogger(ll)           // stompngo logging
	pbc := sngecomm.Pbc()        // Print byte count
	d := senv.Dest() + qns       // Destination
	id := stompngo.Uuid()        // A unique name/id
	nmsgs := qn                  // int number of messages to get, same as queue number
	am := sngecomm.AckMode()     // ACK mode to use on SUBSCRIBE
	nfa := true                  // Need "final" ACK (possiby reset below)
	wh := stompngo.Headers{}     // Starting SUBSCRIBE headers

	// Sanity check ACK mode
	if conn.Protocol() == stompngo.SPL_10 &&
		am == stompngo.AckModeClientIndividual {
		ll.Fatalf("%stag:%s connsess:%s invalid_ack_mode am:%v proto:%v\n",
			exampid, tag, session,
			am, conn.Protocol()) //
	}
	// Do not do final ACK if running ACKs are issued
	if am == stompngo.AckModeClientIndividual ||
		am == stompngo.AckModeAuto {
		nfa = false
	}

	// Show run parameters
	ll.Printf("%stag:%s connsess:%s run_parms\n\tqns:%v\n\tpbc:%v\n\td:%v\n\tid:%v\n\tnmsgs:%v\n\tam:%v\n\tnfa:%v\n\twh:%v\n",
		exampid, tag, session,
		qns, pbc, d, id, nmsgs, am, nfa, wh)

	// Run SUBSCRIBE
	sc := doSubscribe(conn, d, id, am, wh)
	ll.Printf("%stag:%s connsess:%s stomp_subscribe_complete\n",
		exampid, tag, session)

	var md stompngo.MessageData  // Message data from basic read
	var lmd stompngo.MessageData // Possible save (copy) of received data
	mc := 1                      // Initial message number

	// Loop for the requested number of messages
GetLoop:
	for {
		ll.Printf("%stag:%s connsess:%s start_of_read_loop mc:%v nmsgs:%v\n",
			exampid, tag, session, mc, nmsgs)

		mcs := fmt.Sprintf("%d", mc) // string number message count

		// Get something from the stompngo read routine
		select {
		case md = <-sc:
		case md = <-conn.MessageData:
			//
			if md.Message.Command == stompngo.RECEIPT {
				ll.Printf("%stag:%s connsess:%s have_receipt md:%v\n",
					exampid, tag, session,
					md)
				continue GetLoop
			}
			ll.Fatalf("%stag:%s connsess:%s ERROR_frame hdrs:%v body:%v\n",
				exampid, tag, session,
				md.Message.Headers, string(md.Message.Body)) // Handle this ......
		}

		// Save message data for possible use in the final ACK
		if mc == nmsgs && nfa {
			lmd = md // Save last message
		}

		// Basic loop logging
		ll.Printf("%stag:%s connsess:%s channel_read_complete qn:%d mc:%d\n",
			exampid, tag, session,
			qn, mc)
		ll.Printf("%stag:%s connsess:%s message_number:%v\n",
			exampid, tag, session,
			mc)

		// Check if reader returned any error
		if md.Error != nil {
			ll.Fatalf("%stag:%s connsess:%s error_read error:%v",
				exampid, tag, session,
				md.Error) // Handle this ......
		}

		// Show frame type
		ll.Printf("%stag:%s connsess:%s frame_type cmd:%s\n",
			exampid, tag, session,
			md.Message.Command)

		// Pure sanity check:  this should *never* happen based on logic
		// above.
		if md.Message.Command != stompngo.MESSAGE {
			ll.Fatalf("%stag:%s connsess:%s error_frame_type md:%v",
				exampid, tag, session,
				md) // Handle this ......
		}

		// Show Message Headers
		wh := md.Message.Headers
		for j := 0; j < len(wh)-1; j += 2 {
			ll.Printf("%stag:%s connsess:%s Header:%s:%s\n",
				exampid, tag, session,
				wh[j], wh[j+1])
		}
		// Show (part of) Message Body
		if pbc > 0 {
			maxlen := pbc
			if len(md.Message.Body) < maxlen {
				maxlen = len(md.Message.Body)
			}
			ss := string(md.Message.Body[0:maxlen])
			ll.Printf("%stag:%s connsess:%s payload body:%s\n",
				exampid, tag, session,
				ss)
		}

		// Sanity check this message payload
		wm := wlp + mcs // The left part plus the (string) meassage number]
		bm := string(md.Message.Body)
		if bm != wm {
			ll.Fatalf("%stag:%s connsess:%s error_message_payload\n\tGot %s\n\tWant%s\n",
				exampid, tag, session,
				bm, wm) // Handle this ......
		} else {
			ll.Printf("%stag:%s connsess:%s  matched_body_string\n%s\n%s\n",
				exampid, tag, session,
				bm, wm) // Handle this ......)
		}

		// Run individual ACK if required
		if am == stompngo.AckModeClientIndividual {
			wh := md.Message.Headers // Copy Headers
			if ar {                  // ACK receipt wanted
				wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-"+mcs)
			}
			sngecomm.HandleAck(conn, wh, id)
			ll.Printf("%stag:%s connsess:%s  individual_ack_complete mc:%v headers:%v\n",
				exampid, tag, session,
				mc, md.Message.Headers)

		}

		// Check for end of loop condition
		if mc == nmsgs {
			break
		}

		// Increment loop/message counter
		mc++
	}

	qc := make(chan bool)
	go drainSub(session, sc, qc, qn)
	dd := false

	// Issue the final ACK if needed
	if nfa {
		wh := lmd.Message.Headers // Copy Headers
		if ar {                   // ACK receipt wanted
			wh = wh.Add(stompngo.HK_RECEIPT, "rwanted-fin")
		}
		sngecomm.HandleAck(conn, wh, id)
		ll.Printf("%stag:%s connsess:%s  final_ack_complete\n",
			exampid, tag, session)
		if ar {
			ll.Printf("%stag:%s connsess:%s  ack_receive_wait_for_drain qn:%d\n",
				exampid, tag, session,
				qn)
			<-qc // Wait for drainSub
			ll.Printf("%stag:%s connsess:%s  ack_receive_drain_complete qn:%d\n",
				exampid, tag, session,
				qn)
			dd = true
			getReceipt(conn)
		}
	}

	if !dd {
		ll.Printf("%stag:%s connsess:%s  message_loop_wait_for_drain qn:%d\n",
			exampid, tag, session,
			qn)
		<-qc
		ll.Printf("%stag:%s connsess:%s  message_loop_drain_complete qn:%d\n",
			exampid, tag, session,
			qn)
	}

	// Unsubscribe (may be skipped if requested)
	if unsub {
		sngecomm.HandleUnsubscribe(conn, d, id)
		ll.Printf("%stag:%s connsess:%s stomp_unsubscribe_complete\n",
			exampid, tag, session)
	} else {
		ll.Printf("%stag:%s connsess:%s skipping_unsubscribe\n",
			exampid, tag, session)
	}
}
// Handle ACKs for the different protocol levels.
func HandleAck(c *stompngo.Connection, h stompngo.Headers, id string) {
	ah := stompngo.Headers{}
	//
	switch c.Protocol() {
	case stompngo.SPL_12:
		ah = ah.Add("id", h.Value("ack"))
	case stompngo.SPL_11:
		ah = ah.Add("message-id", h.Value("message-id")).Add("subscription", id)
	case stompngo.SPL_10:
		ah = ah.Add("message-id", h.Value("message-id"))
	default:
		llu.Fatalf("v1:%v v2:%v\n", "ack invalid protocol level, should not happen")
	}
	if cv, ok := h.Contains(stompngo.HK_RECEIPT); ok {
		ah = ah.Add(stompngo.HK_RECEIPT, cv)
	}
	e := c.Ack(ah)
	if e != nil {
		llu.Fatalf("v1:%v v2:%v v3:%v\n", "ack failed", e, c.Protocol())
	}
	return
}
Exemple #20
0
func TestPopulator(t *testing.T) {

	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("stomp connection mock", func() {

		var headers stompngo.Headers
		var stomp = New()
		var message string

		g.BeforeEach(func() {
			stomp.Clear()

			// broker headers
			headers = stompngo.Headers{
				"accept-version", "1.1",
				"login", "admin",
				"passcode", "1234",
				"host", "localhost",
			}

			// message headers
			headers = stompngo.Headers{
				"persistent", "true",
				"destination", "/queue/funny",
			}
			message = "Foo Bar"
		})

		g.It("should be successful with all headers present", func() {
			Expect(stomp.Send(headers, message)).To(BeNil())
		})

		g.It("should not be successful if the destination header is blank", func() {
			headers = headers.Delete("destination")
			Expect(stomp.Send(headers, message)).NotTo(BeNil())
		})

		g.It("should answer if it is connected", func() {
			Expect(stomp.Connected()).To(BeTrue())
		})

		g.It("should be able to get messages back afterwards", func() {
			// expected behavior adding to chan
			for i := 0; i < 1000; i++ {
				Expect(stomp.Send(headers, message)).To(BeNil())
			}

			// should be messages in the chan
			Expect(len(stomp.Messages)).To(Equal(1000))

			// pop the messages off of the chan and verify
			for i := 0; i < 1000; i++ {
				msg := <-stomp.Messages
				expectedMessage := &MockStompMessage{
					Order: i,
					Headers: []string{
						"persistent",
						"true",
						"destination",
						"/queue/funny",
					},
					Message: "Foo Bar",
				}

				Expect(msg).To(Equal(*expectedMessage))
			}
		})

		g.It("should allow for a disconnect request", func() {
			err := stomp.Disconnect(stompngo.Headers{})
			Expect(err).NotTo(HaveOccurred())
			Expect(stomp.DisconnectCalled).To(BeTrue())
		})

		g.It("should allow a subscription", func() {
			Expect(stomp.SubscribeCalled).To(BeFalse())
			sub, err := stomp.Subscribe(stompngo.Headers{})
			Expect(err).NotTo(HaveOccurred())
			Expect(stomp.Subscription).ToNot(BeNil())
			Expect(sub).To(Equal(stomp.Subscription))
			Expect(stomp.SubscribeCalled).To(BeTrue())

			msg := stompngo.MessageData{
				Message: stompngo.Message{
					Body: []uint8(message),
				},
			}
			stomp.PutToSubscribe(msg)
			outMsg := <-sub
			Expect(outMsg.Message.BodyString()).To(Equal(message))
			Expect(string(outMsg.Message.Body)).To(Equal(message))
		})

		g.It("should allow an unsubscribe", func() {
			err := stomp.Unsubscribe(stompngo.Headers{})
			Expect(err).NotTo(HaveOccurred())
			Expect(stomp.Subscription).To(BeNil())
		})
	})
}
Exemple #21
0
func main() {

	st := time.Now()

	// ****************************************
	// Set up the connection.
	// Standard example connect sequence
	n, conn, e := sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	// ****************************************
	// App logic here .....
	// Send exactly one message.  Ask for a receipt.

	d := sngecomm.Dest()
	ll.Printf("%stag:%s connsess:%s destination:%v\n",
		exampid, tag, conn.Session(),
		d)

	rid := "recipt-002" // The receipt ID
	sh := stompngo.Headers{"destination", d,
		"receipt", rid} // send headers
	if senv.Persistent() {
		sh = sh.Add("persistent", "true")
	}
	ms := exampid + " message: "
	t := ms + rid
	ll.Printf("%stag:%s connsess:%s sending_now body:%v\n",
		exampid, tag, conn.Session(),
		t)
	e = conn.Send(sh, t)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_bad_send error:%v",
			exampid, tag, conn.Session(),
			e.Error()) // Handle this ......
	}
	ll.Printf("%stag:%s connsess:%s send_complete body:%v\n",
		exampid, tag, conn.Session(),
		t)

	// Look for the receipt
	ll.Printf("%stag:%s connsess:%s start_receipt_read\n",
		exampid, tag, conn.Session())
	rd := <-conn.MessageData // The RECEIPT frame should be on this channel
	if rd.Message.Command != stompngo.RECEIPT {
		ll.Fatalf("%stag:%s connsess:%s bad_frame_command rd:%v\n",
			exampid, tag, conn.Session(),
			rd) // Handle this ......
	}
	ll.Printf("%stag:%s connsess:%s end_receipt_read\n",
		exampid, tag, conn.Session())

	// ****************************************
	// Show details about the RECEIPT MessageData struct
	ll.Printf("%stag:%s connsess:%s receipt_COMMAND command:%s\n",
		exampid, tag, conn.Session(),
		rd.Message.Command)
	ll.Printf("%stag:%s connsess:%s receipt_HEADERS headers:%v\n",
		exampid, tag, conn.Session(),
		rd.Message.Headers)
	ll.Printf("%stag:%s connsess:%s receipt_BODY body:%s\n",
		exampid, tag, conn.Session(),
		string(rd.Message.Body))

	// Step 2 of Verify
	// Verify that the receipt has the id we asked for
	if rd.Message.Headers.Value("receipt-id") != rid {
		ll.Fatalf("%stag:%s connsess:%s bad_receipt_id wanted:%v got:%v\n",
			exampid, tag, conn.Session(),
			rid, rd.Message.Headers.Value("receipt-id")) // Handle this ......
	}
	ll.Printf("%stag:%s connsess:%s receipt_id_verified rid:%s\n",
		exampid, tag, conn.Session(),
		rid)

	e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_disconnect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, conn.Session(),
		time.Now().Sub(st))

}
Exemple #22
0
func main() {

	// Make sure that the queue used by this example do not exist, or are
	// empty.

	// Following is a lengthy piece of code.  Read it striaght from top
	// to bottom.  There is zero complex logic here.

	// What this code will do:
	// Phase 1:
	// - Connect to a broker
	// - Verify a connection spec level
	// - Send a single message to the specified queue on that broker
	// - Disconnect from that broker
	//
	// Phase 2:
	// - Reconnect to the same broker
	// - Subscribe to the specified queue, using "ack:client-individual"
	// - Receive a single message
	// - Send an ACK, asking for a receipt
	//**************************************************************************
	// - Receive a RECEIPT // The point of this exercise.
	// - Show data from the RECEIPT and verify it // The point of this exercise.
	//**************************************************************************
	// - Disconnect from the broker

	// Start

	st := time.Now()

	// **************************************** Phase 1
	// Set up the connection.
	// Standard example connect sequence
	n, conn, e := sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	// ****************************************
	// App logic here .....

	d := sngecomm.Dest()
	ll.Printf("%stag:%s connsess:%s destination:%v\n",
		exampid, tag, conn.Session(),
		d)

	// ****************************************
	// Send exactly one message.
	sh := stompngo.Headers{"destination", sngecomm.Dest()}
	if senv.Persistent() {
		sh = sh.Add("persistent", "true")
	}
	m := exampid + " message: "
	t := m + "1"
	ll.Printf("%stag:%s connsess:%s sending_now body:%v\n",
		exampid, tag, conn.Session(),
		t)
	e = conn.Send(sh, t)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_bad_send error:%v",
			exampid, tag, conn.Session(),
			e.Error()) // Handle this ......
	}
	ll.Printf("%stag:%s connsess:%s send_complete body:%v\n",
		exampid, tag, conn.Session(),
		t)

	// ****************************************
	// Disconnect from the Stomp server
	// Standard example disconnect sequence
	e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_disconnect error:%v",
			exampid, tag, conn.Session(),
			e.Error()) // Handle this ......
	}

	// **************************************** Phase 2

	// Standard example connect sequence
	n, conn, e = sngecomm.CommonConnect(exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_on_connect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	// ****************************************
	// Subscribe here
	id := stompngo.Uuid()
	// Get the "subscribe channel"
	sc := sngecomm.HandleSubscribe(conn, d, id, "client-individual")
	ll.Printf("%stag:%s connsess:%s stomp_subscribe_complete\n",
		exampid, tag, conn.Session())

	// Get data from the broker
	var md stompngo.MessageData // A message data instance
	select {
	case md = <-sc:
	case md = <-conn.MessageData:
		// This would be contain an ERROR or RECEIPT frame.  Both are unexpected
		// in this example.
		ll.Fatalf("%stag:%s connsess:%s bad_frame md:%v",
			exampid, tag, conn.Session(),
			md) // Handle this ......
	}
	ll.Printf("%stag:%s connsess:%s channel_read_complete\n",
		exampid, tag, conn.Session())

	// MessageData has two components:
	// a) a Message struct
	// b) an Error value.  Check the error value as usual
	if md.Error != nil {
		ll.Fatalf("%stag:%s connsess:%s message_error md:%v",
			exampid, tag, conn.Session(),
			md.Error) // Handle this ......
	}

	ll.Printf("%stag:%s connsess:%s read_message_COMMAND command:%s\n",
		exampid, tag, conn.Session(),
		md.Message.Command)
	ll.Printf("%stag:%s connsess:%s read_message_HEADERS headers:%s\n",
		exampid, tag, conn.Session(),
		md.Message.Headers)
	ll.Printf("%stag:%s connsess:%s read_message_BODY body:%s\n",
		exampid, tag, conn.Session(),
		string(md.Message.Body))

	// Here we need to send an ACK.  Required Headers are different between
	// a 1.1 and a 1.2 connection level.
	var ah stompngo.Headers
	if conn.Protocol() == stompngo.SPL_11 { // 1.1
		ah = ah.Add("subscription", md.Message.Headers.Value("subscription"))
		ah = ah.Add("message-id", md.Message.Headers.Value("message-id"))
	} else { // 1.2
		ah = ah.Add("id", md.Message.Headers.Value("ack"))
	}
	// We are also going to ask for a RECEIPT for the ACK
	rid := "receipt-001"
	ah = ah.Add("receipt", rid)
	//
	ll.Printf("%stag:%s connsess:%s ACK_receipt_headers headers:%v\n",
		exampid, tag, conn.Session(),
		ah)
	e = conn.Ack(ah)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s ack_error error:%v",
			exampid, tag, conn.Session(),
			e.Error()) // Handle this ......
	}

	// ****************************************
	// Finally get the RECEIPT.  Where is it?  It is *not* on the "subscribe
	// channel".  It is on the connection level MessageData channel.  Why?
	// Because the broker does *not* include a "subscription" header in
	// RECEIPT frames..
	// ****************************************

	// ***IMPORTANT***
	// ***NOTE*** which channel this RECEIPT MessageData comes in on.

	ll.Printf("%stag:%s connsess:%s start_receipt_read\n",
		exampid, tag, conn.Session())
	var rd stompngo.MessageData
	select {
	case rd = <-sc:
		// This would contain a MESSAGE frame.  It is unexpected here
		// in this example.
		ll.Fatalf("%stag:%s connsess:%s bad_frame_channel rd:%v\n",
			exampid, tag, conn.Session(),
			rd) // Handle this ......
	case rd = <-conn.MessageData: // RECEIPT frame s/b in the MessageData
		// Step 1 of Verify
		if rd.Message.Command != stompngo.RECEIPT {
			ll.Fatalf("%stag:%s connsess:%s bad_frame_command rd:%v\n",
				exampid, tag, conn.Session(),
				rd) // Handle this ......
		}
	}
	ll.Printf("%stag:%s connsess:%s end_receipt_read\n",
		exampid, tag, conn.Session())

	// ****************************************
	// Show details about the RECEIPT MessageData struct
	ll.Printf("%stag:%s connsess:%s receipt_COMMAND command:%s\n",
		exampid, tag, conn.Session(),
		rd.Message.Command)
	ll.Printf("%stag:%s connsess:%s receipt_HEADERS headers:%v\n",
		exampid, tag, conn.Session(),
		rd.Message.Headers)
	ll.Printf("%stag:%s connsess:%s receipt_BODY body:%s\n",
		exampid, tag, conn.Session(),
		string(rd.Message.Body))

	// Step 2 of Verify
	// Verify that the receipt has the id we asked for
	if rd.Message.Headers.Value("receipt-id") != rid {
		ll.Fatalf("%stag:%s connsess:%s bad_receipt_id wanted:%v got:%v\n",
			exampid, tag, conn.Session(),
			rid, rd.Message.Headers.Value("receipt-id")) // Handle this ......
	}
	ll.Printf("%stag:%s connsess:%s receipt_id_verified rid:%s\n",
		exampid, tag, conn.Session(),
		rid)

	// ****************************************
	// Disconnect from the Stomp server
	// Standard example disconnect sequence
	e = sngecomm.CommonDisconnect(n, conn, exampid, tag, ll)
	if e != nil {
		ll.Fatalf("%stag:%s connsess:%s main_disconnect error:%v",
			exampid, tag, sngecomm.Lcs,
			e.Error()) // Handle this ......
	}

	ll.Printf("%stag:%s connsess:%s main_elapsed:%v\n",
		exampid, tag, conn.Session(),
		time.Now().Sub(st))

}