mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-11 16:16:42 +02:00
identify client by id instead of MAC
This commit is contained in:
parent
433a2ff252
commit
9ec135e1b8
7 changed files with 61 additions and 50 deletions
|
@ -30,6 +30,7 @@ public class Client implements JsonSerialisable {
|
|||
private ClientConfig config;
|
||||
private Time_t lastSeen;
|
||||
private boolean connected;
|
||||
private string clientId;
|
||||
private boolean deleted = false;
|
||||
|
||||
public Client(JSONObject json) {
|
||||
|
@ -67,6 +68,7 @@ public class Client implements JsonSerialisable {
|
|||
|
||||
lastSeen = new Time_t(json.getJSONObject("lastSeen"));
|
||||
connected = json.getBoolean("connected");
|
||||
clientId = json.getString("id");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -81,6 +83,7 @@ public class Client implements JsonSerialisable {
|
|||
json.put("config", config.toJson());
|
||||
json.put("lastSeen", lastSeen.toJson());
|
||||
json.put("connected", connected);
|
||||
json.put("id", clientId);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -118,13 +121,20 @@ public class Client implements JsonSerialisable {
|
|||
public String getVisibleName() {
|
||||
if ((config.getName() != null) && !config.getName().isEmpty())
|
||||
return config.getName();
|
||||
return host.getName();
|
||||
String name = host.getName();
|
||||
if (config.getInstance() > 1)
|
||||
name += " #" + config.getInstance();
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
public string getId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
@ -151,6 +161,7 @@ public class Client implements JsonSerialisable {
|
|||
return false;
|
||||
if (config != null ? !config.equals(that.config) : that.config != null) return false;
|
||||
if (connected != that.connected) return false;
|
||||
if (clientId != null ? !clientId.equals(that.clientId) : that.clientId != null) return false;
|
||||
return (deleted == that.deleted);
|
||||
}
|
||||
|
||||
|
@ -160,6 +171,7 @@ public class Client implements JsonSerialisable {
|
|||
result = 31 * result + (snapclient != null ? snapclient.hashCode() : 0);
|
||||
result = 31 * result + (config != null ? config.hashCode() : 0);
|
||||
result = 31 * result + (connected ? 1 : 0);
|
||||
result = 31 * result + (clientId != null ? clientId.hashCode() : 0);
|
||||
result = 31 * result + (deleted ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ public class ClientConfig implements JsonSerialisable {
|
|||
Volume volume;
|
||||
int latency = 0;
|
||||
String stream = "";
|
||||
int instance = 1;
|
||||
|
||||
public ClientConfig() {
|
||||
volume = new Volume();
|
||||
|
@ -45,6 +46,7 @@ public class ClientConfig implements JsonSerialisable {
|
|||
volume = new Volume(json.getJSONObject("volume"));
|
||||
latency = json.getInt("latency");
|
||||
stream = json.getString("stream");
|
||||
instance = json.getInt("instance");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -58,6 +60,7 @@ public class ClientConfig implements JsonSerialisable {
|
|||
json.put("volume", volume.toJson());
|
||||
json.put("latency", latency);
|
||||
json.put("stream", stream);
|
||||
json.put("instance", instance);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -96,6 +99,10 @@ public class ClientConfig implements JsonSerialisable {
|
|||
this.stream = stream;
|
||||
}
|
||||
|
||||
public int getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toJson().toString();
|
||||
|
@ -111,6 +118,7 @@ public class ClientConfig implements JsonSerialisable {
|
|||
if (latency != that.latency) return false;
|
||||
if (name != null ? !name.equals(that.name) : that.name != null) return false;
|
||||
if (stream != null ? !stream.equals(that.stream) : that.stream != null) return false;
|
||||
if (instance != that.instance) return false;
|
||||
return !(volume != null ? !volume.equals(that.volume) : that.volume != null);
|
||||
|
||||
}
|
||||
|
@ -120,6 +128,7 @@ public class ClientConfig implements JsonSerialisable {
|
|||
int result = name != null ? name.hashCode() : 0;
|
||||
result = 31 * result + (volume != null ? volume.hashCode() : 0);
|
||||
result = 31 * result + latency;
|
||||
result = 31 * result + instance;
|
||||
result = 31 * result + (stream != null ? stream.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -145,6 +145,12 @@ int main (int argc, char **argv)
|
|||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (instance <= 0)
|
||||
{
|
||||
cout << "instance id must be >= 1\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
std::clog.rdbuf(new Log("snapclient", LOG_DAEMON));
|
||||
|
||||
signal(SIGHUP, signal_handler);
|
||||
|
|
|
@ -89,21 +89,21 @@ void Config::save()
|
|||
}
|
||||
|
||||
|
||||
ClientInfoPtr Config::getClientInfo(const std::string& macAddress, bool add)
|
||||
ClientInfoPtr Config::getClientInfo(const std::string& clientId, bool add)
|
||||
{
|
||||
if (macAddress.empty())
|
||||
if (clientId.empty())
|
||||
return nullptr;
|
||||
|
||||
for (auto client: clients)
|
||||
{
|
||||
if (client->host.mac == macAddress)
|
||||
if (client->clientId == clientId)
|
||||
return client;
|
||||
}
|
||||
|
||||
if (!add)
|
||||
return nullptr;
|
||||
|
||||
ClientInfoPtr client = make_shared<ClientInfo>(macAddress);
|
||||
ClientInfoPtr client = make_shared<ClientInfo>(clientId);
|
||||
clients.push_back(client);
|
||||
|
||||
return client;
|
||||
|
|
|
@ -34,6 +34,8 @@ T jGet(const json& j, const std::string& what, const T& def)
|
|||
{
|
||||
try
|
||||
{
|
||||
if (!j.count(what))
|
||||
return def;
|
||||
return j[what].get<T>();
|
||||
}
|
||||
catch(...)
|
||||
|
@ -71,7 +73,7 @@ struct Volume
|
|||
|
||||
struct Host
|
||||
{
|
||||
Host(const std::string& _macAddress = "") : name(""), mac(_macAddress), os(""), arch(""), ip("")
|
||||
Host() : name(""), mac(""), os(""), arch(""), ip("")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -112,7 +114,7 @@ struct Host
|
|||
|
||||
struct ClientConfig
|
||||
{
|
||||
ClientConfig() : name(""), volume(100), latency(0), streamId("")
|
||||
ClientConfig() : name(""), volume(100), latency(0), streamId(""), instance(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -122,6 +124,7 @@ struct ClientConfig
|
|||
volume.fromJson(j["volume"]);
|
||||
latency = jGet<int32_t>(j, "latency", 0);
|
||||
streamId = trim_copy(jGet<std::string>(j, "stream", ""));
|
||||
instance = jGet<size_t>(j, "instance", 1);
|
||||
}
|
||||
|
||||
json toJson()
|
||||
|
@ -131,6 +134,7 @@ struct ClientConfig
|
|||
j["volume"] = volume.toJson();
|
||||
j["latency"] = latency;
|
||||
j["stream"] = trim_copy(streamId);
|
||||
j["instance"] = instance;
|
||||
return j;
|
||||
}
|
||||
|
||||
|
@ -138,6 +142,7 @@ struct ClientConfig
|
|||
Volume volume;
|
||||
int32_t latency;
|
||||
std::string streamId;
|
||||
size_t instance;
|
||||
};
|
||||
|
||||
|
||||
|
@ -207,7 +212,7 @@ struct Snapserver : public Snapcast
|
|||
|
||||
struct ClientInfo
|
||||
{
|
||||
ClientInfo(const std::string& _macAddress = "") : host(_macAddress), connected(false)
|
||||
ClientInfo(const std::string& _clientId = "") : clientId(_clientId), connected(false)
|
||||
{
|
||||
lastSeen.tv_sec = 0;
|
||||
lastSeen.tv_usec = 0;
|
||||
|
@ -215,34 +220,10 @@ struct ClientInfo
|
|||
|
||||
void fromJson(const json& j)
|
||||
{
|
||||
if (j.count("host") && !j["host"].is_string())
|
||||
{
|
||||
host.fromJson(j["host"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
host.ip = jGet<std::string>(j, "IP", "");
|
||||
host.mac = jGet<std::string>(j, "MAC", "");
|
||||
host.name = jGet<std::string>(j, "host", "");
|
||||
}
|
||||
|
||||
if (j.count("snapclient"))
|
||||
snapclient.fromJson(j["snapclient"]);
|
||||
else
|
||||
snapclient.version = jGet<std::string>(j, "version", "");
|
||||
|
||||
if (j.count("config"))
|
||||
{
|
||||
config.fromJson(j["config"]);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.name = trim_copy(jGet<std::string>(j, "name", ""));
|
||||
config.volume.fromJson(j["volume"]);
|
||||
config.latency = jGet<int32_t>(j, "latency", 0);
|
||||
config.streamId = trim_copy(jGet<std::string>(j, "stream", ""));
|
||||
}
|
||||
|
||||
clientId = jGet<std::string>(j, "id", j["host"]);
|
||||
host.fromJson(j["host"]);
|
||||
snapclient.fromJson(j["snapclient"]);
|
||||
config.fromJson(j["config"]);
|
||||
lastSeen.tv_sec = jGet<int32_t>(j["lastSeen"], "sec", 0);
|
||||
lastSeen.tv_usec = jGet<int32_t>(j["lastSeen"], "usec", 0);
|
||||
connected = jGet<bool>(j, "connected", true);
|
||||
|
@ -251,6 +232,7 @@ struct ClientInfo
|
|||
json toJson()
|
||||
{
|
||||
json j;
|
||||
j["id"] = clientId;
|
||||
j["host"] = host.toJson();
|
||||
j["snapclient"] = snapclient.toJson();
|
||||
j["config"] = config.toJson();
|
||||
|
@ -260,6 +242,7 @@ struct ClientInfo
|
|||
return j;
|
||||
}
|
||||
|
||||
std::string clientId;
|
||||
Host host;
|
||||
Snapclient snapclient;
|
||||
ClientConfig config;
|
||||
|
|
|
@ -79,8 +79,8 @@ void StreamServer::onDisconnect(StreamSession* streamSession)
|
|||
if (session == nullptr)
|
||||
return;
|
||||
|
||||
logO << "onDisconnect: " << session->macAddress << "\n";
|
||||
ClientInfoPtr clientInfo = Config::instance().getClientInfo(streamSession->macAddress);
|
||||
logO << "onDisconnect: " << session->clientId << "\n";
|
||||
ClientInfoPtr clientInfo = Config::instance().getClientInfo(streamSession->clientId);
|
||||
logD << "sessions: " << sessions_.size() << "\n";
|
||||
// don't block: remove StreamSession in a thread
|
||||
auto func = [](shared_ptr<StreamSession> s)->void{s->stop();};
|
||||
|
@ -246,7 +246,7 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
|||
connection->sendAsync(timeMsg, true);
|
||||
|
||||
// refresh connection state
|
||||
ClientInfoPtr client = Config::instance().getClientInfo(connection->macAddress);
|
||||
ClientInfoPtr client = Config::instance().getClientInfo(connection->clientId);
|
||||
if (client != nullptr)
|
||||
{
|
||||
gettimeofday(&client->lastSeen, NULL);
|
||||
|
@ -257,17 +257,17 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
|||
{
|
||||
msg::Hello helloMsg;
|
||||
helloMsg.deserialize(baseMessage, buffer);
|
||||
connection->macAddress = helloMsg.getMacAddress();
|
||||
logO << "Hello from " << connection->macAddress << ", host: " << helloMsg.getHostName() << ", v" << helloMsg.getVersion()
|
||||
connection->clientId = helloMsg.getClientId();
|
||||
logO << "Hello from " << connection->clientId << ", host: " << helloMsg.getHostName() << ", v" << helloMsg.getVersion()
|
||||
<< ", ClientName: " << helloMsg.getClientName() << ", OS: " << helloMsg.getOS() << ", Arch: " << helloMsg.getArch()
|
||||
<< ", Protocol version: " << helloMsg.getProtocolVersion() << "\n";
|
||||
|
||||
logD << "request kServerSettings: " << connection->macAddress << "\n";
|
||||
logD << "request kServerSettings: " << connection->clientId << "\n";
|
||||
// std::lock_guard<std::mutex> mlock(mutex_);
|
||||
ClientInfoPtr clientInfo = Config::instance().getClientInfo(connection->macAddress, true);
|
||||
ClientInfoPtr clientInfo = Config::instance().getClientInfo(connection->clientId, true);
|
||||
if (clientInfo == nullptr)
|
||||
{
|
||||
logE << "could not get client info for MAC: " << connection->macAddress << "\n";
|
||||
logE << "could not get client info for client: " << connection->clientId << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -281,7 +281,8 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
|||
connection->sendAsync(serverSettings);
|
||||
}
|
||||
|
||||
ClientInfoPtr client = Config::instance().getClientInfo(connection->macAddress);
|
||||
ClientInfoPtr client = Config::instance().getClientInfo(connection->clientId);
|
||||
client->host.mac = helloMsg.getMacAddress();
|
||||
client->host.ip = connection->getIP();
|
||||
client->host.name = helloMsg.getHostName();
|
||||
client->host.os = helloMsg.getOS();
|
||||
|
@ -289,6 +290,7 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
|||
client->snapclient.version = helloMsg.getVersion();
|
||||
client->snapclient.name = helloMsg.getClientName();
|
||||
client->snapclient.protocolVersion = helloMsg.getProtocolVersion();
|
||||
client->config.instance = helloMsg.getInstance();
|
||||
client->connected = true;
|
||||
gettimeofday(&client->lastSeen, NULL);
|
||||
|
||||
|
@ -324,14 +326,13 @@ session_ptr StreamServer::getStreamSession(StreamSession* streamSession) const
|
|||
}
|
||||
|
||||
|
||||
session_ptr StreamServer::getStreamSession(const std::string& mac) const
|
||||
session_ptr StreamServer::getStreamSession(const std::string& clientId) const
|
||||
{
|
||||
// logO << "getStreamSession: " << mac << "\n";
|
||||
std::lock_guard<std::recursive_mutex> mlock(sessionsMutex_);
|
||||
for (auto session: sessions_)
|
||||
{
|
||||
// logO << "getStreamSession, checking: " << session->macAddress << "\n";
|
||||
if (session->macAddress == mac)
|
||||
if (session->clientId == clientId)
|
||||
return session;
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
/// Max playout latency. No need to send PCM data that is older than bufferMs
|
||||
void setBufferMs(size_t bufferMs);
|
||||
|
||||
std::string macAddress;
|
||||
std::string clientId;
|
||||
|
||||
std::string getIP()
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue