Example #1
0
// ZmqRecvMulti Receives a multi-part message and return it as a slice of strings
func ZmqRecvMulti(s *zmq.Socket) []string {
	var msg []string
	more := true
	for more {
		part, _ := s.Recv(0)
		msg = append(msg, part)
		more, _ = s.GetRcvmore()
	}
	return msg
}
Example #2
0
func RecieveClientRequest(receiver *zmq.Socket, myservices map[string]ProcessRequest) (service_required ProcessRequest, message string, err error) {
	for count := 0; ; count++ {
		var request string
		request, err = receiver.Recv(0)
		if err != nil {
			err = errors.New(fmt.Sprintf("Error:Receive:%s", err))
			return
		}
		fmt.Println("\tCurrent: ", request)
		//  Retrieve message parts from the envelope
		//  The first part is either:
		//  a. A heartbeat request
		//  b. The service's SID
		//  The second part: the message
		if count == 0 {
			var isPresent bool
			service_required, isPresent = myservices[request]
			fmt.Printf("%s is present? %s", request, isPresent)
			if !isPresent {
				err = errors.New("Error:InvalidService")
				return
			}
		}
		if count == 1 {
			message = request
		}
		//  Check if there are more in envelope and deal with any errors
		var more bool
		more, err = receiver.GetRcvmore()
		if err != nil {
			err = errors.New(fmt.Sprintf("Error:Receive:%s", err))
			return
		}
		if !more {
			return
		}
	}
}
Example #3
0
func dump(soc *zmq.Socket) {
	fmt.Println("----------------------------------------")
	for {
		//  Process all parts of the message
		message, _ := soc.Recv(0)

		//  Dump the message as text or binary
		fmt.Printf("[%03d] ", len(message))
		if all_char.MatchString(message) {
			fmt.Print(message)
		} else {
			for i := 0; i < len(message); i++ {
				fmt.Printf("%02X ", message[i])
			}
		}
		fmt.Println()

		more, _ := soc.GetRcvmore()
		if !more {
			break
		}
	}
}
Example #4
0
func TestDisconnectInproc(t *testing.T) {

	var pubSocket, subSocket *zmq.Socket
	defer func() {
		for _, s := range []*zmq.Socket{pubSocket, subSocket} {
			if s != nil {
				s.SetLinger(0)
				s.Close()
			}
		}
	}()

	publicationsReceived := 0
	isSubscribed := false

	pubSocket, err := zmq.NewSocket(zmq.XPUB)
	if err != nil {
		t.Fatal("NewSocket XPUB:", err)
	}
	subSocket, err = zmq.NewSocket(zmq.SUB)
	if err != nil {
		t.Fatal("NewSocket SUB:", err)
	}
	err = subSocket.SetSubscribe("foo")
	if err != nil {
		t.Fatal("subSocket.SetSubscribe:", err)
	}

	err = pubSocket.Bind("inproc://someInProcDescriptor")
	if err != nil {
		t.Fatal("pubSocket.Bind:", err)
	}

	iteration := 0

	poller := zmq.NewPoller()
	poller.Add(subSocket, zmq.POLLIN) // read publications
	poller.Add(pubSocket, zmq.POLLIN) // read subscriptions
	for {
		sockets, err := poller.Poll(100 * time.Millisecond)
		if err != nil {
			t.Error("Poll:", err)
			break //  Interrupted
		}

		for _, socket := range sockets {
			if socket.Socket == pubSocket {
				for {
					buffer, err := pubSocket.Recv(0)
					if err != nil {
						t.Fatal("pubSocket.Recv", err)
					}
					exp := "\x01foo"
					if isSubscribed {
						exp = "\x00foo"
					}
					if buffer != exp {
						t.Errorf("pubSocket.Recv: expected %q, got %q", exp, buffer)
					}

					if buffer[0] == 0 {
						if isSubscribed != true {
							t.Errorf("Poller: expected subscribed")
						}
						isSubscribed = false
					} else {
						if isSubscribed != false {
							t.Errorf("Poller: expected not subscribed")
						}
						isSubscribed = true
					}

					more, err := pubSocket.GetRcvmore()
					if err != nil {
						t.Fatal("pubSocket.GetRcvmore:", err)
					}
					if !more {
						break //  Last message part
					}
				}
				break
			}
		}

		for _, socket := range sockets {
			if socket.Socket == subSocket {
				for _, exp := range []string{"foo", "this is foo!", "", ""} {
					msg, err := subSocket.Recv(0)
					if err != nil {
						t.Fatal("subSocket.Recv:", err)
					}
					if msg != exp {
						t.Errorf("subSocket.Recv: expected %q, got %q", exp, msg)
					}
					more, err := subSocket.GetRcvmore()
					if err != nil {
						t.Fatal("subSocket.GetRcvmore:", err)
					}
					if !more {
						publicationsReceived++
						break //  Last message part
					}

				}
				break
			}
		}

		if iteration == 1 {
			err := subSocket.Connect("inproc://someInProcDescriptor")
			if err != nil {
				t.Fatal("subSocket.Connect", err)
			}
		}
		if iteration == 4 {
			err := subSocket.Disconnect("inproc://someInProcDescriptor")
			if err != nil {
				t.Fatal("subSocket.Disconnect", err)
			}
		}
		if iteration > 4 && len(sockets) == 0 {
			break
		}

		_, err = pubSocket.Send("foo", zmq.SNDMORE)
		if err != nil {
			t.Fatal("pubSocket.Send 1", err)
		}
		_, err = pubSocket.Send("this is foo!", 0)
		if err != nil {
			t.Fatal("pubSocket.Send 2", err)
		}

		iteration++

	}

	if publicationsReceived != 3 {
		t.Error("publicationsReceived != 3 ")
	}
	if isSubscribed {
		t.Error("isSubscribed")
	}

	err = pubSocket.Close()
	pubSocket = nil
	if err != nil {
		t.Error("pubSocket.Close:", err)
	}
	err = subSocket.Close()
	subSocket = nil
	if err != nil {
		t.Error("subSocket.Close:", err)
	}
}
Example #5
0
func bounce(server, client *zmq.Socket) (msg string, err error) {

	content := "12345678ABCDEFGH12345678abcdefgh"

	//  Send message from client to server
	rc, err := client.Send(content, zmq.SNDMORE|zmq.DONTWAIT)
	if err != nil {
		return "client.Send SNDMORE|DONTWAIT:", err
	}
	if rc != 32 {
		return "client.Send SNDMORE|DONTWAIT:", err32
	}

	rc, err = client.Send(content, zmq.DONTWAIT)
	if err != nil {
		return "client.Send DONTWAIT:", err
	}
	if rc != 32 {
		return "client.Send DONTWAIT:", err32
	}

	//  Receive message at server side
	msg, err = server.Recv(0)
	if err != nil {
		return "server.Recv 1:", err
	}

	//  Check that message is still the same
	if msg != content {
		return "server.Recv 1:", errors.New(fmt.Sprintf("%q != %q", msg, content))
	}

	rcvmore, err := server.GetRcvmore()
	if err != nil {
		return "server.GetRcvmore 1:", err
	}
	if !rcvmore {
		return "server.GetRcvmore 1:", errors.New(fmt.Sprint("rcvmore ==", rcvmore))
	}

	//  Receive message at server side
	msg, err = server.Recv(0)
	if err != nil {
		return "server.Recv 2:", err
	}

	//  Check that message is still the same
	if msg != content {
		return "server.Recv 2:", errors.New(fmt.Sprintf("%q != %q", msg, content))
	}

	rcvmore, err = server.GetRcvmore()
	if err != nil {
		return "server.GetRcvmore 2:", err
	}
	if rcvmore {
		return "server.GetRcvmore 2:", errors.New(fmt.Sprint("rcvmore == ", rcvmore))
	}

	// The same, from server back to client

	//  Send message from server to client
	rc, err = server.Send(content, zmq.SNDMORE)
	if err != nil {
		return "server.Send SNDMORE:", err
	}
	if rc != 32 {
		return "server.Send SNDMORE:", err32
	}

	rc, err = server.Send(content, 0)
	if err != nil {
		return "server.Send 0:", err
	}
	if rc != 32 {
		return "server.Send 0:", err32
	}

	//  Receive message at client side
	msg, err = client.Recv(0)
	if err != nil {
		return "client.Recv 1:", err
	}

	//  Check that message is still the same
	if msg != content {
		return "client.Recv 1:", errors.New(fmt.Sprintf("%q != %q", msg, content))
	}

	rcvmore, err = client.GetRcvmore()
	if err != nil {
		return "client.GetRcvmore 1:", err
	}
	if !rcvmore {
		return "client.GetRcvmore 1:", errors.New(fmt.Sprint("rcvmore ==", rcvmore))
	}

	//  Receive message at client side
	msg, err = client.Recv(0)
	if err != nil {
		return "client.Recv 2:", err
	}

	//  Check that message is still the same
	if msg != content {
		return "client.Recv 2:", errors.New(fmt.Sprintf("%q != %q", msg, content))
	}

	rcvmore, err = client.GetRcvmore()
	if err != nil {
		return "client.GetRcvmore 2:", err
	}
	if rcvmore {
		return "client.GetRcvmore 2:", errors.New(fmt.Sprint("rcvmore == ", rcvmore))
	}
	return "OK", nil
}
Example #6
0
//  Send a request to a service
func SendRequest(service Service, request, message string) (reply []string, err error) {
	//  Bind to service if not already done
	var requester *zmq.Socket
	fmt.Println("Connecting to '", service.Name, "'' at '", service.Address, "'...")
	requester, err = zmq.NewSocket(zmq.REQ)
	if err != nil {
		log.Println(err)
		return
	}
	requester.Connect(service.Address)

	poller := zmq.NewPoller()
	poller.Add(requester, zmq.POLLIN)

	retries_left := REQUEST_RETRIES
	request_timeout := REQUEST_TIMEOUT
	if request == PPP_HEARTBEAT {
		retries_left = 1
		request_timeout = 1500 * time.Millisecond
	}
	for retries_left > 0 {
		//  Send message
		//  The service required in first packet of envelope
		//  The message for given service in second packet of envelope
		//  Heartbeat messages only contain one message in envelope
		if request == PPP_HEARTBEAT {
			_, err = requester.Send(PPP_HEARTBEAT, 0)
		} else {
			_, err = requester.Send(request, zmq.SNDMORE)
			_, err = requester.Send(message, 0)
		}
		for expect_reply := true; expect_reply; {
			//  Poll socket for a reply, with timeout
			var sockets []zmq.Polled
			sockets, err = poller.Poll(request_timeout)
			if err != nil {
				break //  Interrupted
			}

			//  Wait to receive reply if there are no more messages to send
			if len(sockets) > 0 {
				//  Receive all replies in the envelope before processing
				var more bool
				for count := 0; ; count++ {
					var rep string
					rep, err = requester.Recv(0)
					if err != nil {
						retries_left--
						break
					}

					reply = append(reply, rep)
					//  Unpacking three parts from the message envelope
					//  The first part: the expected service reply signature
					//  The second part is either:
					//  a. error state (empty if no error) OR
					//  b. the heartbeat reply of the server
					//  The third part: the actual message
					if count == 0 && rep != service.Reply {
						err = errors.New("ServiceListOutdated:Bound to wrong service")
						retries_left = 0
						break
					}
					if count == 1 && rep != "" && rep != PPP_READY {
						err = errors.New(rep)
						retries_left = 0
						break
					}
					//  Break from loop if there are no more messages or
					//  an error condition occurs
					more, err = requester.GetRcvmore()
					if !more || err != nil {
						retries_left--
						break
					}
				}

				//  If there was an error retrieving the message, then we
				//  should still expect replies
				if err != nil {
					break
				}
				//  All messages retrieved from packet successfully
				//  Leave the retrieve/retry loops
				retries_left = 0
				expect_reply = false
			} else {
				retries_left--
				if retries_left == 0 {
					if err == nil {
						err = errors.New("Error:TimeOut")
					}
					requester.Close()
					return
				} else {
					err = nil
					reply = nil
					fmt.Println("No response from server, retrying...")
					//  Old socket is confused; close it and open a new one
					requester.Close()
					requester, _ = zmq.NewSocket(zmq.REQ)
					requester.Connect(service.Address)
					// Recreate poller for new client
					poller = zmq.NewPoller()
					poller.Add(requester, zmq.POLLIN)
					//  Send request again, on the new socket
					if request == PPP_HEARTBEAT {
						_, err = requester.Send(PPP_HEARTBEAT, 0)
					} else {
						_, err = requester.Send(request, zmq.SNDMORE)
						_, err = requester.Send(message, 0)
					}
				}
			}
		}
	}
	fmt.Println("\tReceived: ", reply)
	//  Deall with invalid/distorted replies first
	//  Followed by heartbeat replies
	//  Then package reply for return to the function caller
	if len(reply) < 2 {
		err = errors.New(fmt.Sprintf("Error:UnexpectedReply:%s", err))
		requester.Close()
		return
	}
	if reply[1] == PPP_READY {
		reply = append(reply, reply[1])
	}
	reply = reply[2:]
	requester.Close()
	return
}
Example #7
0
func (w *worker) socketLoop(s *zmq.Socket, send <-chan Data, recv chan<- Data, state zmq.State) {
	if recv != nil {
		defer close(recv)
	}

	var (
		sendBuf     Data
		sendPending bool
		recvBuf     Data
		recvPending bool
	)

	for {
		var (
			err error

			sendActive <-chan Data
			recvActive chan<- Data
		)

		if !sendPending {
			sendActive = send
		}

		if recvPending {
			recvActive = recv
		}

		select {
		case <-w.notifier:
			const fullState = zmq.POLLIN | zmq.POLLOUT

			if state&fullState != fullState {
				if state, err = s.GetEvents(); err != nil {
					handleGeneralError(err)
					return
				}
			}

		case <-w.closer:
			return

		case sendBuf, sendPending = <-sendActive:
			if !sendPending {
				send = nil
			}

		case recvActive <- recvBuf:
			recvPending = false
			recvBuf.Bytes = nil
		}

		for {
			loop := false

			if sendPending && state&zmq.POLLOUT != 0 {
				flags := zmq.DONTWAIT

				if sendBuf.More {
					flags |= zmq.SNDMORE
				}

				if _, err = s.SendBytes(sendBuf.Bytes, flags); err == nil {
					sendPending = false
					sendBuf.Bytes = nil
					loop = true
				} else if !handleIOError(err) {
					return
				}

				if state, err = s.GetEvents(); err != nil {
					handleGeneralError(err)
					return
				}
			}

			if !recvPending && state&zmq.POLLIN != 0 {
				if data, err := s.RecvBytes(zmq.DONTWAIT); err == nil {
					if more, err := s.GetRcvmore(); err == nil {
						recvBuf.Bytes = data
						recvBuf.More = more
						recvPending = true
						loop = true
					} else {
						handleGeneralError(err)
						return
					}
				} else if !handleIOError(err) {
					return
				}

				if state, err = s.GetEvents(); err != nil {
					handleGeneralError(err)
					return
				}
			}

			if !loop {
				break
			}
		}
	}
}
Example #8
0
func bounce(server, client *zmq.Socket, willfail bool) {

	content := "12345678ABCDEFGH12345678abcdefgh"

	//  Send message from client to server
	rc, err := client.Send(content, zmq.SNDMORE|zmq.DONTWAIT)
	if checkErr0(err, 1) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"), 2)
	}

	rc, err = client.Send(content, zmq.DONTWAIT)
	if checkErr0(err, 3) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"), 4)
	}

	//  Receive message at server side
	msg, err := server.Recv(0)
	if checkErr0(e(err, willfail), 5) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 6)
	}

	rcvmore, err := server.GetRcvmore()
	if checkErr0(err, 7) {
		return
	}
	if !rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore)), 8)
		return
	}

	//  Receive message at server side
	msg, err = server.Recv(0)
	if checkErr0(err, 9) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 10)
	}

	rcvmore, err = server.GetRcvmore()
	if checkErr0(err, 11) {
		return
	}
	if rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore)), 12)
		return
	}

	// The same, from server back to client

	//  Send message from server to client
	rc, err = server.Send(content, zmq.SNDMORE)
	if checkErr0(err, 13) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"), 14)
	}

	rc, err = server.Send(content, 0)
	if checkErr0(err, 15) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"), 16)
	}

	//  Receive message at client side
	msg, err = client.Recv(0)
	if checkErr0(err, 17) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 18)
	}

	rcvmore, err = client.GetRcvmore()
	if checkErr0(err, 19) {
		return
	}
	if !rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore)), 20)
		return
	}

	//  Receive message at client side
	msg, err = client.Recv(0)
	if checkErr0(err, 21) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)), 22)
	}

	rcvmore, err = client.GetRcvmore()
	if checkErr0(err, 23) {
		return
	}
	if rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore)), 24)
		return
	}

}
Example #9
0
func serveFrontend(frontend *zmq.Socket) (back *zmq.Socket) {
	var header []string
	var service Service
	isPresent := false
	//fmt.Println("\nReceiving message from client...")
	for {
		msg, _ := frontend.Recv(0)
		//fmt.Printf("\tIn-->%s\n", msg)
		message := strings.SplitN(msg, ":", 2)
		if more, _ := frontend.GetRcvmore(); more {
			//  If this part of the message contains no service description
			//  treat is as a header
			if len(message) != 2 {
				header = append(header, msg)
				continue
			}

			//  If the service request is to register a service, register it
			if message[0] == "register" {
				back = registerService(message[1], header, frontend)
				return
			}

			//  If the service requested is not in the service list then assume
			//  it will be at end of message and treat message as part of header
			service, isPresent = services[message[0]]
			if !isPresent {
				header = append(header, msg)
				continue
			}

			//  If the service requested is available send the early parts of
			//  message at this point
			for key := range header {
				//fmt.Printf("\tForwarding to %s at %s: %s\n", service.Name, service.Address, header[key])
				service.Backend.Send(header[key], zmq.SNDMORE)
			}
			header = header[:0] // Empty header to avoid accidental resend below
			service.Backend.Send(message[1], zmq.SNDMORE)
		} else {
			// If the service request is to register a service, register it
			if message[0] == "register" {
				back = registerService(message[1], header, frontend)
				return
			}

			// Has the service already been discovered? -If not, discover it
			if !isPresent {
				service, isPresent = services[message[0]]
			}

			//  If the service is still not discovered at this point, then we
			//   have a problem. Report back to client
			if !isPresent {
				sendToClient("InvalidService", header, "Invalid Service SID", 0, frontend)
				break
			}

			//  Otherwise everything is good fetch the service and send request
			//  Send the assumed header of the message
			for key := range header {
				//fmt.Printf("\tForwarding to %s at %s: %s\n", service.Name, service.Address, header[key])
				service.Backend.Send(header[key], zmq.SNDMORE)
			}
			//  Send the rest of the message
			//fmt.Printf("\tForwarding to %s at %s: %s\n", service.Name, service.Address, message[1])
			service.Backend.Send(message[1], 0)
			//fmt.Println("\tDone")
			break
		}
	}
	return
}
Example #10
0
func bounce(server, client *zmq.Socket) {

	content := "12345678ABCDEFGH12345678abcdefgh"

	//  Send message from client to server
	rc, err := client.Send(content, zmq.SNDMORE|zmq.DONTWAIT)
	if checkErr0(err) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"))
	}

	rc, err = client.Send(content, zmq.DONTWAIT)
	if checkErr0(err) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"))
	}

	//  Receive message at server side
	msg, err := server.Recv(0)
	if checkErr0(err) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)))
	}

	rcvmore, err := server.GetRcvmore()
	if checkErr0(err) {
		return
	}
	if !rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore)))
		return
	}

	//  Receive message at server side
	msg, err = server.Recv(0)
	if checkErr0(err) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)))
	}

	rcvmore, err = server.GetRcvmore()
	if checkErr0(err) {
		return
	}
	if rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore)))
		return
	}

	// The same, from server back to client

	//  Send message from server to client
	rc, err = server.Send(content, zmq.SNDMORE)
	if checkErr0(err) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"))
	}

	rc, err = server.Send(content, 0)
	if checkErr0(err) {
		return
	}
	if rc != 32 {
		checkErr0(errors.New("rc != 32"))
	}

	//  Receive message at client side
	msg, err = client.Recv(0)
	if checkErr0(err) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)))
	}

	rcvmore, err = client.GetRcvmore()
	if checkErr0(err) {
		return
	}
	if !rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore ==", rcvmore)))
		return
	}

	//  Receive message at client side
	msg, err = client.Recv(0)
	if checkErr0(err) {
		return
	}

	//  Check that message is still the same
	if msg != content {
		checkErr0(errors.New(fmt.Sprintf("%q != %q", msg, content)))
	}

	rcvmore, err = client.GetRcvmore()
	if checkErr0(err) {
		return
	}
	if rcvmore {
		checkErr0(errors.New(fmt.Sprint("rcvmore == ", rcvmore)))
		return
	}

}