//send the hint to the server that the connecting is about to be closed. inline void close(SOCKET socket){ sendProtocolMessage(socket, PROTOCOLCODES::CLOSEME, 1); closesocket(socket); if (readList.sockExists(socket)){ readList.popSocket(socket); } }
void Msg2Msg::OnShutdown() { //we have to close this stuff; ListableSocket* sndSocketPtr = NULL; while(!sndSockets.IsEmpty())//close out the socket { sndSocketPtr = sndSockets.RemoveHead(); if(sndSocketPtr->IsOpen()) sndSocketPtr->Close(); delete sndSocketPtr; } ListableSocket* rcvSocketPtr = NULL; while(!rcvSockets.IsEmpty())//close out the socket { rcvSocketPtr = rcvSockets.RemoveHead(); if(rcvSocketPtr->IsOpen()) rcvSocketPtr->Close(); delete rcvSocketPtr; } ListablePipe* sndPipePtr = NULL; while(!sndPipes.IsEmpty())//close out the pipe { sndPipePtr = sndPipes.RemoveHead(); if(sndPipePtr->IsOpen()) sndPipePtr->Close(); delete sndPipePtr; } ListablePipe* rcvPipePtr = NULL; while(!rcvPipes.IsEmpty())//close out the pipe { rcvPipePtr = rcvPipes.RemoveHead(); if(rcvPipePtr->IsOpen()) rcvPipePtr->Close(); delete rcvPipePtr; } ListableFile* sndFilePtr = NULL; while(!sndFiles.IsEmpty())//close out the file { sndFilePtr = sndFiles.RemoveHead(); if(sndFilePtr->IsOpen()) sndFilePtr->Close(); delete sndFilePtr; } if(usingstdin) { //do nothing } if(usingstdout) { //do nothing } TRACE("msg2Msg: Done.\n"); } // end Msg2Msg::OnShutdown()
//send the hint to the server that the connecting is about to be closed. inline void closeAll(){ for (const auto& e : readList.sockets){ SOCKET socket = e.first; sendProtocolMessage(socket, PROTOCOLCODES::CLOSEME, 1); closesocket(socket); if (readList.sockExists(socket)){ readList.popSocket(socket); } if (readList.sockets.size() == 0){ break; } } }
net_socket_private::~net_socket_private() { TRACE("delete net_socket %p\n", this); if (parent != NULL) panic("socket still has a parent!"); if (is_in_socket_list) { MutexLocker _(sSocketLock); sSocketList.Remove(this); } mutex_lock(&lock); // also delete all children of this socket while (net_socket_private* child = pending_children.RemoveHead()) { child->RemoveFromParent(); } while (net_socket_private* child = connected_children.RemoveHead()) { child->RemoveFromParent(); } mutex_unlock(&lock); put_domain_protocols(this); mutex_destroy(&lock); }
static status_t socket_std_ops(int32 op, ...) { switch (op) { case B_MODULE_INIT: { new (&sSocketList) SocketList; mutex_init(&sSocketLock, "socket list"); #if ENABLE_DEBUGGER_COMMANDS add_debugger_command("sockets", dump_sockets, "lists all sockets"); add_debugger_command("socket", dump_socket, "dumps a socket"); #endif return B_OK; } case B_MODULE_UNINIT: ASSERT(sSocketList.IsEmpty()); mutex_destroy(&sSocketLock); #if ENABLE_DEBUGGER_COMMANDS remove_debugger_command("socket", dump_socket); remove_debugger_command("sockets", dump_sockets); #endif return B_OK; default: return B_ERROR; } }
//start listening for connections and processing messages. inline void synchListen(){ _DB std::cout << "Entering synchListen()\n"; listen(serverSocket, SOMAXCONN); SOCKET accepted = -1; bool listening = true; auto lamb = [&](bool& listening){ while (listening && runListenLoop){ socklen_t size = sizeof(serverAddress); accepted = accept(serverSocket, (sockaddr *)&serverAddress, &size); if (accepted == SOCKET_ERROR){ //error } else{ std::lock_guard<std::recursive_mutex> lock(mutex); readList.pushSocket(accepted, serverAddress); _DB std::cout << "Adding SOCKET `" << accepted << "` to connected to `" << readList.getAddressString(accepted) << "`." << std::endl; } } }; auto f = std::async(std::launch::async, lamb, std::ref(listening)); _DB std::cout << "Fired the socket aceptor!\n"; bool run = true; runListenLoop = true; while (run && runListenLoop){ auto list = readList.getReadable(); while (list.size() > 0){ std::lock_guard<std::recursive_mutex> lock(mutex); _DB std::cout << "_________________________________________\n"; //std::lock_guard<std::mutex> lock(mutex); ProtMsg msg = getProtocolMessage(list.front()); int ret = handleProtocol(msg, list.front(), run); _DB std::cout << "handling protocol messages.\n"; if (ret == PROTOCOLCODES::CLOSEME){ readList.popSocket(list.front()); } list.pop_front(); } } _DB std::cout << "Exiting sychlisten loop.\n"; }
//send data to a socket at a specific address. inline void sendData(const std::string& address, char * src, uint32_t size){ SOCKET socket = 0; for (const auto& e : readList.sockets){ if (readList.getAddressString(e.first) == address){ socket = e.first; Socket::sendData(socket, src, size); } } }
bool Msg2Msg::AddNewRcvSocket(const char* socketAddrStr) { char charAddr[255]; memset(charAddr,0,255); ProtoAddress rcv_addr; int rcv_port; //parse socketAddrStr const char* index = strchr(socketAddrStr,'/'); if(index!=NULL) { strncpy(charAddr,socketAddrStr,index-socketAddrStr); if(!(rcv_addr.ResolveFromString(charAddr))) { DMSG(0,"Msg2Msg::AddNewRcvSocket() Error setting address to %s\n",charAddr); return false; } rcv_port = atoi(index+1); } else { rcv_port = atoi(socketAddrStr); } ListableSocket *newSocketPtr = new ListableSocket(ProtoPipe::UDP); if(!newSocketPtr) { DMSG(0,"Msg2MsgAddNewRcvSocket error allocing new socket\n"); return false; } newSocketPtr->SetNotifier(&GetSocketNotifier()); newSocketPtr->SetListener(this,&Msg2Msg::OnSocketListenEvent);//bunny the this will need to be changed if(!(newSocketPtr->Open(rcv_port,ProtoAddress::IPv4))) { DMSG(0,"Msg2MsgAddNewRcvSocket Error Opening the socket rcv port %d\n",rcv_port); delete newSocketPtr; return false; } if(rcv_addr.IsMulticast()) //do multicast stuff { if(!newSocketPtr->JoinGroup(rcv_addr)) { DMSG(0,"Msg2MsgAddNewRcvSocket Error joining the multicast group %s\n",rcv_addr.GetHostString()); newSocketPtr->Close(); delete newSocketPtr; return false; } } rcvSockets.Append(*newSocketPtr); return true; }
void net_socket_private::RemoveFromParent() { ASSERT(!is_in_socket_list && parent != NULL); parent = NULL; mutex_lock(&sSocketLock); sSocketList.Add(this); mutex_unlock(&sSocketLock); is_in_socket_list = true; ReleaseReference(); }
status_t socket_get_next_stat(uint32* _cookie, int family, struct net_stat* stat) { MutexLocker locker(sSocketLock); net_socket_private* socket = NULL; SocketList::Iterator iterator = sSocketList.GetIterator(); uint32 cookie = *_cookie; uint32 count = 0; while (true) { socket = iterator.Next(); if (socket == NULL) return B_ENTRY_NOT_FOUND; // TODO: also traverse the pending connections if (count == cookie) break; if (family == -1 || family == socket->family) count++; } *_cookie = count + 1; stat->family = socket->family; stat->type = socket->type; stat->protocol = socket->protocol; stat->owner = socket->owner; stat->state[0] = '\0'; memcpy(&stat->address, &socket->address, sizeof(struct sockaddr_storage)); memcpy(&stat->peer, &socket->peer, sizeof(struct sockaddr_storage)); stat->receive_queue_size = 0; stat->send_queue_size = 0; // fill in protocol specific data (if supported by the protocol) size_t length = sizeof(net_stat); socket->first_info->control(socket->first_protocol, socket->protocol, NET_STAT_SOCKET, stat, &length); return B_OK; }
static int dump_sockets(int argc, char** argv) { kprintf("address kind owner protocol module_info parent\n"); SocketList::Iterator iterator = sSocketList.GetIterator(); while (net_socket_private* socket = iterator.Next()) { print_socket_line(socket, ""); SocketList::Iterator childIterator = socket->pending_children.GetIterator(); while (net_socket_private* child = childIterator.Next()) { print_socket_line(child, " "); } childIterator = socket->connected_children.GetIterator(); while (net_socket_private* child = childIterator.Next()) { print_socket_line(child, " "); } } return 0; }
status_t socket_open(int family, int type, int protocol, net_socket** _socket) { net_socket_private* socket; status_t status = create_socket(family, type, protocol, &socket); if (status != B_OK) return status; status = socket->first_info->open(socket->first_protocol); if (status != B_OK) { delete socket; return status; } socket->owner = team_get_current_team_id(); socket->is_in_socket_list = true; mutex_lock(&sSocketLock); sSocketList.Add(socket); mutex_unlock(&sSocketLock); *_socket = socket; return B_OK; }
bool Msg2Msg::AddNewSndSocket(const char* socketAddrStr) { char charAddr[255]; memset(charAddr,0,255); ProtoAddress dst_addr; int dst_port; int src_port;//bunny setting this to dst port for now this should be controled seperatly //parse the string const char* index = strchr(socketAddrStr,'/'); if(index!=NULL) { strncpy(charAddr,socketAddrStr,index-socketAddrStr); if(!dst_addr.ResolveFromString(charAddr)) { DMSG(0,"Msg2Msg::AddNewSndSocket: Error setting address to %s\n",socketAddrStr); return false; } dst_port = atoi(index+1); src_port = dst_port; dst_addr.SetPort(dst_port); } else { DMSG(0,"Msg2Msg::AddNewSndSocket: Error missing \"/\" for send socket command\n"); return false; } ListableSocket *newSocketPtr = new ListableSocket(ProtoSocket::UDP); if(!newSocketPtr) { DMSG(0,"Msg2MsgAddNewSndSocket error allocing new socket\n"); return false; } if(!(newSocketPtr->Bind(src_port))) { DMSG(0,"Msg2MsgAddNewSndSocket: Error binding to src_port %d\n",src_port); delete newSocketPtr; return false; } if(!(newSocketPtr->Open(src_port,ProtoAddress::IPv4,false))) { DMSG(0,"msg2MsgAddNewSndSocket: Error opening socket on port %d\n",src_port); delete newSocketPtr; return false; } if(dst_addr.IsMulticast()) { if(!newSocketPtr->JoinGroup(dst_addr)) { DMSG(0,"Msg2MsgAddNewSndSocket: Error joinging multicast Group %s\n",dst_addr.GetHostString()); newSocketPtr->Close(); delete newSocketPtr; return false; } } if(!(newSocketPtr->Connect(dst_addr))) { DMSG(0,"Msg2MsgAddNewSndSocket: Error connecting to %s\n",dst_addr.GetHostString()); newSocketPtr->Close(); delete newSocketPtr; return false; } sndSockets.Append(*newSocketPtr); return true; }
//get a strign that reprisents the address of a port inline std::string getAddressString(SOCKET sock){ std::lock_guard<std::recursive_mutex> lock(mutex); return readList.getAddressString(sock); }
int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout) { #if defined(POCO_HAVE_FD_EPOLL) int epollSize = readList.size() + writeList.size() + exceptList.size(); if (epollSize == 0) return 0; int epollfd = -1; { struct epoll_event eventsIn[epollSize]; memset(eventsIn, 0, sizeof(eventsIn)); struct epoll_event* eventLast = eventsIn; for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it) { poco_socket_t sockfd = it->sockfd(); if (sockfd != POCO_INVALID_SOCKET) { struct epoll_event* e = eventsIn; for (; e != eventLast; ++e) { if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) break; } if (e == eventLast) { e->data.ptr = &(*it); ++eventLast; } e->events |= EPOLLIN; } } for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it) { poco_socket_t sockfd = it->sockfd(); if (sockfd != POCO_INVALID_SOCKET) { struct epoll_event* e = eventsIn; for (; e != eventLast; ++e) { if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) break; } if (e == eventLast) { e->data.ptr = &(*it); ++eventLast; } e->events |= EPOLLOUT; } } for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it) { poco_socket_t sockfd = it->sockfd(); if (sockfd != POCO_INVALID_SOCKET) { struct epoll_event* e = eventsIn; for (; e != eventLast; ++e) { if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) break; } if (e == eventLast) { e->data.ptr = &(*it); ++eventLast; } e->events |= EPOLLERR; } } epollSize = eventLast - eventsIn; epollfd = epoll_create(epollSize); if (epollfd < 0) { char buf[1024]; strerror_r(errno, buf, sizeof(buf)); SocketImpl::error(std::string("Can't create epoll queue: ") + buf); } for (struct epoll_event* e = eventsIn; e != eventLast; ++e) { poco_socket_t sockfd = reinterpret_cast<Socket*>(e->data.ptr)->sockfd(); if (sockfd != POCO_INVALID_SOCKET) { if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0) { char buf[1024]; strerror_r(errno, buf, sizeof(buf)); ::close(epollfd); SocketImpl::error(std::string("Can't insert socket to epoll queue: ") + buf); } } } } struct epoll_event eventsOut[epollSize]; memset(eventsOut, 0, sizeof(eventsOut)); Poco::Timespan remainingTime(timeout); int rc; do { Poco::Timestamp start; rc = epoll_wait(epollfd, eventsOut, epollSize, remainingTime.totalMilliseconds()); if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) { Poco::Timestamp end; Poco::Timespan waited = end - start; if (waited < remainingTime) remainingTime -= waited; else remainingTime = 0; } } while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); ::close(epollfd); if (rc < 0) SocketImpl::error(); SocketList readyReadList; SocketList readyWriteList; SocketList readyExceptList; for (int n = 0; n < rc; ++n) { if (eventsOut[n].events & EPOLLERR) readyExceptList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); if (eventsOut[n].events & EPOLLIN) readyReadList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); if (eventsOut[n].events & EPOLLOUT) readyWriteList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); } std::swap(readList, readyReadList); std::swap(writeList, readyWriteList); std::swap(exceptList, readyExceptList); return readList.size() + writeList.size() + exceptList.size(); #elif defined(POCO_HAVE_FD_POLL) nfds_t nfd = readList.size() + writeList.size() + exceptList.size(); if (0 == nfd) return 0; SharedPollArray pPollArr = new pollfd[nfd]; int idx = 0; for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it) { pPollArr[idx].fd = int(it->sockfd()); pPollArr[idx++].events |= POLLIN; } SocketList::iterator begR = readList.begin(); SocketList::iterator endR = readList.end(); for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it) { SocketList::iterator pos = std::find(begR, endR, *it); if (pos != endR) { pPollArr[pos-begR].events |= POLLOUT; --nfd; } else { pPollArr[idx].fd = int(it->sockfd()); pPollArr[idx++].events |= POLLOUT; } } SocketList::iterator begW = writeList.begin(); SocketList::iterator endW = writeList.end(); for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it) { SocketList::iterator pos = std::find(begR, endR, *it); if (pos != endR) --nfd; else { SocketList::iterator pos = std::find(begW, endW, *it); if (pos != endW) --nfd; else pPollArr[idx++].fd = int(it->sockfd()); } } Poco::Timespan remainingTime(timeout); int rc; do { Poco::Timestamp start; rc = ::poll(pPollArr, nfd, timeout.totalMilliseconds()); if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) { Poco::Timestamp end; Poco::Timespan waited = end - start; if (waited < remainingTime) remainingTime -= waited; else remainingTime = 0; } } while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); if (rc < 0) SocketImpl::error(); SocketList readyReadList; SocketList readyWriteList; SocketList readyExceptList; SocketList::iterator begE = exceptList.begin(); SocketList::iterator endE = exceptList.end(); for (int idx = 0; idx < nfd; ++idx) { SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd)); if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt); slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd)); if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt); slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd)); if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt); } std::swap(readList, readyReadList); std::swap(writeList, readyWriteList); std::swap(exceptList, readyExceptList); return readList.size() + writeList.size() + exceptList.size(); #else fd_set fdRead; fd_set fdWrite; fd_set fdExcept; int nfd = 0; FD_ZERO(&fdRead); for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) { poco_socket_t fd = it->sockfd(); if (fd != POCO_INVALID_SOCKET) { if (int(fd) > nfd) nfd = int(fd); FD_SET(fd, &fdRead); } } FD_ZERO(&fdWrite); for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) { poco_socket_t fd = it->sockfd(); if (fd != POCO_INVALID_SOCKET) { if (int(fd) > nfd) nfd = int(fd); FD_SET(fd, &fdWrite); } } FD_ZERO(&fdExcept); for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) { poco_socket_t fd = it->sockfd(); if (fd != POCO_INVALID_SOCKET) { if (int(fd) > nfd) nfd = int(fd); FD_SET(fd, &fdExcept); } } if (nfd == 0) return 0; Poco::Timespan remainingTime(timeout); int rc; do { struct timeval tv; tv.tv_sec = (long) remainingTime.totalSeconds(); tv.tv_usec = (long) remainingTime.useconds(); Poco::Timestamp start; rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv); if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) { Poco::Timestamp end; Poco::Timespan waited = end - start; if (waited < remainingTime) remainingTime -= waited; else remainingTime = 0; } } while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); if (rc < 0) SocketImpl::error(); SocketList readyReadList; for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) { poco_socket_t fd = it->sockfd(); if (fd != POCO_INVALID_SOCKET) { if (FD_ISSET(fd, &fdRead)) readyReadList.push_back(*it); } } std::swap(readList, readyReadList); SocketList readyWriteList; for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) { poco_socket_t fd = it->sockfd(); if (fd != POCO_INVALID_SOCKET) { if (FD_ISSET(fd, &fdWrite)) readyWriteList.push_back(*it); } } std::swap(writeList, readyWriteList); SocketList readyExceptList; for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) { poco_socket_t fd = it->sockfd(); if (fd != POCO_INVALID_SOCKET) { if (FD_ISSET(fd, &fdExcept)) readyExceptList.push_back(*it); } } std::swap(exceptList, readyExceptList); return rc; #endif // POCO_HAVE_FD_EPOLL }
void close_all(SocketList& list) { SocketListLock lock(list); list.close_all(); }
int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout) { fd_set fdRead; fd_set fdWrite; fd_set fdExcept; int nfd = 0; FD_ZERO(&fdRead); for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) { if (int(it->sockfd()) > nfd) nfd = int(it->sockfd()); FD_SET(it->sockfd(), &fdRead); } FD_ZERO(&fdWrite); for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) { if (int(it->sockfd()) > nfd) nfd = int(it->sockfd()); FD_SET(it->sockfd(), &fdWrite); } FD_ZERO(&fdExcept); for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) { if (int(it->sockfd()) > nfd) nfd = int(it->sockfd()); FD_SET(it->sockfd(), &fdExcept); } Poco::Timespan remainingTime(timeout); int rc; do { struct timeval tv; tv.tv_sec = (long) remainingTime.totalSeconds(); tv.tv_usec = (long) remainingTime.useconds(); Poco::Timestamp start; rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv); if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) { Poco::Timestamp end; Poco::Timespan waited = end - start; if (waited < remainingTime) remainingTime -= waited; else remainingTime = 0; } } while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); if (rc < 0) SocketImpl::error(); SocketList readyReadList; for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) { if (FD_ISSET(it->sockfd(), &fdRead)) readyReadList.push_back(*it); } std::swap(readList, readyReadList); SocketList readyWriteList; for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) { if (FD_ISSET(it->sockfd(), &fdWrite)) readyWriteList.push_back(*it); } std::swap(writeList, readyWriteList); SocketList readyExceptList; for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) { if (FD_ISSET(it->sockfd(), &fdExcept)) readyExceptList.push_back(*it); } std::swap(exceptList, readyExceptList); return rc; }