Skip to content

Commit ec57457

Browse files
riban-bwann0see
authored andcommitted
Add JSON-RPC access to directories and server lists
Squash from: #3249 rpc_notification jamulusclient/serverListReceived rpc_method jamulus/pollServerList Change JSON-RPC for server list. Use pollServerList instead of getServerList. (No result returned from the call.) Change "address" to "url" Adds documentation for new JSON-RPC methods Consistent use of countryId Fixes JSON-RPC docs JSON-RPC fixes for feedback to PR Changes method "jamulus/pollServerList" to "jamulusclient/pollServerList" (for consistency). Changes "url" to "address" in protocol and "server address" in docs. Fixes typo in countryId. JSON-RPC Enhancements Adds jamulusclient/connect method. Adds jamulusclient/disconnect method. Adds jamulusclient/serverInfoReceived notification. Return country string rather than (QT specific) country code. Request server info after server list received (to get each server's ping time and num clients). JSON-RPC enhancements Adds method jamulusclient/recorderState. Changes intrument code to instrument name (remote client may not have access to lookup table). Fixes errors in docs. Fixes coding style Update docs Fix coding style
1 parent fe88e3e commit ec57457

File tree

3 files changed

+218
-12
lines changed

3 files changed

+218
-12
lines changed

docs/JSON-RPC.md

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,57 @@ Results:
129129
| result.version | string | The Jamulus version. |
130130

131131

132+
### jamulus/pollServerList
133+
134+
Request list of servers in a directory
135+
136+
Parameters:
137+
138+
| Name | Type | Description |
139+
| --- | --- | --- |
140+
| params.directory | string | socket address of directory to query, e.g. anygenre1.jamulus.io:22124. |
141+
142+
Results:
143+
144+
| Name | Type | Description |
145+
| --- | --- | --- |
146+
| result | string | "ok" or "error" if bad arguments. |
147+
148+
149+
### jamulusclient/connect
150+
151+
Disconnect client from server
152+
153+
Parameters:
154+
155+
| Name | Type | Description |
156+
| --- | --- | --- |
157+
| params.address | string | Server socket address (ip_addr:port). |
158+
159+
Results:
160+
161+
| Name | Type | Description |
162+
| --- | --- | --- |
163+
| result | string | Always "ok". |
164+
165+
166+
### jamulusclient/disconnect
167+
168+
Disconnect client from server
169+
170+
Parameters:
171+
172+
| Name | Type | Description |
173+
| --- | --- | --- |
174+
| params | object | No parameters (empty object). |
175+
176+
Results:
177+
178+
| Name | Type | Description |
179+
| --- | --- | --- |
180+
| result | string | Always "ok". |
181+
182+
132183
### jamulusclient/getChannelInfo
133184

134185
Returns the client's profile information.
@@ -146,9 +197,9 @@ Results:
146197
| result.id | number | The channel ID. |
147198
| result.name | string | The musician’s name. |
148199
| result.skillLevel | string | The musician’s skill level (beginner, intermediate, expert, or null). |
149-
| result.countryId | number | The musician’s country ID (see QLocale::Country). |
200+
| result.country | string | The musician’s country. |
150201
| result.city | string | The musician’s city. |
151-
| result.instrumentId | number | The musician’s instrument ID (see CInstPictures::GetTable). |
202+
| result.instrument | number | The musician’s instrument. |
152203
| result.skillLevel | string | Your skill level (beginner, intermediate, expert, or null). |
153204

154205

@@ -444,9 +495,9 @@ Parameters:
444495
| params.clients[*].id | number | The channel ID. |
445496
| params.clients[*].name | string | The musician’s name. |
446497
| params.clients[*].skillLevel | string | The musician’s skill level (beginner, intermediate, expert, or null). |
447-
| params.clients[*].countryId | number | The musician’s country ID (see QLocale::Country). |
498+
| params.clients[*].country | string | The musician’s country. |
448499
| params.clients[*].city | string | The musician’s city. |
449-
| params.clients[*].instrumentId | number | The musician’s instrument ID (see CInstPictures::GetTable). |
500+
| params.clients[*].instrument | string | The musician’s instrument. |
450501

451502

452503
### jamulusclient/connected
@@ -471,3 +522,42 @@ Parameters:
471522
| params | object | No parameters (empty object). |
472523

473524

525+
### jamulusclient/recorderState
526+
527+
Emitted when the client is connected to a server who's recorder state changes.
528+
529+
Parameters:
530+
531+
| Name | Type | Description |
532+
| --- | --- | --- |
533+
| params.state | number | The recorder state |
534+
535+
536+
### jamulusclient/serverInfoReceived
537+
538+
Emitted when a server info is received.
539+
540+
Parameters:
541+
542+
| Name | Type | Description |
543+
| --- | --- | --- |
544+
| params.address | string | The server socket address |
545+
| params.pingtime | number | The round-trip ping time in ms |
546+
| params.numClients | number | The quantity of clients connected to the server |
547+
548+
549+
### jamulusclient/serverListReceived
550+
551+
Emitted when the server list is received.
552+
553+
Parameters:
554+
555+
| Name | Type | Description |
556+
| --- | --- | --- |
557+
| params.servers | array | The server list. |
558+
| params.servers[*].address | string | Socket address (ip_address:port) |
559+
| params.servers[*].name | string | Server name |
560+
| params.servers[*].country | string | Server country |
561+
| params.servers[*].city | string | Server city |
562+
563+

src/client.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ class CClient : public QObject
286286
Channel.GetBufErrorRates ( vecErrRates, dLimit, dMaxUpLimit );
287287
}
288288

289+
CProtocol* getConnLessProtocol() { return &ConnLessProtocol; }
290+
289291
// settings
290292
CChannelCoreInfo ChannelInfo;
291293
QString strClientName;

src/clientrpc.cpp

Lines changed: 122 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ CClientRpc::CClientRpc ( CClient* pClient, CRpcServer* pRpcServer, QObject* pare
5353
/// @param {number} params.clients[*].id - The channel ID.
5454
/// @param {string} params.clients[*].name - The musician’s name.
5555
/// @param {string} params.clients[*].skillLevel - The musician’s skill level (beginner, intermediate, expert, or null).
56-
/// @param {number} params.clients[*].countryId - The musician’s country ID (see QLocale::Country).
56+
/// @param {string} params.clients[*].country - The musician’s country.
5757
/// @param {string} params.clients[*].city - The musician’s city.
58-
/// @param {number} params.clients[*].instrumentId - The musician’s instrument ID (see CInstPictures::GetTable).
58+
/// @param {string} params.clients[*].instrument - The musician’s instrument.
5959
connect ( pClient, &CClient::ConClientListMesReceived, [=] ( CVector<CChannelInfo> vecChanInfo ) {
6060
QJsonArray arrChanInfo;
6161
for ( const auto& chanInfo : vecChanInfo )
@@ -64,9 +64,9 @@ CClientRpc::CClientRpc ( CClient* pClient, CRpcServer* pRpcServer, QObject* pare
6464
{ "id", chanInfo.iChanID },
6565
{ "name", chanInfo.strName },
6666
{ "skillLevel", SerializeSkillLevel ( chanInfo.eSkillLevel ) },
67-
{ "countryId", chanInfo.eCountry },
67+
{ "country", QLocale::countryToString ( chanInfo.eCountry ) },
6868
{ "city", chanInfo.strCity },
69-
{ "instrumentId", chanInfo.iInstrument },
69+
{ "instrument", CInstPictures::GetName ( chanInfo.iInstrument ) },
7070
};
7171
arrChanInfo.append ( objChanInfo );
7272
}
@@ -94,11 +94,125 @@ CClientRpc::CClientRpc ( CClient* pClient, CRpcServer* pRpcServer, QObject* pare
9494
} );
9595
} );
9696

97+
/// @rpc_notification jamulusclient/serverListReceived
98+
/// @brief Emitted when the server list is received.
99+
/// @param {array} params.servers - The server list.
100+
/// @param {string} params.servers[*].address - Socket address (ip_address:port)
101+
/// @param {string} params.servers[*].name - Server name
102+
/// @param {string} params.servers[*].country - Server country
103+
/// @param {string} params.servers[*].city - Server city
104+
connect ( pClient->getConnLessProtocol(),
105+
&CProtocol::CLServerListReceived,
106+
[=] ( CHostAddress /* unused */, CVector<CServerInfo> vecServerInfo ) {
107+
QJsonArray arrServerInfo;
108+
for ( const auto& serverInfo : vecServerInfo )
109+
{
110+
QJsonObject objServerInfo{
111+
{ "address", serverInfo.HostAddr.toString() },
112+
{ "name", serverInfo.strName },
113+
{ "country", QLocale::countryToString ( serverInfo.eCountry ) },
114+
{ "city", serverInfo.strCity },
115+
};
116+
arrServerInfo.append ( objServerInfo );
117+
pClient->CreateCLServerListPingMes ( serverInfo.HostAddr );
118+
}
119+
pRpcServer->BroadcastNotification ( "jamulusclient/serverListReceived",
120+
QJsonObject{
121+
{ "servers", arrServerInfo },
122+
} );
123+
} );
124+
125+
/// @rpc_notification jamulusclient/serverInfoReceived
126+
/// @brief Emitted when a server info is received.
127+
/// @param {string} params.address - The server socket address
128+
/// @param {number} params.pingtime - The round-trip ping time in ms
129+
/// @param {number} params.numClients - The quantity of clients connected to the server
130+
connect ( pClient, &CClient::CLPingTimeWithNumClientsReceived, [=] ( CHostAddress InetAddr, int iPingTime, int iNumClients ) {
131+
pRpcServer->BroadcastNotification (
132+
"jamulusclient/serverInfoReceived",
133+
QJsonObject{ { "address", InetAddr.toString() }, { "pingTime", iPingTime }, { "numClients", iNumClients } } );
134+
} );
135+
97136
/// @rpc_notification jamulusclient/disconnected
98137
/// @brief Emitted when the client is disconnected from the server.
99138
/// @param {object} params - No parameters (empty object).
100139
connect ( pClient, &CClient::Disconnected, [=]() { pRpcServer->BroadcastNotification ( "jamulusclient/disconnected", QJsonObject{} ); } );
101140

141+
/// @rpc_notification jamulusclient/recorderState
142+
/// @brief Emitted when the client is connected to a server who's recorder state changes.
143+
/// @param {number} params.state - The recorder state
144+
connect ( pClient, &CClient::RecorderStateReceived, [=] ( const ERecorderState newRecorderState ) {
145+
pRpcServer->BroadcastNotification ( "jamulusclient/recorderState", QJsonObject{ { "state", newRecorderState } } );
146+
} );
147+
148+
/// @rpc_method jamulus/pollServerList
149+
/// @brief Request list of servers in a directory
150+
/// @param {string} params.directory - socket address of directory to query, e.g. anygenre1.jamulus.io:22124.
151+
/// @result {string} result - "ok" or "error" if bad arguments.
152+
pRpcServer->HandleMethod ( "jamulusclient/pollServerList", [=] ( const QJsonObject& params, QJsonObject& response ) {
153+
auto jsonDirectoryIp = params["directory"];
154+
if ( !jsonDirectoryIp.isString() )
155+
{
156+
response["error"] = CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: directory is not a string" );
157+
return;
158+
}
159+
160+
CHostAddress haDirectoryAddress;
161+
if ( NetworkUtil().ParseNetworkAddress ( jsonDirectoryIp.toString(), haDirectoryAddress, false ) )
162+
{
163+
// send the request for the server list
164+
pClient->CreateCLReqServerListMes ( haDirectoryAddress );
165+
response["result"] = "ok";
166+
}
167+
else
168+
{
169+
response["error"] =
170+
CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: directory is not a valid socket address" );
171+
}
172+
173+
response["result"] = "ok";
174+
} );
175+
176+
/// @rpc_method jamulusclient/connect
177+
/// @brief Disconnect client from server
178+
/// @param {string} params.address - Server socket address (ip_addr:port).
179+
/// @result {string} result - Always "ok".
180+
pRpcServer->HandleMethod ( "jamulusclient/connect", [=] ( const QJsonObject& params, QJsonObject& response ) {
181+
auto jsonAddr = params["address"];
182+
if ( !jsonAddr.isString() )
183+
{
184+
response["error"] = CRpcServer::CreateJsonRpcError ( CRpcServer::iErrInvalidParams, "Invalid params: address is not a string" );
185+
return;
186+
}
187+
188+
if ( pClient->SetServerAddr ( jsonAddr.toString() ) )
189+
{
190+
if ( !pClient->IsRunning() )
191+
{
192+
pClient->Start();
193+
}
194+
response["result"] = "ok";
195+
}
196+
else
197+
{
198+
response["error"] = CRpcServer::CreateJsonRpcError ( 1, "Bad server address" );
199+
}
200+
} );
201+
202+
/// @rpc_method jamulusclient/disconnect
203+
/// @brief Disconnect client from server
204+
/// @param {object} params - No parameters (empty object).
205+
/// @result {string} result - Always "ok".
206+
pRpcServer->HandleMethod ( "jamulusclient/disconnect", [=] ( const QJsonObject& params, QJsonObject& response ) {
207+
if ( pClient->IsRunning() )
208+
{
209+
pClient->Stop();
210+
}
211+
212+
response["result"] = "ok";
213+
Q_UNUSED ( params );
214+
} );
215+
102216
/// @rpc_method jamulus/getMode
103217
/// @brief Returns the current mode, i.e. whether Jamulus is running as a server or client.
104218
/// @param {object} params - No parameters (empty object).
@@ -125,17 +239,17 @@ CClientRpc::CClientRpc ( CClient* pClient, CRpcServer* pRpcServer, QObject* pare
125239
/// @result {number} result.id - The channel ID.
126240
/// @result {string} result.name - The musician’s name.
127241
/// @result {string} result.skillLevel - The musician’s skill level (beginner, intermediate, expert, or null).
128-
/// @result {number} result.countryId - The musician’s country ID (see QLocale::Country).
242+
/// @result {string} result.country - The musician’s country.
129243
/// @result {string} result.city - The musician’s city.
130-
/// @result {number} result.instrumentId - The musician’s instrument ID (see CInstPictures::GetTable).
244+
/// @result {number} result.instrument - The musician’s instrument.
131245
/// @result {string} result.skillLevel - Your skill level (beginner, intermediate, expert, or null).
132246
pRpcServer->HandleMethod ( "jamulusclient/getChannelInfo", [=] ( const QJsonObject& params, QJsonObject& response ) {
133247
QJsonObject result{
134248
// TODO: We cannot include "id" here is pClient->ChannelInfo is a CChannelCoreInfo which lacks that field.
135249
{ "name", pClient->ChannelInfo.strName },
136-
{ "countryId", pClient->ChannelInfo.eCountry },
250+
{ "country", QLocale::countryToString ( pClient->ChannelInfo.eCountry ) },
137251
{ "city", pClient->ChannelInfo.strCity },
138-
{ "instrumentId", pClient->ChannelInfo.iInstrument },
252+
{ "instrument", CInstPictures::GetName ( pClient->ChannelInfo.iInstrument ) },
139253
{ "skillLevel", SerializeSkillLevel ( pClient->ChannelInfo.eSkillLevel ) },
140254
};
141255
response["result"] = result;

0 commit comments

Comments
 (0)