Skip to content

Commit 7a756de

Browse files
author
rsatrio
committed
Initial commit
0 parents  commit 7a756de

File tree

10 files changed

+326
-0
lines changed

10 files changed

+326
-0
lines changed

.gitignore

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
HELP.md
2+
.settings
3+
target/
4+
!.mvn/wrapper/maven-wrapper.jar
5+
!**/src/main/**/target/
6+
!**/src/test/**/target/
7+
8+
### STS ###
9+
.apt_generated
10+
.classpath
11+
.factorypath
12+
.project
13+
.settings
14+
.springBeans
15+
.sts4-cache
16+
mvnw
17+
mvnw.cmd
18+
.mvn
19+
### IntelliJ IDEA ###
20+
.idea
21+
*.iws
22+
*.iml
23+
*.ipr
24+
25+
### NetBeans ###
26+
/nbproject/private/
27+
/nbbuild/
28+
/dist/
29+
/nbdist/
30+
/.nb-gradle/
31+
build/
32+
!**/src/main/**/build/
33+
!**/src/test/**/build/
34+
35+
### VS Code ###
36+
.vscode/

README.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Custom Signaling Server for WebRTC Chat App
2+
3+
A simple example Signaling Server for WebRTC using WebSocket Protocol. This application is developed using Spring Boot
4+
5+
6+
## Features
7+
- Custom Signaling Server for WebRTC Chat Application
8+
- Using WebSocket Protocol
9+
10+
11+
## Build
12+
13+
- Use mvn clean package to build the module into jar file
14+
15+
> mvn clean package
16+
17+
## Running the application
18+
19+
- Run the resulting build jar using this command:
20+
> java -jar target\SignallingServer-1.0.jar
21+

pom.xml

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starter-parent</artifactId>
8+
<version>2.6.6</version>
9+
<relativePath/> <!-- lookup parent from repository -->
10+
</parent>
11+
<groupId>com.rizky</groupId>
12+
<artifactId>SignallingServer</artifactId>
13+
<version>1.0</version>
14+
<name>SignallingServer</name>
15+
<properties>
16+
<java.version>1.8</java.version>
17+
</properties>
18+
<dependencies>
19+
<dependency>
20+
<groupId>org.springframework.boot</groupId>
21+
<artifactId>spring-boot-starter-websocket</artifactId>
22+
</dependency>
23+
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-test</artifactId>
27+
<scope>test</scope>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.springframework.boot</groupId>
31+
<artifactId>spring-boot-devtools</artifactId>
32+
</dependency>
33+
</dependencies>
34+
35+
<build>
36+
<plugins>
37+
<plugin>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-maven-plugin</artifactId>
40+
</plugin>
41+
</plugins>
42+
</build>
43+
44+
<description>Signaling Server for WebRTC Data Channel Chat</description>
45+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.rizky.signaling.model;
2+
3+
public class SignalData {
4+
5+
private String userId,type,data,toUid;
6+
7+
8+
public String getToUid() {
9+
return toUid;
10+
}
11+
12+
public void setToUid(String toUid) {
13+
this.toUid = toUid;
14+
}
15+
16+
public String getUserId() {
17+
return userId;
18+
}
19+
20+
public void setUserId(String userId) {
21+
this.userId = userId;
22+
}
23+
24+
public String getType() {
25+
return type;
26+
}
27+
28+
public void setType(String type) {
29+
this.type = type;
30+
}
31+
32+
public String getData() {
33+
return data;
34+
}
35+
36+
public void setData(String data) {
37+
this.data = data;
38+
}
39+
40+
41+
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.rizky.signaling.model;
2+
3+
public enum SignalType {
4+
5+
Login,
6+
UserId,
7+
Offer,
8+
Answer,
9+
Ice,
10+
Logout,
11+
NewMember,
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.rizky.signalling;
2+
3+
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.web.socket.config.annotation.EnableWebSocket;
6+
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
7+
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
8+
9+
@Configuration
10+
@EnableWebSocket
11+
public class SignalingConfiguration implements WebSocketConfigurer{
12+
13+
@Value( "${allowed.origin:*}" )
14+
private String allowedOrigin;
15+
16+
@Override
17+
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
18+
19+
registry.addHandler(new SignalingHandler(), "/socket1").setAllowedOrigins(allowedOrigin);
20+
}
21+
22+
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package com.rizky.signalling;
2+
3+
import java.util.HashMap;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
import java.util.UUID;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
import org.springframework.web.socket.CloseStatus;
12+
import org.springframework.web.socket.TextMessage;
13+
import org.springframework.web.socket.WebSocketSession;
14+
import org.springframework.web.socket.handler.TextWebSocketHandler;
15+
16+
import com.fasterxml.jackson.databind.ObjectMapper;
17+
import com.rizky.signaling.model.SignalData;
18+
import com.rizky.signaling.model.SignalType;
19+
20+
21+
22+
public class SignalingHandler extends TextWebSocketHandler{
23+
24+
25+
List<WebSocketSession>sessions = new LinkedList<WebSocketSession>();
26+
ConcurrentHashMap<String,WebSocketSession>sessionMap = new ConcurrentHashMap<String,WebSocketSession>();
27+
final ObjectMapper map1=new ObjectMapper();
28+
Logger log1=LoggerFactory.getLogger(SignalingHandler.class);
29+
30+
@Override
31+
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
32+
33+
final String msg1=message.getPayload();
34+
SignalData sigData=map1.readValue(msg1, SignalData.class);
35+
log1.debug("Receive message from client:",msg1);
36+
37+
SignalData sigResp=new SignalData();
38+
39+
if(sigData.getType().equalsIgnoreCase(SignalType.Login.toString())) {
40+
SignalData sigResp2=new SignalData();
41+
String userId=UUID.randomUUID().toString();
42+
sigResp2.setUserId("signaling");
43+
sigResp2.setType(SignalType.UserId.toString());
44+
sigResp2.setData(userId);
45+
sessionMap.put(userId, session);
46+
session.sendMessage(new TextMessage(map1.writeValueAsString(sigResp2)));
47+
48+
return ;
49+
}
50+
else if(sigData.getType().equalsIgnoreCase(SignalType.NewMember.toString())) {
51+
52+
sessionMap.values().forEach(a->{
53+
54+
SignalData sigResp2=new SignalData();
55+
sigResp2.setUserId(sigData.getUserId());
56+
sigResp2.setType(SignalType.NewMember.toString());
57+
try {
58+
//Check if websocket is open
59+
if(a.isOpen()) {
60+
log1.debug("Sending New Member from",sigData.getUserId());
61+
a.sendMessage(new TextMessage(map1.writeValueAsString(sigResp2)));
62+
}
63+
}
64+
catch(Exception e) {
65+
log1.error("Error Sending message:",e);
66+
}
67+
});
68+
69+
70+
return ;
71+
}
72+
else if(sigData.getType().equalsIgnoreCase(SignalType.Offer.toString())) {
73+
sigResp=new SignalData();
74+
sigResp.setUserId(sigData.getUserId());
75+
sigResp.setType(SignalType.Offer.toString());
76+
sigResp.setData(sigData.getData());
77+
sigResp.setToUid(sigData.getToUid());
78+
sessionMap.get(sigData.getToUid()).sendMessage(new TextMessage(map1.writeValueAsString(sigResp)));
79+
80+
81+
}
82+
else if(sigData.getType().equalsIgnoreCase(SignalType.Answer.toString())) {
83+
sigResp=new SignalData();
84+
sigResp.setUserId(sigData.getUserId());
85+
sigResp.setType(SignalType.Answer.toString());
86+
sigResp.setData(sigData.getData());
87+
sigResp.setToUid(sigData.getToUid());
88+
sessionMap.get(sigData.getToUid()).sendMessage(new TextMessage(map1.writeValueAsString(sigResp)));
89+
90+
91+
}
92+
else if(sigData.getType().equalsIgnoreCase(SignalType.Ice.toString())) {
93+
sigResp=new SignalData();
94+
sigResp.setUserId(sigData.getUserId());
95+
sigResp.setType(SignalType.Ice.toString());
96+
sigResp.setData(sigData.getData());
97+
sigResp.setToUid(sigData.getToUid());
98+
sessionMap.get(sigData.getToUid()).sendMessage(new TextMessage(map1.writeValueAsString(sigResp)));
99+
100+
101+
}
102+
103+
104+
}
105+
106+
@Override
107+
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
108+
109+
sessions.add(session);
110+
super.afterConnectionEstablished(session);
111+
}
112+
113+
@Override
114+
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
115+
116+
sessions.remove(session);
117+
super.afterConnectionClosed(session, status);
118+
}
119+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.rizky.signalling;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class SignallingServerApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(SignallingServerApplication.class, args);
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
server.port=${PORT:3030}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.rizky.signalling;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.springframework.boot.test.context.SpringBootTest;
5+
6+
@SpringBootTest
7+
class SignallingServerApplicationTests {
8+
9+
@Test
10+
void contextLoads() {
11+
}
12+
13+
}

0 commit comments

Comments
 (0)