rllib  1
rludpsocket.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                         rludpsocket.cpp  -  description
00003                              -------------------
00004     begin                : Tue Apr 03 2007
00005     copyright            : (C) 2007 by Rainer Lehrig
00006     email                : lehrig@t-online.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as        *
00013  *   published by the Free Software Foundation                             *
00014  *                                                                         *
00015  ***************************************************************************/
00016 #include "rludpsocket.h"
00017 #include "rlcutil.h"
00018 #include <stdio.h>
00019 #include <string.h>
00020 
00021 rlIpAdr::rlIpAdr()
00022 {
00023   rlwsa(); // init sockets on windows
00024   memset(&address,0,sizeof(address));
00025 }
00026 
00027 rlIpAdr::~rlIpAdr()
00028 {
00029 }
00030 
00031 int rlIpAdr::setAdr(const char *adr, int port)
00032 {
00033   if(port < 0 || port >= 256*256) return -1;
00034   struct in_addr IpAddress;
00035   struct hostent *host;
00036 
00037   memset(&IpAddress,0,sizeof(IpAddress));
00038   memset(&address,0,sizeof(address));
00039 
00040   host = gethostbyname(adr);
00041   if(host == NULL)
00042   {
00043     // See if the host is specified in "dot address" form
00044     IpAddress.s_addr = inet_addr(adr);
00045     if(IpAddress.s_addr == INADDR_NONE)
00046     {
00047       ::printf("rlIpAdr::setAdr() could not gethostbyname(%s)\n",adr);
00048       return -1;
00049     }
00050   }
00051   else
00052   {
00053     memcpy(&IpAddress,host->h_addr,host->h_length);
00054   }
00055 
00056   address.sin_family = AF_INET;
00057   address.sin_port = htons((short) port);
00058   address.sin_addr = IpAddress;
00059 
00060   return 0;
00061 }
00062 
00063 int rlIpAdr::operator==(rlIpAdr &address1)
00064 {
00065   if(address.sin_family != address1.address.sin_family) return 0;
00066   if(memcmp(&address.sin_addr,&address1.address.sin_addr,sizeof(address.sin_addr)) == 0) return 1;
00067   return 0;
00068 }
00069 
00070 //###################################################################
00071 
00072 rlUdpSocket::rlUdpSocket(int _debug)
00073 {
00074   debug = _debug;
00075   if(debug) ::printf("rlUdpSocket() constructor\n");
00076   rlwsa(); // init sockets on windows
00077   readflag = writeflag = 0;
00078   s = socket(AF_INET,SOCK_DGRAM,0);
00079   if(s < 0)
00080   {
00081     s = -1;
00082     ::printf("rlUdpSocket::rlUdpSocket could not get socket\n");
00083   }
00084 }
00085 
00086 rlUdpSocket::~rlUdpSocket()
00087 {
00088   if(s > 0)
00089   {
00090 #ifdef RLWIN32
00091     closesocket(s);
00092 #else
00093     close(s);
00094 #endif
00095   }
00096 }
00097 
00098 int rlUdpSocket::setSockopt(int opt)
00099 {
00100   const int on = 1;
00101   if(s == -1) return -1;
00102   // set socket options
00103 #ifdef RLWIN32
00104   return setsockopt(s,SOL_SOCKET,opt,(const char *) &on,sizeof(on));
00105 #else
00106   return setsockopt(s,SOL_SOCKET,opt,&on,sizeof(on));
00107 #endif
00108 }
00109 
00110 int rlUdpSocket::setSockopt(int level, int optname, void *optval, int optlen)
00111 {
00112   if(s == -1) return -1;
00113   if(optlen <= 0) return -1;
00114   // set socket options
00115 #ifdef RLWIN32
00116   return setsockopt(s,level,optname,(const char *) &optval,optlen);
00117 #else
00118   return setsockopt(s,level,optname,optval,optlen);
00119 #endif
00120 }
00121 
00122 int rlUdpSocket::bind(int port)
00123 {
00124   if(port < 0 || port >= 256*256) return -1;
00125 
00126   memset(&address,0,sizeof(address));
00127   address.sin_family = AF_INET;
00128   address.sin_port = htons((short) port);
00129   address.sin_addr.s_addr = htonl(INADDR_ANY);
00130   // bind socket
00131   if(::bind(s, (sockaddr *) &address, sizeof(address)) < 0)
00132   {
00133     ::printf("rlUdpSocket::setAdr() bind() failed port=%d\n", port);
00134     return -1;
00135   }
00136   return 0;
00137 }
00138 
00139 int rlUdpSocket::select(int timeout)
00140 {
00141   if(timeout < 0) return -1;
00142   struct timeval timout;
00143   fd_set wset,rset,eset;
00144   int    ret,maxfdp1;
00145 
00146   /* setup sockets to read */
00147   maxfdp1 = s+1;
00148   FD_ZERO(&rset);
00149   FD_SET (s,&rset);
00150   FD_ZERO(&wset);
00151   FD_ZERO(&eset);
00152   timout.tv_sec  =  timeout / 1000;
00153   timout.tv_usec = (timeout % 1000) * 1000;
00154 
00155   ret = ::select(maxfdp1,&rset,&wset,&eset,&timout);
00156   if(ret == 0) return 0; /* timeout */
00157   return 1;
00158 }
00159 
00160 int rlUdpSocket::recvfrom(void *buf, int maxlen, rlIpAdr *source, int timeout)
00161 {
00162   int  ret, len;
00163 
00164   if(timeout >= 0)
00165   {
00166     ret = select(timeout);
00167     if(ret != 1) return -1; // timeout
00168   }
00169   if(debug) ::printf("rlUdpSocket()::recvfrom() ...\n");
00170   len = sizeof(source->address);
00171 #ifdef RLWIN32
00172   ret = ::recvfrom(s, (char *) buf, maxlen, readflag,
00173                   (struct sockaddr *) &source->address, (int FAR *) &len);
00174 #endif
00175 #ifdef RLUNIX
00176   ret = ::recvfrom(s, buf, maxlen, readflag,
00177                   (struct sockaddr *) &source->address, (socklen_t *) &len);
00178 #endif
00179 #ifdef __VMS
00180   ret = ::recvfrom(s, buf, maxlen, readflag,
00181                   (struct sockaddr *) &source->address, (size_t *)  &len);
00182 #endif
00183   if(ret < 0)
00184   {
00185     ::printf("ERROR: rlUdpSocket::read()\n");
00186     return -2;
00187   }
00188   if(debug)
00189   {
00190     unsigned char *cbuf = (unsigned char *) buf;
00191     ::printf("rlUdpSocket()::recvfrom() ret=%d data=[0x%x",ret,cbuf[0]);
00192     for(int i=1; i<ret; i++) ::printf(",0x%x",cbuf[i]);
00193     ::printf("]\n");
00194   }
00195   return ret;
00196 }
00197 
00198 int rlUdpSocket::sendto(const void *buf, int len, rlIpAdr *dest)
00199 {
00200 #ifdef RLWIN32
00201   int ret = ::sendto(s, (const char *) buf, len, writeflag,
00202                     (struct sockaddr *) &dest->address, sizeof(struct sockaddr_in));
00203 #else
00204   int ret = ::sendto(s, buf, len, writeflag,
00205                     (struct sockaddr *) &dest->address, sizeof(struct sockaddr_in));
00206 #endif
00207   if(ret < 0) ::printf("ERROR: rlUdpSocket::sendto()\n");
00208   if(debug)
00209   {
00210     unsigned char *cbuf = (unsigned char *) buf;
00211     ::printf("rlUdpSocket()::sendto() ret=%d data=[0x%x",ret,cbuf[0]);
00212     for(int i=1; i<ret; i++) ::printf(",0x%x",cbuf[i]);
00213     ::printf("]\n");
00214   }
00215   return ret;
00216 }
00217 
00218 int rlUdpSocket::printf(rlIpAdr *dest, const char *format, ...)
00219 {
00220   int ret;
00221   char message[rl_PRINTF_LENGTH]; // should be big enough
00222 
00223   va_list ap;
00224   va_start(ap,format);
00225   ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap);
00226   va_end(ap);
00227   if(ret < 0) return ret;
00228   return sendto(message,strlen(message)+1,dest);
00229 }
00230 
00231 //#define TESTING
00232 #ifdef TESTING
00233 
00234 int main(int ac, char **av)
00235 {
00236   int ret;
00237   char buf[1024];
00238   rlUdpSocket udp;
00239   rlIpAdr dest;
00240   dest.setAdr("localhost",5050);
00241 
00242   if(ac == 2) // client
00243   {
00244     while(1)
00245     {
00246       sleep(1);
00247       ret = udp.sendto(av[1], strlen(av[1])+1, &dest);
00248       if(ret > 0)
00249       {
00250         printf("udp.sendto(%s) ret=%d\n",av[1],ret);
00251       }
00252       else printf("udp.sendto() failed\n");
00253     }
00254   }
00255   else // server
00256   {
00257     rlIpAdr source;
00258     ret = udp.bind(5050);
00259     while(1)
00260     {
00261       if((ret = udp.recvfrom(buf,sizeof(buf), &source, 1000)) > 0)
00262       {
00263         printf("udp.recvfrom(%s) ret=%d\n",buf,ret);
00264         if(dest == source) printf("dest==source\n");
00265         else               printf("dest!=source\n");
00266       }
00267       else printf("udp.recvfrom() failed or timeout\n");
00268     }
00269   }
00270   return 0;
00271 }
00272 
00273 #endif