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