From a3cd45110ac869abcc16bb9db63f515d1706b297 Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Thu, 21 May 2020 19:50:37 +0300 Subject: [PATCH 01/10] NY-10362: Calling to allow all admins plus the owner of the meeting to moderate --- .../conferencecontrol/service/Conference.java | 41 +++++---- .../api/client/FocusInternalApiClient.java | 11 ++- .../nccs/focus/service/CallVerticle.java | 18 ++-- .../nccs/focus/service/Conference.java | 3 +- .../nynjacoin/nccs/focus/service/Focus.java | 5 +- .../restclient/chatroom/ChatRoomClient.java | 16 +++- .../chatroom/ChatRoomClientManualTest.java | 89 +++++++++++++------ gradle.properties | 2 +- 8 files changed, 119 insertions(+), 66 deletions(-) diff --git a/focus/src/main/java/com/nynjacoin/nccs/conferencecontrol/service/Conference.java b/focus/src/main/java/com/nynjacoin/nccs/conferencecontrol/service/Conference.java index a85531bb..a4b2f1ed 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/conferencecontrol/service/Conference.java +++ b/focus/src/main/java/com/nynjacoin/nccs/conferencecontrol/service/Conference.java @@ -159,7 +159,7 @@ class Conference { if (isOwner(accountId)) { return Future.succeededFuture(Boolean.TRUE); } - return chatRoomClient.isMember(conferenceInfo.getOwnerAccountId(), roomId, accountId); + return chatRoomClient.isAdmin(conferenceInfo.getOwnerAccountId(), roomId, accountId); } private boolean joinUnauthorized(String accountId, Member member) { @@ -303,29 +303,28 @@ class Conference { } void manageParticipant(String accountId, ManageParticipanRequest request, Future response) { - if (!isOwner(accountId)) { - response.fail(NccsError.UNAUTHORIZED.exception()); - return; - } - if (!conferenceInfo.isOngoing()) { - response.fail(FocusError.CONFERENCE_BAD_STATE.exception()); - return; - } - focusInternalApiClient - .manageParticipant(accountId, conferenceInfo.getConferenceId(), request, response); + authorizeChangeAccess(accountId) + .compose(aVoid -> { + if (!conferenceInfo.isOngoing()) { + return Future.failedFuture(FocusError.CONFERENCE_BAD_STATE.exception()); + } + return focusInternalApiClient.manageParticipant( + accountId, + conferenceInfo.getConferenceId(), + request); + }) + .setHandler(response); } void manageMember(String accountId, ManageMemberRequest request, Future response) { - if (!isOwner(accountId)) { - response.fail(NccsError.UNAUTHORIZED.exception()); - return; - } - if (!conferenceInfo.isOngoing()) { - response.fail(FocusError.CONFERENCE_BAD_STATE.exception()); - return; - } - focusInternalApiClient.manageMember(conferenceInfo.getConferenceId(), request); - response.complete(Void.getDefaultInstance()); + authorizeChangeAccess(accountId) + .compose(aVoid -> { + if (!conferenceInfo.isOngoing()) { + return Future.failedFuture(FocusError.CONFERENCE_BAD_STATE.exception()); + } + return focusInternalApiClient.manageMember(conferenceInfo.getConferenceId(), request); + }) + .setHandler(response); } void join(String accountId, JoinRequest request, Future response) { diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/internal/api/client/FocusInternalApiClient.java b/focus/src/main/java/com/nynjacoin/nccs/focus/internal/api/client/FocusInternalApiClient.java index 0b8b8633..db9e6715 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/internal/api/client/FocusInternalApiClient.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/internal/api/client/FocusInternalApiClient.java @@ -25,16 +25,15 @@ public class FocusInternalApiClient { callVerticle.endConference(conferenceId); } - public void manageParticipant( + public Future manageParticipant( String accountId, String conferenceId, - ManageParticipanRequest request, - Future response) { + ManageParticipanRequest request) { - callVerticle.manageParticipant(accountId, conferenceId, request, response); + return callVerticle.manageParticipant(accountId, conferenceId, request); } - public void manageMember(String conferenceId, ManageMemberRequest request) { - callVerticle.manageMember(conferenceId, request); + public Future manageMember(String conferenceId, ManageMemberRequest request) { + return callVerticle.manageMember(conferenceId, request); } } diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java b/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java index 5d96595e..6806d168 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java @@ -85,29 +85,33 @@ public class CallVerticle extends NccsVerticle { }); } - public void manageParticipant( + public Future manageParticipant( String accountId, String conferenceId, - ManageParticipanRequest request, - Future response) { + ManageParticipanRequest request) { - ContextPreserver contextPreserver = ContextPreserver.create(response); + ContextPreserver contextPreserver = ContextPreserver.create(); final var logContext = ThreadContext.getContext(); verticleContext.runOnContext(v -> { try (final CloseableThreadContext.Instance tc = CloseableThreadContext.putAll(logContext)) { focus.manageParticipant(accountId, conferenceId, request, contextPreserver.callee()); } catch (Throwable t) { - contextPreserver.callee().fail(t); + contextPreserver.handleCalleeException(t); } }); + return contextPreserver.caller(); } - public void manageMember(String conferenceId, ManageMemberRequest request) { + public Future manageMember(String conferenceId, ManageMemberRequest request) { + ContextPreserver contextPreserver = ContextPreserver.create(); final var logContext = ThreadContext.getContext(); verticleContext.runOnContext(v -> { try (final CloseableThreadContext.Instance tc = CloseableThreadContext.putAll(logContext)) { - focus.manageMember(conferenceId, request); + focus.manageMember(conferenceId, request, contextPreserver.callee()); + } catch (Throwable t) { + contextPreserver.handleCalleeException(t); } }); + return contextPreserver.caller(); } } diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/service/Conference.java b/focus/src/main/java/com/nynjacoin/nccs/focus/service/Conference.java index c9cbbdc1..30bdbfc0 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/service/Conference.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/service/Conference.java @@ -121,7 +121,7 @@ public class Conference { } } - void manageMember(ManageMemberRequest request) { + void manageMember(ManageMemberRequest request, Future response) { logger.debug("Manage member {{}}", TextFormat.shortDebugString(request)); getMemberParticipants(request.getMemberId()).forEach(participant -> { switch (request.getActionCase()) { @@ -135,6 +135,7 @@ public class Conference { break; } }); + response.complete(Void.getDefaultInstance()); } public boolean isEmpty() { diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java b/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java index b5333e6d..a8eb4bf1 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java @@ -193,12 +193,13 @@ public class Focus { conference.manageParticipant(accountId, request, response); } - void manageMember(String conferenceId, ManageMemberRequest request) { + void manageMember(String conferenceId, ManageMemberRequest request, Future response) { Conference conference = conferences.get(conferenceId); if (conference == null) { LOGGER.warn("Conference id {} not found trying to manage participant", conferenceId); + response.fail(FocusError.CONFERENCE_NOT_FOUND.exception("Focus: conference gone")); return; } - conference.manageMember(request); + conference.manageMember(request, response); } } diff --git a/focus/src/main/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClient.java b/focus/src/main/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClient.java index 5fc45f83..4dacf4e5 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClient.java +++ b/focus/src/main/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClient.java @@ -36,6 +36,7 @@ public class ChatRoomClient { private static final String FIELD_DATA = "data"; private static final String FIELD_ERROR = "error"; private static final String FIELD_IS_MEMBER = "is_member"; + private static final String FIELD_IS_ADMIN = "is_admin"; private static final String FIELD_PHONE_ID = "phone_id"; private static final String FIELD_IS_JOINING = "join"; private static final String FIELD_ACCOUNT_IDS = QUERY_PARAM_ACCOUNT_IDS; @@ -102,6 +103,19 @@ public class ChatRoomClient { } public Future areAllMembers(String ownerAccountId, String roomId, List accountIds) { + return areAll(ownerAccountId, roomId, accountIds, FIELD_IS_MEMBER); + } + + public Future isAdmin(String ownerAccountId, String roomId, String accountId) { + return areAll(ownerAccountId, roomId, List.of(accountId), FIELD_IS_ADMIN); + } + + private Future areAll( + String ownerAccountId, + String roomId, + List accountIds, + String filedToCheck) { + var request = webClient .getAbs(membersPath) .putHeader(HEADER_ACCOUNT_ID, ownerAccountId) @@ -120,7 +134,7 @@ public class ChatRoomClient { ValidatingJsonObject member = data.getRequiredJsonObject(i); var error = member.unwrap().getString(FIELD_ERROR); if (Objects.isNull(error)) { - if (!member.getRequiredStringBoolean(FIELD_IS_MEMBER)) { + if (!member.getRequiredStringBoolean(filedToCheck)) { result.complete(Boolean.FALSE); return; } diff --git a/focus/src/test/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClientManualTest.java b/focus/src/test/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClientManualTest.java index a98839d4..146b5a65 100644 --- a/focus/src/test/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClientManualTest.java +++ b/focus/src/test/java/com/nynjacoin/nccs/restclient/chatroom/ChatRoomClientManualTest.java @@ -9,8 +9,8 @@ import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.RunTestOnContext; import io.vertx.ext.unit.junit.VertxUnitRunner; import io.vertx.ext.web.client.WebClient; -import java.util.Collections; import java.util.List; +import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; import org.junit.Ignore; @@ -32,7 +32,6 @@ public class ChatRoomClientManualTest { WebClient webClient = WebClient.create(vertx); - // AuthenticationHandler authenticationHandler = AuthenticationHandler.create("nynja:nynjaTS"); AuthenticationHandler authenticationHandler = AuthenticationHandler.create("nynja:nynjaTS"); JsonRetryExecutor retryExecutor = new JsonRetryExecutor( @@ -56,43 +55,77 @@ public class ChatRoomClientManualTest { } @Test - public void amIMember(TestContext context) { - List accounts = Collections.singletonList("359999111101_166"); - Future result = chatRoomClient.areAllMembers( - "359999111101_166", - "conference_1547131523640_206", - accounts); - result.setHandler(context.asyncAssertSuccess(allMembers -> - System.out.println("Am I member: " + allMembers))); + public void checkAdmin(TestContext context) { + Future result = chatRoomClient.isAdmin( + "37936e07-1930-4317-8719-aadac2524184_2806", + "conference_1588842369467_1160", + "37936e07-1930-4317-8719-aadac2524184_2806"); + result.setHandler(context.asyncAssertSuccess(Assert::assertTrue)); + } + + @Test + public void checkNotAdmin(TestContext context) { + Future result = chatRoomClient.isAdmin( + "37936e07-1930-4317-8719-aadac2524184_2806", + "conference_1588842369467_1160", + "5ef289e7-3c9b-44e2-9dce-637e30f3f02a_2807"); + result.setHandler(context.asyncAssertSuccess(Assert::assertFalse)); } - /* + @Test + public void checkNotMemberIsNotAdminToo(TestContext context) { + Future result = chatRoomClient.isAdmin( + "37936e07-1930-4317-8719-aadac2524184_2806", + "c7d254d4-0654-44ed-ab05-0336d40ce781", + "37936e07-1930-4317-8719-aadac2524184_2806"); + result.setHandler(context.asyncAssertSuccess(Assert::assertFalse)); + } -{address { value: "359999202020_231" } option: DIALOUT display_name: "Rino Gatuzo"} -{address { value: "359898773312_20" } option: DIALOUT display_name: "Nelko Nedelchev"} -{address { value: "359999131313_76" } display_name: "Krassimir Balakov"} + @Test + public void checkMember(TestContext context) { + Future result = chatRoomClient.isMember( + "37936e07-1930-4317-8719-aadac2524184_2806", + "conference_1588842369467_1160", + "37936e07-1930-4317-8719-aadac2524184_2806"); + result.setHandler(context.asyncAssertSuccess(Assert::assertTrue)); + } -692D4F79-E63F-4A41-B17E-A8CEEC2139F7_359898773312_20_153935357591482_7DE313F6-B206-4205-ADCB-7432D8928A81 -692D4F79-E63F-4A41-B17E-A8CEEC2139F7_359898773312_20_153935357591482_7DE313F6-B206-4205-ADCB-7432D8928A81 - */ + @Test + public void checkNotMember(TestContext context) { + Future result = chatRoomClient.isMember( + "37936e07-1930-4317-8719-aadac2524184_2806", + "c7d254d4-0654-44ed-ab05-0336d40ce781", + "37936e07-1930-4317-8719-aadac2524184_2806"); + result.setHandler(context.asyncAssertSuccess(Assert::assertFalse)); + } + + @Test + public void checkAllMembers(TestContext context) { + List accounts = List.of( + "37936e07-1930-4317-8719-aadac2524184_2806", + "5ef289e7-3c9b-44e2-9dce-637e30f3f02a_2807"); + Future result = + chatRoomClient.areAllMembers( + "37936e07-1930-4317-8719-aadac2524184_2806", + "conference_1588842369467_1160", + accounts); + result.setHandler(context.asyncAssertSuccess(Assert::assertTrue)); + } @Test - public void areAllMembers(TestContext context) { + public void checkNotAllMembers(TestContext context) { List accounts = List.of( - "359999131313_76"); -// "359999111101_166", -// "359999111104_169", -// "359999111105_170", -// "359999111106_171"); + "37936e07-1930-4317-8719-aadac2524184_2806", + "5ef289e7-3c9b-44e2-9dce-637e30f3f02a_2807"); Future result = chatRoomClient.areAllMembers( - "359999131313_76", - "692D4F79-E63F-4A41-B17E-A8CEEC2139F7_359898773312_20_153935357591482_7DE313F6-B206-4205-ADCB-7432D8928A81", + "37936e07-1930-4317-8719-aadac2524184_2806", + "c7d254d4-0654-44ed-ab05-0336d40ce781", accounts); - result.setHandler(context.asyncAssertSuccess(allMembers -> - System.out.println("ALL ARE MEMBERS: " + allMembers))); + result.setHandler(context.asyncAssertSuccess(Assert::assertFalse)); } + @Ignore @Test public void addMembers(TestContext context) { List accounts = List.of( @@ -105,6 +138,7 @@ public class ChatRoomClientManualTest { result.setHandler(context.asyncAssertSuccess()); } + @Ignore @Test public void join(TestContext context) { Future result = chatRoomClient.joinMember( @@ -113,6 +147,7 @@ public class ChatRoomClientManualTest { result.setHandler(context.asyncAssertSuccess()); } + @Ignore @Test public void deleteRoom(TestContext context) { chatRoomClient diff --git a/gradle.properties b/gradle.properties index f4b9ae2b..885eb81a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ rxjava2Version = 2.1.13 prometheusVersion = 0.5.0 cassandraDriverVersion = 3.6.0 junitVersion = 4.12 -nccsLibsVersion = 0.21.1 +nccsLibsVersion = 0.22.0-SNAPSHOT -- GitLab From 1a2aa0244b78e8585972238f73751a18bab02074 Mon Sep 17 00:00:00 2001 From: "A.Popov" Date: Wed, 27 May 2020 18:54:26 +0300 Subject: [PATCH 02/10] Added params participant_answer_timeout_seconds --- charts/calling-service/Chart.yaml | 2 +- charts/calling-service/templates/deployment.yaml | 2 ++ charts/calling-service/values.yaml | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/charts/calling-service/Chart.yaml b/charts/calling-service/Chart.yaml index 49c1f71b..72bcbcef 100644 --- a/charts/calling-service/Chart.yaml +++ b/charts/calling-service/Chart.yaml @@ -2,4 +2,4 @@ apiVersion: v1 appVersion: "1.0" description: Calling service Helm chart name: calling-service -version: 0.3.19 +version: 0.3.20 diff --git a/charts/calling-service/templates/deployment.yaml b/charts/calling-service/templates/deployment.yaml index e2371f6f..4b0e734a 100644 --- a/charts/calling-service/templates/deployment.yaml +++ b/charts/calling-service/templates/deployment.yaml @@ -61,6 +61,8 @@ spec: value: "{{ .Values.conference_member_dial_out_timeout_seconds }}" - name: participant_remove_not_responding_delay_seconds value: "{{ .Values.focus.participant_remove_not_responding_delay_seconds }}" + - name: participant_answer_timeout_seconds + value: "{{ .Values.focus.participant_answer_timeout_seconds }}" - name: test_harness_enabled value: "{{ .Values.focus.test_harness_enabled }}" - name: test_harness_static_conferences diff --git a/charts/calling-service/values.yaml b/charts/calling-service/values.yaml index b3226c1f..8e24f477 100644 --- a/charts/calling-service/values.yaml +++ b/charts/calling-service/values.yaml @@ -17,6 +17,7 @@ focus: pullPolicy: IfNotPresent resources: {} test_harness_enabled: true + participant_answer_timeout_seconds: 60 test_harness_static_conferences: "{\"jigasi_1_static\": \"22a27862-1f94-4112-bfa7-e153f32497e3\"}" history: image: -- GitLab From 0d27f99c54e3f6f2e6088836a2d9028f26706ecc Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Wed, 27 May 2020 19:32:15 +0300 Subject: [PATCH 03/10] JWT access token support extended: * extract client id from the JWT * encapsulate into JwtInfo structure * support for web * propagate JwtInfo to the P2P call to be used for call pickup --- .../com/nynjacoin/nccs/call/service/Call.java | 7 ++++++- .../nccs/call/service/CallFactory.java | 10 ++++++---- .../nccs/call/service/P2PCallParticipant.java | 17 ++++++++++------- .../api/ConferenceFactoryGrpcApi.java | 17 ++++++++++------- .../api/ConferenceFactoryWebApi.java | 8 +++----- .../nynjacoin/nccs/focus/api/CallGrpcApi.java | 3 +++ .../nynjacoin/nccs/focus/api/CallWebApi.java | 1 + 7 files changed, 39 insertions(+), 24 deletions(-) diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java index fb7438c3..bb9240d5 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java @@ -4,6 +4,7 @@ import com.google.protobuf.TextFormat; import com.nynjacoin.nccs.callhistory.collector.CDR; import com.nynjacoin.nccs.focus.protocol.FocusError; import com.nynjacoin.nccs.lib.grpc.GrpcTimestamp; +import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.lib.util.InstanceLogger; import com.nynjacoin.nccs.lib.util.UuidGenerator; import com.nynjacoin.nccs.lib.vertx.timer.OneShotTimer; @@ -422,6 +423,7 @@ public class Call { void openMediaControl( String accountId, + JwtInfo jwtInfo, String participantId, GrpcBidiExchange exchange) { @@ -430,7 +432,7 @@ public class Call { findConnectedParticipant(accountId, participantId) .ifPresentOrElse( participant -> participant.reconnect(exchange), - () -> addParticipant(accountId, participantId, exchange) + () -> addParticipant(accountId, jwtInfo.getClientId(), participantId, exchange) ); } @@ -533,6 +535,7 @@ public class Call { private void addParticipant( String accountId, + String clientId, String participantId, GrpcBidiExchange exchange) { @@ -543,6 +546,7 @@ public class Call { this, handshakeCollector.getConnectionId(), accountId, + clientId, participantId, exchange); participant.announce(handshakeCollector.getPartyConnectionId(), false); @@ -558,6 +562,7 @@ public class Call { this, UuidGenerator.generate(), accountId, + clientId, participantId, exchange); if (participants.isEmpty()) { diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java index d8345019..d4641ae9 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java @@ -2,6 +2,7 @@ package com.nynjacoin.nccs.call.service; import com.nynjacoin.nccs.callhistory.collector.HistoryEventsProcessor; import com.nynjacoin.nccs.focus.protocol.FocusError; +import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.lib.util.UuidGenerator; import com.nynjacoin.nccs.restclient.bubble.BubbleSender; import com.nynjacoin.nccs.restclient.push.PushNotificationSender; @@ -55,9 +56,9 @@ public class CallFactory { return pushNotificationSender; } - public BubbleSender getBubbleSender() { return bubbleSender; } + BubbleSender getBubbleSender() { return bubbleSender; } - public HistoryEventsProcessor getHistory() { return history; } + HistoryEventsProcessor getHistory() { return history; } public void createCall( String accountId, @@ -118,11 +119,12 @@ public class CallFactory { public void openMediaControl( String accountId, + JwtInfo jwtInfo, String callId, String participantId, - GrpcBidiExchange exchange) { + GrpcBidiExchange exchange) { - getCall(callId).openMediaControl(accountId, participantId, exchange); + getCall(callId).openMediaControl(accountId, jwtInfo, participantId, exchange); } public void hangup( diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java index 11a6d376..62ee3ca2 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java @@ -32,6 +32,7 @@ public class P2PCallParticipant { private final String connectionId; private final Call parent; private final String accountId; + private final String clientId; private final String participantId; private final Timer keepAliveTimer; private final Timer reconnectTimer; @@ -40,16 +41,18 @@ public class P2PCallParticipant { private Long lastReceiveStamp; P2PCallParticipant( - Call parent, - String connectionId, - String accountId, - String participantId, - GrpcBidiExchange exchange) { - - logger = new InstanceLogger(LOGGER, parent.getId() + ':' + accountId + ':' + participantId); + Call parent, + String connectionId, + String accountId, + String clientId, String participantId, + GrpcBidiExchange exchange) { + + logger = new InstanceLogger(LOGGER, parent.getId() + ':' + accountId + ':' + clientId + + ':' + participantId); this.connectionId = connectionId; this.parent = parent; this.accountId = accountId; + this.clientId = clientId; this.participantId = participantId; Vertx vertx = parent.getVertx(); keepAliveTimer = new PeriodicTimer(vertx, KEEP_ALIVE_PERIOD * 1000L, this::checkAlive); diff --git a/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryGrpcApi.java b/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryGrpcApi.java index 8794b5aa..6258ec3e 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryGrpcApi.java +++ b/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryGrpcApi.java @@ -2,6 +2,7 @@ package com.nynjacoin.nccs.conferencefactory.api; import com.nynjacoin.nccs.conferencefactory.service.ConferenceFactoryVerticle; import com.nynjacoin.nccs.lib.grpc.GrpcContextKeys; +import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.protocol.cfp.ConferenceFactoryGrpc; import com.nynjacoin.nccs.protocol.cfp.CreateConferenceRequest; import com.nynjacoin.nccs.protocol.cfp.CreateConferenceResponse; @@ -44,11 +45,11 @@ public class ConferenceFactoryGrpcApi Future response) { String accountId = GrpcContextKeys.ACCOUNT_ID.get(); - String jwtAccountId = GrpcContextKeys.JWT_ACCOUNT_ID.get(); + JwtInfo jwtInfo = GrpcContextKeys.JWT_INFO.get(); verticle.runOnContext( - () -> - verticle.conferenceFactory.createConference(jwtAccountId, accountId, request, response), + () -> verticle.conferenceFactory + .createConference(jwtInfo.getAccountId(), accountId, request, response), response, GrpcContextKeys.LOG_CONTEXT.get() ); @@ -60,11 +61,12 @@ public class ConferenceFactoryGrpcApi Future response) { String accountId = GrpcContextKeys.ACCOUNT_ID.get(); - String jwtAccountId = GrpcContextKeys.JWT_ACCOUNT_ID.get(); + JwtInfo jwtInfo = GrpcContextKeys.JWT_INFO.get(); verticle.runOnContext( () -> - verticle.conferenceFactory.startConference(jwtAccountId, accountId, request, response), + verticle.conferenceFactory + .startConference(jwtInfo.getAccountId(), accountId, request, response), response, GrpcContextKeys.LOG_CONTEXT.get() ); @@ -104,10 +106,11 @@ public class ConferenceFactoryGrpcApi Future response) { String accountId = GrpcContextKeys.ACCOUNT_ID.get(); - String jwtAccountId = GrpcContextKeys.JWT_ACCOUNT_ID.get(); + JwtInfo jwtInfo = GrpcContextKeys.JWT_INFO.get(); verticle.runOnContext( - () -> verticle.conferenceFactory.enterRoom(jwtAccountId, accountId, request, response), + () -> verticle.conferenceFactory + .enterRoom(jwtInfo.getAccountId(), accountId, request, response), response, GrpcContextKeys.LOG_CONTEXT.get() ); diff --git a/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryWebApi.java b/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryWebApi.java index dac62da2..3ab6cffa 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryWebApi.java +++ b/focus/src/main/java/com/nynjacoin/nccs/conferencefactory/api/ConferenceFactoryWebApi.java @@ -26,8 +26,6 @@ import io.vertx.ext.web.RoutingContext; public class ConferenceFactoryWebApi implements WebApi { - private static final String UNKNOWN_JWT_ACCOUNT_ID = "unknown-jwt-account-id"; - public ConferenceFactoryWebApi(ConferenceFactoryVerticle conferenceFactoryVerticle) { this.verticle = conferenceFactoryVerticle; } @@ -55,7 +53,7 @@ public class ConferenceFactoryWebApi implements WebApi { FocusWebMetadata focusWebMetadata = new FocusWebMetadata(ctx); String accountId = focusWebMetadata.get(CommonMetadataKey.ACCOUNT_ID); - String jwtAccountId = UNKNOWN_JWT_ACCOUNT_ID; + String jwtAccountId = focusWebMetadata.getJwtInfo().getAccountId(); CreateConferenceRequest request = CreateConferenceRequest.parseFrom(body); Future response = WebResponseHandler.future(ctx); @@ -73,7 +71,7 @@ public class ConferenceFactoryWebApi implements WebApi { FocusWebMetadata focusWebMetadata = new FocusWebMetadata(ctx); String accountId = focusWebMetadata.get(CommonMetadataKey.ACCOUNT_ID); - String jwtAccountId = UNKNOWN_JWT_ACCOUNT_ID; + String jwtAccountId = focusWebMetadata.getJwtInfo().getAccountId(); StartConferenceRequest request = StartConferenceRequest.parseFrom(body); Future response = WebResponseHandler.future(ctx); @@ -123,7 +121,7 @@ public class ConferenceFactoryWebApi implements WebApi { FocusWebMetadata focusWebMetadata = new FocusWebMetadata(ctx); String accountId = focusWebMetadata.get(CommonMetadataKey.ACCOUNT_ID); - String jwtAccountId = UNKNOWN_JWT_ACCOUNT_ID; + String jwtAccountId = focusWebMetadata.getJwtInfo().getAccountId(); var request = EnterRoomRequest.parseFrom(body); Future response = WebResponseHandler.future(ctx); diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java index eaf01d7f..ca9f65b6 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java @@ -6,6 +6,7 @@ import com.nynjacoin.nccs.focus.grpcweb.InstanceIdParser; import com.nynjacoin.nccs.focus.service.CallVerticle; import com.nynjacoin.nccs.lib.grpc.GrpcContextKeys; import com.nynjacoin.nccs.focus.args.OpenMediaControl; +import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.protocol.csp.CallGrpc; import com.nynjacoin.nccs.protocol.csp.HandshakePacket; import com.nynjacoin.nccs.protocol.def.Void; @@ -35,9 +36,11 @@ public class CallGrpcApi extends CallGrpc.CallVertxImplBase { var instanceIdParser = new InstanceIdParser(); if (instanceIdParser.getInstanceId().startsWith(CallFactory.P2P_CALL_ID_PREFIX)) { + JwtInfo jwtInfo = GrpcContextKeys.JWT_INFO.get(); p2pCallVerticle.runOnContext( () -> p2pCallVerticle.callFactory.openMediaControl( accountId, + jwtInfo, instanceIdParser.getInstanceId(), instanceIdParser.getParticipantId(), exchange), diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java index 009bde30..4d046ada 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java @@ -112,6 +112,7 @@ public class CallWebApi implements WebApi { p2pCallVerticle.runOnContext( () -> p2pCallVerticle.callFactory.openMediaControl( focusWebMetadata.getAccountId(), + focusWebMetadata.getJwtInfo(), focusWebMetadata.getInstanceId(), focusWebMetadata.getParticipantId(), exchange), -- GitLab From 750c54a0c56683df51c407daa3f14f1e4d774848 Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Thu, 28 May 2020 01:20:29 +0300 Subject: [PATCH 04/10] Call pickup: * publish peer connection info for my devices in the call * do not announce my other peer connections to me --- .../com/nynjacoin/nccs/call/service/Call.java | 25 ++++++++++++++++--- .../nccs/call/service/P2PCallParticipant.java | 18 ++++++++++--- protocol/public/src/main/proto | 2 +- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java index bb9240d5..e753e75a 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java @@ -8,6 +8,7 @@ import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.lib.util.InstanceLogger; import com.nynjacoin.nccs.lib.util.UuidGenerator; import com.nynjacoin.nccs.lib.vertx.timer.OneShotTimer; +import com.nynjacoin.nccs.protocol.sp.useractivity.PeerConnectionInfo; import com.nynjacoin.nccs.restclient.bubble.BubbleSender.AnswerStatus; import com.nynjacoin.nccs.restclient.bubble.BubbleSender.ContentType; import com.nynjacoin.nccs.restclient.push.PushNotificationSender; @@ -546,6 +547,7 @@ public class Call { this, handshakeCollector.getConnectionId(), accountId, + isCaller(accountId), clientId, participantId, exchange); @@ -562,6 +564,7 @@ public class Call { this, UuidGenerator.generate(), accountId, + isCaller(accountId), clientId, participantId, exchange); @@ -577,8 +580,11 @@ public class Call { participant.announce(handshakeCollector.getConnectionId(), true); } else { participants.values().forEach(p -> { - participant.announce(p.getConnectionId(), true); - p.announce(participant.getConnectionId(), false); + // Ignore this check here if we go for point-to-multipoint x-way media exchange. + if (p.isCaller() != participant.isCaller()) { + participant.announce(p.getConnectionId(), true); + p.announce(participant.getConnectionId(), false); + } }); } } @@ -591,7 +597,7 @@ public class Call { return; } var participant = participants.get(handshakeCollector.getPartyConnectionId()); - if (!isCaller(participant.getAccountId())) { + if (!participant.isCaller()) { logger.warn("Refused to publish non-caller offer"); return; } @@ -680,10 +686,23 @@ public class Call { .setAcceptTime(GrpcTimestamp.create(getAcceptTime())) .setCompleteTime(GrpcTimestamp.create(getCompleteTime())) .setInitialOffer(getInitialOffer(forCaller, false)) + .addAllPeerConnectionInfo(getPeerConnectionInfo(forCaller)) )) ).build(); } + private Iterable getPeerConnectionInfo(boolean forCaller) { + return participants.values().stream() + .filter(p -> p.isCaller() == forCaller) + .map(p -> PeerConnectionInfo.newBuilder() + .setClientId(p.getClientId()) + .setParticipantId(p.getParticipantId()) + .setConnectionId(p.getConnectionId()) + .build() + ) + .collect(Collectors.toList()); + } + private Offer getInitialOffer(boolean forCaller, boolean forPush) { if (forCaller || handshakeCollector == null || handshakeCollector.getOffer() == null) { return Offer.getDefaultInstance(); diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java index 62ee3ca2..b3c3fd54 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java @@ -32,6 +32,7 @@ public class P2PCallParticipant { private final String connectionId; private final Call parent; private final String accountId; + private final boolean isCaller; private final String clientId; private final String participantId; private final Timer keepAliveTimer; @@ -44,7 +45,9 @@ public class P2PCallParticipant { Call parent, String connectionId, String accountId, - String clientId, String participantId, + boolean isCaller, + String clientId, + String participantId, GrpcBidiExchange exchange) { logger = new InstanceLogger(LOGGER, parent.getId() + ':' + accountId + ':' + clientId + @@ -52,6 +55,7 @@ public class P2PCallParticipant { this.connectionId = connectionId; this.parent = parent; this.accountId = accountId; + this.isCaller = isCaller; this.clientId = clientId; this.participantId = participantId; Vertx vertx = parent.getVertx(); @@ -72,10 +76,18 @@ public class P2PCallParticipant { return accountId; } + String getClientId() { + return clientId; + } + public String getParticipantId() { return participantId; } + public boolean isCaller() { + return isCaller; + } + void reconnect(GrpcBidiExchange exchange) { closeExchange(TerminateReason.REPLACED); reconnectTimer.cancel(); @@ -87,9 +99,9 @@ public class P2PCallParticipant { destroy(); } - void announce(String participantId, boolean sendOffer) { + void announce(String connectionId, boolean sendOffer) { HandshakePacket announcement = HandshakePacket.newBuilder() - .setConnectionId(participantId) + .setConnectionId(connectionId) .addMessage(HandshakeMessage.newBuilder() .setConnectionOpened(ConnectionOpened.newBuilder().setSendOffer(sendOffer))) .build(); diff --git a/protocol/public/src/main/proto b/protocol/public/src/main/proto index 4b377275..ced6152f 160000 --- a/protocol/public/src/main/proto +++ b/protocol/public/src/main/proto @@ -1 +1 @@ -Subproject commit 4b377275dcb527b3c19c5c48c5769bececbb130c +Subproject commit ced6152fa6bc7dc8ee8fcec3d867b2d66924f082 -- GitLab From cbf8de5a37fdf00173d8db13ab48a5b4dae8582d Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Thu, 28 May 2020 14:35:22 +0300 Subject: [PATCH 05/10] Fix: update p2p call activity for added/removed participants. --- focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java index e753e75a..05971e87 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java @@ -590,6 +590,7 @@ public class Call { } participants.put(participant.getConnectionId(), participant); missingPartyTimer.cancel(); + publishUpdate(participant.isCaller()); } private void onCollectedOffer() { @@ -627,6 +628,7 @@ public class Call { handshakeCollector = null; } checkStartMissingPartyTimer(); + publishUpdate(participant.isCaller()); } private void sendPushToCallee() { -- GitLab From 6e30e454de168e4eef5b46d3b415db6d071d9988 Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Thu, 28 May 2020 15:03:05 +0300 Subject: [PATCH 06/10] Change misleading field name. --- .../main/java/com/nynjacoin/nccs/call/service/Call.java | 8 ++++---- protocol/public/src/main/proto | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java index 05971e87..2ac7996e 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java @@ -8,7 +8,7 @@ import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.lib.util.InstanceLogger; import com.nynjacoin.nccs.lib.util.UuidGenerator; import com.nynjacoin.nccs.lib.vertx.timer.OneShotTimer; -import com.nynjacoin.nccs.protocol.sp.useractivity.PeerConnectionInfo; +import com.nynjacoin.nccs.protocol.sp.useractivity.P2PParticipantInfo; import com.nynjacoin.nccs.restclient.bubble.BubbleSender.AnswerStatus; import com.nynjacoin.nccs.restclient.bubble.BubbleSender.ContentType; import com.nynjacoin.nccs.restclient.push.PushNotificationSender; @@ -688,15 +688,15 @@ public class Call { .setAcceptTime(GrpcTimestamp.create(getAcceptTime())) .setCompleteTime(GrpcTimestamp.create(getCompleteTime())) .setInitialOffer(getInitialOffer(forCaller, false)) - .addAllPeerConnectionInfo(getPeerConnectionInfo(forCaller)) + .addAllParticipantInfo(getPeerConnectionInfo(forCaller)) )) ).build(); } - private Iterable getPeerConnectionInfo(boolean forCaller) { + private Iterable getPeerConnectionInfo(boolean forCaller) { return participants.values().stream() .filter(p -> p.isCaller() == forCaller) - .map(p -> PeerConnectionInfo.newBuilder() + .map(p -> P2PParticipantInfo.newBuilder() .setClientId(p.getClientId()) .setParticipantId(p.getParticipantId()) .setConnectionId(p.getConnectionId()) diff --git a/protocol/public/src/main/proto b/protocol/public/src/main/proto index ced6152f..22f5f3eb 160000 --- a/protocol/public/src/main/proto +++ b/protocol/public/src/main/proto @@ -1 +1 @@ -Subproject commit ced6152fa6bc7dc8ee8fcec3d867b2d66924f082 +Subproject commit 22f5f3eb9cbf5828da15d3f5a0e74031a5ecd0d7 -- GitLab From d324b6b1c2176b234838920dca9d66442d775a0a Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Thu, 28 May 2020 22:26:59 +0300 Subject: [PATCH 07/10] Call pickup: extend hangup to allow dropping my other participants. --- .../com/nynjacoin/nccs/call/service/Call.java | 88 +++- .../nccs/call/service/CallFactory.java | 5 +- .../nccs/call/service/P2PCallParticipant.java | 16 +- .../nynjacoin/nccs/focus/api/CallGrpcApi.java | 16 +- .../nynjacoin/nccs/focus/api/CallWebApi.java | 3 +- .../nccs/focus/service/CallVerticle.java | 3 +- .../nynjacoin/nccs/focus/service/Focus.java | 3 +- .../mediacontroller/JvbMediaParticipant.java | 21 +- .../mediacontroller/MediaParticipant.java | 3 +- protocol/public/src/main/proto | 2 +- .../nccs/sandbox/grpc/NccsClient.java | 425 +++++++++--------- .../nccs/sandbox/grpc_vertx/CallClient.java | 54 ++- 12 files changed, 359 insertions(+), 280 deletions(-) diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java index 2ac7996e..5daa82ce 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/Call.java @@ -8,6 +8,9 @@ import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.lib.util.InstanceLogger; import com.nynjacoin.nccs.lib.util.UuidGenerator; import com.nynjacoin.nccs.lib.vertx.timer.OneShotTimer; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; +import com.nynjacoin.nccs.protocol.csp.HangupRequest.ReasonCode; +import com.nynjacoin.nccs.protocol.csp.TerminateReason; import com.nynjacoin.nccs.protocol.sp.useractivity.P2PParticipantInfo; import com.nynjacoin.nccs.restclient.bubble.BubbleSender.AnswerStatus; import com.nynjacoin.nccs.restclient.bubble.BubbleSender.ContentType; @@ -229,6 +232,12 @@ public class Call { onCallEnded(call, callEndedBy, EventName.HANGUP); } + @Override + public void onTerminateParticipants(Call call, P2PCallParticipant participant, + boolean myOtherParticipants) { + call.terminateParticipants(participant, myOtherParticipants); + } + @Override CallState.Builder buildUpdate(boolean forCaller, Call call) { return CallState.newBuilder().setActive(CallState.Active.getDefaultInstance()); @@ -245,6 +254,11 @@ public class Call { public void onHangup(Call call, CallEndedBy callEndedBy) { } + @Override + public void onTerminateParticipants(Call call, P2PCallParticipant participant, + boolean myOtherParticipants) { + } + @Override void onTimeout(Call call) { call.destroy(); @@ -306,6 +320,14 @@ public class Call { throw FocusError.CALL_BAD_STATE.exception(); } + void onMissingPartyTimeout(Call call) { + } + + void onTerminateParticipants(Call call, P2PCallParticipant participant, + boolean myOtherParticipants) { + throw FocusError.CALL_BAD_STATE.exception(); + } + Long getTimeout() { return timeout; } @@ -319,14 +341,11 @@ public class Call { call.setCompleteTime(new Date()); call.setCallEndReason(CallEndReason.getDefaultInstance()); call.setCallEndedBy(callEndedBy); - call.terminateParticipants(); + call.terminateParticipantsAtCallEnd(); call.publishAndPush(); call.publishCdr(); call.sendBubble(); } - - public void onMissingPartyTimeout(Call call) { - } } private static final Logger LOGGER = LogManager.getLogger(Call.class); @@ -334,25 +353,25 @@ public class Call { private final Vertx vertx; private final CallFactory parent; + private final InstanceLogger logger; private final UserActivityPublisher userActivityPublisher; private final PushNotificationSender pushNotificationSender; private final CallInfo callInfo; private final Timer missingPartyTimer; private int transitionSequence; - private State state; - private Date startTime; + private Date startTime; private Date confirmTime; + private Date acceptTime; private Date completeTime; private CallEndedBy callEndedBy; - private CallEndReason callEndReason; + private Map participants; private ParticipantHandshakeCollector handshakeCollector; - Call( CallFactory parent, UserActivityPublisher userActivityPublisher, @@ -416,10 +435,36 @@ public class Call { response.complete(Void.getDefaultInstance()); } - void hangup(String accountId, Future response) { + @SuppressWarnings("DuplicateExpressions") + void hangup(String accountId, String participantId, HangupRequest request, + Future response) { + authorize(accountId); - state.onHangup(this, isCallee(accountId) ? CallEndedBy.CALLEE : CallEndedBy.CALLER); - response.complete(Void.getDefaultInstance()); + if (request.getReasonCode() != ReasonCode.USER_ACTION) { + logger.warn("Client hangup with abnormal reason {} {} {}", + accountId, request.getReasonCode(), request.getReasonMessage()); + } + switch (request.getScope()) { + case DEFAULT: + case CALL: + state.onHangup(this, isCallee(accountId) ? CallEndedBy.CALLEE : CallEndedBy.CALLER); + response.complete(Void.getDefaultInstance()); + break; + case THIS_PARTICIPANT: + findConnectedParticipant(accountId, participantId).ifPresentOrElse( + participant -> state.onTerminateParticipants(this, participant, false), + () -> response.fail(FocusError.PARTICIPANT_NOT_FOUND.exception()) + ); + break; + case MY_OTHER_PARTICIPANTS: + findConnectedParticipant(accountId, participantId).ifPresentOrElse( + participant -> state.onTerminateParticipants(this, participant, true), + () -> response.fail(FocusError.PARTICIPANT_NOT_FOUND.exception()) + ); + break; + default: + response.fail(NccsError.UNIMPLEMENTED.exception("Scope not implemented")); + } } void openMediaControl( @@ -616,9 +661,26 @@ public class Call { .findFirst(); } - private void terminateParticipants() { + private void terminateParticipantsAtCallEnd() { // copy the list as termination will modify the original participants field - new ArrayList<>(participants.values()).forEach(P2PCallParticipant::terminate); + new ArrayList<>(participants.values()).forEach(p -> p.terminate(TerminateReason.CALL_ENDED)); + } + + private void terminateParticipants(P2PCallParticipant participant, boolean myOtherParticipants) { + if (myOtherParticipants) { + participants.values().stream() + .filter(p -> p != participant && p.isCaller() == participant.isCaller()) + .forEach(this::terminateParticipant); + } else { + terminateParticipant(participant); + } + } + + private void terminateParticipant(P2PCallParticipant participant) { + participants.values().stream() + .filter(p -> p.isCaller() != participant.isCaller()) + .forEach(p -> p.retract(participant.getConnectionId())); + participant.terminate(TerminateReason.PARTICIPANT_HUNG_UP); } void removeMe(P2PCallParticipant participant) { diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java index d4641ae9..f2a16a80 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/CallFactory.java @@ -4,6 +4,7 @@ import com.nynjacoin.nccs.callhistory.collector.HistoryEventsProcessor; import com.nynjacoin.nccs.focus.protocol.FocusError; import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.lib.util.UuidGenerator; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; import com.nynjacoin.nccs.restclient.bubble.BubbleSender; import com.nynjacoin.nccs.restclient.push.PushNotificationSender; import com.nynjacoin.nccs.protocol.cfp.CreateCallRequest; @@ -131,10 +132,10 @@ public class CallFactory { String accountId, String callId, String participantId, - Void request, + HangupRequest request, Future response) { - getCall(callId).hangup(accountId, response); + getCall(callId).hangup(accountId, participantId, request, response); } private Call getCall(String callId) { diff --git a/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java b/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java index b3c3fd54..e3dcb8b8 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java +++ b/focus/src/main/java/com/nynjacoin/nccs/call/service/P2PCallParticipant.java @@ -5,6 +5,7 @@ import com.nynjacoin.nccs.lib.util.InstanceLogger; import com.nynjacoin.nccs.lib.vertx.timer.OneShotTimer; import com.nynjacoin.nccs.lib.vertx.timer.PeriodicTimer; import com.nynjacoin.nccs.lib.vertx.timer.Timer; +import com.nynjacoin.nccs.protocol.csp.ConnectionClosed; import com.nynjacoin.nccs.protocol.csp.ConnectionOpened; import com.nynjacoin.nccs.protocol.csp.HandshakeMessage; import com.nynjacoin.nccs.protocol.csp.HandshakePacket; @@ -84,7 +85,7 @@ public class P2PCallParticipant { return participantId; } - public boolean isCaller() { + boolean isCaller() { return isCaller; } @@ -94,8 +95,8 @@ public class P2PCallParticipant { attachExchange(exchange); } - void terminate() { - closeExchange(TerminateReason.CALL_ENDED); + void terminate(TerminateReason terminateReason) { + closeExchange(terminateReason); destroy(); } @@ -108,6 +109,15 @@ public class P2PCallParticipant { send(announcement); } + void retract(String connectionId) { + HandshakePacket retraction = HandshakePacket.newBuilder() + .setConnectionId(connectionId) + .addMessage(HandshakeMessage.newBuilder() + .setConnectionClosed(ConnectionClosed.newBuilder())) + .build(); + send(retraction); + } + private void attachExchange(GrpcBidiExchange exchange) { this.exchange = exchange; lastReceiveStamp = System.currentTimeMillis(); diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java index ca9f65b6..f476806a 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallGrpcApi.java @@ -9,6 +9,7 @@ import com.nynjacoin.nccs.focus.args.OpenMediaControl; import com.nynjacoin.nccs.lib.grpc.JwtInfo; import com.nynjacoin.nccs.protocol.csp.CallGrpc; import com.nynjacoin.nccs.protocol.csp.HandshakePacket; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; import com.nynjacoin.nccs.protocol.def.Void; import io.vertx.core.Future; import io.vertx.grpc.GrpcBidiExchange; @@ -72,17 +73,16 @@ public class CallGrpcApi extends CallGrpc.CallVertxImplBase { ); exchange.endHandler( - (param) -> { - confCallVerticle.onUpStreamEnd( - accountId, - instanceIdParser.getInstanceId(), - instanceIdParser.getParticipantId()); - }); - } + (param) -> confCallVerticle.onUpStreamEnd( + accountId, + instanceIdParser.getInstanceId(), + instanceIdParser.getParticipantId()) + ); + } } @Override - public void hangup(Void request, Future response) { + public void hangup(HangupRequest request, Future response) { String accountId = GrpcContextKeys.ACCOUNT_ID.get(); var instanceIdParser = new InstanceIdParser(); diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java index 4d046ada..f0b2559b 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/api/CallWebApi.java @@ -12,6 +12,7 @@ import com.nynjacoin.nccs.lib.grpc.web.WebApi; import com.nynjacoin.nccs.lib.grpc.web.WebEventTarget; import com.nynjacoin.nccs.lib.grpc.web.WebResponseHandler; import com.nynjacoin.nccs.protocol.csp.HandshakePacket; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; import com.nynjacoin.nccs.protocol.def.Void; import com.nynjacoin.nccs.lib.grpc.protocol.error.NccsWrappingException; import io.grpc.Context; @@ -147,7 +148,7 @@ public class CallWebApi implements WebApi { ctx.request().bodyHandler(NccsWrappingException.wrap(bodyBuffer -> { FocusWebMetadata focusWebMetadata = new FocusWebMetadata(ctx); - Void request = Void.parseFrom(bodyBuffer.getBytes()); + HangupRequest request = HangupRequest.parseFrom(bodyBuffer.getBytes()); Future response = WebResponseHandler.future(ctx); if (focusWebMetadata.getInstanceId().startsWith(CallFactory.P2P_CALL_ID_PREFIX)) { diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java b/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java index 6806d168..cae5b150 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/service/CallVerticle.java @@ -6,6 +6,7 @@ import com.nynjacoin.nccs.lib.vertx.dispatch.ContextPreserver; import com.nynjacoin.nccs.lib.vertx.dispatch.NccsVerticle; import com.nynjacoin.nccs.protocol.ccp.ManageMemberRequest; import com.nynjacoin.nccs.protocol.ccp.ManageParticipanRequest; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; import com.nynjacoin.nccs.protocol.def.Void; import io.vertx.core.Context; import io.vertx.core.Future; @@ -52,7 +53,7 @@ public class CallVerticle extends NccsVerticle { String accountId, String conferenceId, String participantId, - Void request, + HangupRequest request, Future response) { final var logContext = GrpcContextKeys.LOG_CONTEXT.get(); diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java b/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java index a8eb4bf1..21eb4f71 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/service/Focus.java @@ -10,6 +10,7 @@ import com.nynjacoin.nccs.mediacontroller.MediaController; import com.nynjacoin.nccs.protocol.ccp.ManageMemberRequest; import com.nynjacoin.nccs.protocol.ccp.ManageParticipanRequest; import com.nynjacoin.nccs.protocol.csp.HandshakePacket; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; import com.nynjacoin.nccs.protocol.csp.TerminateReason; import com.nynjacoin.nccs.protocol.def.Void; import com.nynjacoin.nccs.stateholder.service.StateHolderVerticle; @@ -153,7 +154,7 @@ public class Focus { String accountId, String conferenceId, String participantId, - Void request, + HangupRequest request, Future response) { getParticipant(conferenceId, participantId).getMediaParticipant().hangup(request, response); diff --git a/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaParticipant.java b/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaParticipant.java index c86db80c..f62a3ec4 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaParticipant.java +++ b/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaParticipant.java @@ -14,6 +14,8 @@ import com.nynjacoin.nccs.protocol.csp.HandshakeError; import com.nynjacoin.nccs.protocol.csp.HandshakeErrorCode; import com.nynjacoin.nccs.protocol.csp.HandshakeMessage; import com.nynjacoin.nccs.protocol.csp.HandshakePacket; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; +import com.nynjacoin.nccs.protocol.csp.HangupRequest.ReasonCode; import com.nynjacoin.nccs.protocol.csp.KeepAlive; import com.nynjacoin.nccs.protocol.csp.MediaPaused; import com.nynjacoin.nccs.protocol.csp.MediaResumed; @@ -176,9 +178,22 @@ public class JvbMediaParticipant implements MediaParticipant { } @Override - public void hangup(Void request, Future response) { - hangup(TerminateReason.HANGUP); - response.complete(Void.getDefaultInstance()); + public void hangup(HangupRequest request, Future response) { + if (request.getReasonCode() != ReasonCode.USER_ACTION) { + logger.warn("Client hangup with abnormal reason {} {}", + request.getReasonCode(), request.getReasonMessage()); + } + switch (request.getScope()) { + case DEFAULT: + case THIS_PARTICIPANT: + hangup(TerminateReason.HANGUP); + response.complete(Void.getDefaultInstance()); + break; + default: + hangup(TerminateReason.CLIENT_ERROR); + response.fail(NccsError.UNIMPLEMENTED.exception("Scope not implemented")); + break; + } } @Override diff --git a/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/MediaParticipant.java b/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/MediaParticipant.java index 5ddc06a2..33670a15 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/MediaParticipant.java +++ b/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/MediaParticipant.java @@ -2,6 +2,7 @@ package com.nynjacoin.nccs.mediacontroller; import com.nynjacoin.nccs.focus.args.OpenMediaControl; import com.nynjacoin.nccs.protocol.csp.HandshakePacket; +import com.nynjacoin.nccs.protocol.csp.HangupRequest; import com.nynjacoin.nccs.protocol.def.MediaContentType; import com.nynjacoin.nccs.protocol.def.Void; import io.vertx.core.Future; @@ -15,7 +16,7 @@ public interface MediaParticipant { void onHandshake(HandshakePacket handshakePacket); - void hangup(Void request, Future response); + void hangup(HangupRequest request, Future response); void eject(); diff --git a/protocol/public/src/main/proto b/protocol/public/src/main/proto index 22f5f3eb..d48d9291 160000 --- a/protocol/public/src/main/proto +++ b/protocol/public/src/main/proto @@ -1 +1 @@ -Subproject commit 22f5f3eb9cbf5828da15d3f5a0e74031a5ecd0d7 +Subproject commit d48d92919520c2e90769769b392f019fe9c7c36e diff --git a/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java b/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java index a8e834b5..52ffb555 100644 --- a/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java +++ b/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java @@ -78,30 +78,24 @@ public class NccsClient { private final CallFactoryStub callFactory; private final Metadata callInvitationMetadata = new Metadata(); private final CallInvitationStub callInvitation; - private String host; - private Integer port; - private String scheme; - public String accountId = "account-id-3"; + String accountId = "account-id-3"; private Random random = new Random(); /** * Construct client for accessing RouteGuide server at {@code host:port}. */ - public NccsClient(String scheme, String host, Integer port) { + NccsClient(String scheme, String host, Integer port) { this(scheme.equalsIgnoreCase("https")? ManagedChannelBuilder.forAddress(host, port).useTransportSecurity() : ManagedChannelBuilder.forAddress(host,port).usePlaintext()); - this.host = host; - this.port = port; - this.scheme = scheme; info("Connecting to {0}://{1}:{2}", scheme, host, port.toString()); } /** * Construct client for accessing RouteGuide server using the existing channel. */ - public NccsClient(ManagedChannelBuilder channelBuilder) { + private NccsClient(ManagedChannelBuilder channelBuilder) { channel = channelBuilder.build(); conferenceFactoryMetadata = new Metadata(); conferenceFactoryMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); @@ -120,7 +114,7 @@ public class NccsClient { callInvitation = MetadataUtils.attachHeaders(CallInvitationGrpc.newStub(channel), callInvitationMetadata); } - public NccsClient setAccount(String accountId) { + NccsClient setAccount(String accountId) { this.accountId = accountId; conferenceFactoryMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); conferenceMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); @@ -128,24 +122,24 @@ public class NccsClient { return this; } - public void shutdown() throws InterruptedException { + void shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } public static class RequestObserverContainer { private StreamObserver requestObserver; - public StreamObserver getRequestObserver() { + StreamObserver getRequestObserver() { return requestObserver; } - public void setRequestObserver( - StreamObserver requestObserver) { + void setRequestObserver( + StreamObserver requestObserver) { this.requestObserver = requestObserver; } } - public Observable fetch(String topic, String instanceId) { + Observable fetch(String topic, String instanceId) { return Observable.create(emitter -> { FetchRequest fetchRequest = FetchRequest.newBuilder(FetchRequest.newBuilder() .setTopic(topic) @@ -159,7 +153,7 @@ public class NccsClient { StateHolderGrpc.StateHolderStub stateHolder = MetadataUtils.attachHeaders(StateHolderGrpc.newStub(channel), stateHolderMetadata); - stateHolder.fetch(fetchRequest, new StreamObserver() { + stateHolder.fetch(fetchRequest, new StreamObserver<>() { @Override public void onNext(UpdatePacket value) { emitter.onNext(value); @@ -180,68 +174,68 @@ public class NccsClient { // conference-factory - public Single createConference() { + Single createConference() { return createConference(CreateConferenceRequest.newBuilder() .setExternalId(String.valueOf(Math.random() * 1000))); } - public Single createConference(CreateConferenceRequest.Builder confBuilder) { + Single createConference(CreateConferenceRequest.Builder confBuilder) { return Single.create(emitter -> { CreateConferenceRequest createConferenceRequest = confBuilder.build(); conferenceFactory.createConference(createConferenceRequest, - new StreamObserver() { - @Override - public void onNext(CreateConferenceResponse value) { - emitter.onSuccess(value); - } - - @Override - public void onError(Throwable t) { - info("Error on create conference"); - emitter.onError(t); - } - - @Override - public void onCompleted() { - } - }); + new StreamObserver<>() { + @Override + public void onNext(CreateConferenceResponse value) { + emitter.onSuccess(value); + } + + @Override + public void onError(Throwable t) { + info("Error on create conference"); + emitter.onError(t); + } + + @Override + public void onCompleted() { + } + }); }); } - public Single getConferenceId(String linkId) { + Single getConferenceId(String linkId) { return Single.create(emitter -> { conferenceFactoryMetadata.removeAll(CommonMetadataKey.ACCOUNT_ID); GetConferenceIdRequest request = GetConferenceIdRequest.newBuilder().setLinkId(linkId).build(); conferenceFactory.getConferenceId(request, - new StreamObserver() { - @Override - public void onNext(GetConferenceIdResponse value) { - emitter.onSuccess(value); - } - - @Override - public void onError(Throwable t) { - info("Error on getConferenceId by link"); - emitter.onError(t); - } - - @Override - public void onCompleted() { - } - }); + new StreamObserver<>() { + @Override + public void onNext(GetConferenceIdResponse value) { + emitter.onSuccess(value); + } + + @Override + public void onError(Throwable t) { + info("Error on getConferenceId by link"); + emitter.onError(t); + } + + @Override + public void onCompleted() { + } + }); }); } // conference - public Single updateConferenceInfo(String conferenceId, String subject) { + Single updateConferenceInfo(String conferenceId, String subject) { UpdateConferenceInfoRequest updateRequest = UpdateConferenceInfoRequest.newBuilder() .setSubject(subject).build(); return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.updateConferenceInfo(updateRequest, new StreamObserver() { + conference.updateConferenceInfo(updateRequest, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -260,7 +254,7 @@ public class NccsClient { }); } - public Single addMember(String conferenceId, String accountId) { + Single addMember(String conferenceId, String accountId) { Address address = Address.newBuilder() .setType(Address.Type.ACCOUNT) @@ -274,10 +268,11 @@ public class NccsClient { return addMember(conferenceId, addMemberRequest); } - public Single addMember(String conferenceId, AddMemberRequest addMemberRequest) { + private Single addMember(String conferenceId, + AddMemberRequest addMemberRequest) { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.addMember(addMemberRequest, new StreamObserver() { + conference.addMember(addMemberRequest, new StreamObserver<>() { @Override public void onNext(AddMemberResponse value) { emitter.onSuccess(value); @@ -296,7 +291,7 @@ public class NccsClient { }); } - public Single stopScreenSharing( + private Single stopScreenSharing( String conferenceId, String participantId) { return Single.create(emitter -> { @@ -324,7 +319,7 @@ public class NccsClient { }); } - public Single bindByLink(String conferenceId) { + Single bindByLink(String conferenceId) { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); BindByLinkRequest request = BindByLinkRequest.newBuilder().setPii(PersonallyIdentifiableInformation.getDefaultInstance()) @@ -332,32 +327,32 @@ public class NccsClient { .build(); conference.bindByLink(request, - new StreamObserver() { - @Override - public void onNext(BindByLinkResponse value) { - emitter.onSuccess(value); - } - - @Override - public void onError(Throwable t) { - info("Error on bindByLink"); - emitter.onError(t); - } - - @Override - public void onCompleted() { - } - }); + new StreamObserver<>() { + @Override + public void onNext(BindByLinkResponse value) { + emitter.onSuccess(value); + } + + @Override + public void onError(Throwable t) { + info("Error on bindByLink"); + emitter.onError(t); + } + + @Override + public void onCompleted() { + } + }); }); } - public Single removeMember(String conferenceId, String memberId) { + Single removeMember(String conferenceId, String memberId) { RemoveMemberRequest removeRequest = RemoveMemberRequest.newBuilder() .setMemberId(memberId).build(); return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.removeMember(removeRequest, new StreamObserver() { + conference.removeMember(removeRequest, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -376,7 +371,7 @@ public class NccsClient { }); } - public Single removeMember(Participant participant) { + private Single removeMember(Participant participant) { info("Remove member: {}", participant); return Single.create(emitter -> { RemoveMemberRequest removeMemberRequest = RemoveMemberRequest.newBuilder() @@ -384,7 +379,7 @@ public class NccsClient { .build(); conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, participant.getConferenceId()); conferenceMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); - conference.removeMember(removeMemberRequest, new StreamObserver() { + conference.removeMember(removeMemberRequest, new StreamObserver<>() { @Override public void onNext(Void value) { info("Remove member response: {}", value); @@ -404,12 +399,12 @@ public class NccsClient { }); } - public Observable getMembers(String conferenceId) { + Observable getMembers(String conferenceId) { GetMembersRequest req = GetMembersRequest.newBuilder().getDefaultInstanceForType(); return Observable.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.getMembers(req, new StreamObserver() { + conference.getMembers(req, new StreamObserver<>() { @Override public void onNext(MemberInfo value) { emitter.onNext(value); @@ -428,14 +423,14 @@ public class NccsClient { }); } - public Single startConference(String conferenceId) { + Single startConference(String conferenceId) { return startConference(conferenceId, Void.getDefaultInstance()); } - public Single startConference(String conferenceId, Void startRequest) { + private Single startConference(String conferenceId, Void startRequest) { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.start(startRequest, new StreamObserver() { + conference.start(startRequest, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -454,13 +449,13 @@ public class NccsClient { }); } - public Single endConference(String conferenceId) { + Single endConference(String conferenceId) { info("Ending conference: {}", conferenceId); return Single.create(emitter -> { Void destroyRequest = Void.getDefaultInstance(); conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); conferenceMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); - conference.end(destroyRequest, new StreamObserver() { + conference.end(destroyRequest, new StreamObserver<>() { @Override public void onNext(Void value) { info("Destroy response: {}", value); @@ -480,13 +475,13 @@ public class NccsClient { }); } - public Single endConference(Participant participant) { + private Single endConference(Participant participant) { info("Ending conference: {}", participant); return Single.create(emitter -> { Void destroyRequest = Void.getDefaultInstance(); conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, participant.getConferenceId()); conferenceMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); - conference.end(destroyRequest, new StreamObserver() { + conference.end(destroyRequest, new StreamObserver<>() { @Override public void onNext(Void value) { info("Destroy response: {}", value); @@ -514,7 +509,7 @@ public class NccsClient { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.manageParticipant(req, new StreamObserver() { + conference.manageParticipant(req, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -541,7 +536,7 @@ public class NccsClient { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.manageParticipant(req, new StreamObserver() { + conference.manageParticipant(req, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -560,7 +555,7 @@ public class NccsClient { }); } - public Single pauseMemberMedia(String conferenceId, String memberId, MediaContentType media) { + Single pauseMemberMedia(String conferenceId, String memberId, MediaContentType media) { ManageMemberRequest req = ManageMemberRequest.newBuilder() .setMemberId(memberId) .setPauseMedia(PauseMedia.newBuilder().addMedia(media).build()) @@ -568,7 +563,7 @@ public class NccsClient { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.manageMember(req, new StreamObserver() { + conference.manageMember(req, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -587,7 +582,7 @@ public class NccsClient { }); } - public Single resumeMemberMedia(String conferenceId, String memberId, MediaContentType media) { + Single resumeMemberMedia(String conferenceId, String memberId, MediaContentType media) { ManageMemberRequest req = ManageMemberRequest.newBuilder() .setMemberId(memberId) .setResumeMedia(ResumeMedia.newBuilder().addMedia(media).build()) @@ -595,7 +590,7 @@ public class NccsClient { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.manageMember(req, new StreamObserver() { + conference.manageMember(req, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -614,14 +609,14 @@ public class NccsClient { }); } - public Single joinConference(String conferenceId, String memberId) { + Single joinConference(String conferenceId, String memberId) { return Single.create(emitter -> { JoinRequest joinRequest = JoinRequest.newBuilder() .setMemberId(memberId) .build(); conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); conferenceMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); - conference.join(joinRequest, new StreamObserver() { + conference.join(joinRequest, new StreamObserver<>() { @Override public void onNext(JoinResponse value) { emitter.onSuccess(value); @@ -640,14 +635,14 @@ public class NccsClient { }); } - public Single joinConference(Participant participant) { + private Single joinConference(Participant participant) { return Single.create(emitter -> { JoinRequest joinRequest = JoinRequest.newBuilder() .setMemberId(participant.getMemeberId()) .build(); conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, participant.getConferenceId()); conferenceMetadata.put(CommonMetadataKey.ACCOUNT_ID, participant.getAccountId()); - conference.join(joinRequest, new StreamObserver() { + conference.join(joinRequest, new StreamObserver<>() { @Override public void onNext(JoinResponse value) { emitter.onSuccess(value); @@ -673,7 +668,7 @@ public class NccsClient { return Single.create(emitter -> { conferenceMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); - conference.reject(req, new StreamObserver() { + conference.reject(req, new StreamObserver<>() { @Override public void onNext(Void value) { emitter.onSuccess(value); @@ -694,7 +689,7 @@ public class NccsClient { // call_factory - public Single createCall(String myAccountId, String toAccountId) { + Single createCall(String myAccountId, String toAccountId) { return Single.create(emitter -> { CreateCallRequest request = CreateCallRequest.newBuilder() @@ -704,7 +699,7 @@ public class NccsClient { .build(); callFactoryMetadata.put(CommonMetadataKey.ACCOUNT_ID, myAccountId); - callFactory.createCall(request, new StreamObserver() { + callFactory.createCall(request, new StreamObserver<>() { @Override public void onNext(CreateCallResponse value) { callMetadata.put(FocusMetadataKey.INSTANCE_ID, value.getCallId()); @@ -730,83 +725,84 @@ public class NccsClient { } - public Single confirmCall(String myAccountId, String callId) { + Single confirmCall(String myAccountId, String callId) { info("confirm call {0}", callId); callInvitationMetadata.put(FocusMetadataKey.INSTANCE_ID, callId); callInvitationMetadata.put(CommonMetadataKey.ACCOUNT_ID, myAccountId); - return Single.create(emitter -> { - callInvitation.confirm(Void.getDefaultInstance(), new StreamObserver() { - @Override - public void onNext(Void voidValue) { - emitter.onSuccess(callId); - } + return Single.create(emitter -> callInvitation.confirm( + Void.getDefaultInstance(), + new StreamObserver<>() { + @Override + public void onNext(Void voidValue) { + emitter.onSuccess(callId); + } - @Override - public void onError(Throwable t) { - info("Error on confirmCall"); - emitter.onError(t); - } + @Override + public void onError(Throwable t) { + info("Error on confirmCall"); + emitter.onError(t); + } - @Override - public void onCompleted() { - } - }); - }); + @Override + public void onCompleted() { + } + })); } public Single silenceCall(String myAccountId, String callId) { info("silence call {0}", callId); callInvitationMetadata.put(FocusMetadataKey.INSTANCE_ID, callId); callInvitationMetadata.put(CommonMetadataKey.ACCOUNT_ID, myAccountId); - return Single.create(emitter -> { - callInvitation.silence(Void.getDefaultInstance(), new StreamObserver() { - @Override - public void onNext(Void voidValue) { - emitter.onSuccess(callId); - } + return Single.create( + emitter -> + callInvitation.silence( + Void.getDefaultInstance(), + new StreamObserver<>() { + @Override + public void onNext(Void voidValue) { + emitter.onSuccess(callId); + } - @Override - public void onError(Throwable t) { - info("Error on silenceCall"); - emitter.onError(t); - } + @Override + public void onError(Throwable t) { + info("Error on silenceCall"); + emitter.onError(t); + } - @Override - public void onCompleted() { - } - }); - }); + @Override + public void onCompleted() {} + })); } - public Single acceptCall(String myAccountId, String callId) { + Single acceptCall(String myAccountId, String callId) { info("accept call {0}", callId); callInvitationMetadata.put(FocusMetadataKey.INSTANCE_ID, callId); callInvitationMetadata.put(CommonMetadataKey.ACCOUNT_ID, myAccountId); - return Single.create(emitter -> { - callInvitation.accept(Void.getDefaultInstance(), new StreamObserver() { - @Override - public void onNext(Void voidValue) { - emitter.onSuccess(callId); - } + return Single.create(emitter -> callInvitation.accept( + Void.getDefaultInstance(), + new StreamObserver<>() { + @Override + public void onNext(Void voidValue) { + emitter.onSuccess(callId); + } - @Override - public void onError(Throwable t) { - info("Error on acceptCall"); - emitter.onError(t); - } + @Override + public void onError(Throwable t) { + info("Error on acceptCall"); + emitter.onError(t); + } - @Override - public void onCompleted() { - } - }); - }); + @Override + public void onCompleted() { + } + })); } public Single acceptCall(String callId) { return acceptCall(accountId, callId); } - public Single rejectCall(String myAccountId, String callId) { + private Single rejectCall(String myAccountId, String callId) { info("reject call {0}", callId); callInvitationMetadata.put(FocusMetadataKey.INSTANCE_ID, callId); callInvitationMetadata.put(CommonMetadataKey.ACCOUNT_ID, myAccountId); @@ -814,7 +810,7 @@ public class NccsClient { RejectRequest request = RejectRequest.newBuilder() .setEndReason(CallEndReason.newBuilder().setCodeValue(100).setMessage("Integration test").build()) .build(); - callInvitation.reject(request, new StreamObserver() { + callInvitation.reject(request, new StreamObserver<>() { @Override public void onNext(Void voidValue) { emitter.onSuccess(callId); @@ -837,41 +833,40 @@ public class NccsClient { return rejectCall(accountId, callId); } - public Single hangup(String myAccountId, String callId, String participantId) { + Single hangup(String myAccountId, String callId, String participantId) { info("hangup call {0}", callId); callInvitationMetadata.put(FocusMetadataKey.INSTANCE_ID, callId); callInvitationMetadata.put(CommonMetadataKey.ACCOUNT_ID, myAccountId); callInvitationMetadata.put(FocusMetadataKey.PARTICIPANT_ID, participantId); - return Single.create(emitter -> { - call.hangup(Void.getDefaultInstance(), - new StreamObserver() { - @Override - public void onNext(Void voidValue) { - emitter.onSuccess(callId); - } + return Single.create(emitter -> call.hangup( + HangupRequest.getDefaultInstance(), + new StreamObserver<>() { + @Override + public void onNext(Void voidValue) { + emitter.onSuccess(callId); + } - @Override - public void onError(Throwable t) { - info("Error on hangup"); - emitter.onError(t); - } + @Override + public void onError(Throwable t) { + info("Error on hangup"); + emitter.onError(t); + } - @Override - public void onCompleted() { - } - }); - }); + @Override + public void onCompleted() { + } + })); } public Single hangup(String callId) { return hangup(accountId, callId, UUID.randomUUID().toString()); } - public Single openMediaControl(String myAccountId) { + Single openMediaControl(String myAccountId) { info("openMediaControl for {0}", myAccountId); return Single.create(emitter -> { callMetadata.put(CommonMetadataKey.ACCOUNT_ID, myAccountId); - call.openMediaControl(new StreamObserver() { + call.openMediaControl(new StreamObserver<>() { @Override public void onNext(HandshakePacket value) { emitter.onSuccess(value); @@ -896,7 +891,7 @@ public class NccsClient { Single startConferenceSelf() { return createConference() - .map(resp -> resp.getConferenceId()) + .map(CreateConferenceResponse::getConferenceId) .flatMap(confId -> { Address address = Address.newBuilder() @@ -928,12 +923,12 @@ public class NccsClient { final RequestObserverContainer requestObserverContainer = new RequestObserverContainer(); - Completable completable = Completable.create(emitter -> { + return Completable.create(emitter -> { callMetadata.put(FocusMetadataKey.INSTANCE_ID, conferenceId); callMetadata.put(FocusMetadataKey.PARTICIPANT_ID, participantId); callMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); StreamObserver requestObserver = - call.openMediaControl(new StreamObserver() { + call.openMediaControl(new StreamObserver<>() { @Override public void onNext(HandshakePacket packet) { info("Participant {0} got handshake packet: {1}", @@ -964,25 +959,25 @@ public class NccsClient { } HandshakePacket answerPacket = HandshakePacket.newBuilder() - .setConnectionId("conn-id") - .addMessage(HandshakeMessage.newBuilder() - .setAnswer(Answer.newBuilder() - .setContent(offer) - .build()) - .build()) - .build(); + .setConnectionId("conn-id") + .addMessage(HandshakeMessage.newBuilder() + .setAnswer(Answer.newBuilder() + .setContent(offer) + .build()) + .build()) + .build(); requestObserverContainer.getRequestObserver().onNext(answerPacket); } void sendIceCandidate() { HandshakePacket iceCandidate = HandshakePacket.newBuilder() - .setConnectionId("conn-id") - .addMessage(HandshakeMessage.newBuilder() - .setIceCandidate(IceCandidate.newBuilder() - .setContent("ICE CANDIDATE") - .build()) - .build()) - .build(); + .setConnectionId("conn-id") + .addMessage(HandshakeMessage.newBuilder() + .setIceCandidate(IceCandidate.newBuilder() + .setContent("ICE CANDIDATE") + .build()) + .build()) + .build(); requestObserverContainer.getRequestObserver().onNext(iceCandidate); } @@ -1000,22 +995,21 @@ public class NccsClient { }); requestObserverContainer.setRequestObserver(requestObserver); }); - return completable; } - public Completable handshake(Participant participant) { + private Completable handshake(Participant participant) { info("Opening handshake for {0}", participant); final RequestObserverContainer requestObserverContainer = new RequestObserverContainer(); - Completable completable = Completable.create(emitter -> { + return Completable.create(emitter -> { callMetadata.put(FocusMetadataKey.INSTANCE_ID, participant.getConferenceId()); callMetadata.put(FocusMetadataKey.PARTICIPANT_ID, participant.getParticipantId()); callMetadata.put(CommonMetadataKey.ACCOUNT_ID, participant.getAccountId()); StreamObserver requestObserver = - call.openMediaControl(new StreamObserver() { + call.openMediaControl(new StreamObserver<>() { @Override public void onNext(HandshakePacket packet) { info("Participant {0} got handshake packet: {1}", @@ -1046,25 +1040,25 @@ public class NccsClient { } HandshakePacket answerPacket = HandshakePacket.newBuilder() - .setConnectionId("conn-id") - .addMessage(HandshakeMessage.newBuilder() - .setAnswer(Answer.newBuilder() - .setContent(offer) - .build()) - .build()) - .build(); + .setConnectionId("conn-id") + .addMessage(HandshakeMessage.newBuilder() + .setAnswer(Answer.newBuilder() + .setContent(offer) + .build()) + .build()) + .build(); requestObserverContainer.getRequestObserver().onNext(answerPacket); } void sendIceCandidate() { HandshakePacket iceCandidate = HandshakePacket.newBuilder() - .setConnectionId("conn-id") - .addMessage(HandshakeMessage.newBuilder() - .setIceCandidate(IceCandidate.newBuilder() - .setContent("ICE CANDIDATE") - .build()) - .build()) - .build(); + .setConnectionId("conn-id") + .addMessage(HandshakeMessage.newBuilder() + .setIceCandidate(IceCandidate.newBuilder() + .setContent("ICE CANDIDATE") + .build()) + .build()) + .build(); requestObserverContainer.getRequestObserver().onNext(iceCandidate); } @@ -1082,7 +1076,6 @@ public class NccsClient { }); requestObserverContainer.setRequestObserver(requestObserver); }); - return completable; } static class SingleValueContainer { @@ -1093,14 +1086,10 @@ public class NccsClient { this.t = null; } - ; - public SingleValueContainer(T t) { this.t = t; } - ; - public T get() { return t; } @@ -1148,7 +1137,7 @@ public class NccsClient { this.memeberId = memeberId; } - public String getParticipantId() { + String getParticipantId() { return participantId; } @@ -1213,7 +1202,7 @@ public class NccsClient { // private String[] accountIds = {"a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a0"}; private String[] accountIds = {"a1"}; private String[] accountIdsToBeAddedByNonOwner = {"b1"}; - final CountDownLatch rxLatch = new CountDownLatch(1); + private final CountDownLatch rxLatch = new CountDownLatch(1); private void goStopScreenSharing(String ownerId, String conferenceId, String participantId) throws InterruptedException { @@ -1229,7 +1218,7 @@ public class NccsClient { rxLatch.await(60, TimeUnit.SECONDS); } - void goConference(String linkId) throws InterruptedException { + private void goConference(String linkId) throws InterruptedException { if (linkId != null) { info("Getting conference id ...{0}", getConferenceId(linkId).blockingGet()); return; @@ -1359,7 +1348,7 @@ public class NccsClient { .setType(Type.ACCOUNT) .setValue("a5")) .build(); - callFactory.createCall(request, new StreamObserver() { + callFactory.createCall(request, new StreamObserver<>() { @Override public void onNext(CreateCallResponse value) { String callId = value.getCallId(); @@ -1367,11 +1356,11 @@ public class NccsClient { callMetadata.put(FocusMetadataKey.PARTICIPANT_ID, UuidGenerator.generate()); callInvitationMetadata.put(FocusMetadataKey.INSTANCE_ID, callId); - callInvitation.confirm(Void.getDefaultInstance(), new StreamObserver() { + callInvitation.confirm(Void.getDefaultInstance(), new StreamObserver<>() { @Override public void onNext(Void value) { callMetadata.put(CommonMetadataKey.ACCOUNT_ID, accountId); - call.openMediaControl(new StreamObserver() { + call.openMediaControl(new StreamObserver<>() { @Override public void onNext(HandshakePacket value) { diff --git a/sandbox/grpc_vertx/src/main/java/com/nynjacoin/nccs/sandbox/grpc_vertx/CallClient.java b/sandbox/grpc_vertx/src/main/java/com/nynjacoin/nccs/sandbox/grpc_vertx/CallClient.java index 1a8da3d5..d7a9f98c 100644 --- a/sandbox/grpc_vertx/src/main/java/com/nynjacoin/nccs/sandbox/grpc_vertx/CallClient.java +++ b/sandbox/grpc_vertx/src/main/java/com/nynjacoin/nccs/sandbox/grpc_vertx/CallClient.java @@ -49,17 +49,16 @@ public class CallClient { private final ManagedChannel channel; private final CallStub asyncStub; - private Random random = new Random(); private TestHelper testHelper; /** Construct client for accessing RouteGuide server at {@code host:port}. */ - public CallClient(String host, int port) { + private CallClient(String host, int port) { this(ManagedChannelBuilder.forAddress(host, port).usePlaintext()); } /** Construct client for accessing RouteGuide server using the existing channel. */ - public CallClient(ManagedChannelBuilder channelBuilder) { + private CallClient(ManagedChannelBuilder channelBuilder) { channel = channelBuilder.build(); Metadata metadata = new Metadata(); @@ -69,18 +68,18 @@ public class CallClient { asyncStub = MetadataUtils.attachHeaders(CallGrpc.newStub(channel), metadata); } - public void shutdown() throws InterruptedException { + private void shutdown() throws InterruptedException { channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); } public static class RequestObserverContainer { private StreamObserver requestObserver; - public StreamObserver getRequestObserver() { + StreamObserver getRequestObserver() { return requestObserver; } - public void setRequestObserver( + void setRequestObserver( StreamObserver requestObserver) { this.requestObserver = requestObserver; } @@ -92,13 +91,13 @@ public class CallClient { * Bi-directional example, which can only be asynchronous. Send some chat messages, and print any * chat messages that are sent from the server. */ - public CountDownLatch handshake() { + private CountDownLatch handshake() { info("*** Handshake"); final CountDownLatch finishLatch = new CountDownLatch(1); StreamObserver requestObserver = - asyncStub.openMediaControl(new StreamObserver() { + asyncStub.openMediaControl(new StreamObserver<>() { @Override public void onNext(HandshakePacket packet) { info("Got message:{0}", packet); @@ -113,7 +112,7 @@ public class CallClient { // } } - void sendAnswer(String offer) { + private void sendAnswer(String offer) { try { SessionDescription sdp = SessionDescription.Parse(offer); @@ -137,7 +136,7 @@ public class CallClient { requestObserverContainer.getRequestObserver().onNext(answerPacket); } - void sendIceCandidate() { + private void sendIceCandidate() { HandshakePacket iceCandidate = HandshakePacket.newBuilder() .setConnectionId("conn-id") .addMessage(HandshakeMessage.newBuilder() @@ -195,7 +194,7 @@ public class CallClient { return finishLatch; } - void onCompleted() { + private void onCompleted() { // Mark the end of requests requestObserverContainer.getRequestObserver().onCompleted(); } @@ -241,7 +240,6 @@ public class CallClient { */ @VisibleForTesting void setRandom(Random random) { - this.random = random; } /** @@ -265,28 +263,28 @@ public class CallClient { this.testHelper = testHelper; } - public CountDownLatch hangup() { + private CountDownLatch hangup() { final CountDownLatch hangupLatch = new CountDownLatch(1); - asyncStub.hangup(Void.getDefaultInstance(), + asyncStub.hangup(HangupRequest.getDefaultInstance(), - new StreamObserver() { + new StreamObserver<>() { - @Override - public void onNext(Void value) { - hangupLatch.countDown(); - } + @Override + public void onNext(Void value) { + hangupLatch.countDown(); + } - @Override - public void onError(Throwable t) { + @Override + public void onError(Throwable t) { - } + } - @Override - public void onCompleted() { - info("Finished hangup"); - hangupLatch.countDown(); - } - }); + @Override + public void onCompleted() { + info("Finished hangup"); + hangupLatch.countDown(); + } + }); return hangupLatch; } -- GitLab From d32a45a625065b03e7fa829fc6b746ab1dd09c7e Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Thu, 28 May 2020 22:38:59 +0300 Subject: [PATCH 08/10] Build fix. --- .../java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java b/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java index 52ffb555..c5146708 100644 --- a/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java +++ b/sandbox/grpc/src/main/java/com/nynjacoin/nccs/sandbox/grpc/NccsClient.java @@ -945,7 +945,7 @@ public class NccsClient { // } } - void sendAnswer(String offer) { + private void sendAnswer(String offer) { try { SessionDescription sdp = SessionDescription.Parse(offer); @@ -969,7 +969,7 @@ public class NccsClient { requestObserverContainer.getRequestObserver().onNext(answerPacket); } - void sendIceCandidate() { + private void sendIceCandidate() { HandshakePacket iceCandidate = HandshakePacket.newBuilder() .setConnectionId("conn-id") .addMessage(HandshakeMessage.newBuilder() @@ -1026,7 +1026,7 @@ public class NccsClient { // } } - void sendAnswer(String offer) { + private void sendAnswer(String offer) { try { SessionDescription sdp = SessionDescription.Parse(offer); @@ -1050,7 +1050,7 @@ public class NccsClient { requestObserverContainer.getRequestObserver().onNext(answerPacket); } - void sendIceCandidate() { + private void sendIceCandidate() { HandshakePacket iceCandidate = HandshakePacket.newBuilder() .setConnectionId("conn-id") .addMessage(HandshakeMessage.newBuilder() -- GitLab From 9ae43d0b9e9804eb4c0eb5e8a66a365b470e360d Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Mon, 1 Jun 2020 15:49:10 +0300 Subject: [PATCH 09/10] NY-10542 Improve video quality - enable RTCP-FB --- .../nccs/focus/config/FocusConfigKey.java | 1 + .../nccs/mediacontroller/JvbMediaBridge.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/focus/src/main/java/com/nynjacoin/nccs/focus/config/FocusConfigKey.java b/focus/src/main/java/com/nynjacoin/nccs/focus/config/FocusConfigKey.java index fb86f7a0..40d732ff 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/focus/config/FocusConfigKey.java +++ b/focus/src/main/java/com/nynjacoin/nccs/focus/config/FocusConfigKey.java @@ -16,6 +16,7 @@ public enum FocusConfigKey { CONFERENCE_MEMBERS_COUNT_LIMIT("conference_members_count_limit"), CONFERENCE_DESTROY_EMPTY_DELAY_MINUTES("conference_destroy_empty_delay_minutes"), CONFERENCE_MEMBER_DIAL_OUT_TIMEOUT_SECONDS("conference_member_dial_out_timeout_seconds"), + CONFERENCE_MEDIA_ENABLE_RTCP_FB("conference_media_enable_rtcp_fb"), PARTICIPANT_REMOVE_NOT_RESPONDING_DELAY_SECONDS("participant_remove_not_responding_delay_seconds"), PARTICIPANT_ANSWER_TIMEOUT_SECONDS("participant_answer_timeout_seconds"), diff --git a/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaBridge.java b/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaBridge.java index dfc864b2..9021dcb4 100644 --- a/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaBridge.java +++ b/focus/src/main/java/com/nynjacoin/nccs/mediacontroller/JvbMediaBridge.java @@ -38,6 +38,7 @@ public class JvbMediaBridge implements MediaBridge { private final Conference conference; private final InstanceLogger logger; private final long destroyConfDelay; + private final boolean enableRtcpFeedback; private final Map participants; private final Timer idleTimer; private final Timer keepAliveTimer; @@ -57,6 +58,8 @@ public class JvbMediaBridge implements MediaBridge { this.destroyConfDelay = TimeUnit.MINUTES.toMillis( mediaController.getConfig() .getInteger(FocusConfigKey.CONFERENCE_DESTROY_EMPTY_DELAY_MINUTES.key())); + this.enableRtcpFeedback = mediaController.getConfig() + .getBoolean(FocusConfigKey.CONFERENCE_MEDIA_ENABLE_RTCP_FB.key(), true); this.participants = new LinkedHashMap<>(); this.idleTimer = new OneShotTimer( mediaController.getVertx(), @@ -123,6 +126,22 @@ public class JvbMediaBridge implements MediaBridge { md.addRTPMapAttribute(100, "VP8", 90000); md.addFormatAttribute(100, "x-google-start-bitrate=800"); + + /* + * rtcp-fb - rtcp feedback handshake + * a=rtcp-fb:100 ccm fir - codec control message: full intra-frame request + * a=rtcp-fb:100 nack - general nack (indicate lost packets) + * a=rtcp-fb:100 nack pli - nack: picture loss indication + * a=rtcp-fb:100 transport-cc - transport congestion control + * */ + + if (enableRtcpFeedback) { + md.addAttribute("rtcp-fb", "100 ccm fir"); + md.addAttribute("rtcp-fb", "100 nack"); + md.addAttribute("rtcp-fb", "100 nack pli"); + md.addAttribute("rtcp-fb", "100 transport-cc"); + } + return md; } -- GitLab From 907a096536c32d6fa708916adc1dfcee33d837e9 Mon Sep 17 00:00:00 2001 From: Ilia Krustev Date: Tue, 2 Jun 2020 14:17:43 +0300 Subject: [PATCH 10/10] Switch to nccs-libs 0.22.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 885eb81a..b688aad2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ rxjava2Version = 2.1.13 prometheusVersion = 0.5.0 cassandraDriverVersion = 3.6.0 junitVersion = 4.12 -nccsLibsVersion = 0.22.0-SNAPSHOT +nccsLibsVersion = 0.22.0 -- GitLab