Skip to content

Commit

Permalink
Fix #1 and Basic Message Framework (#5)
Browse files Browse the repository at this point in the history
* Development update
-Upgrade to a safer POST method
-Added a framework for message receiving and sending
  • Loading branch information
Oct-autumn authored Nov 15, 2021
1 parent f4f17ff commit 96390e7
Show file tree
Hide file tree
Showing 12 changed files with 602 additions and 1 deletion.
86 changes: 86 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>cn.csuosa</groupId>
<artifactId>ChattingRoom-server</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>
</properties>

<dependencies>
<!-- Spring Boot 相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.6</version>
</dependency>

<!-- JLine 相关依赖 -->
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>3.20.0</version>
</dependency>
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-terminal-jansi</artifactId>
<version>3.20.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.5</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>14</source>
<target>14</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
</build>

</project>
123 changes: 123 additions & 0 deletions src/main/java/cn/CSUOSA/ChattingRoomServer/Channel/ChannelActions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package cn.CSUOSA.ChattingRoomServer.Channel;

import cn.CSUOSA.ChattingRoomServer.Main;
import cn.CSUOSA.ChattingRoomServer.OverWriteMethod.Out;
import cn.CSUOSA.ChattingRoomServer.ReturnParams.BoolMsgWithObj;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import static cn.CSUOSA.ChattingRoomServer.User.UserActions.verifyUser;

@RestController
@RequestMapping("/channel")
public class ChannelActions
{
public static boolean verifyChannel(String name, String ticket)
{
if (ticket == null)
ticket = "";
if (name.length() > 64 || (!ticket.isEmpty() && ticket.length() != 6))
return false;
else
{
//查找是否含有非法字符
for (char ch : name.toCharArray())
{
if (((ch < 48) || (ch > 57)) && ((ch < 65) || (ch > 90)) && ((ch < 97) || (ch > 122)))
{
return false;
}
}
for (char ch : ticket.toCharArray())
{
if (((ch < 48) || (ch > 57)) && ((ch < 65) || (ch > 90)) && ((ch < 97) || (ch > 122)))
{
return false;
}
}
return Main.ChannelList.containsKey(name) && Main.ChannelList.get(name).getTicket().equals(ticket);
}
}

//用户登录相关
@PostMapping("/reg")
public BoolMsgWithObj channelRegistry(@RequestParam(value = "usrNick") String usrNick, @RequestParam(value = "name") String name, String usrTicket, @Nullable String ticket)
{
if (!verifyUser(usrNick, usrTicket))
return new BoolMsgWithObj(false, "Authentication failed.");

if (name.length() > 64 || (ticket != null && ticket.length() != 6))
return new BoolMsgWithObj(false, "Name or Ticket too long.");
else
{
//查找是否含有非法字符
for (char ch : name.toCharArray())
{
if (((ch < 48) || (ch > 57)) && ((ch < 65) || (ch > 90)) && ((ch < 97) || (ch > 122)))
{
return new BoolMsgWithObj(false, "Invalid name.");
}
}
if (ticket != null)
for (char ch : ticket.toCharArray())
{
if (((ch < 48) || (ch > 57)) && ((ch < 65) || (ch > 90)) && ((ch < 97) || (ch > 122)))
{
return new BoolMsgWithObj(false, "Invalid ticket.");
}
}
if (Main.ChannelList.containsKey(name))
return new BoolMsgWithObj(false, "Channel already opened.");

Out.Info("Channel [" + name + "] Opened");
Main.ChannelList.put(name, new ChannelInfo(name, (ticket == null) ? "" : ticket));
Out.Info("User [" + usrNick + "] joined channel [" + name + "]");
Main.ChannelList.get(name).addMember(Main.UserList.get(usrNick));
return new BoolMsgWithObj(true, "");
}
}

@PostMapping("/join")
public BoolMsgWithObj channelJoin(@RequestParam(value = "usrNick") String usrNick, @RequestParam(value = "name") String name, String usrTicket, @Nullable String ticket)
{
if (!verifyUser(usrNick, usrTicket))
return new BoolMsgWithObj(false, "Authentication failed.");

if (name.length() > 64 || (ticket != null && ticket.length() != 6))
return new BoolMsgWithObj(false, "Nick or Ticket too long.");
else
{
//查找是否含有非法字符
for (char ch : name.toCharArray())
{
if (((ch < 48) || (ch > 57)) && ((ch < 65) || (ch > 90)) && ((ch < 97) || (ch > 122)))
{
return new BoolMsgWithObj(false, "Invalid name.");
}
}
if (ticket != null)
for (char ch : ticket.toCharArray())
{
if (((ch < 48) || (ch > 57)) && ((ch < 65) || (ch > 90)) && ((ch < 97) || (ch > 122)))
{
return new BoolMsgWithObj(false, "Invalid ticket.");
}
}
if (!Main.ChannelList.containsKey(name))
return new BoolMsgWithObj(false, "Channel does not exist.");
if (!Main.ChannelList.get(name).getTicket().isEmpty() && ticket == null)
return new BoolMsgWithObj(false, "This channel needs a ticket.");
if (!Main.ChannelList.get(name).getTicket().isEmpty() && ticket != null && !Main.ChannelList.get(name).getTicket().equals(ticket))
return new BoolMsgWithObj(false, "Wrong ticket.");
if (Main.ChannelList.get(name).getMembers().contains(Main.UserList.get(usrNick)))
return new BoolMsgWithObj(false, "You have already in this channel.");

Out.Info("User [" + usrNick + "] joined channel [" + name + "]");
Main.ChannelList.get(name).addMember(Main.UserList.get(usrNick));
return new BoolMsgWithObj(true, "");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cn.CSUOSA.ChattingRoomServer.Channel;

import cn.CSUOSA.ChattingRoomServer.Main;
import cn.CSUOSA.ChattingRoomServer.OverWriteMethod.Out;
import cn.CSUOSA.ChattingRoomServer.User.UserInfo;

public class ChannelChecker implements Runnable
{
@Override
public void run()
{
if (!Main.ChannelList.isEmpty())
{
ChannelInfo channelInfo;
for (String nowKey : Main.ChannelList.keySet())
{
channelInfo = Main.ChannelList.get(nowKey);
for (UserInfo nowMember : channelInfo.getMembers())
if (nowMember != null && !Main.UserList.containsKey(nowMember.getNick()))
{
Out.Info("User [" + nowMember.getNick() + "] left channel [" + nowKey + "]");
channelInfo.removeMember(nowMember);
if (channelInfo.getMembers().isEmpty())
break;
}
if (channelInfo.getMembers().isEmpty())
{
Main.ChannelList.remove(nowKey);
Out.Info("Channel [" + nowKey + "] Closed");
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package cn.CSUOSA.ChattingRoomServer.Channel;

import cn.CSUOSA.ChattingRoomServer.Message.MessageInfo;
import cn.CSUOSA.ChattingRoomServer.User.UserInfo;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class ChannelInfo
{
private final List<UserInfo> members;
private final ConcurrentHashMap<Integer, MessageInfo> messageList;
private final String name;
private final String ticket;

Expand All @@ -16,6 +19,7 @@ public ChannelInfo(String name, String ticket)
this.name = name;
this.ticket = ticket;
members = new ArrayList<>();
messageList = new ConcurrentHashMap<>();
}

public boolean addMember(UserInfo member)
Expand All @@ -37,7 +41,7 @@ public boolean removeMember(UserInfo member)
}
return false;
}

public String getName() {return name;}

public String getTicket() {return ticket;}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cn.CSUOSA.ChattingRoomServer.ConsoleController;

import cn.CSUOSA.ChattingRoomServer.Main;
import cn.CSUOSA.ChattingRoomServer.OverWriteMethod.Out;
import org.jline.reader.LineReaderBuilder;
import org.jline.terminal.TerminalBuilder;

import java.io.IOException;

public class CmdProcessor implements Runnable
{
@Override
public void run()
{
try
{
Main.terminal = TerminalBuilder.builder()
.system(true)
.jansi(true)
.build();

Main.lineReader = LineReaderBuilder.builder()
.terminal(Main.terminal)
.build();

String prompt = "ChatServer> ";
while (true)
{
String line = Main.lineReader.readLine(prompt);
String[] args = line.split(" ");
CommandProcessor(args);
}
} catch (IOException e)
{
e.printStackTrace();
}
}

private void CommandProcessor(String[] args)
{
switch (args[0])
{
case "exit", "Exit", "EXIT" -> {
Out.Warn("Server Exit.");
System.exit(0);
}
case "list", "List", "LIST" -> Processors.listObject(args);
}
}
}
40 changes: 40 additions & 0 deletions src/main/java/cn/CSUOSA/ChattingRoomServer/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cn.CSUOSA.ChattingRoomServer;

import cn.CSUOSA.ChattingRoomServer.Channel.ChannelInfo;
import cn.CSUOSA.ChattingRoomServer.ConsoleController.CmdProcessor;
import cn.CSUOSA.ChattingRoomServer.User.UserInfo;
import cn.CSUOSA.ChattingRoomServer.User.UserMapTimer;
import org.jline.reader.LineReader;
import org.jline.terminal.Terminal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

@SpringBootApplication
public class Main
{
public static ConcurrentHashMap<String, UserInfo> UserList;
public static HashMap<String, ChannelInfo> ChannelList;
public static UserMapTimer userMapTimer = new UserMapTimer();
public static Terminal terminal;
public static LineReader lineReader;
private static ConfigurableApplicationContext CAC;
@Autowired
Environment environment;

public static void main(String[] args)
{
UserList = new ConcurrentHashMap<>();
ChannelList = new HashMap<>();

CAC = SpringApplication.run(Main.class, args);
new Thread(userMapTimer).start();

new Thread(new CmdProcessor()).start();
}
}
Loading

0 comments on commit 96390e7

Please sign in to comment.