identify client by id instead of MAC

This commit is contained in:
Johannes Pohl 2016-11-24 12:02:32 +01:00
parent 433a2ff252
commit 9ec135e1b8
7 changed files with 61 additions and 50 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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()
{