Fast Research Interface Library  Manual and Documentation
src/FastResearchInterfaceLibrary/friudp.cpp
Go to the documentation of this file.
00001 /*{{[PH]
00002 ****************************************************************************
00003  Project:  FRI
00004 
00005   This material is the exclusive property of KUKA Roboter GmbH 
00006   and must be returned to KUKA Roboter GmbH immediately upon 
00007   request.  This material and the information illustrated or 
00008   contained herein may not be used, reproduced, stored in a 
00009   retrieval system, or transmitted in whole or in part in any 
00010   way - electronic, mechanical, photocopying, recording, or 
00011   otherwise, without the prior written consent of KUKA Roboter GmbH.  
00012   
00013                  All Rights Reserved
00014                  Copyright (C)  2009
00015                   KUKA Roboter GmbH
00016                   Augsburg, Germany
00017   
00018 [PH]}}
00019 */
00020 
00021 /*
00022 {{[FH]
00023 ****************************************************************************
00024   friUdp.cpp
00025        
00026       NOTE: This sample, as the corresponding FRI (Fast Research inteface) is subject to radical change
00027       
00028       
00029 [FH]}}
00030 */ 
00031 
00032 /* @{ */
00033 
00039 #include "friudp.h"
00040 
00041 #ifdef WIN32
00042 #include <winsock2.h>
00043 #pragma comment(lib, "ws2_32.lib") 
00044 #endif // WIN32
00045 
00046 
00047 friUdp::friUdp(int port, char * remoteHost) : serverPort(port)
00048 {
00049        /* check struct sizes */
00050     if (!FRI_CHECK_SIZES_OK)
00051     {
00052         printf("data structure size error!\n");
00053         exit(1);
00054     }
00055 
00056     m_timestamp=0;
00057     // Make shure, that e.g. simulink uses no stupid standard definition - e.g. 0
00058     if ( serverPort < 10 )
00059     {
00060         serverPort=FRI_DEFAULT_SERVER_PORT; 
00061     }
00062 
00063 #ifdef WIN32
00064     StartWinsock();
00065 #endif
00066   Init(remoteHost);
00067 }
00068 
00069 
00070 friUdp::~friUdp()
00071 {
00072   Close();
00073 
00074 }
00075 
00076 #ifdef WIN32
00077 int friUdp::StartWinsock(void)
00078 {
00079     WSADATA WSAData;
00080     return WSAStartup(MAKEWORD(2,0), &WSAData);
00081 }
00082 #endif// WIN32
00083 
00084 void friUdp::Init(char * remoteHost)
00085 {
00086     struct sockaddr_in servAddr;
00087     m_timestamp = 0;
00088     memset(&servAddr, 0, sizeof(servAddr));
00089     memset(&krcAddr, 0, sizeof(krcAddr));
00090 
00091     /* socket creation */
00092     udpSock = socket(PF_INET, SOCK_DGRAM, 0);
00093     if (udpSock < 0)
00094     {
00095         printf("opening socket failed!\n");
00096         exit(1);
00097     }
00098 #ifdef HAVE_TIME_STAMP_RECEIVE
00099     {
00100         int temp = 1;
00101         if (setsockopt(udpSock, SOL_SOCKET, SO_TIMESTAMP, &temp, sizeof(int)) < 0)
00102         {
00103             printf("failed to enable receive time stamps\n");
00104             exit(1);
00105         }
00106     }
00107 #endif
00108     /* bind local server port */
00109     servAddr.sin_family = AF_INET;
00110     servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00111     servAddr.sin_port = htons(serverPort);
00112 
00113     if (bind(udpSock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
00114     {
00115         printf("binding port number %d failed!\n", serverPort);
00116         Close();
00117         exit(1);
00118     }
00119     // if the remote host is specified, 
00120     // preinitialize the socket properly
00121     if ( remoteHost ) 
00122     {
00123         printf("preinitialized remote host to %s\n",remoteHost);
00124         krcAddr.sin_addr.s_addr = inet_addr(remoteHost);
00125         krcAddr.sin_family = AF_INET;
00126         krcAddr.sin_port=htons(serverPort);     
00127     }
00128 
00129 
00130 #ifdef HAVE_GETHOSTNAME
00131     /* get IP(s) and port number and display them (just for
00132      convenience, so debugging friOpen is easier) */
00133     {
00134         char hostname[100];
00135         struct hostent * host;
00136         int i;
00137 
00138         gethostname(hostname, sizeof(hostname));
00139         host = gethostbyname(hostname);
00140         if (host != NULL)
00141         {
00142             for (i=0; host->h_addr_list[i]!=0; i++)
00143             {
00144                 struct in_addr addr;
00145                 memcpy(&addr, host->h_addr_list[i], sizeof(addr));
00146                 printf("IP %s - Port %d\n", inet_ntoa(addr), serverPort);
00147             }
00148         }
00149     }
00150 #endif // 
00151 
00152 
00153 }
00154 
00155 
00156 
00157 /* reveive one packet from KRC (blocking!) */
00158 int friUdp::Recv(tFriMsrData *packet)
00159 {
00160     if (udpSock >= 0)
00161     {
00162         int received;
00163         struct timeval ts;
00164         
00165         received = RecvPacket(udpSock, packet, &ts, &krcAddr);
00166 
00167         if (received == sizeof(tFriMsrData))
00168         {
00169 #ifdef HAVE_TIME_STAMP_RECEIVE
00170 
00171             /* FIXME: need another #ifdef for VxWorks */
00172 #ifdef QNX
00173             struct timespec ts;
00174             clock_gettime(CLOCK_REALTIME, &ts);
00175             m_timestamp = (double)ts.tv_sec + (double)ts.tv_nsec/1.0e9;
00176 #else
00177             m_timestamp = (double)ts.tv_sec + (double)ts.tv_usec/1.0e6;
00178 #endif // QNX
00179 #endif // HAVE_TIME_STAMP
00180             return 0;
00181         }
00182         else
00183         {
00184             printf("received something, but wrong size %d (expected %d)...\n",received, (int)sizeof(tFriMsrData));
00185             fflush(stdout);
00186         }
00187     }
00188     memset(packet, 0, sizeof(tFriMsrData));
00189     return -1;
00190 }
00191 
00192 
00193 
00194 /* send one answer packet to KRC */
00195 int friUdp::Send(tFriCmdData *data)
00196 {
00197     krcAddr.sin_family = AF_INET;
00198 #ifdef KRC_IP_ADDRESS
00199     krcAddr.sin_addr.s_addr = inet_addr(KRC_IP_ADDRESS);
00200 #endif
00201 #ifdef KRC_RECEIVE_PORT
00202     krcAddr.sin_port = htons(KRC_RECEIVE_PORT);
00203 #endif
00204 
00205     if ((udpSock >= 0) && (ntohs(krcAddr.sin_port) != 0))
00206     {
00207         int sent;
00208         sent = sendto(udpSock, (char *) data, sizeof(tFriCmdData), 0,
00209                       (struct sockaddr *)&krcAddr, sizeof(krcAddr));
00210         if (sent == sizeof(tFriCmdData))
00211         {
00212             return 0;
00213         }
00214     }
00215     return -1;
00216 }
00217 
00218 
00219 
00220 
00221 /* close the socket */
00222 void friUdp::Close(void)
00223 {
00224     if (udpSock >= 0)
00225     {
00226 #ifdef WIN32
00227         closesocket(udpSock); 
00228         WSACleanup(); 
00229 #else
00230         close(udpSock);
00231 #endif
00232     }
00233     udpSock = -1;
00234 }
00235 
00236 
00237 #ifdef HAVE_TIME_STAMP_RECEIVE
00238 // Socket option SO_TIMESTAMP is supported 
00239 /* receive with timestamp  */
00240 int friUdp::RecvPacket(int fd, tFriMsrData* p, struct timeval* ts, struct sockaddr_in* client) 
00241 {
00242         struct msghdr msg;
00243         struct iovec vec[1];
00244         union {
00245                 struct cmsghdr cm;
00246                 char control[20];
00247         } cmsg_un;
00248         struct cmsghdr *cmsg;
00249         struct timeval *tv = NULL;
00250         int n;
00251         
00252         vec[0].iov_base = p;
00253         vec[0].iov_len = sizeof(*p);
00254         
00255         memset(&msg, 0, sizeof(msg));
00256         memset(&cmsg_un, 0, sizeof(cmsg_un));
00257         
00258         msg.msg_name = (caddr_t)client;
00259         if(client)
00260                 msg.msg_namelen = sizeof(*client);
00261         else
00262                 msg.msg_namelen = 0;
00263         msg.msg_iov = vec;
00264         msg.msg_iovlen = 1;
00265         msg.msg_control = cmsg_un.control;
00266         msg.msg_controllen = sizeof(cmsg_un.control);
00267         msg.msg_flags = 0;
00268         
00269         n = recvmsg(fd, &msg, 0); // MSG_DONTWAIT
00270         if(n < 0) {
00271                 perror("recvmsg");
00272                 return -1;
00273         }
00274         if(msg.msg_flags & MSG_TRUNC) {
00275                 printf("received truncated message\n");
00276                 return -1;
00277         }
00278         if(!ts)
00279                 return n;
00280 
00281         /* get time stamp of packet */
00282         if(msg.msg_flags & MSG_CTRUNC) {
00283                 printf("received truncated ancillary data\n");
00284                 return -1;
00285         }
00286         if(msg.msg_controllen < sizeof(cmsg_un.control)) {
00287                 printf("received short ancillary data (%d/%d)\n", msg.msg_controllen, (int)sizeof(cmsg_un.control));
00288                 return -1;
00289         }
00290         for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
00291                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_TIMESTAMP)
00292                         tv = (struct timeval *)CMSG_DATA(cmsg);
00293         }
00294         if(tv) {
00295             ts->tv_sec = tv->tv_sec;
00296             ts->tv_usec = tv->tv_usec;
00297         }
00298         return n;
00299 }
00300 
00301 #else
00302 /* receive with timestamp  */
00303 int friUdp::RecvPacket(int udpSock, tFriMsrData* data, struct timeval* ts, struct sockaddr_in* client) 
00304 {
00305 
00306       if (udpSock >= 0)
00307     {
00308 #ifdef WIN32
00309           int sockAddrSize = sizeof(struct sockaddr_in);
00310 #else
00311           socklen_t sockAddrSize = sizeof(struct sockaddr_in);
00312 #endif
00313 
00314         int received;
00315         
00316         received = recvfrom(udpSock, (char *) data, sizeof(tFriMsrData), 0,
00317                             (struct sockaddr *)&krcAddr, &sockAddrSize);
00318 
00319     return received;
00320       }
00321       return -1;
00322 }
00323 
00324 #endif // HAVE_TIME_STAMP_RECEIVE
00325 
00326 
00327 #ifdef VXWORKS //USE_BERKELEY_PACKAGE_FILTER_VXWORKS
00328 #define DEBUG_BPF_READ
00329 
00330 #include "vxworks.h" 
00331 #include "bpfDrv.h" 
00332 #include "ioLib.h"
00333 #include <logLib.h> 
00334 #include <sys/ioctl.h>
00335 //#include "drv/netif/smNetLib.h"
00336 #include <wrn/coreip/net/ethernet.h> 
00337 #include <wrn/coreip/net/if.h>
00338 #include <wrn/coreip/netinet/ip.h>
00339 #include <wrn/coreip/netinet/udp.h>
00340 
00341 #ifdef DEBUG_BPF_READ
00342 #include <iostream>
00343 #include "friremote.h"
00344 
00345 #endif
00346  
00347 
00348 /*
00349  * Packet filter program...
00350  *
00351  * XXX: Changes to the filter program may require changes to the
00352  * constant offsets used in if_register_send to patch the BPF program!
00353  */
00354 struct bpf_insn friUpdSock_bpf_filter[] = {
00355     /* Make sure this is an IP packet... */
00356     BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
00357     BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
00358 
00359     /* Make sure it's a UDP packet... */
00360     BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
00361     BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
00362 
00363     /* Make sure this isn't a fragment... */
00364     BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
00365     BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
00366 
00367     /* Get the IP header length... */
00368     BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
00369 
00370     /* Make sure it's to the right port... */
00371     BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),
00372     BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),      /* patch */
00373 
00374     /* If we passed all the tests, ask for the whole packet. */
00375     BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
00376 
00377     /* Otherwise, drop it. */
00378     BPF_STMT(BPF_RET+BPF_K, 0),
00379 };
00380 
00381 int friUpdSock_bpf_filter_len = sizeof(friUpdSock_bpf_filter) / sizeof(struct bpf_insn);
00382 struct bpf_program  mybpf;
00383 
00384 
00385 void testBPF1(int socketPort, char * devName) 
00386 { 
00387 
00388   int bpffd = 0; 
00389   struct bpf_hdr * buf = NULL; 
00390   char * pbuffer = NULL; 
00391   int buflen; 
00392   int len,i; 
00394   char dev[8] = "gei0"; 
00395   struct ifreq ifr; 
00396   int trueValue=1; 
00397   int Rcvlen; 
00398  
00399     if ( socketPort <= 10) socketPort = 12345;
00400     if ( devName != NULL )
00401     {
00402         strncpy(dev,devName,8);
00403         dev[8]=0;
00404     }
00405   mybpf.bf_len = friUpdSock_bpf_filter_len; 
00406   mybpf.bf_insns = friUpdSock_bpf_filter; 
00407  
00408 
00409   /* Patch the server port into the BPF program...
00410        *
00411        * XXX: changes to filter program may require changes to the
00412        * insn number(s) used below!
00413        */
00414   friUpdSock_bpf_filter[8].k = socketPort;
00415 
00416   bpfDrv();
00417  
00418   if ( bpfDevCreate("/dev/bpf",2,4096) == ERROR)
00419   {
00420     printf("bpfDevCreate failed \n");
00421     return;
00422   }
00423   bpffd = open( "/dev/bpf0",0,0);
00424   if ( bpffd <= 0)
00425     {
00426         printf("open /dev/bpf0 failed\n");
00427         return;
00428     }
00429  
00430   memset(&ifr, sizeof(struct ifreq), 0); 
00431   strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); 
00432  #define IOCTRL_CAST_THIRD_ARG (int)
00433  
00434  
00435  
00436     if (ioctl(bpffd,BIOCIMMEDIATE, IOCTRL_CAST_THIRD_ARG &trueValue) < 0) 
00437    { 
00438     printf("Error BIOCIMMEDIATE \n");
00439  
00440   }    
00441  
00442  
00443  
00444   if (ioctl(bpffd,(BIOCSETF),IOCTRL_CAST_THIRD_ARG (caddr_t)(&mybpf)) < 0) 
00445   { 
00446     perror("Error BIOCSETF \n");
00447     goto errorMark;
00448   }
00449 
00450   if (ioctl(bpffd,(BIOCSETIF),IOCTRL_CAST_THIRD_ARG (caddr_t)&ifr) < 0) 
00451    { 
00452      printf("ERROR BIOCSETIF %s \n",dev);
00453      goto errorMark;
00454     
00455  
00456    } 
00457    if (ioctl(bpffd,BIOCGBLEN, IOCTRL_CAST_THIRD_ARG &buflen) < 0) 
00458     { 
00459      printf("Error BIOCGBLEN \n");
00460  
00461    } 
00462 
00463  
00464     if (buflen > 4096) buflen=4096;
00465   buf = (struct bpf_hdr *)malloc(buflen); 
00466   //bzero(buf,buflen);  
00467   memset(buf,0x0,buflen);
00468   while ((len = read(bpffd,(char *)buf,buflen)) != 0) 
00469   {
00470     // im bpf header steht noch ein Timestamp -- waere gut fuer Timing thematik
00471     //
00472      
00473 //  Empfangene Rohdaten ohne bpf Header 
00474     pbuffer = (char *)buf + buf->bh_hdrlen; 
00475  
00476 // Empfangene Rohdatenlaenge ohne bpf Header
00477      Rcvlen = len - (buf->bh_hdrlen); 
00478 //
00479 // Wie trennt man nun die "Nutzdaten" von den Verwaltungsdaten??
00480 //
00481 
00482   struct ip * iph = (struct ip *) ((char *) buf + buf->bh_hdrlen + sizeof(struct ether_header));
00483   struct udphdr * udph = (struct udphdr *) ((char *) iph + sizeof(struct ip));
00484   char * userData = ((char *) udph) + sizeof( struct udphdr); 
00485 
00486   tFriCmdData * cmd = ( tFriCmdData * ) userData;
00487   #ifdef DEBUG_BPF_READ
00488     printf("recvLen %d\n",Rcvlen);
00489   printf("IP SRC:\t\t%s\n", inet_ntoa(iph->ip_src));
00490   printf("IP DST:\t\t%s\n", inet_ntoa(iph->ip_dst));
00491   printf("UDP SRC:\t%u\n", ntohs(udph->uh_sport));
00492   printf("UDP DST:\t%u\n", ntohs(udph->uh_dport));
00493   printf("Len #:\t\t%u\n", ntohs(udph->uh_ulen));
00494   #endif
00495 
00496      logMsg("BUF LEN = 0x%x\n",Rcvlen,0,0,0,0,0); 
00497  
00498     std::cout << (*cmd) << std::endl;
00499      for (i=0;i< ntohs(udph->uh_ulen);i++) 
00500      {
00501          printf(" %2x", userData[i]);
00502          if ((i % 10) == 9)
00503          {
00504              printf("\n");//,0,0,0,0,0,0);
00505          }
00506      }
00507     printf("\nFull packet \n");
00508      for (i=0;i< Rcvlen;i++) 
00509          {
00510              printf(" %2x(%4d)", pbuffer[i],pbuffer[i]);
00511              if ((i % 10) == 9)
00512              {
00513                  printf("\n");//,0,0,0,0,0,0);
00514              }
00515          }
00516   } 
00517 errorMark:
00518     printf("leaving %s\n",__PRETTY_FUNCTION__);
00519     if ( buf) 
00520         free(buf);
00521   if ( bpffd > 0 )   
00522         close (bpffd);
00523     bpfDevDelete("/dev/bpf");
00524  
00525 } 
00526 
00527 
00528 
00529 #endif
00530 
00531 
00532 /*****************************************************************************
00533  $Log: $
00534  *****************************************************************************/
00535 
00536 
00537 
00538 /* @} */
This document was generated with Doxygen on Thu Apr 12 2012 11:18:54. User documentation of the Fast Research Interface Library for the KUKA Lightweight Robot IV by the Stanford Robotics Research Group. Copyright 2010–2012.