otsdaq_utilities  v2_02_00
MF_ReceiveAndForward.cpp
1 //MF_ReceiveAndForward.cpp
2 // by rrivera at fnal dot gov
3 // created Feb 2016
4 //
5 // This is a simple UDP receive and forward program
6 // for MessageFacility packets.
7 //
8 // It echos packets received and only appends '|' as decoration.
9 //
10 //
11 //
12 //
13 //compile with:
14 //g++ MF_ReceiveAndForward.cpp -o MF_ReceiveAndForward.o
15 //
16 //if developing, consider appending -D_GLIBCXX_DEBUG to get more
17 //descriptive error messages
18 //
19 //run with:
20 //./MF_ReceiveAndForward.o <optional port file name>
21 //
22 //
23 // Port Config File Format:
24 // RECEIVING_PORT <port number>
25 // FORWARDING_PORT <port number>
26 //
27 //
28 
29 #include <iostream>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #include <netdb.h>
40 
41 
42 using namespace std;
43 
44 
45 #define MAXBUFLEN 5000
46 
47 // get sockaddr, IPv4 or IPv6:
48 void *get_in_addr(struct sockaddr *sa)
49 {
50  if (sa->sa_family == AF_INET) {
51  return &(((struct sockaddr_in*)sa)->sin_addr);
52  }
53 
54  return &(((struct sockaddr_in6*)sa)->sin6_addr);
55 }
56 
57 int makeSocket(const char * ip, int port, struct addrinfo*& p)
58 {
59  int sockfd;
60  struct addrinfo hints, *servinfo;
61  int rv;
62  int numbytes;
63  struct sockaddr_storage their_addr;
64  socklen_t addr_len;
65  char s[INET6_ADDRSTRLEN];
66 
67  memset(&hints, 0, sizeof hints);
68  hints.ai_family = AF_UNSPEC;
69  hints.ai_socktype = SOCK_DGRAM;
70  char portStr[10];
71  sprintf(portStr,"%d",port);
72  if ((rv = getaddrinfo(ip, portStr, &hints, &servinfo)) != 0) {
73  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
74  return 1;
75  }
76 
77  // loop through all the results and make a socket
78  for(p = servinfo; p != NULL; p = p->ai_next) {
79  if ((sockfd = socket(p->ai_family, p->ai_socktype,
80  p->ai_protocol)) == -1) {
81  perror("sw: socket");
82  continue;
83  }
84 
85  break;
86  }
87 
88  if (p == NULL) {
89  fprintf(stderr, "sw: failed to create socket\n");
90  return 2;
91  }
92 
93  freeaddrinfo(servinfo);
94 
95  return sockfd;
96 }
97 
98 int main(int argc, char** argv)
99 {
100  std::cout << "\n\n" << __FILE__ << "\tStarting...\n\n" << std::endl;
101 
102  std::string myPort_("3000"); //set default
103  std::string myFwdPort_("3001"); //set default
104  std::string myFwdIP_("127.0.0.1"); //set default
105  if(argc >= 2)
106  {
107  std::cout << "\n\n" << __FILE__ << "\t port parameter file:" <<
108  argv[1] << "\n\n" << std::endl;
109  FILE *fp = fopen(argv[1],"r");
110  if(fp)
111  {
112  char tmp[100];
113  char tmpParamStr[100];
114  fgets(tmp,100,fp);
115  sscanf(tmp,"%*s %s",tmpParamStr);
116  myPort_ = tmpParamStr;
117  fgets(tmp,100,fp);
118  sscanf(tmp,"%*s %s",tmpParamStr);
119  myFwdPort_ = tmpParamStr;
120  fgets(tmp,100,fp);
121  sscanf(tmp,"%*s %s",tmpParamStr);
122  myFwdIP_ = tmpParamStr;
123  fclose(fp);
124  }
125  else //else use defaults
126  std::cout << "\n\n" << __FILE__ << "\t port parameter file failed to open: " <<
127  argv[1] << "\n\n" << std::endl;
128 
129  }
130  std::cout << "\n\n" << __FILE__ << "\t Forwarding from: " << myPort_ <<
131  " to: " << myFwdIP_ << ":" << myFwdPort_ << "\n\n" << std::endl;
132 
133  int myFwdPort;
134  sscanf(myFwdPort_.c_str(),"%d",&myFwdPort);
135 
136  int sockfd;
137  int sendSockfd=0;
138 
139  struct addrinfo hints, *servinfo, *p;
140  int rv;
141  int numbytes;
142  struct sockaddr_storage their_addr;
143  char buff[MAXBUFLEN];
144  socklen_t addr_len;
145  char s[INET6_ADDRSTRLEN];
146 
147  memset(&hints, 0, sizeof hints);
148  hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
149  hints.ai_socktype = SOCK_DGRAM;
150  hints.ai_flags = AI_PASSIVE; // use my IP
151 
152  if ((rv = getaddrinfo(
153  NULL,
154  myPort_.c_str(),
155  &hints,
156  &servinfo)) != 0)
157  {
158  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
159  return 1;
160  }
161 
162  // loop through all the results and bind to the first we can
163  for(p = servinfo; p != NULL; p = p->ai_next) {
164  if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
165  perror("listener: socket");
166  continue;
167  }
168 
169  if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
170  close(sockfd);
171  perror("listener: bind");
172  continue;
173  }
174 
175  break;
176  }
177 
178  if (p == NULL) {
179  fprintf(stderr, "listener: failed to bind socket\n");
180  return 2;
181  }
182 
183  freeaddrinfo(servinfo);
184 
188 
189 
190 
191 
192  //hardware "registers"
193  uint64_t data_gen_cnt = 0;
194  uint64_t data_gen_rate = 1<<16;
195  uint8_t dataEnabled = 0;
196 
197  const unsigned int RX_ADDR_OFFSET = 2;
198  const unsigned int RX_DATA_OFFSET = 10;
199  const unsigned int TX_DATA_OFFSET = 2;
200 
201  unsigned int packetSz;
202 
203  //for timeout/select
204  struct timeval tv;
205  fd_set readfds, masterfds;
206  tv.tv_sec = 0;
207  tv.tv_usec = 500000;
208  FD_ZERO(&masterfds);
209  FD_SET(sockfd, &masterfds);
210 
211  time_t count = 0;
212 
213  int mf_p,mf_i,mf_j; //for extracting message
214  const int MF_POS_OF_TYPE = 5;
215  const int MF_POS_OF_MSG = 11;
216  bool firstPartPresent;
217 
218  //this should ip/port of Console xdaq app Receiver port
219  sendSockfd = makeSocket(myFwdIP_.c_str(), myFwdPort, p);
220 
221  while(1)
222  {
223  readfds = masterfds; //copy to reset timeout select
224  select(sockfd+1, &readfds, NULL, NULL, &tv);
225 
226  if (FD_ISSET(sockfd, &readfds))
227  {
228  //packet received
229  //cout << "hw: Line " << __LINE__ << ":::" << "Packet Received!" << endl;
230 
231  addr_len = sizeof their_addr;
232  if ((numbytes = recvfrom(sockfd, buff, MAXBUFLEN-1 , 0,
233  (struct sockaddr *)&their_addr, &addr_len)) == -1) {
234  perror("recvfrom");
235  exit(1);
236  }
237 
238  // printf("hw: got packet from %s\n",
239  // inet_ntop(their_addr.ss_family,
240  // get_in_addr((struct sockaddr *)&their_addr),
241  // s, sizeof s));
242  // printf("hw: packet is %d bytes long\n", numbytes);
243  // printf("packet contents: ");
244  //
245  // for(int i=0;i<numbytes;++i)
246  // {
247  // if((i-RX_ADDR_OFFSET)%8==0) printf("\n");
248  // printf("%2.2X", (unsigned char)buff[i]);
249  // }
250  // printf("\n");
251 
252 
253 
254 
255 
256 
257  //print message without decoration
258  //find position of message and save to p
259  //by jumping to the correct '|' marker
260  buff[numbytes] = '\0'; //make sure it is null terminated
261 
262  //DEBUG -- for indentifying strange MessageFacility bug with clipped messages
263  //std::cout << "+" << ((int)strlen(buff)==numbytes?1:0) << " " << buff << std::endl;
264  // if((int)strlen(buff)!=numbytes)
265  // {
266  // for(int iii=strlen(buff)-3;iii<numbytes;++iii)
267  // std::cout << (int)buff[iii] << "-" << (char)buff[iii] << " ";
268  // std::cout << numbytes << " " << strlen(buff) << std::endl;
269  // std::cout << std::endl;
270  // }
271 
272  //count markers to find message
273 
274  //std::cout << "|||" << buff << std::endl; // show all
275 
276  for(mf_p=0,mf_i=0;mf_i<numbytes && mf_p<MF_POS_OF_TYPE;++mf_i)
277  if(buff[mf_i] == '|') ++mf_p; //count markers
278 
279  for(mf_j=mf_i;mf_j<numbytes && mf_p<MF_POS_OF_TYPE+1;++mf_j)
280  if(buff[mf_j] == '|') ++mf_p; //count markers
281 
282  //print first part (message type)
283  if(mf_i<mf_j && mf_j<numbytes)
284  {
285  buff[mf_j-1] = '\0';
286  std::cout << &buff[mf_i-1];
287 
288  //tab for all types but Warning
289  if(strcmp(&buff[mf_i-1],"|Warning") != 0)
290  std::cout << "\t";
291 
292  firstPartPresent = true;
293  }
294  else
295  firstPartPresent = false;
296 
297  for(mf_i=mf_j;mf_i<numbytes && mf_p<MF_POS_OF_MSG;++mf_i)
298  if(buff[mf_i] == '|') ++mf_p; //count markers
299 
300  //print second part
301  if(mf_i<numbytes) //if valid find, show message
302  std::cout << &buff[mf_i-1] << std::endl; // show msg after '|'
303  else if(firstPartPresent)
304  std::cout << std::endl;
305 
306 
307 
308 
309 
310 
311  //forward packet onto sendSockfd
312 
313  if ((numbytes = sendto(sendSockfd, buff, numbytes, 0, p->ai_addr, p->ai_addrlen)) == -1) {
314  perror("hw: sendto");
315  exit(1);
316  }
317  //printf("hw: sent %d bytes on\n", numbytes);
318 
319  }
320  else
321  sleep(1); //one second
322  }
323 
324  close(sockfd);
325  close(sendSockfd);
326 
327  return 0;
328 }
329