예제 #1
0
func DoForwardData(appDlCh, appUlCh, crossCh chan []byte, device string) {
	siface := &serial.Config{Name: device, Baud: 57600}
	serReader, err := serial.OpenPort(siface)
	if err != nil {
		fmt.Println("error opening serial interface:", err.Error())
		os.Exit(1)
	}
	defer serReader.Close()
	ser := SerialReader{serReader}
	serCh := devreader.MakeChannel(ser)

LOOP:
	for {
		select {
		case payload := <-serCh:
			crossCh <- payload
			fmt.Printf("read nfc data\n- ascii: %s\n- hex: %x\n", string(payload), string(payload))

		case _, more := <-appDlCh:
			if !more {
				close(appUlCh)
				break LOOP
			}
		}
	}
	fmt.Println("stopped forwarding nfc data")
}
예제 #2
0
파일: udp_mcast.go 프로젝트: herrfz/gowdc
// args:
// - addr: multicast group/address to listen to
// - port: port number; addr:port builds the mcast socket
// - iface: name of network interface to listen to
// - d_dl_sock:
// - stopch:
func ListenUDPMcast(addr, port, iface string, d_dl_sock *zmq.Socket,
	stopch chan bool) {
	eth, err := net.InterfaceByName(iface)
	if err != nil {
		fmt.Println("Error interface:", err.Error())
		os.Exit(1)
	}

	group := net.ParseIP(addr)
	if group == nil {
		fmt.Println("Error: invalid group address:", addr)
		os.Exit(1)
	}

	// listen to all udp packets on mcast port
	c, err := net.ListenPacket("udp4", "0.0.0.0:"+port)
	if err != nil {
		fmt.Println("Error listening for mcast:", err.Error())
		os.Exit(1)
	}
	// close the listener when the application closes
	defer c.Close()

	// join mcast group
	p := ipv4.NewPacketConn(c)
	if err := p.JoinGroup(eth, &net.UDPAddr{IP: group}); err != nil {
		fmt.Println("Error joining:", err.Error())
		os.Exit(1)
	}
	fmt.Println("Listening on " + addr + ":" + port)

	// enable transmissons of control message
	if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
		fmt.Println("Error control message", err.Error())
	}

	c1 := devreader.MakeChannel(UMSocket{p, group})

LOOP:
	for {
		select {
		case v1 := <-c1:
			fmt.Println("received UDP multicast")
			// forward to coord node
			d_dl_sock.Send(string(v1), 0)

		case <-stopch:
			break LOOP
		}

	}
}
예제 #3
0
파일: coordnode.go 프로젝트: herrfz/gowdc
func ListenCoordNode(d_ul_sock *zmq.Socket, u_conn *net.UDPConn, stopch chan bool) {
	fmt.Println("Listening to coordinator node uplink")

	cn_ch := devreader.MakeChannel(CNSocket{d_ul_sock})

LOOP:
	for {
		select {
		case cn_buf := <-cn_ch:
			fmt.Println("received from coordinator node")
			u_conn.Write([]byte(cn_buf))
			fmt.Println("sent coord node response over UDP")

		case <-stopch:
			break LOOP
		}
	}
}
예제 #4
0
파일: serial.go 프로젝트: herrfz/coordnode
// main goroutine loop
func DoSerialDataRequest(dlCh, ulCh chan []byte, device string) {
	// trailing LQI, ED, RX status, RX slot; TODO, all zeros for now
	// I have to add one 0x00 to remove server error!! why!!
	var trail = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}

	c := &serial.Config{Name: device, Baud: 9600}
	s, err := serial.OpenPort(c)
	if err != nil {
		fmt.Println("error opening serial interface:", err.Error())
		os.Exit(1)
	}
	defer s.Close()

	serial := SerialReader{s}
	rxch := devreader.MakeChannel(serial)

	// automatic serial sender just for testing
	stopch := make(chan bool)
	go testWriteSerial(stopch)

	// handshake
	hello := Message{1, []byte{}}
	msgHello := hello.GenerateMessage()
	s.Write(msgHello)
	fmt.Println("sent hello:", hex.EncodeToString(msgHello), "waiting for ack...")
	buf, err := receiveWithTimeout(rxch, 10)
	fmt.Println("received hello ack:", hex.EncodeToString(buf))
	if err != nil {
		fmt.Println("error reading serial handshake:", err.Error())
		os.Exit(1)
	}
	rcvd := Message{}
	rcvd.ParseBuffer(buf)
	if rcvd.mtype != 2 {
		fmt.Println("invalid hello ack")
		os.Exit(1)
	}

LOOP:
	for {
		select {
		case buf, more := <-dlCh:
			if !more {
				fmt.Println("stopping serial worker...")
				close(ulCh)
				break LOOP
			}

			wdcReq := WDC_REQ{}
			wdcReq.ParseWDCReq(buf)
			if wdcReq.MSDULEN != len(wdcReq.MSDU) {
				fmt.Println("MSDU length mismatch, on frame:", wdcReq.MSDULEN, ", received:", len(wdcReq.MSDU))
				continue
			}

			MSDU := make([]byte, len(wdcReq.MSDU))
			copy(MSDU, wdcReq.MSDU) // if I don't do this the MSDU gets corrupted!?!?!?
			MPDU := MakeMPDU([]byte{0x01, 0x98}, wdcReq.DSTPAN, wdcReq.DSTADDR, []byte{0xff, 0xff}, []byte{0xff, 0xff}, MSDU)
			app := Message{mtype: 3, data: MPDU}
			msgApp := app.GenerateMessage()
			s.Write(msgApp)
			fmt.Println("written to serial:", hex.EncodeToString(msgApp))

		case buf := <-rxch:
			if len(buf) == 0 {
				continue
			}

			rcvd := Message{}
			err := rcvd.ParseBuffer(buf)
			if err != nil {
				fmt.Println("error parsing buffer:", err.Error(), hex.EncodeToString(buf))
				continue
			}

			switch rcvd.mtype {
			case 1, 2:
				continue

			case 3:
				ind := MakeWDCInd(rcvd.data, trail) // rcvd.data must be an MPDU
				ulCh <- ind

			case 4:
				fmt.Println("received debug message:", hex.EncodeToString(rcvd.data))

			}
		}
	}
	fmt.Println("serial worker stopped")
}
예제 #5
0
파일: serial.go 프로젝트: herrfz/coordnode
// FOR LOOPBACK TESTING ONLY, simply exits when device not available
// TODO: hard code path
func testWriteSerial(stopch chan bool) {
	c := &serial.Config{Name: "/dev/pts/4", Baud: 9600}
	s, err := serial.OpenPort(c)
	if err != nil {
		fmt.Println("error opening loopback test serial interface:", err.Error())
		close(stopch)
		return
	}
	defer s.Close()

	serial := SerialReader{s}
	testrxch := devreader.MakeChannel(serial)

LOOP:
	for {
		select {
		case <-stopch:
			break LOOP

		case buf := <-testrxch:
			if len(buf) == 0 {
				continue
			}

			rcvd := Message{}
			err := rcvd.ParseBuffer(buf)
			if err != nil {
				fmt.Println("error parsing buffer:", err.Error())
				debug := Message{4, buf}
				msgDebug := debug.GenerateMessage()
				s.Write(msgDebug)
				continue
			}

			switch rcvd.mtype {
			case 1:
				helloAck := Message{2, []byte{}}
				msgHelloAck := helloAck.GenerateMessage()
				s.Write(msgHelloAck)

				test := Message{4, []byte{0xde, 0xad, 0xca, 0xfe}}
				msgTest := test.GenerateMessage()
				s.Write(msgTest)

			case 2:
				continue

			case 3:
				fmt.Println("received application message:", hex.EncodeToString(rcvd.data))

			case 4:
				fmt.Println("received debug message:", hex.EncodeToString(rcvd.data))

			}

		case <-time.After(30 * time.Second):
			msg := Message{mtype: 4, data: []byte{0xde, 0xad, 0xbe, 0xef}}
			buf := msg.GenerateMessage()
			s.Write(buf)
			fmt.Println("test: written to serial:", hex.EncodeToString(buf))
		}
	}
	fmt.Println("testWriteSerial stopped")
}
예제 #6
0
func main() {
	nodeSerial := flag.String("nodeSerial", "", "serial device to connect to node")
	wdcSerial := flag.String("wdcSerial", "", "serial device to connect to wdc")
	fwdSerial := flag.String("fwdSerial", "", "serial device to read and forward data from a real node") // TODO: enable list of serial interfaces
	nJamming := flag.Int("nJamming", 0, "number of sensors sending jamming data")
	nSensors := flag.Int("nSensors", 0, "number of sensors sending arbitrary data")
	secure := flag.Bool("sec", true, "apply security processing")
	flag.Parse()

	// check serial devices
	if *wdcSerial == "" {
		fmt.Println("serial connection to wdc is not provided")
		os.Exit(1)
	}

	// register interrupt signal
	intrCh := make(chan os.Signal)
	signal.Notify(intrCh, os.Interrupt)

	// register total nodes and corresponding handler goroutines
	mapNodes := make(map[int]node)
	for i := 0; i < *nJamming; i++ {
		mapNodes[i] = node{app.DoSendJamming, ""}
	}
	for i := *nJamming; i < *nJamming+*nSensors; i++ {
		mapNodes[i] = node{app.DoSendData, ""}
	}
	if *fwdSerial != "" {
		mapNodes[*nJamming+*nSensors] = node{app.DoForwardData, *fwdSerial}
	}

	// configure serial device connecting to wdc
	siface := &serial.Config{Name: *wdcSerial, Baud: 9600}
	serReader, err := serial.OpenPort(siface)
	if err != nil {
		fmt.Println("error opening serial interface:", err.Error())
		os.Exit(1)
	}
	defer serReader.Close()
	ser := SerialReader{serReader}
	wdcCh := devreader.MakeChannel(ser)

	for addr, curnode := range mapNodes {
		// if nodeSerial is used, we just need one passthrough goroutine
		if *nodeSerial != "" {
			dlCh := make(chan []byte)
			ulCh := make(chan []byte)
			go worker.DoSerialDataRequest(dlCh, ulCh, *nodeSerial)
			break
		}

		// otherwise, start one goroutine per node
		go func(addr int, curnode node) {
			nodeAddr := make([]byte, 2)
			binary.LittleEndian.PutUint16(nodeAddr, uint16(addr))

			// channel for receiving wdc message
			nodeWdcCh := make(chan []byte)
			nodeWdcChannels = append(nodeWdcChannels, nodeWdcCh)

			// channels for node's processing goroutine
			dlCh := make(chan []byte)
			ulCh := make(chan []byte)
			chPool = append(chPool, ulCh)

			// channels for node's application goroutine
			appDlCh := make(chan []byte)
			appUlCh := make(chan []byte)

			// channel for sharing data between worker and app
			crossCh := make(chan []byte)

			go curnode.appFunction(appDlCh, appUlCh, crossCh, curnode.device)
			go worker.DoDataRequest(nodeAddr, dlCh, ulCh, appDlCh, appUlCh, crossCh, *secure)

		LOOP:
			for {
				select {
				case wdcReq, more := <-nodeWdcCh:
					if !more {
						close(dlCh)
						break LOOP
					}

					reqmsg := worker.WDC_REQ{}
					reqmsg.ParseWDCReq([]byte(wdcReq))
					if bytes.Equal(reqmsg.DSTADDR, nodeAddr) || bytes.Equal(reqmsg.DSTADDR, []byte{0xff, 0xff}) { // only process message that is sent to us or broadcast
						dlCh <- []byte(wdcReq)
					}

				case nodeInd := <-ulCh:
					mutex.Lock()
					serReader.Write(nodeInd) // ignore error on wdc serial write
					mutex.Unlock()
					fmt.Println("sent node uplink message")
				}
			}
			fmt.Println("node stopped")
		}(addr, curnode)
	}

MAINLOOP:
	for {
		select {
		case wdcReq := <-wdcCh:
			go func() { // process wdc message in a separate goroutine
				wdcRes := worker.ProcessMessage(wdcReq)
				if wdcRes != nil {
					mutex.Lock()
					serReader.Write(wdcRes) // ignore error on wdc serial write
					mutex.Unlock()
					fmt.Println("sent answer to WDC request")
				}
			}()

			// if MAC_DATA_REQUEST, pass it to node goroutines
			if len(wdcReq) != 0 && wdcReq[1] == 0x17 {
				for _, ch := range nodeWdcChannels {
					ch <- wdcReq
				}
			}

		case <-intrCh:
			for idx := range nodeWdcChannels {
				close(nodeWdcChannels[idx])
				<-chPool[idx]
			}
			break MAINLOOP
		}
	}
	fmt.Println("program stopped")
}