$treeview $search $mathjax $extrastylesheet
otsdaq_utilities
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 // MF_ReceiveAndForward.cpp 00002 // by rrivera at fnal dot gov 00003 // created Feb 2016 00004 // 00005 // This is a simple UDP receive and forward program 00006 // for MessageFacility packets. 00007 // 00008 // It echos packets received and only appends '|' as decoration. 00009 // 00010 // 00011 // 00012 // 00013 // compile with: 00014 // g++ MF_ReceiveAndForward.cpp -o MF_ReceiveAndForward.o 00015 // 00016 // if developing, consider appending -D_GLIBCXX_DEBUG to get more 00017 // descriptive error messages 00018 // 00019 // run with: 00020 //./MF_ReceiveAndForward.o <optional port file name> 00021 // 00022 // 00023 // Port Config File Format: 00024 // RECEIVING_PORT <port number> 00025 // FORWARDING_PORT <port number> 00026 // 00027 // 00028 00029 #include <arpa/inet.h> 00030 #include <errno.h> 00031 #include <netdb.h> 00032 #include <netinet/in.h> 00033 #include <stdio.h> 00034 #include <stdlib.h> 00035 #include <string.h> 00036 #include <sys/socket.h> 00037 #include <sys/types.h> 00038 #include <unistd.h> 00039 #include <iostream> 00040 00041 using namespace std; 00042 00043 #define MAXBUFLEN 5000 00044 00045 // get sockaddr, IPv4 or IPv6: 00046 void* get_in_addr(struct sockaddr* sa) 00047 { 00048 if(sa->sa_family == AF_INET) 00049 { 00050 return &(((struct sockaddr_in*)sa)->sin_addr); 00051 } 00052 00053 return &(((struct sockaddr_in6*)sa)->sin6_addr); 00054 } 00055 00056 int makeSocket(const char* ip, int port, struct addrinfo*& p) 00057 { 00058 int sockfd; 00059 struct addrinfo hints, *servinfo; 00060 int rv; 00061 int numbytes; 00062 struct sockaddr_storage their_addr; 00063 socklen_t addr_len; 00064 char s[INET6_ADDRSTRLEN]; 00065 00066 memset(&hints, 0, sizeof hints); 00067 hints.ai_family = AF_UNSPEC; 00068 hints.ai_socktype = SOCK_DGRAM; 00069 char portStr[10]; 00070 sprintf(portStr, "%d", port); 00071 if((rv = getaddrinfo(ip, portStr, &hints, &servinfo)) != 0) 00072 { 00073 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 00074 return 1; 00075 } 00076 00077 // loop through all the results and make a socket 00078 for(p = servinfo; p != NULL; p = p->ai_next) 00079 { 00080 if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 00081 { 00082 perror("sw: socket"); 00083 continue; 00084 } 00085 00086 break; 00087 } 00088 00089 if(p == NULL) 00090 { 00091 fprintf(stderr, "sw: failed to create socket\n"); 00092 return 2; 00093 } 00094 00095 freeaddrinfo(servinfo); 00096 00097 return sockfd; 00098 } 00099 00100 int main(int argc, char** argv) 00101 { 00102 std::cout << "\n\n" << __FILE__ << "\tStarting...\n\n" << std::endl; 00103 00104 std::string myPort_("3000"); // set default 00105 std::string myFwdPort_("3001"); // set default 00106 std::string myFwdIP_("127.0.0.1"); // set default 00107 if(argc >= 2) 00108 { 00109 std::cout << "\n\n" 00110 << __FILE__ << "\t port parameter file:" << argv[1] << "\n\n" 00111 << std::endl; 00112 FILE* fp = fopen(argv[1], "r"); 00113 if(fp) 00114 { 00115 char tmp[100]; 00116 char tmpParamStr[100]; 00117 fgets(tmp, 100, fp); 00118 sscanf(tmp, "%*s %s", tmpParamStr); 00119 myPort_ = tmpParamStr; 00120 fgets(tmp, 100, fp); 00121 sscanf(tmp, "%*s %s", tmpParamStr); 00122 myFwdPort_ = tmpParamStr; 00123 fgets(tmp, 100, fp); 00124 sscanf(tmp, "%*s %s", tmpParamStr); 00125 myFwdIP_ = tmpParamStr; 00126 fclose(fp); 00127 } 00128 else // else use defaults 00129 std::cout << "\n\n" 00130 << __FILE__ << "\t port parameter file failed to open: " << argv[1] 00131 << "\n\n" 00132 << std::endl; 00133 } 00134 std::cout << "\n\n" 00135 << __FILE__ << "\t Forwarding from: " << myPort_ << " to: " << myFwdIP_ 00136 << ":" << myFwdPort_ << "\n\n" 00137 << std::endl; 00138 00139 int myFwdPort; 00140 sscanf(myFwdPort_.c_str(), "%d", &myFwdPort); 00141 00142 int sockfd; 00143 int sendSockfd = 0; 00144 00145 struct addrinfo hints, *servinfo, *p; 00146 int rv; 00147 int numbytes; 00148 struct sockaddr_storage their_addr; 00149 char buff[MAXBUFLEN]; 00150 socklen_t addr_len; 00151 char s[INET6_ADDRSTRLEN]; 00152 00153 memset(&hints, 0, sizeof hints); 00154 hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4 00155 hints.ai_socktype = SOCK_DGRAM; 00156 hints.ai_flags = AI_PASSIVE; // use my IP 00157 00158 if((rv = getaddrinfo(NULL, myPort_.c_str(), &hints, &servinfo)) != 0) 00159 { 00160 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 00161 return 1; 00162 } 00163 00164 // loop through all the results and bind to the first we can 00165 for(p = servinfo; p != NULL; p = p->ai_next) 00166 { 00167 if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 00168 { 00169 perror("listener: socket"); 00170 continue; 00171 } 00172 00173 if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) 00174 { 00175 close(sockfd); 00176 perror("listener: bind"); 00177 continue; 00178 } 00179 00180 break; 00181 } 00182 00183 if(p == NULL) 00184 { 00185 fprintf(stderr, "listener: failed to bind socket\n"); 00186 return 2; 00187 } 00188 00189 freeaddrinfo(servinfo); 00190 00194 00195 // hardware "registers" 00196 uint64_t data_gen_cnt = 0; 00197 uint64_t data_gen_rate = 1 << 16; 00198 uint8_t dataEnabled = 0; 00199 00200 const unsigned int RX_ADDR_OFFSET = 2; 00201 const unsigned int RX_DATA_OFFSET = 10; 00202 const unsigned int TX_DATA_OFFSET = 2; 00203 00204 unsigned int packetSz; 00205 00206 // for timeout/select 00207 struct timeval tv; 00208 fd_set readfds, masterfds; 00209 tv.tv_sec = 0; 00210 tv.tv_usec = 500000; 00211 FD_ZERO(&masterfds); 00212 FD_SET(sockfd, &masterfds); 00213 00214 time_t count = 0; 00215 00216 int mf_p, mf_i, mf_j; // for extracting message 00217 const int MF_POS_OF_TYPE = 5; 00218 const int MF_POS_OF_MSG = 11; 00219 bool firstPartPresent; 00220 00221 // this should ip/port of Console xdaq app Receiver port 00222 sendSockfd = makeSocket(myFwdIP_.c_str(), myFwdPort, p); 00223 00224 while(1) 00225 { 00226 readfds = masterfds; // copy to reset timeout select 00227 select(sockfd + 1, &readfds, NULL, NULL, &tv); 00228 00229 if(FD_ISSET(sockfd, &readfds)) 00230 { 00231 // packet received 00232 // cout << "hw: Line " << __LINE__ << ":::" << "Packet Received!" << endl; 00233 00234 addr_len = sizeof their_addr; 00235 if((numbytes = recvfrom(sockfd, 00236 buff, 00237 MAXBUFLEN - 1, 00238 0, 00239 (struct sockaddr*)&their_addr, 00240 &addr_len)) == -1) 00241 { 00242 perror("recvfrom"); 00243 exit(1); 00244 } 00245 00246 // printf("hw: got packet from %s\n", 00247 // inet_ntop(their_addr.ss_family, 00248 // get_in_addr((struct sockaddr *)&their_addr), 00249 // s, sizeof s)); 00250 // printf("hw: packet is %d bytes long\n", numbytes); 00251 // printf("packet contents: "); 00252 // 00253 // for(int i=0;i<numbytes;++i) 00254 // { 00255 // if((i-RX_ADDR_OFFSET)%8==0) printf("\n"); 00256 // printf("%2.2X", (unsigned char)buff[i]); 00257 // } 00258 // printf("\n"); 00259 00260 // print message without decoration 00261 // find position of message and save to p 00262 // by jumping to the correct '|' marker 00263 buff[numbytes] = '\0'; // make sure it is null terminated 00264 00265 // DEBUG -- for indentifying strange MessageFacility bug with clipped messages 00266 // std::cout << "+" << ((int)strlen(buff)==numbytes?1:0) << " " << buff << 00267 // std::endl; if((int)strlen(buff)!=numbytes) 00268 // { 00269 // for(int iii=strlen(buff)-3;iii<numbytes;++iii) 00270 // std::cout << (int)buff[iii] << "-" << (char)buff[iii] << " 00271 //"; std::cout << numbytes << " " << strlen(buff) << std::endl; 00272 // std::cout << std::endl; 00273 // } 00274 00275 // count markers to find message 00276 00277 // std::cout << "|||" << buff << std::endl; // show all 00278 00279 for(mf_p = 0, mf_i = 0; mf_i < numbytes && mf_p < MF_POS_OF_TYPE; ++mf_i) 00280 if(buff[mf_i] == '|') 00281 ++mf_p; // count markers 00282 00283 for(mf_j = mf_i; mf_j < numbytes && mf_p < MF_POS_OF_TYPE + 1; ++mf_j) 00284 if(buff[mf_j] == '|') 00285 ++mf_p; // count markers 00286 00287 // print first part (message type) 00288 if(mf_i < mf_j && mf_j < numbytes) 00289 { 00290 buff[mf_j - 1] = '\0'; 00291 std::cout << &buff[mf_i - 1]; 00292 00293 // tab for all types but Warning 00294 if(strcmp(&buff[mf_i - 1], "|Warning") != 0) 00295 std::cout << "\t"; 00296 00297 firstPartPresent = true; 00298 } 00299 else 00300 firstPartPresent = false; 00301 00302 for(mf_i = mf_j; mf_i < numbytes && mf_p < MF_POS_OF_MSG; ++mf_i) 00303 if(buff[mf_i] == '|') 00304 ++mf_p; // count markers 00305 00306 // print second part 00307 if(mf_i < numbytes) // if valid find, show message 00308 std::cout << &buff[mf_i - 1] << std::endl; // show msg after '|' 00309 else if(firstPartPresent) 00310 std::cout << std::endl; 00311 00312 // forward packet onto sendSockfd 00313 00314 if((numbytes = sendto( 00315 sendSockfd, buff, numbytes, 0, p->ai_addr, p->ai_addrlen)) == -1) 00316 { 00317 perror("hw: sendto"); 00318 exit(1); 00319 } 00320 // printf("hw: sent %d bytes on\n", numbytes); 00321 } 00322 else 00323 sleep(1); // one second 00324 } 00325 00326 close(sockfd); 00327 close(sendSockfd); 00328 00329 return 0; 00330 }