otsdaq_demo  v2_05_02_indev
udp_data_emulator.cpp
1 // This is a simple emulator of a "data gen" front-end (hardware) interface
2 // using the otsdaq UDP protocol.
3 //
4 // compile with:
5 // g++ udp_data_emulator.cpp -o test.o
6 //
7 // if developing, consider appending -D_GLIBCXX_DEBUG to get more
8 // descriptive error messages
9 //
10 // run with:
11 //./hw.o
12 //
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
18 #include <unistd.h>
19 #include <fstream>
20 #include <iomanip>
21 #include <iostream>
22 #include <sstream>
23 
24 #include <arpa/inet.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <netdb.h>
29 #include <netinet/in.h>
30 #include <sys/mman.h>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 
34 //#define ZED_IP "192.168.133.6" // the ZED IP users will be connecting to
35 //#define ZED_IP "192.168.133.5" // the ZED IP users will be connecting to
36 #define COMMUNICATION_PORT "2035" // the port on ZedBoard for communicating with XDAQ
37 #define STREAMING_PORT "2036" // the port on ZedBoard for streaming to XDAQ
38 #define DESTINATION_IP "192.168.133.5" // the IP for the destination of the datastream
39 #define DESTINATION_PORT 2039 // the port for the destination of the datastream
40 #define MAXBUFLEN 1492
41 
42 //========================================================================================================================
43 // get sockaddr, IPv4 or IPv6:
44 void* get_in_addr(struct sockaddr* sa)
45 {
46  if(sa->sa_family == AF_INET)
47  {
48  return &(((struct sockaddr_in*)sa)->sin_addr);
49  }
50 
51  return &(((struct sockaddr_in6*)sa)->sin6_addr);
52 }
53 
54 //========================================================================================================================
55 int makeSocket(const char* ip, const char* port, struct addrinfo*& /*addressInfo*/)
56 {
57  int socketId = 0;
58  struct addrinfo hints, *servinfo, *p;
59  //int sendSockfd = 0;
60  int rv;
61  //int numbytes;
62  //struct sockaddr_storage their_addr;
63  //char buff[MAXBUFLEN];
64  //socklen_t addr_len;
65  //char s[INET6_ADDRSTRLEN];
66 
67  memset(&hints, 0, sizeof hints);
68  // hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
69  hints.ai_family = AF_INET; // set to AF_INET to force IPv4
70  hints.ai_socktype = SOCK_DGRAM;
71  if(ip == NULL)
72  hints.ai_flags = AI_PASSIVE; // use my IP
73 
74  if((rv = getaddrinfo(ip, port, &hints, &servinfo)) != 0)
75  {
76  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
77  return 1;
78  }
79 
80  // loop through all the results and bind to the first we can
81  for(p = servinfo; p != NULL; p = p->ai_next)
82  {
83  if((socketId = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
84  {
85  perror("listener: socket");
86  continue;
87  }
88 
89  if(bind(socketId, p->ai_addr, p->ai_addrlen) == -1)
90  {
91  close(socketId);
92  perror("listener: bind");
93  continue;
94  }
95 
96  break;
97  }
98 
99  if(p == NULL)
100  {
101  fprintf(stderr, "listener: failed to bind socket\n");
102  return 2;
103  }
104  freeaddrinfo(servinfo);
105  return socketId;
106 }
107 
108 //========================================================================================================================
109 struct sockaddr_in setupSocketAddress(const char* ip, unsigned int port)
110 {
111  // std::cout << __PRETTY_FUNCTION__ << std::endl;
112  // network stuff
113  struct sockaddr_in socketAddress;
114  socketAddress.sin_family = AF_INET; // use IPv4 host byte order
115  socketAddress.sin_port = htons(port); // short, network byte order
116 
117  if(inet_aton(ip, &socketAddress.sin_addr) == 0)
118  {
119  std::cout << "FATAL: Invalid IP address " << ip << std::endl;
120  exit(0);
121  }
122 
123  memset(&(socketAddress.sin_zero), '\0', 8); // zero the rest of the struct
124  return socketAddress;
125 }
126 
127 //========================================================================================================================
128 int send(int toSocket, struct sockaddr_in& toAddress, const std::string& buffer)
129 {
130  std::cout << "Socket Descriptor #: " << toSocket << " ip: " << std::hex
131  << toAddress.sin_addr.s_addr << std::dec
132  << " port: " << ntohs(toAddress.sin_port) << std::endl;
133  if(sendto(toSocket,
134  buffer.c_str(),
135  buffer.size(),
136  0,
137  (struct sockaddr*)&(toAddress),
138  sizeof(sockaddr_in)) < (int)(buffer.size()))
139  {
140  std::cout << "Error writing buffer" << std::endl;
141  return -1;
142  }
143  return 0;
144 }
145 
146 //========================================================================================================================
147 int receive(int fromSocket, struct sockaddr_in& fromAddress, std::string& buffer)
148 {
149  struct timeval tv;
150  tv.tv_sec = 1;
151  tv.tv_usec = 0; // set timeout period for select()
152  fd_set fileDescriptor; // setup set for select()
153  FD_ZERO(&fileDescriptor);
154  FD_SET(fromSocket, &fileDescriptor);
155  select(fromSocket + 1, &fileDescriptor, 0, 0, &tv);
156 
157  if(FD_ISSET(fromSocket, &fileDescriptor))
158  {
159  std::string bufferS;
160  // struct sockaddr_in fromAddress;
161  socklen_t addressLength = sizeof(fromAddress);
162  int nOfBytes;
163  buffer.resize(MAXBUFLEN);
164  if((nOfBytes = recvfrom(fromSocket,
165  &buffer[0],
166  MAXBUFLEN,
167  0,
168  (struct sockaddr*)&fromAddress,
169  &addressLength)) == -1)
170  return -1;
171 
172  // Confirm you've received the message by returning message to sender
173  send(fromSocket, fromAddress, buffer);
174  buffer.resize(nOfBytes);
175  // char address[INET_ADDRSTRLEN];
176  // inet_ntop(AF_INET, &(fromAddress.sin_addr), address, INET_ADDRSTRLEN);
177  // unsigned long fromIPAddress = fromAddress.sin_addr.s_addr;
178  // unsigned short fromPort = fromAddress.sin_port;
179  }
180  else
181  return -1;
182 
183  return 0;
184 }
185 
186 //========================================================================================================================
187 int main(void)
188 {
190  // Bind UDP socket //
192 
193  // sendSockfd = makeSocket(string("localhost").c_str(),myport,p);
194 
195  struct addrinfo /*hints,*//* *servinfo,*/ *p;
196 
197  int communicationSocket = makeSocket(0, COMMUNICATION_PORT, p);
198  //int streamingSocket = makeSocket(0, STREAMING_PORT, p);
199  //struct sockaddr_in streamingReceiver = setupSocketAddress(DESTINATION_IP, DESTINATION_PORT);
200  struct sockaddr_in messageSender;
201 
202  std::string communicationBuffer;
203 
207 
208  std::cout << "Waiting for DAQ communication..." << std::endl;
209  bool triggered = false;
210  const unsigned ndata = 2 * 64;
211  unsigned count = 0;
212  while(1)
213  {
214  // std::cout << time(NULL)%60 << std::endl;
215  if(receive(communicationSocket, messageSender, communicationBuffer) >= 0)
216  {
217  std::cout << "Message received!!!" << std::endl;
218  std::cout << communicationBuffer << std::endl;
219 
220  if(communicationBuffer == "START")
221  {
222  triggered = true;
223  }
224  else if(communicationBuffer == "STOP")
225  {
226  std::cout << 4 * 66 * count << std::endl;
227  triggered = false;
228  count = 0;
229  }
230  }
231 
232  if(triggered)
233  {
234  unsigned simdata[ndata + 5];
235  simdata[0] = 0xFFFFFFFF;
236  simdata[1] = 0xFFFFFFFF;
237  simdata[2] = 0xFFFFFFFF;
238  simdata[3] = 0xFFFFFFFF;
239  simdata[4] = 0xFFFFFFFF;
240  // unsigned i_0 = 0x21;
241  for(unsigned i = 0; i < ndata; i++)
242  {
243  unsigned noise = rand() & 0x00FF00FF;
244  simdata[i + 5] = 0x00FF00FF + noise;
245 
246  std::cout << std::hex << std::setw(8) << std::setfill('0') << simdata[i]
247  << std::endl;
248  }
249 
250  // sendto(streamingSocket, simdata, sizeof(simdata), 0,
251  // (struct sockaddr *)&streamingReceiver,
252  // sizeof(streamingReceiver));
253  ++count;
254  }
255  usleep(1000);
256  }
257 
258  close(communicationSocket);
259 
260  return 0;
261 }