Compare commits

..
10 Commits
19 changed files with 116 additions and 31 deletions
+5
View File
@@ -264,6 +264,11 @@ push.ios.server.address http://localhost:8085/ios/push
##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空 ##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空
#message.forward.types 1,2,3 #message.forward.types 1,2,3
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。此转发不受${message.forward.types}限制。
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#message.mentionmsg.forward.url http://localhost:8888/im_event/message
##设备信息转发地址 ##设备信息转发地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!! ##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#things_message.forward.url http://localhost:8888/im_event/things/message #things_message.forward.url http://localhost:8888/im_event/things/message
+1 -1
View File
@@ -5,7 +5,7 @@
<relativePath>../</relativePath> <relativePath>../</relativePath>
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.71</version> <version>0.73</version>
</parent> </parent>
<artifactId>moquette-broker</artifactId> <artifactId>moquette-broker</artifactId>
@@ -18,6 +18,8 @@ import cn.wildfirechat.pojos.OutputGetIMTokenData;
import com.xiaoleilu.loServer.handler.Response; import com.xiaoleilu.loServer.handler.Response;
import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest;
import cn.wildfirechat.common.ErrorCode; import cn.wildfirechat.common.ErrorCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import win.liyufan.im.IMTopic; import win.liyufan.im.IMTopic;
import java.util.Base64; import java.util.Base64;
@@ -25,7 +27,7 @@ import java.util.Base64;
@Route(APIPath.User_Get_Token) @Route(APIPath.User_Get_Token)
@HttpMethod("POST") @HttpMethod("POST")
public class GetIMTokenAction extends AdminAction { public class GetIMTokenAction extends AdminAction {
private static final Logger LOG = LoggerFactory.getLogger(GetIMTokenAction.class);
@Override @Override
public boolean isTransactionAction() { public boolean isTransactionAction() {
return false; return false;
@@ -49,6 +51,8 @@ public class GetIMTokenAction extends AdminAction {
} }
String token = Base64.getEncoder().encodeToString(data); String token = Base64.getEncoder().encodeToString(data);
LOG.info("get im token success {},{},{}", userId, input.getClientId(), token.substring(0, Math.min(10, token.length())));
return new Result(errorCode1, new OutputGetIMTokenData(userId, token)); return new Result(errorCode1, new OutputGetIMTokenData(userId, token));
} else { } else {
return new Result(errorCode1); return new Result(errorCode1);
@@ -128,6 +128,8 @@ public final class BrokerConstants {
public static final String MESSAGE_Forward_Url = "message.forward.url"; public static final String MESSAGE_Forward_Url = "message.forward.url";
public static final String MESSAGE_Forward_Types = "message.forward.types"; public static final String MESSAGE_Forward_Types = "message.forward.types";
public static final String MESSAGE_MentionMsg_Forward_Url = "message.mentionmsg.forward.url";
public static final String SERVER_MULTI_ENDPOINT = "server.multi_endpoint"; public static final String SERVER_MULTI_ENDPOINT = "server.multi_endpoint";
public static final String SERVER_MULTI_PLATFROM_NOTIFICATION = "server.multi_platform_notification"; public static final String SERVER_MULTI_PLATFROM_NOTIFICATION = "server.multi_platform_notification";
@@ -0,0 +1,33 @@
/*
* This file is part of the Wildfire Chat package.
* (c) Heavyrain2012 <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
package io.moquette.imhandler;
import cn.wildfirechat.common.ErrorCode;
import cn.wildfirechat.proto.WFCMessage;
import com.hazelcast.util.StringUtil;
import com.xiaoleilu.loServer.model.FriendData;
import io.moquette.spi.impl.Qos1PublishHandler;
import io.netty.buffer.ByteBuf;
import win.liyufan.im.IMTopic;
import java.util.List;
@Handler(value = IMTopic.ClearSessionTopic)
public class DisconnectHandler extends IMHandler<Byte> {
@Override
public ErrorCode action(ByteBuf ackPayload, String clientID, String fromUser, boolean isAdmin, Byte request, Qos1PublishHandler.IMCallback callback) {
if (request == 8) {
m_sessionsStore.cleanSession(fromUser, clientID);
} else if(request == 1) {
m_sessionsStore.disableSession(fromUser, clientID);
}
return ErrorCode.ERROR_CODE_SUCCESS;
}
}
@@ -19,6 +19,7 @@ import win.liyufan.im.I18n;
import win.liyufan.im.IMTopic; import win.liyufan.im.IMTopic;
import win.liyufan.im.MessageShardingUtil; import win.liyufan.im.MessageShardingUtil;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_ALREADY_FRIENDS;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS; import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
@Handler(IMTopic.HandleFriendRequestTopic) @Handler(IMTopic.HandleFriendRequestTopic)
@@ -86,6 +87,10 @@ public class HandleFriendRequestHandler extends IMHandler<WFCMessage.HandleFrien
publisher.publishNotification(IMTopic.NotifyFriendTopic, fromUser, heads[1]); publisher.publishNotification(IMTopic.NotifyFriendTopic, fromUser, heads[1]);
} }
} }
if(errorCode == ERROR_CODE_ALREADY_FRIENDS) {
errorCode = ERROR_CODE_SUCCESS;
}
return errorCode; return errorCode;
} }
} }
@@ -33,6 +33,7 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
private int mSensitiveType = 0; //命中敏感词时,0 失败,1 吞掉, 2 敏感词替换成*。 private int mSensitiveType = 0; //命中敏感词时,0 失败,1 吞掉, 2 敏感词替换成*。
private String mForwardUrl = null; private String mForwardUrl = null;
private Set<Integer> mForwardMessageTypes = new HashSet<>(); private Set<Integer> mForwardMessageTypes = new HashSet<>();
private String mMentionForwardUrl = null;
private int mBlacklistStrategy = 0; //黑名单中时,0失败,1吞掉。 private int mBlacklistStrategy = 0; //黑名单中时,0失败,1吞掉。
private boolean mNoForwardAdminMessage = false; private boolean mNoForwardAdminMessage = false;
@@ -43,10 +44,8 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
public SendMessageHandler() { public SendMessageHandler() {
super(); super();
String forwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Forward_Url); mForwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Forward_Url);
if (!StringUtil.isNullOrEmpty(forwardUrl)) { if (!StringUtil.isNullOrEmpty(mForwardUrl)) {
mForwardUrl = forwardUrl;
String forwardTypes = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Forward_Types); String forwardTypes = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_Forward_Types);
if (!StringUtil.isNullOrEmpty(forwardTypes)) { if (!StringUtil.isNullOrEmpty(forwardTypes)) {
String[] tss = forwardTypes.split(","); String[] tss = forwardTypes.split(",");
@@ -56,6 +55,8 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
} }
} }
mMentionForwardUrl = mServer.getConfig().getProperty(BrokerConstants.MESSAGE_MentionMsg_Forward_Url);
try { try {
mSensitiveType = Integer.parseInt(mServer.getConfig().getProperty(BrokerConstants.SENSITIVE_Filter_Type)); mSensitiveType = Integer.parseInt(mServer.getConfig().getProperty(BrokerConstants.SENSITIVE_Filter_Type));
} catch (Exception e) { } catch (Exception e) {
@@ -169,10 +170,14 @@ public class SendMessageHandler extends IMHandler<WFCMessage.Message> {
} }
message = message.toBuilder().setFromUser(fromUser).setMessageId(messageId).setServerTimestamp(timestamp).build(); message = message.toBuilder().setFromUser(fromUser).setMessageId(messageId).setServerTimestamp(timestamp).build();
if (mForwardUrl != null && (mForwardMessageTypes.isEmpty() || mForwardMessageTypes.contains(message.getContent().getType())) && !(isAdmin && mNoForwardAdminMessage)) { if (!StringUtil.isNullOrEmpty(mForwardUrl) && (mForwardMessageTypes.isEmpty() || mForwardMessageTypes.contains(message.getContent().getType())) && !(isAdmin && mNoForwardAdminMessage)) {
publisher.forwardMessage(message, mForwardUrl); publisher.forwardMessage(message, mForwardUrl);
} }
if(!StringUtil.isNullOrEmpty(mMentionForwardUrl) && message.hasContent() && message.getContent().getMentionedType() != 0 && !(isAdmin && mNoForwardAdminMessage)) {
publisher.forwardMessage(message, mMentionForwardUrl);
}
if (!isAdmin) { if (!isAdmin) {
if(StringUtil.isNullOrEmpty(mRemoteSensitiveServerUrl)) { if(StringUtil.isNullOrEmpty(mRemoteSensitiveServerUrl)) {
Set<String> matched = m_messagesStore.handleSensitiveWord(message.getContent().getSearchableContent()); Set<String> matched = m_messagesStore.handleSensitiveWord(message.getContent().getSearchableContent());
@@ -640,6 +640,17 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
} }
if(fromMessageId == 1) { //lite mode
if(maps == null || maps.isEmpty()) {
head = 0;
} else {
head = maps.lastKey();
}
builder.setCurrent(head);
builder.setHead(head);
return builder.build();
}
mReadLock.lock(); mReadLock.lock();
int size = 0; int size = 0;
try { try {
@@ -2845,7 +2856,7 @@ public class MemoryMessagesStore implements IMessagesStore {
public ErrorCode handleFriendRequest(String userId, WFCMessage.HandleFriendRequest request, WFCMessage.Message.Builder msgBuilder, long[] heads, boolean isAdmin) { public ErrorCode handleFriendRequest(String userId, WFCMessage.HandleFriendRequest request, WFCMessage.Message.Builder msgBuilder, long[] heads, boolean isAdmin) {
HazelcastInstance hzInstance = m_Server.getHazelcastInstance(); HazelcastInstance hzInstance = m_Server.getHazelcastInstance();
boolean alreadyFriend = false;
if(!isAdmin && request.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Accepted) { if(!isAdmin && request.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Accepted) {
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS); MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
@@ -2857,10 +2868,9 @@ public class MemoryMessagesStore implements IMessagesStore {
for (FriendData fd : friends) { for (FriendData fd : friends) {
if (fd.getFriendUid().equals(request.getTargetUid())) { if (fd.getFriendUid().equals(request.getTargetUid())) {
if (fd.getState() == 0) { if (fd.getState() == 0) {
return ErrorCode.ERROR_CODE_ALREADY_FRIENDS; alreadyFriend = true;
} else {
break;
} }
break;
} }
} }
} }
@@ -2939,7 +2949,7 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
if (existRequest != null) { if (existRequest != null) {
if (mFriendRequestExpiration > 0 && System.currentTimeMillis() - existRequest.getUpdateDt() > mFriendRequestExpiration) { if (!alreadyFriend && mFriendRequestExpiration > 0 && System.currentTimeMillis() - existRequest.getUpdateDt() > mFriendRequestExpiration) {
return ErrorCode.ERROR_CODE_FRIEND_REQUEST_EXPIRED; return ErrorCode.ERROR_CODE_FRIEND_REQUEST_EXPIRED;
} else { } else {
existRequest = existRequest.toBuilder().setStatus(request.getStatus()).setUpdateDt(System.currentTimeMillis()).build(); existRequest = existRequest.toBuilder().setStatus(request.getStatus()).setUpdateDt(System.currentTimeMillis()).build();
@@ -2965,7 +2975,7 @@ public class MemoryMessagesStore implements IMessagesStore {
} }
} }
if(request.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Accepted){ if(!alreadyFriend && request.getStatus() == ProtoConstants.FriendRequestStatus.RequestStatus_Accepted){
MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS); MultiMap<String, FriendData> friendsMap = hzInstance.getMultiMap(USER_FRIENDS);
FriendData friendData1 = new FriendData(userId, request.getTargetUid(), "", request.getExtra(), 0, 0, System.currentTimeMillis()); FriendData friendData1 = new FriendData(userId, request.getTargetUid(), "", request.getExtra(), 0, 0, System.currentTimeMillis());
databaseStore.persistOrUpdateFriendData(friendData1); databaseStore.persistOrUpdateFriendData(friendData1);
@@ -2986,6 +2996,9 @@ public class MemoryMessagesStore implements IMessagesStore {
callbackRelationEvent(userId, request.getTargetUid(), 0, "1"); callbackRelationEvent(userId, request.getTargetUid(), 0, "1");
} }
if(alreadyFriend) {
return ErrorCode.ERROR_CODE_ALREADY_FRIENDS;
}
return ErrorCode.ERROR_CODE_SUCCESS; return ErrorCode.ERROR_CODE_SUCCESS;
} }
} else { } else {
@@ -531,7 +531,7 @@ public class MemorySessionStore implements ISessionsStore {
if (session.getUsername().equals(username)) { if (session.getUsername().equals(username)) {
return session; return session;
} else { } else {
cleanSession(clientID); cleanSession(null, clientID);
} }
} }
return null; return null;
@@ -739,9 +739,9 @@ public class MemorySessionStore implements ISessionsStore {
@Override @Override
public void disableSession(String clientId) { public void disableSession(String userId, String clientId) {
Session session = sessions.get(clientId); Session session = sessions.get(clientId);
if (session != null && session.getDeleted() == 0) { if (session != null && session.getDeleted() == 0 && (userId == null || session.getUsername().equals(userId))) {
databaseStore.updateSessionDeleted(session.getUsername(), clientId, 1); databaseStore.updateSessionDeleted(session.getUsername(), clientId, 1);
ConcurrentSkipListSet<String> sessionSet = getUserSessionSet(session.username); ConcurrentSkipListSet<String> sessionSet = getUserSessionSet(session.username);
sessionSet.remove(clientId); sessionSet.remove(clientId);
@@ -750,7 +750,7 @@ public class MemorySessionStore implements ISessionsStore {
} }
@Override @Override
public void cleanSession(String clientID) { public void cleanSession(String userId, String clientID) {
LOG.info("Fooooooooo <{}>", clientID); LOG.info("Fooooooooo <{}>", clientID);
Session session = sessions.get(clientID); Session session = sessions.get(clientID);
@@ -758,6 +758,11 @@ public class MemorySessionStore implements ISessionsStore {
LOG.error("Can't find the session for client <{}>", clientID); LOG.error("Can't find the session for client <{}>", clientID);
return; return;
} }
if(userId != null && !session.getUsername().equals(userId)) {
return;
}
ConcurrentSkipListSet<String> sessionSet = getUserSessionSet(session.username); ConcurrentSkipListSet<String> sessionSet = getUserSessionSet(session.username);
sessionSet.remove(clientID); sessionSet.remove(clientID);
@@ -109,19 +109,19 @@ public class ClientSession {
} }
public void disconnect(boolean cleanSession, boolean disableSession) { public void disconnect(String userId, boolean cleanSession, boolean disableSession) {
if (cleanSession) { if (cleanSession) {
LOG.info("Client disconnected. Removing its subscriptions. ClientId={}", clientID); LOG.info("Client disconnected. Removing its subscriptions. ClientId={}", clientID);
// cleanup topic subscriptions // cleanup topic subscriptions
cleanSession(); cleanSession(userId);
} else if(disableSession) { } else if(disableSession) {
LOG.info("Client disconnected. disable session. ClientId={}", clientID); LOG.info("Client disconnected. disable session. ClientId={}", clientID);
m_sessionsStore.disableSession(this.clientID); m_sessionsStore.disableSession(userId, this.clientID);
} }
} }
public void cleanSession() { public void cleanSession(String userId) {
m_sessionsStore.cleanSession(this.clientID); m_sessionsStore.cleanSession(userId, this.clientID);
} }
@@ -150,8 +150,8 @@ public interface ISessionsStore {
*/ */
int getSecondPhaseAckPendingMessages(String clientID); int getSecondPhaseAckPendingMessages(String clientID);
void disableSession(String clientId); void disableSession(String userId, String clientId);
void cleanSession(String clientID); void cleanSession(String userId, String clientID);
boolean isMultiEndpointSupported(); boolean isMultiEndpointSupported();
@@ -44,12 +44,14 @@ import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import win.liyufan.im.HttpUtils; import win.liyufan.im.HttpUtils;
import win.liyufan.im.IMTopic;
import win.liyufan.im.Utility; import win.liyufan.im.Utility;
import java.util.*; import java.util.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import static cn.wildfirechat.common.ErrorCode.ERROR_CODE_SUCCESS;
import static io.moquette.spi.impl.InternalRepublisher.createPublishForQos; import static io.moquette.spi.impl.InternalRepublisher.createPublishForQos;
import static cn.wildfirechat.common.IMExceptionEvent.EventType.EVENT_CALLBACK_Exception; import static cn.wildfirechat.common.IMExceptionEvent.EventType.EVENT_CALLBACK_Exception;
import static io.moquette.spi.impl.Utils.readBytesAndRewind; import static io.moquette.spi.impl.Utils.readBytesAndRewind;
@@ -582,7 +584,7 @@ public class ProtocolProcessor {
//disconnect the session //disconnect the session
m_sessionsStore.sessionForClient(clientID).disconnect(isDup, isRetain); m_sessionsStore.sessionForClient(clientID).disconnect(session.getUsername(), isDup, isRetain);
} }
@@ -107,8 +107,12 @@ public class DBUtil {
} }
Flyway flyway = Flyway.configure().dataSource(comboPooledDataSource).locations(migrateLocation).baselineOnMigrate(true).load(); Flyway flyway = Flyway.configure().dataSource(comboPooledDataSource).locations(migrateLocation).baselineOnMigrate(true).load();
if(!IsEmbedDB && (flyway.info().current() == null || flyway.info().current().getVersion().getMajor().intValue() < 43)) { if(!IsEmbedDB) {
System.out.println("数据库执行初始化或升级需要较长时间,可能长达数分钟或更长,请耐心等待,不要中断。。。"); if(flyway.info().current() == null) {
System.out.println("数据库执行初始化需要较长时间,可能长达数分钟或更长,请耐心等待,不要中断。。。");
} else if(flyway.info().current().getVersion().getMajor().intValue() < 43) {
System.out.println("数据库执行升级需要较长时间,可能长达数分钟或更长,请耐心等待,不要中断。。。");
}
} }
flyway.migrate(); flyway.migrate();
@@ -80,4 +80,6 @@ public interface IMTopic {
String LoadRemoteMessagesTopic = "LRM"; String LoadRemoteMessagesTopic = "LRM";
String KickoffPCClientTopic = "KPCC"; String KickoffPCClientTopic = "KPCC";
String ClearSessionTopic = "CST";
} }
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.71</version> <version>0.73</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -6,7 +6,7 @@
<!--<relativePath>../pom.xml</relativePath>--> <!--<relativePath>../pom.xml</relativePath>-->
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.71</version> <version>0.73</version>
</parent> </parent>
<artifactId>distribution</artifactId> <artifactId>distribution</artifactId>
@@ -262,6 +262,11 @@ push.ios.server.address http://localhost:8085/ios/push
##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空 ##需要转发的消息类型,当有多个时以英文逗号分割。如果转发所有消息,请注释掉配置或者设置为空
#message.forward.types 1,2,3 #message.forward.types 1,2,3
##提醒消息转发地址,@全体用户和@某个用户消息会回调此地址。此转发不受${message.forward.types}限制。
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#message.mentionmsg.forward.url http://localhost:8888/im_event/message
##设备信息转发地址 ##设备信息转发地址
##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!! ##注意回调是单线程回调,接收服务必须在同一内网,且异步处理快速返回,否则会有延迟问题!!
#things_message.forward.url http://localhost:8087/im_event/things/message #things_message.forward.url http://localhost:8087/im_event/things/message
+1 -1
View File
@@ -12,7 +12,7 @@
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>0.71</version> <version>0.73</version>
<name>Wildfire Chat</name> <name>Wildfire Chat</name>
<description>Wildfire Chat Server</description> <description>Wildfire Chat Server</description>
<inceptionYear>2019</inceptionYear> <inceptionYear>2019</inceptionYear>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>wildfirechat-parent</artifactId> <artifactId>wildfirechat-parent</artifactId>
<groupId>cn.wildfirechat</groupId> <groupId>cn.wildfirechat</groupId>
<version>0.71</version> <version>0.73</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>