Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

UDPSocket.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 dEVICE cOMMUNITIES dEVELOPMENT tOOLKIT 
00003 
00004 DCDT_UDPSocket.h
00005 
00006 COPYRIGHT (C) 2002   Alessandro Mazzini (mazzini@airlab.elet.polimi.it)
00007 
00008 
00009 This library is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU Lesser General Public
00011 License as published by the Free Software Foundation; either
00012 version 2 of the License, or (at your option) any later version.
00013 
00014 This library is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public
00020 License along with this library; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
00022 
00023 ****************************************************************************/
00024 
00025 #ifndef UDPSOCKET_H
00026 #define UDPSOCKET_H
00027 
00028 #include <netdb.h>
00029 #include <Socket.h>
00030 
00031 class UDPSocket : public Socket
00032 {
00033  public:
00034   inline void Open(int fd = 0);
00035   inline void Send(const DCDT_Msg* msg);
00036   inline void SendHS(int addr, short port, HSMsgHeader *header, void* payload);
00037   inline void Send(DCDT_Msg* msg, const char* dest, short port);
00038   inline void Send(DCDT_Msg* msg, int addr, short port);
00039   inline DCDT_Msg* Receive();
00040   inline void ReceiveHS(HSMsgHeader*& header, void*& payload);
00041   inline void MC_Set(int group, int ifaddr);
00042 
00043  private:
00044   int multi_addr;
00045   short multi_port;
00046 };
00047 
00048 inline void
00049 UDPSocket::Open(int fd)
00050 {
00051   if (opened)
00052     return;
00053   if (fd) sockfd = fd;
00054   else if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00055     throw ChannelError(errno);
00056   opened = 1;
00057 
00058   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDPSocket successfully opened"));
00059 }
00060 
00066 inline void UDPSocket::Send(const DCDT_Msg* msg)
00067 {
00068   fd_set wset;
00069   struct timeval tv, *tv_ptr = NULL;
00070   msghdr mh;
00071   iovec iov[2];
00072   int nsent;
00073 
00074   if (!opened || !connected)
00075     return;
00076 
00077   FD_ZERO(&wset);
00078   FD_SET(sockfd, &wset);
00079   if (unblock_send_flag)
00080   {
00081     tv.tv_sec = 0;
00082     tv.tv_usec = 0;
00083     tv_ptr = &tv;
00084   }
00085   else if (tsend_flag)
00086   {
00087     tv.tv_sec = tsend_value.tv_sec;
00088     tv.tv_usec = tsend_value.tv_usec;
00089     tv_ptr = &tv;
00090   }
00091   else if (tlost_flag)
00092   {
00093     tv.tv_sec = tlost_value.tv_sec;
00094     tv.tv_usec = tlost_value.tv_usec;
00095     tv_ptr = &tv;
00096   }
00097   switch (select(sockfd+1, NULL, &wset, NULL, tv_ptr))
00098   {
00099     case 0: throw TimeOut();
00100     case -1: throw ConnError(errno);
00101   }
00102 
00103   memset(&mh, 0, sizeof(mh));
00104   iov[0].iov_base = msg->GetHeader();
00105   iov[0].iov_len = MSGHEADER_LEN;
00106   iov[1].iov_base = msg->GetPayload();
00107   iov[1].iov_len = msg->ReadPayloadLen();
00108   mh.msg_iov = iov;
00109   mh.msg_iovlen = 2;
00110 
00111   if ((nsent = sendmsg(sockfd, &mh, 0)) < 0)
00112     throw ConnError(errno);
00113   else if (nsent < (int)(MSGHEADER_LEN + iov[1].iov_len)) {
00114 
00115     TRC_PRINT ( DCDT_TRC_COMM, TRC0, ("Error: UDP bytes sent: %i ( Req. %d )", nsent, (int)MSGHEADER_LEN + iov[1].iov_len ));
00116 
00117     throw ConnError();
00118   }
00119 
00120   TRC_PRINT ( DCDT_TRC_COMM, TRC0, ("UDP bytes sent: %i message successfully sent", nsent));
00121 
00122 }
00123 
00124 
00130 inline void
00131 UDPSocket::SendHS(int addr, short port, HSMsgHeader *header, void* payload)
00132 {
00133   fd_set wset;
00134   struct timeval tv, *tv_ptr = NULL;
00135   struct sockaddr_in destaddr;
00136   msghdr mh;
00137   iovec iov[2];
00138   int nsent;
00139 
00140   if (!opened)
00141     return;
00142 
00143   FD_ZERO(&wset);
00144   FD_SET(sockfd, &wset);
00145   if (tsend_flag)
00146   {
00147     tv.tv_sec = tsend_value.tv_sec;
00148     tv.tv_usec = tsend_value.tv_usec;
00149     tv_ptr = &tv;
00150   }
00151   else if (tlost_flag)
00152   {
00153     tv.tv_sec = tlost_value.tv_sec;
00154     tv.tv_usec = tlost_value.tv_usec;
00155     tv_ptr = &tv;
00156   }
00157   switch (select(sockfd+1, NULL, &wset, NULL, tv_ptr))
00158   {
00159     case 0: throw TimeOut();
00160     case -1: throw ConnError(errno);
00161   }
00162 
00163   memset(&destaddr, 0, sizeof(destaddr));
00164   destaddr.sin_family = AF_INET;
00165   destaddr.sin_addr.s_addr = (in_addr_t)addr;
00166   destaddr.sin_port = port;
00167 
00168   memset(&mh, 0, sizeof(mh));
00169   mh.msg_name = &destaddr;
00170   mh.msg_namelen = sizeof(destaddr);
00171 
00172   /* Valgrind da' un errore perche' "header" e "payload" possono essere
00173      non inizializzati ( verificare ) */
00174   iov[0].iov_base = header;
00175   iov[0].iov_len = HSMSGHEADER_LEN;
00176   iov[1].iov_base = payload;
00177   iov[1].iov_len = header->payload_len;
00178 
00179   mh.msg_iov = iov;
00180   mh.msg_iovlen = 2;
00181 
00182   if ((nsent = sendmsg(sockfd, &mh, 0)) < 0)
00183     throw ConnError(errno);
00184   else if (nsent < (int)(iov[0].iov_len + iov[1].iov_len)) {
00185 
00186     TRC_PRINT( DCDT_TRC_COMM, TRC0, ("Error: UDP bytes sent: %i ( Expected %d )", nsent, (int)(iov[0].iov_len + iov[1].iov_len) ));
00187 
00188     throw ConnError();
00189   }
00190 
00191   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP bytes sent: %i message successfully sent", nsent));
00192 
00193 }
00194 
00195 
00203 inline void
00204 UDPSocket::Send(DCDT_Msg* msg, const char* addr, short port)
00205 {
00206   fd_set wset;
00207   struct timeval tv, *tv_ptr = NULL;
00208   struct sockaddr_in destaddr;
00209   msghdr mh;
00210   iovec iov[2];
00211   int nsent;
00212   
00213   if (!opened)
00214     return;
00215 
00216   FD_ZERO(&wset);
00217   FD_SET(sockfd, &wset);
00218   if (unblock_send_flag) {
00219     tv.tv_sec = 0;
00220     tv.tv_usec = 0;
00221     tv_ptr = &tv;
00222   }
00223   else if (tsend_flag) {
00224     tv.tv_sec = tsend_value.tv_sec;
00225     tv.tv_usec = tsend_value.tv_usec;
00226     tv_ptr = &tv;
00227   }
00228   else if (tlost_flag) {
00229     tv.tv_sec = tlost_value.tv_sec;
00230     tv.tv_usec = tlost_value.tv_usec;
00231     tv_ptr = &tv;
00232   }
00233   
00234   switch (select(sockfd+1, NULL, &wset, NULL, tv_ptr)) {
00235   case 0: throw TimeOut();
00236   case -1: throw ConnError(errno);
00237   }
00238 
00239   memset(&destaddr, 0, sizeof(destaddr));
00240   destaddr.sin_family = AF_INET;
00241   if (inet_pton(AF_INET, addr, &destaddr.sin_addr) < 1) {
00242     throw ChannelError(errno);
00243   }
00244   destaddr.sin_port = port;
00245   
00246   memset(&mh, 0, sizeof(mh));
00247   mh.msg_name = &destaddr;
00248   mh.msg_namelen = sizeof(destaddr);
00249   iov[0].iov_base = msg->GetHeader();
00250   iov[0].iov_len = MSGHEADER_LEN;
00251   iov[1].iov_base = msg->GetPayload();
00252   iov[1].iov_len = msg->ReadPayloadLen();
00253   mh.msg_iov = iov;
00254   mh.msg_iovlen = 2;
00255   
00256   if ((nsent = sendmsg(sockfd, &mh, 0)) < 0) {
00257     throw ConnError(errno);
00258   }
00259   else if (nsent < (int)(MSGHEADER_LEN + iov[1].iov_len)) {
00260     // sending error
00261     TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP bytes sent: %i", nsent));
00262     throw ConnError();
00263   }
00264   
00265   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP bytes sent: %i message successfully sent", nsent));
00266   
00267 }
00268 
00271 inline void
00272 UDPSocket::Send(DCDT_Msg* msg, int addr, short port)
00273 {
00274   fd_set wset;
00275   struct timeval tv, *tv_ptr = NULL;
00276   struct sockaddr_in destaddr;
00277   msghdr mh;
00278   iovec iov[2];
00279   int nsent;
00280 
00281   if (!opened)
00282     return;
00283 
00284   FD_ZERO(&wset);
00285   FD_SET(sockfd, &wset);
00286   if (unblock_send_flag)
00287   {
00288     tv.tv_sec = 0;
00289     tv.tv_usec = 0;
00290     tv_ptr = &tv;
00291   }
00292   else if (tsend_flag)
00293   {
00294     tv.tv_sec = tsend_value.tv_sec;
00295     tv.tv_usec = tsend_value.tv_usec;
00296     tv_ptr = &tv;
00297   }
00298   else if (tlost_flag)
00299   {
00300     tv.tv_sec = tlost_value.tv_sec;
00301     tv.tv_usec = tlost_value.tv_usec;
00302     tv_ptr = &tv;
00303   }
00304   switch (select(sockfd+1, NULL, &wset, NULL, tv_ptr))
00305   {
00306     case 0: throw TimeOut();
00307     case -1: throw ConnError(errno);
00308   }
00309 
00310   memset(&destaddr, 0, sizeof(destaddr));
00311   destaddr.sin_family = AF_INET;
00312   destaddr.sin_addr.s_addr = (in_addr_t)addr;
00313   destaddr.sin_port = port;
00314 
00315   memset(&mh, 0, sizeof(mh));
00316   mh.msg_name = &destaddr;
00317   mh.msg_namelen = sizeof(destaddr);
00318   iov[0].iov_base = msg->GetHeader();
00319   iov[0].iov_len = MSGHEADER_LEN;
00320   iov[1].iov_base = msg->GetPayload();
00321   iov[1].iov_len = msg->ReadPayloadLen();
00322   mh.msg_iov = iov;
00323   mh.msg_iovlen = 2;
00324 
00325   if ((nsent = sendmsg(sockfd, &mh, 0)) < 0) {
00326     throw ConnError(errno);
00327   }
00328   else if (nsent < (int)(MSGHEADER_LEN + iov[1].iov_len)) {
00329     // sending problem
00330     TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP bytes sent: %i", nsent));
00331     throw ConnError();
00332   }
00333 
00334   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP bytes sent: %i message successfully sent", nsent));
00335 }
00336 
00344 inline DCDT_Msg*
00345 UDPSocket::Receive()
00346 {
00347   DCDT_MsgHeader *msg_header;
00348   int plen;
00349   void *msg_payload;
00350   DCDT_Msg *msg;
00351   void *buf;
00352   msghdr mh;
00353   iovec iov[2];
00354 
00355   int nread = 0;
00356   fd_set rset;
00357   struct timeval tv, *tv_ptr = NULL;
00358 
00359   if (!opened)
00360     return NULL;
00361 
00362   FD_ZERO(&rset);
00363   FD_SET(sockfd, &rset);
00364   if (unblock_recv_flag) {
00365     tv.tv_sec = 0;
00366     tv.tv_usec = 0;
00367     tv_ptr = &tv;
00368   }
00369   else if (trecv_flag) {
00370     tv.tv_sec = trecv_value.tv_sec;
00371     tv.tv_usec = trecv_value.tv_usec;
00372     tv_ptr = &tv;
00373   }
00374   else if (tlost_flag) {
00375     tv.tv_sec = tlost_value.tv_sec;
00376     tv.tv_usec = tlost_value.tv_usec;
00377     tv_ptr = &tv;
00378   }
00379   switch (select(sockfd+1, &rset, NULL, NULL, tv_ptr)) {
00380   case 0: return NULL;
00381   case -1: throw ConnError(errno);
00382   }
00383 
00384   // preparing data structure
00385   memset(&mh, 0, sizeof(mh));
00386   msg_header = new DCDT_MsgHeader;
00387   buf = malloc(MAX_PAYLOAD_LEN);
00388   iov[0].iov_base = msg_header;
00389   iov[0].iov_len = MSGHEADER_LEN;
00390   iov[1].iov_base = buf;
00391   iov[1].iov_len = MAX_PAYLOAD_LEN;
00392   mh.msg_iov = iov;
00393   mh.msg_iovlen = 2;
00394   if ((nread = recvmsg(sockfd, &mh, 0)) < 0) {
00395     free(buf);
00396     delete msg_header;
00397     throw ConnError(errno);
00398   }
00399   else if (nread == 0 || nread < (int)MSGHEADER_LEN) {
00400     free(buf);
00401     delete msg_header;
00402     throw ConnError();
00403   }
00404 
00405   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP byte read: %i", nread));
00406 
00407   msg = new DCDT_Msg(msg_header);
00408   if (nread < (int)(MSGHEADER_LEN + (plen = msg->ReadPayloadLen()))) {
00409     free(buf);
00410     delete msg;
00411     throw ConnError();
00412   }
00413 
00414   msg_payload = malloc(plen = msg->ReadPayloadLen());
00415   memcpy(msg_payload, buf, plen);
00416   msg->SetPayload(msg_payload, plen);
00417 
00418   free(buf);
00419 
00420   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP message successfully received"));
00421 
00422   return msg;
00423 }
00424 
00431 inline void
00432 UDPSocket::ReceiveHS(HSMsgHeader*& header, void*& payload)
00433 {
00434   HSMsgHeader *msg_header;
00435   void *data;
00436   msghdr mh;
00437   iovec iov[2];
00438 
00439   int nread = 0;
00440   fd_set rset;
00441   struct timeval tv, *tv_ptr = NULL;
00442 
00443   if (!opened)
00444     return;
00445 
00446   FD_ZERO(&rset);
00447   FD_SET(sockfd, &rset);
00448 
00449   if (trecv_flag)
00450   {
00451     tv.tv_sec = trecv_value.tv_sec;
00452     tv.tv_usec = trecv_value.tv_usec;
00453     tv_ptr = &tv;
00454   }
00455   switch (select(sockfd+1, &rset, NULL, NULL, tv_ptr)) {
00456     case 0:
00457       throw TimeOut();
00458     case -1:
00459       throw ConnError(errno);
00460   }
00461 
00462   // preparing data structure
00463   memset(&mh, 0, sizeof(mh));
00464   msg_header = new HSMsgHeader();
00465   data = malloc(MAX_HSPAYLOAD_LEN);
00466   iov[0].iov_base = msg_header;
00467   iov[0].iov_len = HSMSGHEADER_LEN;
00468   iov[1].iov_base = data;
00469   iov[1].iov_len = MAX_HSPAYLOAD_LEN;
00470   mh.msg_iov = iov;
00471   mh.msg_iovlen = 2;
00472   if ((nread = recvmsg(sockfd, &mh, 0)) < 0) {
00473     free(data);
00474     delete msg_header;
00475     throw ConnError(errno);
00476   }
00477   else if (nread == 0 || nread < (int)HSMSGHEADER_LEN) {
00478     free(data);
00479     delete msg_header;
00480     throw ConnError();
00481   }
00482 
00483   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP byte read: %i", nread));
00484 
00485   if (nread < (int)(HSMSGHEADER_LEN + (msg_header->payload_len))) {
00486     free(data);
00487     delete msg_header;
00488     throw ConnError();
00489   }
00490 
00491   payload = malloc(msg_header->payload_len);
00492   memcpy(payload, data, msg_header->payload_len);
00493   free(data);
00494   header = msg_header;
00495 
00496   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("UDP message successfully received"));
00497 }
00498 
00499 
00504 inline void
00505 UDPSocket::MC_Set(int group, int ifaddr)
00506 {
00507   struct ip_mreq mreq;
00508 
00509   if (!opened)
00510     return;
00511   
00512   mreq.imr_multiaddr.s_addr = multi_addr = group;
00513   mreq.imr_interface.s_addr = ifaddr;
00514   
00515   if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
00516     throw ChannelError(errno);
00517   
00518   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("Multicast option successfully set"));
00519 
00520   u_char val = (u_char)0;
00521   
00522   if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &val, sizeof(val)) < 0)
00523     throw ChannelError(errno);
00524   
00525   TRC_PRINT( DCDT_TRC_COMM, TRC0, ("Multicast unloop option successfully set"));
00526 
00527 }
00528 
00529 #endif

Generated on Sun Jun 19 10:35:50 2005 for dcdt by  doxygen 1.3.9.1