Skip to content

Commit 4ce9a23

Browse files
committed
Send signal API method using OpenVidu API + Subscription to signal:lowerYourHand in frontend
1 parent 630101e commit 4ce9a23

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

backend/src/main/java/urjc/ovteaching/OpenViduComponent.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,52 @@
11
package urjc.ovteaching;
22

3+
import java.io.IOException;
4+
import java.io.UnsupportedEncodingException;
5+
import java.security.KeyManagementException;
6+
import java.security.KeyStoreException;
7+
import java.security.NoSuchAlgorithmException;
8+
import java.security.cert.CertificateException;
9+
import java.security.cert.X509Certificate;
310
import java.util.Collection;
411
import java.util.HashMap;
512
import java.util.HashSet;
613
import java.util.Map;
714
import java.util.Optional;
815
import java.util.Set;
916
import java.util.concurrent.ConcurrentHashMap;
17+
import java.util.concurrent.TimeUnit;
1018

19+
import javax.net.ssl.SSLContext;
20+
21+
import org.apache.http.HttpHeaders;
22+
import org.apache.http.HttpResponse;
23+
import org.apache.http.auth.AuthScope;
24+
import org.apache.http.auth.UsernamePasswordCredentials;
25+
import org.apache.http.client.CredentialsProvider;
26+
import org.apache.http.client.HttpClient;
27+
import org.apache.http.client.config.RequestConfig;
28+
import org.apache.http.client.methods.HttpPost;
29+
import org.apache.http.conn.ssl.NoopHostnameVerifier;
30+
import org.apache.http.entity.StringEntity;
31+
import org.apache.http.impl.client.BasicCredentialsProvider;
32+
import org.apache.http.impl.client.HttpClientBuilder;
33+
import org.apache.http.ssl.SSLContextBuilder;
34+
import org.apache.http.ssl.TrustStrategy;
35+
import org.apache.http.util.EntityUtils;
1136
import org.springframework.beans.factory.annotation.Autowired;
1237
import org.springframework.beans.factory.annotation.Value;
1338
import org.springframework.stereotype.Component;
1439

40+
import com.google.gson.Gson;
41+
import com.google.gson.JsonObject;
42+
1543
import io.openvidu.java.client.OpenVidu;
1644
import io.openvidu.java.client.OpenViduHttpException;
1745
import io.openvidu.java.client.OpenViduJavaClientException;
1846
import io.openvidu.java.client.OpenViduRole;
1947
import io.openvidu.java.client.Recording;
48+
import io.openvidu.java.client.RecordingLayout;
49+
import io.openvidu.java.client.RecordingProperties;
2050
import io.openvidu.java.client.Session;
2151
import io.openvidu.java.client.SessionProperties;
2252
import io.openvidu.java.client.TokenOptions;
@@ -37,6 +67,8 @@ public class OpenViduComponent {
3767
private OpenVidu openVidu;
3868
private String OPENVIDU_URL;
3969
private String SECRET;
70+
71+
private HttpClient httpClient;
4072

4173
private Map<Long, Session> roomIdSession;
4274
private Map<String, Map<Long, String[]>> sessionIdUserIdToken;
@@ -47,6 +79,28 @@ public OpenViduComponent(@Value("${openvidu.secret}") String secret, @Value("${o
4779
this.openVidu = new OpenVidu(OPENVIDU_URL, SECRET);
4880
this.roomIdSession = new ConcurrentHashMap<>();
4981
this.sessionIdUserIdToken = new ConcurrentHashMap<>();
82+
83+
TrustStrategy trustStrategy = new TrustStrategy() {
84+
@Override
85+
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
86+
return true;
87+
}
88+
};
89+
CredentialsProvider provider = new BasicCredentialsProvider();
90+
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("OPENVIDUAPP", this.SECRET);
91+
provider.setCredentials(AuthScope.ANY, credentials);
92+
SSLContext sslContext;
93+
try {
94+
sslContext = new SSLContextBuilder().loadTrustMaterial(null, trustStrategy).build();
95+
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
96+
throw new RuntimeException(e);
97+
}
98+
RequestConfig.Builder requestBuilder = RequestConfig.custom();
99+
requestBuilder = requestBuilder.setConnectTimeout(30000);
100+
requestBuilder = requestBuilder.setConnectionRequestTimeout(30000);
101+
this.httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestBuilder.build())
102+
.setConnectionTimeToLive(30, TimeUnit.SECONDS).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
103+
.setSSLContext(sslContext).setDefaultCredentialsProvider(provider).build();
50104
}
51105

52106
public boolean isSessionCreated(Room room) {
@@ -160,4 +214,31 @@ public String stopRecording(Room room) {
160214
}
161215
return null;
162216
}
217+
218+
public void sendSignalToEveryone(Room room, String type, String data) throws UnsupportedEncodingException, IOException {
219+
Session session = this.roomIdSession.get(room.getId());
220+
221+
HttpPost request = new HttpPost(this.OPENVIDU_URL + "/api/signal");
222+
223+
JsonObject json = new JsonObject();
224+
json.addProperty("session", session.getSessionId());
225+
json.addProperty("type", "signal:" + type);
226+
json.addProperty("data", data);
227+
228+
StringEntity params = new StringEntity(json.toString());
229+
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
230+
request.setEntity(params);
231+
232+
HttpResponse response = this.httpClient.execute(request);
233+
try {
234+
int statusCode = response.getStatusLine().getStatusCode();
235+
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
236+
return;
237+
} else {
238+
throw new IOException("Openvidu error: " + statusCode);
239+
}
240+
} finally {
241+
EntityUtils.consumeQuietly(response.getEntity());
242+
}
243+
}
163244
}

backend/src/main/java/urjc/ovteaching/rooms/controllers/OpenViduController.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package urjc.ovteaching.rooms.controllers;
22

3+
import java.io.IOException;
4+
35
import javax.servlet.http.HttpServletRequest;
46

57
import org.json.simple.JSONObject;
@@ -11,6 +13,7 @@
1113
import org.springframework.web.bind.annotation.GetMapping;
1214
import org.springframework.web.bind.annotation.PathVariable;
1315
import org.springframework.web.bind.annotation.PostMapping;
16+
import org.springframework.web.bind.annotation.RequestBody;
1417
import org.springframework.web.bind.annotation.RequestMapping;
1518
import org.springframework.web.bind.annotation.RestController;
1619

@@ -227,4 +230,38 @@ public ResponseEntity<String> stopRecording(@PathVariable String roomName, HttpS
227230
}
228231
return new ResponseEntity<>(recordingId, HttpStatus.OK);
229232
}
233+
234+
/**
235+
* Sends a signal with the type and data associated
236+
*
237+
* @return HttpStatus of the operation
238+
*/
239+
@PostMapping("/room/{roomName}/signal/{type}")
240+
public ResponseEntity<?> sendSignal(@PathVariable String roomName, @PathVariable String type, @RequestBody JSONObject data, HttpServletRequest request) {
241+
if (!request.isUserInRole("USER")) { // User not logged
242+
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
243+
}
244+
Room room = roomServ.findByName(roomName);
245+
User user = userServ.findByName(request.getUserPrincipal().getName());
246+
// User currentUser = this.userComponent.getLoggedUser();
247+
248+
if (room == null) { // No room with that name
249+
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
250+
}
251+
if (!room.isModerator(user)) { // User not in that room
252+
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
253+
}
254+
if (!this.openViduComponent.isSessionCreated(room) || this.openViduComponent.isSessionEmpty(room)) {
255+
// No session created for that room or it is empty
256+
return new ResponseEntity<>(HttpStatus.CONFLICT);
257+
}
258+
259+
try {
260+
this.openViduComponent.sendSignalToEveryone(room, type, data.toString());
261+
} catch (IOException e) {
262+
System.err.println(e.toString());
263+
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
264+
}
265+
return new ResponseEntity<>(HttpStatus.OK);
266+
}
230267
}

frontend/src/app/video-room/video-room.component.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
281281
if(this.userService.isModOfRoom(this.roomName)) {
282282
this.subscribedToChat('chatMod', this.messageListMod, this.modChatComponent);
283283
}
284+
this.subscribedToLowerHand();
284285
this.connectToSession();
285286
}
286287

@@ -772,6 +773,15 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
772773
});
773774
}
774775

776+
private subscribedToLowerHand() {
777+
this.session.on('signal:lowerYourHand', (event:any) => {
778+
if(event.from===undefined) {
779+
//Only do something if "from" is undefined, which means the signal was called by the backend
780+
this.raiseHand();
781+
}
782+
});
783+
}
784+
775785
private sendSignalUserChanged(user: UserModel, isFirstTime?: boolean): void {
776786
const session = user.isLocal() ? this.session : this.sessionScreen;
777787
const data = {

0 commit comments

Comments
 (0)