mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-13 17:16:42 +02:00
requestMsg
git-svn-id: svn://elaine/murooma/trunk@267 d8a302eb-03bc-478d-80e4-98257eca68ef
This commit is contained in:
parent
444ec9b4ee
commit
19e77f0f20
7 changed files with 170 additions and 60 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "common/serverSettings.h"
|
#include "common/serverSettings.h"
|
||||||
#include "common/timeMsg.h"
|
#include "common/timeMsg.h"
|
||||||
|
#include "common/requestMsg.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ void Controller::onMessageReceived(SocketConnection* connection, const BaseMessa
|
||||||
delete pcmChunk;
|
delete pcmChunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (baseMessage.type == message_type::header)
|
/* else if (baseMessage.type == message_type::header)
|
||||||
{
|
{
|
||||||
if (decoder != NULL)
|
if (decoder != NULL)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +59,7 @@ void Controller::onMessageReceived(SocketConnection* connection, const BaseMessa
|
||||||
cout << "ServerSettings port: " << serverSettings->port << "\n";
|
cout << "ServerSettings port: " << serverSettings->port << "\n";
|
||||||
streamClient = new StreamClient(this, ip, serverSettings->port);
|
streamClient = new StreamClient(this, ip, serverSettings->port);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,14 +86,27 @@ void Controller::worker()
|
||||||
// Decoder* decoder;
|
// Decoder* decoder;
|
||||||
active_ = true;
|
active_ = true;
|
||||||
|
|
||||||
while ((sampleFormat == NULL) && (streamClient == NULL))
|
RequestMsg requestMsg("serverSettings");
|
||||||
{
|
shared_ptr<ServerSettings> serverSettings(NULL);
|
||||||
usleep(10000);
|
while (!(serverSettings = controlConnection->sendReq<ServerSettings>(&requestMsg, 2000)));
|
||||||
}
|
cout << "ServerSettings port: " << serverSettings->port << "\n";
|
||||||
|
streamClient = new StreamClient(this, ip, serverSettings->port);
|
||||||
streamClient->start();
|
|
||||||
|
|
||||||
stream = new Stream(SampleFormat(*sampleFormat));
|
requestMsg.request = "sampleFormat";
|
||||||
|
while (!(sampleFormat = controlConnection->sendReq<SampleFormat>(&requestMsg, 2000)));
|
||||||
|
cout << "SampleFormat rate: " << sampleFormat->rate << ", bits: " << sampleFormat->bits << ", channels: " << sampleFormat->channels << "\n";
|
||||||
|
|
||||||
|
if (decoder != NULL)
|
||||||
|
{
|
||||||
|
requestMsg.request = "headerChunk";
|
||||||
|
shared_ptr<HeaderMessage> headerChunk(NULL);
|
||||||
|
while (!(headerChunk = controlConnection->sendReq<HeaderMessage>(&requestMsg, 2000)));
|
||||||
|
decoder->setHeader(headerChunk.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
streamClient->start();
|
||||||
|
stream = new Stream(*sampleFormat);
|
||||||
stream->setBufferLen(bufferMs);
|
stream->setBufferLen(bufferMs);
|
||||||
|
|
||||||
Player player(stream);
|
Player player(stream);
|
||||||
|
@ -101,23 +116,17 @@ void Controller::worker()
|
||||||
while (active_)
|
while (active_)
|
||||||
{
|
{
|
||||||
usleep(1000000);//1000000);
|
usleep(1000000);//1000000);
|
||||||
TimeMsg timeMsg;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
shared_ptr<PendingRequest> reply = controlConnection->sendRequest(&timeMsg, 2000);
|
RequestMsg requestMsg("time");
|
||||||
|
shared_ptr<TimeMsg> reply = controlConnection->sendReq<TimeMsg>(&requestMsg, 2000);
|
||||||
if (reply)
|
if (reply)
|
||||||
{
|
{
|
||||||
if (reply->response->type == message_type::timemsg)
|
//cout << "Reply: " << reply->message.type << ", size: " << reply->message.size << ", sent: " << reply->message.sent.sec << "," << reply->message.sent.usec << ", recv: " << reply->message.received.sec << "," << reply->message.received.usec << "\n";
|
||||||
{
|
double latency = (reply->received.sec - reply->sent.sec) + (reply->received.usec - reply->sent.usec) / 1000000.;
|
||||||
//cout << "Reply: " << reply->response->type << ", size: " << reply->response->size << ", sent: " << reply->response->sent.sec << "," << reply->response->sent.usec << ", recv: " << reply->response->received.sec << "," << reply->response->received.usec << "\n";
|
// cout << "C2S: " << timeMsg.latency << ", S2C: " << latency << ", diff: " << (timeMsg.latency - latency) / 2 << endl;
|
||||||
TimeMsg timeMsg;
|
timeBuffer.add((reply->latency - latency) * 10000 / 2);
|
||||||
timeMsg.deserialize(*reply->response, reply->buffer);
|
cout << timeBuffer.median() << "\n";
|
||||||
double latency = (timeMsg.received.sec - timeMsg.sent.sec) + (timeMsg.received.usec - timeMsg.sent.usec) / 1000000.;
|
|
||||||
cout << "C2S: " << timeMsg.latency << ", S2C: " << latency << ", diff: " << (timeMsg.latency - latency) / 2 << endl;
|
|
||||||
timeBuffer.add((timeMsg.latency - latency) / 2);
|
|
||||||
cout << timeBuffer.median() << "\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
|
|
|
@ -24,11 +24,11 @@ private:
|
||||||
std::thread* controllerThread;
|
std::thread* controllerThread;
|
||||||
StreamClient* streamClient;
|
StreamClient* streamClient;
|
||||||
ClientConnection* controlConnection;
|
ClientConnection* controlConnection;
|
||||||
SampleFormat* sampleFormat;
|
|
||||||
Decoder* decoder;
|
Decoder* decoder;
|
||||||
Stream* stream;
|
Stream* stream;
|
||||||
int bufferMs;
|
int bufferMs;
|
||||||
std::string ip;
|
std::string ip;
|
||||||
|
std::shared_ptr<SampleFormat> sampleFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@ enum message_type
|
||||||
payload = 2,
|
payload = 2,
|
||||||
sampleformat = 3,
|
sampleformat = 3,
|
||||||
serversettings = 4,
|
serversettings = 4,
|
||||||
timemsg = 5
|
timemsg = 5,
|
||||||
|
requestmsg = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,7 +89,6 @@ struct tv
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct BaseMessage
|
struct BaseMessage
|
||||||
{
|
{
|
||||||
BaseMessage() : type(base), id(0), refersTo(0)
|
BaseMessage() : type(base), id(0), refersTo(0)
|
||||||
|
@ -168,6 +168,18 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct SerializedMessage
|
||||||
|
{
|
||||||
|
~SerializedMessage()
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseMessage message;
|
||||||
|
char* buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
52
common/requestMsg.h
Normal file
52
common/requestMsg.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef REQUEST_MSG_H
|
||||||
|
#define REQUEST_MSG_H
|
||||||
|
|
||||||
|
#include "message.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
class RequestMsg : public BaseMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RequestMsg() : BaseMessage(message_type::requestmsg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestMsg(const std::string& _request) : BaseMessage(message_type::requestmsg), request(_request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~RequestMsg()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void read(std::istream& stream)
|
||||||
|
{
|
||||||
|
int16_t size;
|
||||||
|
stream.read(reinterpret_cast<char *>(&size), sizeof(int16_t));
|
||||||
|
request.resize(size);
|
||||||
|
stream.read(&request[0], size);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32_t getSize()
|
||||||
|
{
|
||||||
|
return sizeof(int16_t) + request.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string request;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void doserialize(std::ostream& stream)
|
||||||
|
{
|
||||||
|
int16_t size(request.size());
|
||||||
|
stream.write(reinterpret_cast<char *>(&size), sizeof(int16_t));
|
||||||
|
stream.write(request.c_str(), size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ void SocketConnection::stop()
|
||||||
|
|
||||||
bool SocketConnection::send(BaseMessage* message)
|
bool SocketConnection::send(BaseMessage* message)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> mlock(mutex_);
|
// std::unique_lock<std::mutex> mlock(mutex_);
|
||||||
//cout << "send: " << message->type << ", size: " << message->getSize() << "\n";
|
//cout << "send: " << message->type << ", size: " << message->getSize() << "\n";
|
||||||
if (!connected())
|
if (!connected())
|
||||||
return false;
|
return false;
|
||||||
|
@ -64,26 +64,33 @@ bool SocketConnection::send(BaseMessage* message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
shared_ptr<PendingRequest> SocketConnection::sendRequest(BaseMessage* message, size_t timeout)
|
shared_ptr<SerializedMessage> SocketConnection::sendRequest(BaseMessage* message, size_t timeout)
|
||||||
{
|
{
|
||||||
shared_ptr<PendingRequest> response(NULL);
|
shared_ptr<SerializedMessage> response(NULL);
|
||||||
if (++reqId == 0)
|
if (++reqId == 0)
|
||||||
++reqId;
|
++reqId;
|
||||||
message->id = reqId;
|
message->id = reqId;
|
||||||
shared_ptr<PendingRequest> pendingRequest(new PendingRequest(reqId));
|
shared_ptr<PendingRequest> pendingRequest(new PendingRequest(reqId));
|
||||||
pendingRequests.insert(pendingRequest);
|
|
||||||
std::mutex mtx;
|
{
|
||||||
std::unique_lock<std::mutex> lck(mtx);
|
std::unique_lock<std::mutex> mlock(mutex_);
|
||||||
|
pendingRequests.insert(pendingRequest);
|
||||||
|
}
|
||||||
|
// std::mutex mtx;
|
||||||
|
std::unique_lock<std::mutex> lck(m);
|
||||||
send(message);
|
send(message);
|
||||||
if (pendingRequest->cv.wait_for(lck,std::chrono::milliseconds(timeout)) == std::cv_status::no_timeout)
|
if (pendingRequest->cv.wait_for(lck,std::chrono::milliseconds(timeout)) == std::cv_status::no_timeout)
|
||||||
{
|
{
|
||||||
response = pendingRequest;
|
response = pendingRequest->response;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cout << "timeout while waiting for response to: " << reqId << "\n";
|
cout << "timeout while waiting for response to: " << reqId << "\n";
|
||||||
}
|
}
|
||||||
pendingRequests.erase(pendingRequest);
|
{
|
||||||
|
std::unique_lock<std::mutex> mlock(mutex_);
|
||||||
|
pendingRequests.erase(pendingRequest);
|
||||||
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,18 +110,23 @@ void SocketConnection::getNextMessage()
|
||||||
tv t;
|
tv t;
|
||||||
baseMessage.received = t;
|
baseMessage.received = t;
|
||||||
|
|
||||||
for (auto req: pendingRequests)
|
|
||||||
{
|
{
|
||||||
if (req->id == baseMessage.refersTo)
|
std::unique_lock<std::mutex> mlock(mutex_);
|
||||||
|
for (auto req: pendingRequests)
|
||||||
{
|
{
|
||||||
|
if (req->id == baseMessage.refersTo)
|
||||||
|
{
|
||||||
//cout << "getNextMessage response: " << baseMessage.type << ", size: " << baseMessage.size << "\n";
|
//cout << "getNextMessage response: " << baseMessage.type << ", size: " << baseMessage.size << "\n";
|
||||||
//long latency = (baseMessage.received.sec - baseMessage.sent.sec) * 1000000 + (baseMessage.received.usec - baseMessage.sent.usec);
|
//long latency = (baseMessage.received.sec - baseMessage.sent.sec) * 1000000 + (baseMessage.received.usec - baseMessage.sent.usec);
|
||||||
//cout << "latency: " << latency << "\n";
|
//cout << "latency: " << latency << "\n";
|
||||||
req->response = new BaseMessage(baseMessage);
|
req->response.reset(new SerializedMessage());
|
||||||
req->buffer = (char*)malloc(baseMessage.size);
|
req->response->message = baseMessage;
|
||||||
memcpy(req->buffer, &buffer[0], baseMessage.size);
|
req->response->buffer = (char*)malloc(baseMessage.size);
|
||||||
req->cv.notify_one();
|
memcpy(req->response->buffer, &buffer[0], baseMessage.size);
|
||||||
return;
|
std::unique_lock<std::mutex> lck(m);
|
||||||
|
req->cv.notify_one();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,10 @@ class SocketConnection;
|
||||||
|
|
||||||
struct PendingRequest
|
struct PendingRequest
|
||||||
{
|
{
|
||||||
PendingRequest(uint16_t reqId) : id(reqId), response(NULL), buffer(NULL) {};
|
PendingRequest(uint16_t reqId) : id(reqId), response(NULL) {};
|
||||||
~PendingRequest()
|
|
||||||
{
|
|
||||||
if (response != NULL);
|
|
||||||
delete response;
|
|
||||||
if (buffer != NULL)
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
BaseMessage* response;
|
std::shared_ptr<SerializedMessage> response;
|
||||||
char* buffer;
|
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,7 +43,18 @@ public:
|
||||||
virtual void start();
|
virtual void start();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
virtual bool send(BaseMessage* _message);
|
virtual bool send(BaseMessage* _message);
|
||||||
virtual std::shared_ptr<PendingRequest> sendRequest(BaseMessage* message, size_t timeout);
|
virtual std::shared_ptr<SerializedMessage> sendRequest(BaseMessage* message, size_t timeout);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::shared_ptr<T> sendReq(BaseMessage* message, size_t timeout)
|
||||||
|
{
|
||||||
|
std::shared_ptr<SerializedMessage> reply = sendRequest(message, timeout);
|
||||||
|
if (!reply)
|
||||||
|
return NULL;
|
||||||
|
std::shared_ptr<T> msg(new T);
|
||||||
|
msg->deserialize(reply->message, reply->buffer);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool active()
|
virtual bool active()
|
||||||
{
|
{
|
||||||
|
@ -79,7 +82,8 @@ protected:
|
||||||
tcp::resolver::iterator iterator;
|
tcp::resolver::iterator iterator;
|
||||||
std::thread* receiverThread;
|
std::thread* receiverThread;
|
||||||
mutable std::mutex mutex_;
|
mutable std::mutex mutex_;
|
||||||
std::set<std::shared_ptr<PendingRequest>> pendingRequests;
|
std::mutex m;
|
||||||
|
std::set<std::shared_ptr<PendingRequest>> pendingRequests;
|
||||||
uint16_t reqId;
|
uint16_t reqId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "controlServer.h"
|
#include "controlServer.h"
|
||||||
#include "common/timeMsg.h"
|
#include "common/timeMsg.h"
|
||||||
|
#include "common/requestMsg.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,16 +12,36 @@ ControlServer::ControlServer(unsigned short port) : port_(port), headerChunk(NUL
|
||||||
void ControlServer::onMessageReceived(SocketConnection* connection, const BaseMessage& baseMessage, char* buffer)
|
void ControlServer::onMessageReceived(SocketConnection* connection, const BaseMessage& baseMessage, char* buffer)
|
||||||
{
|
{
|
||||||
// cout << "onMessageReceived: " << baseMessage.type << ", size: " << baseMessage.size << ", sent: " << baseMessage.sent.sec << "," << baseMessage.sent.usec << ", recv: " << baseMessage.received.sec << "," << baseMessage.received.usec << "\n";
|
// cout << "onMessageReceived: " << baseMessage.type << ", size: " << baseMessage.size << ", sent: " << baseMessage.sent.sec << "," << baseMessage.sent.usec << ", recv: " << baseMessage.received.sec << "," << baseMessage.received.usec << "\n";
|
||||||
if (baseMessage.type == message_type::timemsg)
|
if (baseMessage.type == message_type::requestmsg)
|
||||||
{
|
{
|
||||||
TimeMsg timeMsg;
|
RequestMsg requestMsg;
|
||||||
timeMsg.deserialize(baseMessage, buffer);
|
requestMsg.deserialize(baseMessage, buffer);
|
||||||
|
cout << "request: " << requestMsg.request << "\n";
|
||||||
|
if (requestMsg.request == "time")
|
||||||
|
{
|
||||||
// timeMsg.latency = (timeMsg.received.sec - timeMsg.sent.sec) * 1000000 + (timeMsg.received.usec - timeMsg.sent.usec);
|
// timeMsg.latency = (timeMsg.received.sec - timeMsg.sent.sec) * 1000000 + (timeMsg.received.usec - timeMsg.sent.usec);
|
||||||
timeMsg.latency = (timeMsg.received.sec - timeMsg.sent.sec) + (timeMsg.received.usec - timeMsg.sent.usec) / 1000000.;
|
TimeMsg timeMsg;
|
||||||
|
timeMsg.refersTo = requestMsg.id;
|
||||||
|
timeMsg.latency = (requestMsg.received.sec - requestMsg.sent.sec) + (requestMsg.received.usec - requestMsg.sent.usec) / 1000000.;
|
||||||
// tv diff = timeMsg.received - timeMsg.sent;
|
// tv diff = timeMsg.received - timeMsg.sent;
|
||||||
// cout << "Latency: " << diff.sec << "." << diff.usec << "\n";
|
// cout << "Latency: " << diff.sec << "." << diff.usec << "\n";
|
||||||
timeMsg.refersTo = timeMsg.id;
|
connection->send(&timeMsg);
|
||||||
connection->send(&timeMsg);
|
}
|
||||||
|
else if (requestMsg.request == "serverSettings")
|
||||||
|
{
|
||||||
|
serverSettings->refersTo = requestMsg.id;
|
||||||
|
connection->send(serverSettings);
|
||||||
|
}
|
||||||
|
else if (requestMsg.request == "sampleFormat")
|
||||||
|
{
|
||||||
|
sampleFormat->refersTo = requestMsg.id;
|
||||||
|
connection->send(sampleFormat);
|
||||||
|
}
|
||||||
|
else if (requestMsg.request == "headerChunk")
|
||||||
|
{
|
||||||
|
headerChunk->refersTo = requestMsg.id;
|
||||||
|
connection->send(headerChunk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +57,9 @@ void ControlServer::acceptor()
|
||||||
ServerConnection* session = new ServerConnection(this, sock);
|
ServerConnection* session = new ServerConnection(this, sock);
|
||||||
sessions.insert(shared_ptr<ServerConnection>(session));
|
sessions.insert(shared_ptr<ServerConnection>(session));
|
||||||
session->start();
|
session->start();
|
||||||
session->send(serverSettings);
|
// session->send(serverSettings);
|
||||||
session->send(sampleFormat);
|
// session->send(sampleFormat);
|
||||||
session->send(headerChunk);
|
// session->send(headerChunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue