uint FgLinkGraph<NodeData,LinkData>::addLink( const LinkData & data, const vector<uint> & sources, const vector<uint> & sinks) { FGASSERT(sinks.size() > 0); // A Link must have at least 1 sink uint linkIdx = uint(m_links.size()); m_links.push_back(Link(sources,sinks,data)); // Update the node cross-referencing: for (size_t ii=0; ii<sinks.size(); ii++) { FGASSERT(sinks[ii] < uint(m_nodes.size())); FGASSERT(!fgContains(sources,sinks[ii])); // Causes nasty bugs later Node & node = m_nodes[sinks[ii]]; if (node.incomingLink.valid()) fgThrow("A FgLinkGraph node cannot be a sink for more than 1 link",fgToString(ii)); node.incomingLink = linkIdx; } for (size_t ii=0; ii<sources.size(); ii++) { FGASSERT(sources[ii] < uint(m_nodes.size())); Node & node = m_nodes[sources[ii]]; node.outgoingLinks.push_back(linkIdx); } return linkIdx; }
WinsockDll() { // Initialize Winsock DLL version 2.2: int itmp = WSAStartup(MAKEWORD(2,2),&wsaData); if(itmp != 0) FGASSERT_FALSE1(fgToString(itmp)); }
bool fgTcpClient( const string & hostname, uint16 port, const string & data, bool getResponse, string & response) { initWinsock(); SOCKET socketHandle; struct addrinfo * addressInfo; socketHandle = INVALID_SOCKET; addressInfo = NULL; struct addrinfo hints; int itmp; ZeroMemory(&hints,sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; // Resolve the server address and port. itmp = getaddrinfo( hostname.c_str(), // Hostname or IP # fgToString(port).c_str(), // Service name or port # &hints, &addressInfo); // RETURNED if (itmp != 0) return false; // Server does not appear to exist struct addrinfo *ptr = NULL; // Attempt to connect to an IP address until one succeeds. It's possible // for more than 1 to be returned if there are more than 1 namespace service // providers (for instance local hosts file vs. DNS server), according to // MS docs: for(ptr=addressInfo; ptr != NULL ;ptr=ptr->ai_next) { socketHandle = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (socketHandle == INVALID_SOCKET) { // Couldn't use scope guard for freeaddrinfo due to compile issues: freeaddrinfo(addressInfo); FGASSERT_FALSE1(fgToString(WSAGetLastError())); } // Try to connect to the server itmp = connect( socketHandle, ptr->ai_addr, (int)ptr->ai_addrlen); if (itmp == 0) break; else { closesocket(socketHandle); socketHandle = INVALID_SOCKET; } } freeaddrinfo(addressInfo); if (socketHandle == INVALID_SOCKET) return false; // Unable to connect, server not listening ? // 'send' will block for buffering since we've created a blocking socket, so the // value returned is always either the data size or an error: itmp = send(socketHandle,data.data(),int(data.size()),0); FGASSERT1(itmp != SOCKET_ERROR,fgToString(WSAGetLastError())); // close socket for sending to cause server's recv/read to return a zero // size data packet if server is waiting for more (ie to flush the stream). itmp = shutdown(socketHandle,SD_SEND); FGASSERT1(itmp != SOCKET_ERROR,fgToString(WSAGetLastError())); if (getResponse) { response.clear(); do { char buff[1024]; // If server doesn't respond and closes connection we'll immediately get // a value of zero here and nothing will be placed in buff. Otherwise // we'll continue to receive data until server closes connection causing // the zero message: itmp = recv(socketHandle,buff,sizeof(buff),0); FGASSERT1(itmp != SOCKET_ERROR,fgToString(WSAGetLastError())); if (itmp > 0) response += string(buff,itmp); } while (itmp > 0); FGASSERT(itmp == 0); } // Couldn't use scope guard due to compile issues: closesocket(socketHandle); return true; }
void fgTcpServer( uint16 port, bool respond, bool(*handler)(const string & ipAddr,const string & dataIn,string & response), size_t maxRecvBytes) { initWinsock(); SOCKET sockListen = INVALID_SOCKET; // Set up the listening socket: struct addrinfo hints; ZeroMemory(&hints,sizeof(hints)); hints.ai_family = AF_INET; // IPv4 hints.ai_socktype = SOCK_STREAM; // A reliable, 2-way, stream-based connection (requires TCP) hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; struct addrinfo *addrInfoPtr = NULL; int itmp = getaddrinfo(NULL,fgToString(port).c_str(),&hints,&addrInfoPtr); FGASSERT1(itmp == 0,fgToString(itmp)); sockListen = socket(addrInfoPtr->ai_family,addrInfoPtr->ai_socktype,addrInfoPtr->ai_protocol); if (sockListen == INVALID_SOCKET) { freeaddrinfo(addrInfoPtr); FGASSERT_FALSE1(fgToString(WSAGetLastError())); } itmp = bind(sockListen,addrInfoPtr->ai_addr,(int)addrInfoPtr->ai_addrlen); if (itmp == SOCKET_ERROR) { closesocket(sockListen); freeaddrinfo(addrInfoPtr); FGASSERT_FALSE1(fgToString(WSAGetLastError())); } itmp = listen(sockListen, SOMAXCONN); if (itmp == SOCKET_ERROR) { closesocket(sockListen); freeaddrinfo(addrInfoPtr); FGASSERT_FALSE1(fgToString(WSAGetLastError())); } freeaddrinfo(addrInfoPtr); // Receive messages and respond until finished: SOCKET sockClient; bool handlerRetval = true; do { fgout << fgnl << "> " << std::flush; sockaddr_in sa; sa.sin_family = AF_INET; socklen_t sz = sizeof(sa); sockClient = accept(sockListen,(sockaddr*)(&sa),&sz); if (sockClient == INVALID_SOCKET) { closesocket(sockListen); FGASSERT_FALSE1(fgToString(WSAGetLastError())); } char * clientStringPtr = inet_ntoa(sa.sin_addr); FGASSERT(clientStringPtr != NULL); string ipAddr = string(clientStringPtr); //fgout << "receiving from " << ipAddr << " ... " << std::flush; string dataBuff; int itmp = 0; do { char recvbuf[1024]; // recv() will return when either it has filled the buffer, copied over everthing // from the socket input buffer (only if non-empty), or when the the read connection // is closed by the client. Otherwise it will block (ie if input buffer empty): itmp = recv(sockClient,recvbuf,sizeof(recvbuf),0); fgout << "." << std::flush; if (itmp > 0) dataBuff += string(recvbuf,itmp); } while ((itmp > 0) && (dataBuff.size() <= maxRecvBytes)); if (itmp != 0) { closesocket(sockClient); if (itmp < 0) fgout << "TCP RECV ERROR: " << itmp; else if (itmp > 0) fgout << " OVERSIZE MESSAGE IGNORED."; fgout << std::flush; continue; } fgout << ": " << std::flush; if (!respond) // Avoid timeout errors on the data socket for long handlers that don't respond: closesocket(sockClient); string response; try { handlerRetval = handler(ipAddr,dataBuff,response); } catch(FgException const & e) { fgout << "Handler exception (FG4 exception): " << e.no_tr_message(); } catch(std::exception const & e) { fgout << "Handler exception (std::exception): " << e.what(); } catch(...) { fgout << "Handler exception (unknown type)"; } if (respond) { if (!response.empty()) { int bytesSent = send(sockClient,response.data(),int(response.size()),0); shutdown(sockClient,SD_SEND); if (bytesSent != int(response.size())) fgout << "TCP SEND ERROR: " << bytesSent << " (of " << response.size() << ")."; } closesocket(sockClient); } fgout << std::flush; } while (handlerRetval == true); closesocket(sockListen); }