URIReader optimizations/improvements, support for getHost/getBinHost functions, socket lib improvements + related improvements

This commit is contained in:
Thulinma 2023-04-10 03:45:14 +02:00
parent 4df771eb02
commit 1df76eff16
6 changed files with 70 additions and 42 deletions

View file

@ -357,7 +357,7 @@ namespace Comms{
dataPage.init(userPageName, 0, false, false);
if (!dataPage){
std::string host;
Socket::hostBytesToStr(ip.data(), 16, host);
Socket::hostBytesToStr(ip.data(), ip.size(), host);
pid_t thisPid;
std::deque<std::string> args;
args.push_back(Util::getMyPath() + "MistSession");

View file

@ -1221,7 +1221,7 @@ std::string Socket::Connection::getBoundAddress() const{
/// Gets binary IPv6 address for connection, if available.
/// Guaranteed to be either empty or 16 bytes long.
std::string Socket::Connection::getBinHost(){
std::string Socket::Connection::getBinHost() const{
return getIPv6BinAddr(remoteaddr);
}
@ -1726,6 +1726,22 @@ void Socket::UDPConnection::setSocketFamily(int AF_TYPE){\
family = AF_TYPE;
}
/// Allocates enough space for the largest type of address we support, so that receive calls can write to it.
void Socket::UDPConnection::allocateDestination(){
if (destAddr && destAddr_size < sizeof(sockaddr_in6)){
free(destAddr);
destAddr = 0;
}
if (!destAddr){
destAddr = malloc(sizeof(sockaddr_in6));
if (destAddr){
destAddr_size = sizeof(sockaddr_in6);
memset(destAddr, 0, sizeof(sockaddr_in6));
((struct sockaddr_in *)destAddr)->sin_family = AF_UNSPEC;
}
}
}
/// Stores the properties of the receiving end of this UDP socket.
/// This will be the receiving end for all SendNow calls.
void Socket::UDPConnection::SetDestination(std::string destIp, uint32_t port){
@ -1824,7 +1840,8 @@ void Socket::UDPConnection::GetDestination(std::string &destIp, uint32_t &port){
/// Gets the properties of the receiving end of this UDP socket.
/// This will be the receiving end for all SendNow calls.
std::string Socket::UDPConnection::getBinDestination(){
std::string binList = getIPv6BinAddr(*(sockaddr_in6*)destAddr);
std::string binList;
if (destAddr && destAddr_size){binList = getIPv6BinAddr(*(sockaddr_in6*)destAddr);}
if (binList.size() < 16){return std::string("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16);}
return binList.substr(0, 16);
}// Socket::UDPConnection GetDestination
@ -2081,12 +2098,14 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str
bool Socket::UDPConnection::Receive(){
if (sock == -1){return false;}
data.truncate(0);
socklen_t destsize = destAddr_size;
int r = recvfrom(sock, data, data.rsize(), MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)destAddr, &destsize);
sockaddr_in6 addr;
socklen_t destsize = sizeof(addr);
int r = recvfrom(sock, data, data.rsize(), MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&addr, &destsize);
if (r == -1){
if (errno != EAGAIN){INFO_MSG("UDP receive: %d (%s)", errno, strerror(errno));}
return false;
}
if (destAddr && destsize && destAddr_size >= destsize){memcpy(destAddr, &addr, destsize);}
data.append(0, r);
down += r;
//Handle UDP packets that are too large

View file

@ -134,7 +134,7 @@ namespace Socket{
void setBlocking(bool blocking); ///< Set this socket to be blocking (true) or nonblocking (false).
bool isBlocking(); ///< Check if this socket is blocking (true) or nonblocking (false).
std::string getHost() const; ///< Gets hostname for connection, if available.
std::string getBinHost();
std::string getBinHost() const;
void setHost(std::string host); ///< Sets hostname for connection manually.
std::string getBoundAddress() const;
int getSocket(); ///< Returns internal socket number.
@ -216,6 +216,7 @@ namespace Socket{
int getSock();
uint16_t bind(int port, std::string iface = "", const std::string &multicastAddress = "");
void setBlocking(bool blocking);
void allocateDestination();
void SetDestination(std::string hostname, uint32_t port);
void GetDestination(std::string &hostname, uint32_t &port);
std::string getBinDestination();

View file

@ -277,6 +277,16 @@ namespace HTTP{
return false;
}
std::string URIReader::getHost() const{
if (stateType == HTTP::File){return "";}
return downer.getSocket().getHost();
}
std::string URIReader::getBinHost() const{
if (stateType == HTTP::File){return std::string("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16);}
return downer.getSocket().getBinHost();
}
void URIReader::readAll(size_t (*dataCallback)(const char *data, size_t len)){
while (!isEOF()){readSome(dataCallback, 419430);}
}
@ -306,31 +316,25 @@ namespace HTTP{
// readsome with callback
void URIReader::readSome(size_t wantedLen, Util::DataCallback &cb){
if (isEOF()){return;}
// Files read from the memory-mapped file
if (stateType == HTTP::File){
// dataPtr = mapped + curPos;
uint64_t dataLen = 0;
if (wantedLen < totalSize){
if ((wantedLen + curPos) > totalSize){
dataLen = totalSize - curPos; // restant
// INFO_MSG("file curpos: %llu, dataLen: %llu, totalSize: %llu ", curPos, dataLen, totalSize);
}else{
dataLen = wantedLen;
}
}else{
dataLen = totalSize;
}
std::string t = std::string(mapped + curPos, dataLen);
cb.dataCallback(t.c_str(), dataLen);
// Simple bounds check, don't read beyond the end of the file
uint64_t dataLen = ((wantedLen + curPos) > totalSize) ? totalSize - curPos : wantedLen;
cb.dataCallback(mapped + curPos, dataLen);
curPos += dataLen;
}else if (stateType == HTTP::HTTP){
return;
}
// HTTP-based read from the Downloader
if (stateType == HTTP::HTTP){
// Note: this function returns true if the full read was completed only.
// It's the reason this function returns void rather than bool.
downer.continueNonBlocking(cb);
}else{// streaming mode
return;
}
// Everything else uses the socket directly
int s = downer.getSocket().Received().bytes(wantedLen);
if (!s){
// Only attempt to read more if nothing was in the buffer
if (downer.getSocket() && downer.getSocket().spool()){
s = downer.getSocket().Received().bytes(wantedLen);
}else{
@ -338,11 +342,12 @@ namespace HTTP{
return;
}
}
// Future optimization: augment the Socket::Buffer to handle a Util::DataCallback as argument.
// Would remove the need for this extra copy here.
Util::ResizeablePointer buf;
downer.getSocket().Received().remove(buf, s);
cb.dataCallback(buf, s);
}
}
/// Readsome blocking function.
void URIReader::readSome(char *&dataPtr, size_t &dataLen, size_t wantedLen){

View file

@ -67,6 +67,9 @@ namespace HTTP{
std::string userAgentOverride;
std::string getHost() const; ///< Gets hostname for connection, or [::] if local.
std::string getBinHost() const; ///< Gets binary form hostname for connection, or [::] if local.
private:
// Internal state variables
bool (*cbProgress)(uint8_t); ///< The progress callback, if any. Not called if set to a null pointer.

View file

@ -836,7 +836,7 @@ namespace Mist{
}
// this is necessary so that we can get the remote IP when creating STUN replies.
udp.SetDestination("0.0.0.0", 4444);
udp.allocateDestination();
// we set parseData to `true` to start the data flow. Is also
// used to break out of our loop in `onHTTP()`.
@ -1153,7 +1153,7 @@ namespace Mist{
// function. The `webRTCInputOutputThreadFunc()` is basically empty
// and all work for the thread is done here.
void OutWebRTC::handleWebRTCInputOutputFromThread(){
udp.SetDestination("0.0.0.0", 4444);
udp.allocateDestination();
while (keepGoing()){
if (!handleWebRTCInputOutput()){Util::sleep(20);}
}