📄 sock.cc
字号:
throw new SysException(0, "Sock::JoinMulticast", "No address specified"); /* is the address actually a multicast address */ if(!IN_MULTICAST(multi_addr)) throw new SysException(0, "Sock::JoinMulticast", "Address specified is not a multicast address"); /* fill the struct */ listenport = htons(4011); memset(&multicast, 0, sizeof(multicast)); multicast.sin_family = AF_INET; multicast.sin_port = listenport; // already in net order multicast.sin_addr.s_addr = htonl(multi_addr); /* local */ memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = listenport; // already in net order local.sin_addr.s_addr = htonl(INADDR_ANY); /* create a socket */ multi_sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if(multi_sockfd == -1) throw new SysException(errno, "Sock::JoinMulticast:socket()"); /* allow socket re-use */ int tmp = 1; if(setsockopt(multi_sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&tmp, sizeof(tmp)) == -1) throw new SysException(errno, "Sock::JoinMulticast:setsockopt(REUSE)"); /* bind to the multicast address */ if(bind(multi_sockfd, (struct sockaddr*)&local, sizeof(local)) != 0) throw new SysException(errno, "Sock::JoinMulticast:bind()"); /* setup the multicast struct */ mreq.imr_interface.s_addr = local.sin_addr.s_addr; mreq.imr_multiaddr.s_addr = multicast.sin_addr.s_addr; /* join a multicast group */ if(setsockopt(multi_sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1) throw new SysException(errno, "Sock::JoinMulticast:setsockopt(ADD)"); /* Dont go outside the local net */ tchar = 1; if(setsockopt(multi_sockfd, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&tchar, sizeof(tchar)) == -1) throw new SysException(errno, "Sock::JoinMulticast:setsockopt(TTL)"); /* Dont receive sent packets */ tchar = 0; if(setsockopt(multi_sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&tchar, sizeof(tchar)) == -1) throw new SysException(errno, "Sock::JoinMulticast:setsockopt(LOOP)"); log->Event(LEVEL_INFO, "Sock::JoinMulticast", 1, "Joined multicast group", inet_ntoa(mreq.imr_multiaddr)); // we are now listening listen_multi = 1; return(0);}/****************************************************************************** * LeaveMulticast - leave a multicast group * ******************************************************************************/intSock::LeaveMulticast(){ struct ip_mreq mreq; /* setup the multicast struct */ mreq.imr_interface.s_addr = htonl(INADDR_ANY); mreq.imr_multiaddr.s_addr = multicast.sin_addr.s_addr; /* leave a sock group */ if(setsockopt(multi_sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1) throw new SysException(errno, "Sock::LeaveMulticast:setsockopt(DROP)"); /* close */ shutdown(multi_sockfd, 2); close(multi_sockfd); log->Event(LEVEL_INFO, "Sock::LeaveMulticast", 1, "Left multicast group", inet_ntoa(mreq.imr_multiaddr)); listen_multi = 0; return(0);}/****************************************************************************** * AllowBroadcast - allow broadcasts * ******************************************************************************/intSock::AllowBroadcast(){ int tmp=1; int pos = 0; for(pos=0; pos < ifnum; pos++) { if(setsockopt(sockfds[pos], SOL_SOCKET, SO_BROADCAST, (const char *)&tmp, sizeof(tmp)) == -1) throw new SysException(errno, "Sock::AllowBroadcast:setsockopt()"); } log->Event(LEVEL_INFO, "Sock::AllowBroadcast", 1, "Allowing broadcasts"); listen_broad = 1; return(0);}/****************************************************************************** * DenyBroadcast - deny broadcasts * ******************************************************************************/intSock::DenyBroadcast(){ int tmp=0; int pos = 0; for(pos=0; pos < ifnum; pos++) { if(setsockopt(sockfds[pos], SOL_SOCKET, SO_BROADCAST, (const char *)&tmp, sizeof(tmp)) == -1) throw new SysException(errno, "Sock::DenyBroadcast:setsockopt()"); } log->Event(LEVEL_INFO, "Sock::DenyBroadcast", 1, "Disallowing broadcasts"); listen_broad = 0; return(0);}/****************************************************************************** * Close - close a routing socket * ******************************************************************************/intSock::Close(){ int pos; if(listen_broad) DenyBroadcast(); if(listen_multi) LeaveMulticast(); for(pos=0; pos < ifnum; pos++) { shutdown(sockfds[pos], 2); close(sockfds[pos]); } log->Event(LEVEL_INFO, "Sock::Close", 1, "Released interface(s)"); return(0);}/****************************************************************************** * Read - read some data from the socket * ******************************************************************************/intSock::Read(unsigned char *buf, int maxlen, struct sockaddr_in *client_addr, struct sockaddr_in *server_addr){ int readlen=0; int size; int pos; int selret; int maxfdno=0; int livefd = 0; fd_set fdset; struct sockaddr_in *from=NULL; // get the max fd no if(NULL != sockfds) for(pos = 0; pos < ifnum; pos++) if(sockfds[pos] > maxfdno) maxfdno = sockfds[pos]; if((listen_multi == 1) && (multi_sockfd > maxfdno)) maxfdno = multi_sockfd; maxfdno++; // need to select from all sockets while(true) { // register all of the fd numbers FD_ZERO(&fdset); if(NULL != sockfds) for(pos = 0; pos < ifnum; pos++) FD_SET(sockfds[pos], &fdset); if(listen_multi == 1) FD_SET(multi_sockfd, &fdset); // wait for the next packet selret = select(maxfdno, &fdset, NULL, NULL, NULL); if(selret == -1) if(errno == EINTR) break; else throw new SysException(errno, "Sock::Read:select()"); // how many fds setup? if(selret < 1) goto Sock_Read_next; // where did it come from? if(NULL != sockfds) for(pos = 0; pos < ifnum; pos++) if(FD_ISSET(sockfds[pos], &fdset)) { livefd = sockfds[pos]; from = &(bind_addrs[pos]); break; } // was the multicast fd set if(listen_multi && FD_ISSET(multi_sockfd, &fdset)) { from = &default_addr; livefd = multi_sockfd; } // read the next packet size=sizeof(struct sockaddr_in); readlen = recvfrom(livefd, (char*)buf, maxlen, 0, (struct sockaddr*)client_addr, (socklen_t*)&size); if(readlen == -1) if(errno == EINTR) break; else throw new SysException(errno, "Sock::Read:read()"); if(readlen == 0) goto Sock_Read_next; // copy the server address memcpy(server_addr, from, sizeof(*from)); // receive any packet on unicast/multicast/broadcast if((client_addr->sin_port == clientport) || (livefd == multi_sockfd)) // HACK! break; Sock_Read_next: size=size; } return(readlen);}/****************************************************************************** * GetHostname - get the hostname of the connected socket * ******************************************************************************/char *Sock::GetHostname(const struct sockaddr_in *address){ struct hostent *h_info; // get the address info h_info = gethostbyaddr((const char*)&(address->sin_addr.s_addr), sizeof(address->sin_addr.s_addr), AF_INET); if(h_info == NULL) {#ifdef HAVE_HSTRERROR log->Event(LEVEL_INFO, "Sock::GetHostname:gethostbyaddr()", 1, hstrerror(h_errno));#else log->Event(LEVEL_INFO, "Sock::GetHostname:gethostbyaddr()", 1, "Resolver error occourred");#endif return(NULL); } return(h_info->h_name);}/****************************************************************************** * Send - send some data to the client * ******************************************************************************/intSock::Send(unsigned char *buf, int maxlen, struct sockaddr_in *client_addr, struct sockaddr_in *server_addr){ int livefd=0; int ifno, len; int found = 0; // firstly, make some routing choices for(ifno=0; ifno < ifnum; ifno++) { if(bind_addrs[ifno].sin_addr.s_addr == server_addr->sin_addr.s_addr) { livefd = sockfds[ifno]; found++; break; } } if(multicast.sin_addr.s_addr == server_addr->sin_addr.s_addr) { found++; livefd = multi_sockfd; } // which interface? if(found == 0) throw new SysException(1, "Sock::Send", "Not bound to interface"); // send the message len = sendto(livefd, (char*)buf, maxlen, 0, (struct sockaddr*)client_addr, sizeof(struct sockaddr_in)); // ok? if(-1 == len) throw new SysException(errno, "Sock::Send:sendto()"); if(maxlen != len) throw new SysException(1, "Sock::Send", "Packet truncated"); return(len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -