00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00173
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
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
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
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
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