void EthernetSocket::send(EthernetFrame &ef, const DataBuffer &data) { uint8_t * buff = sendBuffer.data(); size_t size {}; if (ef.sourceMac.isUnset()) { ef.sourceMac = interfaceMac; } // Copy Supplied Ethernet Frame ef.copyTo(buff); size += ef.destinationMac.getMacArray().size() + ef.sourceMac.getMacArray().size() + sizeof(u_int16_t); buff += size; // Copy payload data if (sendBuffer.size() - size < data.size()) { throw runtime_error("send: Data too large"); } copy(data.begin(), data.end(), buff); size += data.size(); // Send packet if (sendto(sockfd, sendBuffer.data(), size, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)) < 0) { throw runtime_error(string("send: ") + strerror(errno)); } }
void Consumer::printInOrderData() { while (true) { const auto i = m_bufferedData.find(m_nextToPrint); if (i == m_bufferedData.end()) break; const Block& content = i->second->getContent(); std::cout.write(reinterpret_cast<const char*>(content.value()), content.value_size()); m_bufferedData.erase(i); m_nextToPrint++; } }
void UpnpPortMapping::mapPort(const std::string& gateway, const std::string& client, uint16_t port, PortType type, bool enable) { { std::lock_guard<std::mutex> guard(state->stateMutex); for (auto it = state->pendingRequests.begin(); it != state->pendingRequests.end(); it++) { if ((*it)->getHostname() == gateway) { UpnpMappingState::TodoMapping todo; todo.mapping = { gateway, port, type }; todo.client = client; todo.enable = enable; todo.blockingStream = (*it).get(); state->waitingMapping.push_back(todo); return; } } } std::string portStr = std::to_string(port); std::string portType = type == PortType::Tcp ? "TCP" : "UDP"; auto request = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<s:Envelope xmlns:s =\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "<s:Body>\n" "<u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">\n" "<NewRemoteHost></NewRemoteHost>\n" "<NewExternalPort>" + portStr + "</NewExternalPort>\n" "<NewProtocol>" + portType + "</NewProtocol>\n" "<NewInternalPort>" + portStr + "</NewInternalPort>\n" "<NewInternalClient>" + client + "</NewInternalClient>\n" "<NewEnabled>" + std::string(enable ? "1" : "0") + "</NewEnabled>\n" "<NewPortMappingDescription>mtTorrent UPnP " + portStr + " " + portType + "</NewPortMappingDescription>\n" "<NewLeaseDuration>0</NewLeaseDuration>\n" "</u:AddPortMapping>\n" "</s:Body>\n" "</s:Envelope>\r\n"; auto httpHeader = createUpnpHttpHeader(gateway + ":1900", request.length(), "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"); auto stream = std::make_shared<TcpAsyncStream>(io); state->pendingRequests.push_back(stream); auto streamPtr = stream.get(); auto upnpState = state; stream->onConnectCallback = [streamPtr, httpHeader, request]() { DataBuffer buffer; buffer.assign(httpHeader.begin(), httpHeader.end()); buffer.insert(buffer.end(), request.begin(), request.end()); streamPtr->write(buffer); }; stream->onReceiveCallback = [streamPtr, upnpState, gateway, port, type]() { auto data = streamPtr->getReceivedData(); auto header = HttpHeaderInfo::readFromBuffer(data); if (header.valid && data.size() >= (header.dataStart + header.dataSize)) { streamPtr->consumeData(header.dataStart + header.dataSize); std::lock_guard<std::mutex> guard(upnpState->stateMutex); if (header.success) { upnpState->mappedPorts.push_back({ gateway, port, type }); } } }; stream->onCloseCallback = [streamPtr, upnpState, this](int code) { { std::lock_guard<std::mutex> guard(upnpState->stateMutex); for (auto it = upnpState->pendingRequests.begin(); it != upnpState->pendingRequests.end(); it++) { if ((*it).get() == streamPtr) { upnpState->pendingRequests.erase(it); break; } } } if (upnpState->active) { checkPendingMapping(streamPtr); } }; stream->connect(gateway, 1900); }
void UpnpPortMapping::unmapPort(const std::string& gateway, uint16_t port, PortType type) { std::string portStr = std::to_string(port); std::string portType = type == PortType::Tcp ? "TCP" : "UDP"; auto request = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "<s:Body>\n" "<u:DeletePortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">\n" "<NewRemoteHost></NewRemoteHost>\n" "<NewProtocol>" + portType + "</NewProtocol>\n" "<NewExternalPort>" + portStr + "</NewExternalPort>\n" "</u:DeletePortMapping>\n" "</s:Body>\n" "</s:Envelope>\r\n"; auto httpHeader = createUpnpHttpHeader(gateway + ":1900", request.length(), "urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping"); auto stream = std::make_shared<TcpAsyncStream>(io); auto streamPtr = stream.get(); state->pendingRequests.push_back(stream); auto upnpState = state; stream->onConnectCallback = [streamPtr, upnpState, httpHeader, request]() { DataBuffer buffer; buffer.assign(httpHeader.begin(), httpHeader.end()); buffer.insert(buffer.end(), request.begin(), request.end()); std::lock_guard<std::mutex> guard(upnpState->stateMutex); streamPtr->write(buffer); }; stream->onReceiveCallback = [streamPtr, upnpState, gateway, port, type]() { auto data = streamPtr->getReceivedData(); auto header = HttpHeaderInfo::readFromBuffer(data); if (header.valid && data.size() >= (header.dataStart + header.dataSize)) { streamPtr->consumeData(header.dataStart + header.dataSize); std::lock_guard<std::mutex> guard(upnpState->stateMutex); if (header.success) { for (auto it = upnpState->mappedPorts.begin(); it != upnpState->mappedPorts.end(); it++) { if (it->gateway == gateway && it->port == port && it->type == type) { upnpState->mappedPorts.erase(it); break; } } } } }; stream->onCloseCallback = [streamPtr, upnpState](int code) { std::lock_guard<std::mutex> guard(upnpState->stateMutex); for (auto it = upnpState->pendingRequests.begin(); it != upnpState->pendingRequests.end(); it++) { if ((*it).get() == streamPtr) { upnpState->pendingRequests.erase(it); break; } } }; stream->connect(gateway, 1900); }