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

InnerSocket.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 dEVICE cOMMUNITIES dEVELOPMENT tOOLKIT 
00003 
00004 DCDT_InnerSocket.h
00005 
00006 COPYRIGHT (C) 2002   Alessandro Mazzini (mazzini@airlab.elet.polimi.it)
00007                      Cristian Giussani (cgiussani@fastflow.it)
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 INNERSOCKET_H
00026 #define INNERSOCKET_H
00027 
00028 #include <unistd.h>
00029 #include <netinet/in.h>
00030 #include <arpa/inet.h>
00031 #include <string.h>
00032 #include <iostream>
00033 #include <sys/socket.h>
00034 #include <sys/un.h>
00035 #include <errno.h>
00036 #include <stdlib.h>
00037 #include <DCDT_Defs.h>
00038 #include <DCDT_Msg.h>
00039 
00040 
00041 
00042 class InnerSocket
00043 {
00044  public:
00045   InnerSocket()
00046     {
00047       sockfd = opened = bound = connected = tconn_flag = tlost_flag = tsend_flag = trecv_flag = 0;
00048       tconn_value.tv_sec = tconn_value.tv_usec = tlost_value.tv_sec = tlost_value.tv_usec = 0;
00049       tsend_value.tv_sec = tsend_value.tv_usec = trecv_value.tv_sec = trecv_value.tv_usec = 0;
00050       unblock_send_flag = unblock_recv_flag = 0;
00051       name = NULL;
00052     };
00053   
00054   ~InnerSocket()
00055     {
00056       if ( name )
00057         delete[] name;
00058     };
00059   
00060   inline void Open();
00061   inline void Bind(char *n);
00062   inline void Connect(char *n);
00063   inline void Send(const DCDT_Msg *msg);
00064   inline DCDT_Msg* Receive();
00065   inline void SendHS(char *to, HSMsgHeader *header, char* payload);
00066   inline void ReceiveHS(HSMsgHeader*& header, char*& payload);
00067   inline void Close();
00068   inline void ForcedClose();
00069   inline void SetLostTimer(int usec);
00070   inline void LostTimerOn();
00071   inline void LostTimerOff();
00072   inline void SetConnTimer(int usec);
00073   inline void ConnTimerOn();
00074   inline void ConnTimerOff();
00075   inline void SetSendTimer(int usec);
00076   inline void SendTimerOn();
00077   inline void SendTimerOff();
00078   inline void UnblockSend();
00079   inline void SetReceiveTimer(int usec);
00080   inline void ReceiveTimerOn();
00081   inline void ReceiveTimerOff();
00082   inline void UnblockReceive();
00083 
00084 protected:
00085   int sockfd, opened, bound, connected, tconn_flag, tlost_flag, tsend_flag, trecv_flag;
00086   int unblock_send_flag, unblock_recv_flag;
00087   struct timeval tconn_value, tlost_value, tsend_value, trecv_value;
00088   char *name;
00089 };
00090 
00091 inline void InnerSocket::Open()
00092 {
00093   if (opened)
00094     return;
00095 
00096   if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
00097     throw ChannelError(errno);
00098 
00099   opened = 1;
00100 
00101   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("InnerSocket successfully opened"));
00102 }
00103 
00104 inline void InnerSocket::Bind(char *n)
00105 {
00106   struct sockaddr_un addr;
00107 
00108   if (!opened || bound || !n)
00109     return;
00110 
00111   if (name)
00112     delete[] name;
00113 
00114   name = new char[strlen(n) + 1];
00115   strcpy(name, n);
00116 
00117   memset(&addr, 0, sizeof(addr));
00118   strcpy(addr.sun_path, name);
00119 
00120   addr.sun_family = AF_UNIX;
00121 
00122   remove(n);
00123   if (bind(sockfd, (struct sockaddr *) &addr, strlen(addr.sun_path) + sizeof (addr.sun_family)) < 0)
00124     throw ChannelError(errno);
00125 
00126   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("InnerSocket successfully bound to: %s", name));
00127 
00128   bound = 1;
00129 }
00130 
00131 inline void InnerSocket::Connect(char *n)
00132 {
00133   struct sockaddr_un addr;
00134 
00135   if (!opened || connected)
00136     return;
00137 
00138   memset(&addr, 0, sizeof(addr));
00139   strcpy(addr.sun_path, n);
00140   // SETTARE LA sun_len?
00141   addr.sun_family = AF_UNIX;
00142   if (connect(sockfd, (struct sockaddr *)&addr, strlen(addr.sun_path) + sizeof (addr.sun_family)) < 0)
00143     throw ConnError(errno);
00144 
00145   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("InnerSocket successfully connected to: %s", n));
00146 
00147   connected = 1;
00148 }
00149 
00150 inline void InnerSocket::Send(const DCDT_Msg* msg)
00151 {
00152   fd_set wset;
00153   struct timeval tv, *tv_ptr = NULL;
00154   msghdr mh;
00155   iovec iov[1];
00156   int nsent;
00157 
00158   if (!opened || !connected)
00159     return;
00160 
00161   FD_ZERO(&wset);
00162   FD_SET(sockfd, &wset);
00163   if (unblock_send_flag)
00164   {
00165     tv.tv_sec = 0;
00166     tv.tv_usec = 0;
00167     tv_ptr = &tv;
00168   }
00169   else if (tsend_flag)
00170   {
00171     tv.tv_sec = tsend_value.tv_sec;
00172     tv.tv_usec = tsend_value.tv_usec;
00173     tv_ptr = &tv;
00174   }
00175   else if (tlost_flag)
00176   {
00177     tv.tv_sec = tlost_value.tv_sec;
00178     tv.tv_usec = tlost_value.tv_usec;
00179     tv_ptr = &tv;
00180   }
00181   switch (select(sockfd+1, NULL, &wset, NULL, tv_ptr))
00182   {
00183     case 0: throw TimeOut();
00184     case -1: throw ConnError(errno);
00185   }
00186 
00187   /* Send two messages so the receiver can get the header, know what's the length of the payload, allocate it and then receive the payload */
00188   memset(&mh, 0, sizeof(mh));
00189   iov[0].iov_base = msg->GetHeader();
00190   iov[0].iov_len = MSGHEADER_LEN;
00191   mh.msg_iov = iov;
00192   mh.msg_iovlen = 1;
00193 
00194   if ((nsent = sendmsg(sockfd, &mh, 0)) < 0)
00195     throw ConnError(errno);
00196   else if (nsent != MSGHEADER_LEN ) {
00197 
00198     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner bytes sent: %i", nsent));
00199 
00200     throw ConnError();
00201   }
00202 
00203   iov[0].iov_base = msg->GetPayload();
00204   iov[0].iov_len = msg->ReadPayloadLen();
00205   if ((nsent = sendmsg(sockfd, &mh, 0)) < 0)
00206     throw ConnError(errno);
00207   else if (nsent != (int)iov[0].iov_len) {
00208 
00209     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner bytes sent: %i", nsent));
00210 
00211     throw ConnError();
00212   }
00213 
00214   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner bytes sent: %i message successfully sent", nsent));
00215 
00216 }
00217 
00218 inline void InnerSocket::SendHS(char *to, HSMsgHeader *header, char* payload)
00219 {
00220   fd_set wset;
00221   struct timeval tv, *tv_ptr = NULL;
00222   struct sockaddr_un addr;
00223   msghdr mh;
00224   iovec iov[2];
00225   int nsent;
00226 
00227   if (!opened)
00228     return;
00229 
00230   FD_ZERO(&wset);
00231   FD_SET(sockfd, &wset);
00232   if (unblock_send_flag)
00233   {
00234     tv.tv_sec = 0;
00235     tv.tv_usec = 0;
00236     tv_ptr = &tv;
00237   }
00238   else if (tsend_flag)
00239   {
00240     tv.tv_sec = tsend_value.tv_sec;
00241     tv.tv_usec = tsend_value.tv_usec;
00242     tv_ptr = &tv;
00243   }
00244   else if (tlost_flag)
00245   {
00246     tv.tv_sec = tlost_value.tv_sec;
00247     tv.tv_usec = tlost_value.tv_usec;
00248     tv_ptr = &tv;
00249   }
00250   switch (select(sockfd+1, NULL, &wset, NULL, tv_ptr))
00251   {
00252     case 0: throw TimeOut();
00253     case -1: throw ConnError(errno);
00254   }
00255 
00256   memset(&addr, 0, sizeof(addr));
00257   strcpy(addr.sun_path, to);
00258   addr.sun_family = AF_UNIX;
00259 
00260   memset(&mh, 0, sizeof(mh));
00261   mh.msg_name = &addr;
00262   mh.msg_namelen = sizeof(addr);
00263 
00264   iov[0].iov_base = header;
00265   iov[0].iov_len = HSMSGHEADER_LEN;
00266   iov[1].iov_base = payload;
00267   header->payload_len = iov[1].iov_len = strlen(payload)+1;
00268 
00269   mh.msg_iov = iov;
00270   mh.msg_iovlen = 2;
00271 
00272   if ((nsent = sendmsg(sockfd, &mh, 0)) < 0)
00273     throw ConnError(errno);
00274   else if (nsent < (int)(iov[0].iov_len + iov[1].iov_len)) {
00275     
00276     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner bytes sent: %i", nsent));
00277   
00278     throw ConnError();
00279   }
00280   
00281   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner bytes sent: %i message successfully sent", nsent));
00282 }
00283 
00284 
00285 inline DCDT_Msg* InnerSocket::Receive()
00286 {
00287   DCDT_MsgHeader *msg_header;
00288   int plen;
00289   DCDT_Msg *msg;
00290   void *buf;
00291   msghdr mh;
00292   iovec iov[1];
00293 
00294   int nread = 0;
00295   fd_set rset;
00296   struct timeval tv, *tv_ptr = NULL;
00297 
00298   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("InnerSocket::Receive"));
00299 
00300   if (!opened)
00301     return NULL;
00302 
00303   FD_ZERO(&rset);
00304   FD_SET(sockfd, &rset);
00305   if (unblock_recv_flag)
00306   {
00307     tv.tv_sec = 0;
00308     tv.tv_usec = 0;
00309     tv_ptr = &tv;
00310   }
00311   else if (trecv_flag)
00312   {
00313     tv.tv_sec = trecv_value.tv_sec;
00314     tv.tv_usec = trecv_value.tv_usec;
00315     tv_ptr = &tv;
00316   }
00317   else if (tlost_flag)
00318   {
00319     tv.tv_sec = tlost_value.tv_sec;
00320     tv.tv_usec = tlost_value.tv_usec;
00321     tv_ptr = &tv;
00322   }
00323   switch (select(sockfd+1, &rset, NULL, NULL, tv_ptr)) {
00324     case 0: return NULL;
00325     case -1: throw ConnError(errno);
00326   }
00327 
00328   // preparing data structure
00329   memset(&mh, 0, sizeof(mh));
00330   msg_header = new DCDT_MsgHeader;
00331   iov[0].iov_base = msg_header;
00332   iov[0].iov_len = MSGHEADER_LEN;
00333   mh.msg_iov = iov;
00334   mh.msg_iovlen = 1;
00335   if ((nread = recvmsg(sockfd, &mh, 0)) < 0) {
00336     delete msg_header;
00337     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("recvmsg error %d", nread));
00338     throw ConnError(errno);
00339   }
00340   else if (nread == 0 || nread != (int)MSGHEADER_LEN) {
00341     delete msg_header;
00342     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("recvmsg error %d", nread));
00343     throw ConnError();
00344   }
00345 
00346   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner byte read: %i", nread));
00347 
00348   msg = new DCDT_Msg(msg_header);
00349   plen = msg->ReadPayloadLen();
00350   buf = malloc ( plen );
00351   memset ( buf, 0, plen );
00352   iov[0].iov_base = buf;
00353   iov[0].iov_len = plen;
00354   mh.msg_iov = iov;
00355   mh.msg_iovlen = 1;
00356   if ((nread = recvmsg(sockfd, &mh, 0)) != plen ) {
00357     free(buf);
00358     delete msg_header;
00359     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("recvmsg error %d", nread));
00360     throw ConnError(errno);
00361   }
00362 
00363   msg->SetPayload( buf, plen );
00364  
00365   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner message successfully received"));
00366 
00367   return msg;
00368 }
00369 
00370 inline void InnerSocket::ReceiveHS(HSMsgHeader*& header, char*& payload)
00371 {
00372   HSMsgHeader *msg_header;
00373   char *data;
00374   msghdr mh;
00375   iovec iov[2];
00376 
00377   int nread = 0;
00378   fd_set rset;
00379   struct timeval tv, *tv_ptr = NULL;
00380 
00381   if (!opened)
00382     return;
00383 
00384   FD_ZERO(&rset);
00385   FD_SET(sockfd, &rset);
00386   if (unblock_recv_flag)
00387   {
00388     tv.tv_sec = 0;
00389     tv.tv_usec = 0;
00390     tv_ptr = &tv;
00391   }
00392   else if (trecv_flag)
00393   {
00394     tv.tv_sec = trecv_value.tv_sec;
00395     tv.tv_usec = trecv_value.tv_usec;
00396     tv_ptr = &tv;
00397   }
00398   else if (tlost_flag)
00399   {
00400     tv.tv_sec = tlost_value.tv_sec;
00401     tv.tv_usec = tlost_value.tv_usec;
00402     tv_ptr = &tv;
00403   }
00404   switch (select(sockfd+1, &rset, NULL, NULL, tv_ptr)) {
00405     case 0:
00406       throw TimeOut();
00407     case -1:
00408       throw ConnError(errno);
00409   }
00410 
00411   // preparing data structure
00412   memset(&mh, 0, sizeof(mh));
00413   msg_header = new HSMsgHeader();
00414   data = new char[UNIX_PATH_MAX];
00415   iov[0].iov_base = msg_header;
00416   iov[0].iov_len = HSMSGHEADER_LEN;
00417   iov[1].iov_base = data;
00418   iov[1].iov_len = UNIX_PATH_MAX;
00419   mh.msg_iov = iov;
00420   mh.msg_iovlen = 2;
00421   if ((nread = recvmsg(sockfd, &mh, 0)) < 0) {
00422     delete[] data;
00423     delete msg_header;
00424     throw ConnError(errno);
00425   }
00426   else if (nread == 0 || nread < (int)HSMSGHEADER_LEN) {
00427     delete[] data;
00428     delete msg_header;
00429     throw ConnError();
00430   }
00431 
00432   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner byte read: %i", nread));
00433 
00434   if (nread < (int)(HSMSGHEADER_LEN + (msg_header->payload_len))) {
00435     delete[] data;
00436     delete msg_header;
00437     throw ConnError();
00438   }
00439 
00440   TRC_PRINT( DCDT_TRC_COMM, TRC1, ("Inner message successfully received"));
00441 
00442   if ( header != NULL )
00443     printf ( "InnerSocket.h: header != NULL\n" );
00444 
00445   header = msg_header;
00446   payload = new char[msg_header->payload_len];
00447   memcpy(payload, data, msg_header->payload_len);
00448   delete[] data;
00449 }
00450 
00454 inline void InnerSocket::Close()
00455 {
00456   if (opened) {
00457     if (close(sockfd) < 0)
00458       throw ConnError(errno);
00459     connected = opened = bound = sockfd = 0;
00460     remove(name);
00461 
00462     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("InnerSocket successfully closed"));
00463   }
00464 }
00465 
00466 inline void InnerSocket::ForcedClose()
00467 {
00468   if (opened) {
00469     shutdown(sockfd, SHUT_RDWR);
00470     connected = opened = bound = sockfd = 0;
00471     remove(name);
00472 
00473     TRC_PRINT( DCDT_TRC_COMM, TRC1, ("InnerSocket successfully shut"));
00474   }
00475 }
00476 
00477 
00478 inline void InnerSocket::SetLostTimer(int usec)
00479 {
00480   tlost_value.tv_usec = usec % 1000000;
00481   tlost_value.tv_sec = usec / 1000000;
00482 };
00483 
00484 inline void InnerSocket::LostTimerOn()
00485 {
00486   tlost_flag = 1;
00487 };
00488 
00489 inline void InnerSocket::LostTimerOff()
00490 {
00491   tlost_flag = 0;
00492 };
00493 
00494 inline void InnerSocket::SetConnTimer(int usec)
00495 {
00496   tconn_value.tv_usec = usec % 1000000;
00497   tconn_value.tv_sec = usec / 1000000;
00498 };
00499 
00500 inline void InnerSocket::ConnTimerOn()
00501 {
00502   tconn_flag = 1;
00503 };
00504 
00505 inline void InnerSocket::ConnTimerOff()
00506 {
00507   tconn_flag = 0;
00508 };
00509 
00510 inline void InnerSocket::SetSendTimer(int usec)
00511 {
00512   tsend_value.tv_usec = usec % 1000000;
00513   tsend_value.tv_sec = usec / 1000000;
00514 };
00515 
00516 inline void InnerSocket::SendTimerOn()
00517 {
00518   tsend_flag = 1;
00519   unblock_send_flag = 0;
00520 };
00521 
00522 inline void InnerSocket::SendTimerOff()
00523 {
00524   tsend_flag = 0;
00525 };
00526 
00527 inline void InnerSocket::UnblockSend()
00528 {
00529   unblock_send_flag = 1;
00530 }
00531 
00532 inline void InnerSocket::SetReceiveTimer(int usec)
00533 {
00534   trecv_value.tv_usec = usec % 1000000;
00535   trecv_value.tv_sec = usec / 1000000;
00536 };
00537 
00538 inline void InnerSocket::ReceiveTimerOn()
00539 {
00540   trecv_flag = 1;
00541   unblock_recv_flag = 0;
00542 };
00543 
00544 inline void InnerSocket::ReceiveTimerOff()
00545 {
00546   trecv_flag = 0;
00547 };
00548 
00549 inline void InnerSocket::UnblockReceive()
00550 {
00551   unblock_recv_flag = 1;
00552 }
00553 
00554 #endif

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