com.litongjava.tio.core.Tio Maven / Gradle / Ivy
package com.litongjava.tio.core;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.litongjava.tio.client.ClientChannelContext;
import com.litongjava.tio.client.ClientTioConfig;
import com.litongjava.tio.client.ReconnConf;
import com.litongjava.tio.core.ChannelContext.CloseCode;
import com.litongjava.tio.core.intf.Packet;
import com.litongjava.tio.core.intf.Packet.Meta;
import com.litongjava.tio.core.maintain.GlobalIpBlacklist;
import com.litongjava.tio.server.ServerTioConfig;
import com.litongjava.tio.utils.convert.Converter;
import com.litongjava.tio.utils.lock.ReadLockHandler;
import com.litongjava.tio.utils.lock.SetWithLock;
import com.litongjava.tio.utils.page.Page;
import com.litongjava.tio.utils.page.PageUtils;
/**
* The Class Tio. t-io用户关心的API几乎全在这
*
* @author tanyaowu
*/
public class Tio {
public static class IpBlacklist {
/**
* 把ip添加到黑名单,此黑名单只针对tioConfig有效,其它tioConfig不会把这个ip视为黑名单
* @param tioConfig
* @param ip
* @author tanyaowu
*/
public static boolean add(TioConfig tioConfig, String ip) {
return tioConfig.ipBlacklist.add(ip);
}
/**
* 添加全局ip黑名单
* @param ip
* @return
* @author tanyaowu
*/
public static boolean add(String ip) {
return GlobalIpBlacklist.INSTANCE.global.add(ip);
}
/**
* 清空黑名单,只针对tioConfig有效
* @param tioConfig
* @author tanyaowu
*/
public static void clear(TioConfig tioConfig) {
tioConfig.ipBlacklist.clear();
}
/**
* 清空全局黑名单
* @author tanyaowu
*/
public static void clear() {
GlobalIpBlacklist.INSTANCE.global.clear();
}
/**
* 获取ip黑名单列表
* @param tioConfig
* @return
* @author tanyaowu
*/
public static Collection getAll(TioConfig tioConfig) {
return tioConfig.ipBlacklist.getAll();
}
/**
* 获取全局黑名单
* @return
* @author tanyaowu
*/
public static Collection getAll() {
return GlobalIpBlacklist.INSTANCE.global.getAll();
}
/**
* 是否在黑名单中
* @param tioConfig
* @param ip
* @return
* @author tanyaowu
*/
public static boolean isInBlacklist(TioConfig tioConfig, String ip) {
if (tioConfig.ipBlacklist != null) {
return tioConfig.ipBlacklist.isInBlacklist(ip) || GlobalIpBlacklist.INSTANCE.global.isInBlacklist(ip);
} else {
return GlobalIpBlacklist.INSTANCE.global.isInBlacklist(ip);
}
}
/**
* 把ip从黑名单中删除
* @param tioConfig
* @param ip
* @author tanyaowu
*/
public static void remove(TioConfig tioConfig, String ip) {
tioConfig.ipBlacklist.remove(ip);
}
/**
* 删除全局黑名单
* @param ip
* @author tanyaowu
*/
public static void remove(String ip) {
GlobalIpBlacklist.INSTANCE.global.remove(ip);
}
}
/** The log. */
private static Logger log = LoggerFactory.getLogger(Tio.class);
/**
* 绑定业务id
* @param channelContext
* @param bsId
* @author tanyaowu
*/
public static void bindBsId(ChannelContext channelContext, String bsId) {
channelContext.tioConfig.bsIds.bind(channelContext, bsId);
}
/**
* 绑定群组
* @param channelContext
* @param group
* @author tanyaowu
*/
public static void bindGroup(ChannelContext channelContext, String group) {
channelContext.tioConfig.groups.bind(group, channelContext);
}
/**
* 将用户绑定到群组
* @param tioConfig
* @param userid
* @param group
*/
public static void bindGroup(TioConfig tioConfig, String userid, String group) {
SetWithLock setWithLock = Tio.getByUserid(tioConfig, userid);
if (setWithLock != null) {
setWithLock.handle(new ReadLockHandler>() {
@Override
public void handler(Set set) {
for (ChannelContext channelContext : set) {
Tio.bindGroup(channelContext, group);
}
}
});
}
}
/**
* 绑定token
* @param channelContext
* @param token
* @author tanyaowu
*/
public static void bindToken(ChannelContext channelContext, String token) {
channelContext.tioConfig.tokens.bind(token, channelContext);
}
/**
* 绑定用户
* @param channelContext
* @param userid
* @author tanyaowu
*/
public static void bindUser(ChannelContext channelContext, String userid) {
channelContext.tioConfig.users.bind(userid, channelContext);
}
/**
* 阻塞发送消息到指定ChannelContext
* @param channelContext
* @param packet
* @return
* @author tanyaowu
*/
public static Boolean bSend(ChannelContext channelContext, Packet packet) {
if (channelContext == null) {
return false;
}
CountDownLatch countDownLatch = new CountDownLatch(1);
return send(channelContext, packet, countDownLatch, PacketSendMode.SINGLE_BLOCK);
}
/**
* 发送到指定的ip和port
* @param tioConfig
* @param ip
* @param port
* @param packet
* @author tanyaowu
*/
public static Boolean bSend(TioConfig tioConfig, String ip, int port, Packet packet) {
return send(tioConfig, ip, port, packet, true);
}
/**
* 发消息到所有连接
* @param tioConfig
* @param packet
* @param channelContextFilter
* @author tanyaowu
*/
public static Boolean bSendToAll(TioConfig tioConfig, Packet packet, ChannelContextFilter channelContextFilter) {
return sendToAll(tioConfig, packet, channelContextFilter, true);
}
/**
* 阻塞发消息给指定业务ID
* @param tioConfig
* @param bsId
* @param packet
* @author tanyaowu
*/
public static Boolean bSendToBsId(TioConfig tioConfig, String bsId, Packet packet) {
return sendToBsId(tioConfig, bsId, packet, true);
}
/**
* 发消息到组
* @param tioConfig
* @param group
* @param packet
* @author tanyaowu
*/
public static Boolean bSendToGroup(TioConfig tioConfig, String group, Packet packet) {
return bSendToGroup(tioConfig, group, packet, null);
}
/**
* 发消息到组
* @param tioConfig
* @param group
* @param packet
* @param channelContextFilter
* @author tanyaowu
*/
public static Boolean bSendToGroup(TioConfig tioConfig, String group, Packet packet,
ChannelContextFilter channelContextFilter) {
return sendToGroup(tioConfig, group, packet, channelContextFilter, true);
}
/**
* 发消息给指定ChannelContext id
* @param channelContextId
* @param packet
* @author tanyaowu
*/
public static Boolean bSendToId(TioConfig tioConfig, String channelContextId, Packet packet) {
return sendToId(tioConfig, channelContextId, packet, true);
}
/**
* 阻塞发送到指定ip对应的集合
* @param tioConfig
* @param ip
* @param packet
* @author: tanyaowu
*/
public static Boolean bSendToIp(TioConfig tioConfig, String ip, Packet packet) {
return bSendToIp(tioConfig, ip, packet, null);
}
/**
* 阻塞发送到指定ip对应的集合
* @param tioConfig
* @param ip
* @param packet
* @param channelContextFilter
* @return
* @author: tanyaowu
*/
public static Boolean bSendToIp(TioConfig tioConfig, String ip, Packet packet,
ChannelContextFilter channelContextFilter) {
return sendToIp(tioConfig, ip, packet, channelContextFilter, true);
}
/**
* 发消息到指定集合
* @param tioConfig
* @param setWithLock
* @param packet
* @param channelContextFilter
* @author tanyaowu
*/
public static Boolean bSendToSet(TioConfig tioConfig, SetWithLock setWithLock, Packet packet,
ChannelContextFilter channelContextFilter) {
return sendToSet(tioConfig, setWithLock, packet, channelContextFilter, true);
}
/**
* 阻塞发消息到指定token
* @param tioConfig
* @param token
* @param packet
* @return
* @author tanyaowu
*/
public static Boolean bSendToToken(TioConfig tioConfig, String token, Packet packet) {
return sendToToken(tioConfig, token, packet, true);
}
/**
* 阻塞发消息给指定用户
* @param tioConfig
* @param userid
* @param packet
* @return
* @author tanyaowu
*/
public static Boolean bSendToUser(TioConfig tioConfig, String userid, Packet packet) {
return sendToUser(tioConfig, userid, packet, true);
}
/**
* 关闭连接
* @param channelContext
* @param remark
* @author tanyaowu
*/
public static void close(ChannelContext channelContext, String remark) {
close(channelContext, null, remark);
}
/**
*
* @param channelContext
* @param remark
* @param closeCode
*/
public static void close(ChannelContext channelContext, String remark, CloseCode closeCode) {
close(channelContext, null, remark, closeCode);
}
/**
* 关闭连接
* @param channelContext
* @param throwable
* @param remark
* @author tanyaowu
*/
public static void close(ChannelContext channelContext, Throwable throwable, String remark) {
close(channelContext, throwable, remark, false);
}
public static void close(ChannelContext channelContext, Throwable throwable, String remark, CloseCode closeCode) {
close(channelContext, throwable, remark, false, closeCode);
}
public static void close(ChannelContext channelContext, Throwable throwable, String remark, boolean isNeedRemove) {
close(channelContext, throwable, remark, isNeedRemove, true);
}
public static void close(ChannelContext channelContext, Throwable throwable, String remark, boolean isNeedRemove,
CloseCode closeCode) {
close(channelContext, throwable, remark, isNeedRemove, true, closeCode);
}
public static void close(ChannelContext channelContext, Throwable throwable, String remark, boolean isNeedRemove,
boolean needCloseLock) {
close(channelContext, throwable, remark, isNeedRemove, needCloseLock, null);
}
/**
*
* @param channelContext
* @param throwable
* @param remark
* @param isNeedRemove
* @param needCloseLock
*/
public static void close(ChannelContext channelContext, Throwable throwable, String remark, boolean isNeedRemove,
boolean needCloseLock, CloseCode closeCode) {
if (channelContext == null) {
return;
}
if (channelContext.isWaitingClose) {
log.debug("{} Waiting to be closed", channelContext);
return;
}
// 先立即取消各项任务,这样可防止有新的任务被提交进来
channelContext.decodeRunnable.setCanceled(true);
channelContext.handlerRunnable.setCanceled(true);
channelContext.sendRunnable.setCanceled(true);
WriteLock writeLock = null;
if (needCloseLock) {
writeLock = channelContext.closeLock.writeLock();
boolean tryLock = writeLock.tryLock();
if (!tryLock) {
return;
}
channelContext.isWaitingClose = true;
writeLock.unlock();
} else {
channelContext.isWaitingClose = true;
}
if (closeCode == null) {
if (channelContext.getCloseCode() == CloseCode.INIT_STATUS) {
channelContext.setCloseCode(CloseCode.NO_CODE);
}
} else {
channelContext.setCloseCode(closeCode);
}
if (channelContext.asynchronousSocketChannel != null) {
try {
channelContext.asynchronousSocketChannel.shutdownInput();
} catch (Throwable e) {
// log.error(e.toString(), e);
}
try {
channelContext.asynchronousSocketChannel.shutdownOutput();
} catch (Throwable e) {
// log.error(e.toString(), e);
}
try {
channelContext.asynchronousSocketChannel.close();
} catch (Throwable e) {
// log.error(e.toString(), e);
}
}
channelContext.closeMeta.setRemark(remark);
channelContext.closeMeta.setThrowable(throwable);
if (!isNeedRemove) {
if (channelContext.isServer()) {
isNeedRemove = true;
} else {
ClientChannelContext clientChannelContext = (ClientChannelContext) channelContext;
if (!ReconnConf.isNeedReconn(clientChannelContext, false)) { // 不需要重连
isNeedRemove = true;
}
}
}
channelContext.closeMeta.setNeedRemove(isNeedRemove);
channelContext.tioConfig.closeRunnable.addMsg(channelContext);
channelContext.tioConfig.closeRunnable.execute();
}
/**
* 关闭连接
* @param tioConfig
* @param clientIp
* @param clientPort
* @param throwable
* @param remark
* @author tanyaowu
*/
public static void close(TioConfig tioConfig, String clientIp, Integer clientPort, Throwable throwable,
String remark) {
ChannelContext channelContext = tioConfig.clientNodes.find(clientIp, clientPort);
close(channelContext, throwable, remark);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param ip
* @param remark
* @return
*/
public static void closeIp(TioConfig tioConfig, String ip, String remark) {
closeIp(tioConfig, ip, remark, null);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param ip
* @param remark
* @param closeCode
*/
public static void closeIp(TioConfig tioConfig, String ip, String remark, CloseCode closeCode) {
SetWithLock setWithLock = Tio.getByIp(tioConfig, ip);
closeSet(tioConfig, setWithLock, remark, closeCode);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param group
* @param remark
* @return
*/
public static void closeGroup(TioConfig tioConfig, String group, String remark) {
closeGroup(tioConfig, group, remark, null);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param group
* @param remark
* @param closeCode
*/
public static void closeGroup(TioConfig tioConfig, String group, String remark, CloseCode closeCode) {
SetWithLock setWithLock = Tio.getByGroup(tioConfig, group);
closeSet(tioConfig, setWithLock, remark, closeCode);
}
/**
* 关闭用户的所有连接
* @param tioConfig
* @param userid
* @param remark
* @return
*/
public static void closeUser(TioConfig tioConfig, String userid, String remark) {
closeUser(tioConfig, userid, remark, null);
}
/**
* 关闭某用户的所有连接
* @param tioConfig
* @param userid
* @param remark
* @param closeCode
*/
public static void closeUser(TioConfig tioConfig, String userid, String remark, CloseCode closeCode) {
SetWithLock setWithLock = Tio.getByUserid(tioConfig, userid);
closeSet(tioConfig, setWithLock, remark, closeCode);
}
/**
* 关闭token的所有连接
* @param tioConfig
* @param token
* @param remark
* @return
*/
public static void closeToken(TioConfig tioConfig, String token, String remark) {
closeToken(tioConfig, token, remark, null);
}
/**
* 关闭某token的所有连接
* @param tioConfig
* @param token
* @param remark
* @param closeCode
*/
public static void closeToken(TioConfig tioConfig, String token, String remark, CloseCode closeCode) {
SetWithLock setWithLock = Tio.getByToken(tioConfig, token);
closeSet(tioConfig, setWithLock, remark, closeCode);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param ip
* @param remark
* @return
*/
public static void removeIp(TioConfig tioConfig, String ip, String remark) {
removeIp(tioConfig, ip, remark, null);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param ip
* @param remark
* @param removeCode
*/
public static void removeIp(TioConfig tioConfig, String ip, String remark, CloseCode removeCode) {
SetWithLock setWithLock = Tio.getByIp(tioConfig, ip);
removeSet(tioConfig, setWithLock, remark, removeCode);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param group
* @param remark
* @return
*/
public static void removeGroup(TioConfig tioConfig, String group, String remark) {
removeGroup(tioConfig, group, remark, null);
}
/**
* 关闭某群所有连接
* @param tioConfig
* @param group
* @param remark
* @param removeCode
*/
public static void removeGroup(TioConfig tioConfig, String group, String remark, CloseCode removeCode) {
SetWithLock setWithLock = Tio.getByGroup(tioConfig, group);
removeSet(tioConfig, setWithLock, remark, removeCode);
}
/**
* 关闭用户的所有连接
* @param tioConfig
* @param userid
* @param remark
* @return
*/
public static void removeUser(TioConfig tioConfig, String userid, String remark) {
removeUser(tioConfig, userid, remark, null);
}
/**
* 关闭某用户的所有连接
* @param tioConfig
* @param userid
* @param remark
* @param removeCode
*/
public static void removeUser(TioConfig tioConfig, String userid, String remark, CloseCode removeCode) {
SetWithLock setWithLock = Tio.getByUserid(tioConfig, userid);
removeSet(tioConfig, setWithLock, remark, removeCode);
}
/**
* 关闭token的所有连接
* @param tioConfig
* @param token
* @param remark
* @return
*/
public static void removeToken(TioConfig tioConfig, String token, String remark) {
removeToken(tioConfig, token, remark, null);
}
/**
* 关闭某token的所有连接
* @param tioConfig
* @param token
* @param remark
* @param removeCode
*/
public static void removeToken(TioConfig tioConfig, String token, String remark, CloseCode removeCode) {
SetWithLock setWithLock = Tio.getByToken(tioConfig, token);
removeSet(tioConfig, setWithLock, remark, removeCode);
}
/**
* 关闭集合
* @param tioConfig
* @param setWithLock
* @param remark
* @param closeCode
* @author tanyaowu
*/
public static void closeSet(TioConfig tioConfig, SetWithLock setWithLock, String remark,
CloseCode closeCode) {
if (setWithLock != null) {
setWithLock.handle(new ReadLockHandler>() {
@Override
public void handler(Set set) {
for (ChannelContext channelContext : set) {
Tio.close(channelContext, remark, closeCode);
}
}
});
}
}
/**
* 移除集合
* @param tioConfig
* @param setWithLock
* @param remark
* @param closeCode
* @author tanyaowu
*/
public static void removeSet(TioConfig tioConfig, SetWithLock setWithLock, String remark,
CloseCode closeCode) {
if (setWithLock != null) {
setWithLock.handle(new ReadLockHandler>() {
@Override
public void handler(Set set) {
for (ChannelContext channelContext : set) {
Tio.remove(channelContext, remark, closeCode);
}
}
});
}
}
/**
* 获取所有连接,包括当前处于断开状态的
* @param tioConfig
* @return
* @author tanyaowu
*/
public static SetWithLock getAll(TioConfig tioConfig) {
return tioConfig.connections;
}
/**
* 获取所有连接,包括当前处于断开状态的
* @param tioConfig
* @return
* @author tanyaowu
* @deprecated 用getAll(TioConfig tioConfig)
*/
public static SetWithLock getAllChannelContexts(TioConfig tioConfig) {
return getAll(tioConfig);
}
/**
* 此API仅供 tio client使用
* 获取所有处于正常连接状态的连接
* @param clientTioConfig
* @return
* @author tanyaowu
*/
public static SetWithLock getConnecteds(ClientTioConfig clientTioConfig) {
return clientTioConfig.connecteds;
}
/**
* 此API仅供 tio client使用
* 获取所有处于正常连接状态的连接
* @param clientTioConfig
* @return
* @author tanyaowu
* @deprecated 用getAllConnecteds(ClientTioConfig clientTioConfig)
*/
public static SetWithLock getAllConnectedsChannelContexts(ClientTioConfig clientTioConfig) {
return getConnecteds(clientTioConfig);
}
/**
* 根据业务id找ChannelContext
* @param tioConfig
* @param bsId
* @return
* @author tanyaowu
*/
public static ChannelContext getByBsId(TioConfig tioConfig, String bsId) {
return tioConfig.bsIds.find(tioConfig, bsId);
}
/**
* 根据业务id找ChannelContext
* @param tioConfig
* @param bsId
* @return
* @author tanyaowu
* @deprecated 用getByBsId(TioConfig tioConfig, String bsId)
*/
public static ChannelContext getChannelContextByBsId(TioConfig tioConfig, String bsId) {
return getByBsId(tioConfig, bsId);
}
/**
* 根据clientip和clientport获取ChannelContext
* @param tioConfig
* @param clientIp
* @param clientPort
* @return
* @author tanyaowu
*/
public static ChannelContext getByClientNode(TioConfig tioConfig, String clientIp, Integer clientPort) {
return tioConfig.clientNodes.find(clientIp, clientPort);
}
/**
* 根据clientip和clientport获取ChannelContext
* @param tioConfig
* @param clientIp
* @param clientPort
* @return
* @author tanyaowu
* @deprecated getByClientNode(tioConfig, clientIp, clientPort)
*/
public static ChannelContext getChannelContextByClientNode(TioConfig tioConfig, String clientIp, Integer clientPort) {
return getByClientNode(tioConfig, clientIp, clientPort);
}
/**
* 根据ChannelContext.id获取ChannelContext
* @param channelContextId
* @return
* @author tanyaowu
*/
public static ChannelContext getByChannelContextId(TioConfig tioConfig, String channelContextId) {
return tioConfig.ids.find(tioConfig, channelContextId);
}
/**
* 根据ChannelContext.id获取ChannelContext
* @param channelContextId
* @return
* @author tanyaowu
* @deprecated 用getByChannelContextId(tioConfig, channelContextId)
*/
public static ChannelContext getChannelContextById(TioConfig tioConfig, String channelContextId) {
return getByChannelContextId(tioConfig, channelContextId);
}
/**
* 获取一个组的所有客户端
* @param tioConfig
* @param group
* @return
* @author tanyaowu
*/
public static SetWithLock getByGroup(TioConfig tioConfig, String group) {
return tioConfig.groups.clients(tioConfig, group);
}
/**
* 获取一个组的所有客户端
* @param tioConfig
* @param group
* @return
* @author tanyaowu
* @deprecated 用getByGroup(tioConfig, group)
*/
public static SetWithLock getChannelContextsByGroup(TioConfig tioConfig, String group) {
return getByGroup(tioConfig, group);
}
/**
* 根据token获取SetWithLock
* @param tioConfig
* @param token
* @return
* @author tanyaowu
*/
public static SetWithLock getByToken(TioConfig tioConfig, String token) {
return tioConfig.tokens.find(tioConfig, token);
}
/**
* 根据客户端ip获取SetWithLock
* @param tioConfig
* @param ip
* @return
* @author tanyaowu
*/
public static SetWithLock getByIp(TioConfig tioConfig, String ip) {
return tioConfig.ips.clients(tioConfig, ip);
}
/**
* 根据token获取SetWithLock
* @param tioConfig
* @param token
* @return
* @author tanyaowu
* @deprecated 用getByToken(tioConfig, token)
*/
public static SetWithLock getChannelContextsByToken(TioConfig tioConfig, String token) {
return getByToken(tioConfig, token);
}
/**
* 根据userid获取SetWithLock
* @param tioConfig
* @param userid
* @return
* @author tanyaowu
*/
public static SetWithLock getByUserid(TioConfig tioConfig, String userid) {
return tioConfig.users.find(tioConfig, userid);
}
/**
* 根据userid获取SetWithLock
* @param tioConfig
* @param userid
* @return
* @author tanyaowu
* @deprecated 用getByUserid(tioConfig, userid)
*/
public static SetWithLock getChannelContextsByUserid(TioConfig tioConfig, String userid) {
return getByUserid(tioConfig, userid);
}
/**
*
* @param tioConfig
* @param pageIndex
* @param pageSize
* @return
* @author tanyaowu
*/
public static Page getPageOfAll(TioConfig tioConfig, Integer pageIndex, Integer pageSize) {
return getPageOfAll(tioConfig, pageIndex, pageSize, null);
}
/**
*
* @param tioConfig
* @param pageIndex
* @param pageSize
* @param converter
* @return
*/
public static Page getPageOfAll(TioConfig tioConfig, Integer pageIndex, Integer pageSize,
Converter converter) {
SetWithLock setWithLock = Tio.getAllChannelContexts(tioConfig);
return PageUtils.fromSetWithLock(setWithLock, pageIndex, pageSize, converter);
}
/**
* 这个方法是给客户器端用的
* @param clientTioConfig
* @param pageIndex
* @param pageSize
* @return
* @author tanyaowu
*/
public static Page getPageOfConnecteds(ClientTioConfig clientTioConfig, Integer pageIndex,
Integer pageSize) {
return getPageOfConnecteds(clientTioConfig, pageIndex, pageSize, null);
}
/**
* 这个方法是给客户器端用的
* @param clientTioConfig
* @param pageIndex
* @param pageSize
* @param converter
* @return
* @author tanyaowu
*/
public static Page getPageOfConnecteds(ClientTioConfig clientTioConfig, Integer pageIndex, Integer pageSize,
Converter converter) {
SetWithLock setWithLock = Tio.getAllConnectedsChannelContexts(clientTioConfig);
return PageUtils.fromSetWithLock(setWithLock, pageIndex, pageSize, converter);
}
/**
*
* @param tioConfig
* @param group
* @param pageIndex
* @param pageSize
* @return
* @author tanyaowu
*/
public static Page getPageOfGroup(TioConfig tioConfig, String group, Integer pageIndex,
Integer pageSize) {
return getPageOfGroup(tioConfig, group, pageIndex, pageSize, null);
}
/**
*
* @param tioConfig
* @param group
* @param pageIndex
* @param pageSize
* @param converter
* @return
*/
public static Page getPageOfGroup(TioConfig tioConfig, String group, Integer pageIndex, Integer pageSize,
Converter converter) {
SetWithLock setWithLock = Tio.getChannelContextsByGroup(tioConfig, group);
return PageUtils.fromSetWithLock(setWithLock, pageIndex, pageSize, converter);
}
/**
* 群组有多少个连接
* @param tioConfig
* @param group
* @return
*/
public static int groupCount(TioConfig tioConfig, String group) {
SetWithLock setWithLock = tioConfig.groups.clients(tioConfig, group);
if (setWithLock == null) {
return 0;
}
Set set = setWithLock.getObj();
if (set == null) {
return 0;
}
return set.size();
}
/**
* 某通道是否在某群组中
* @param group
* @param channelContext
* @return true:在该群组
* @author: tanyaowu
*/
public static boolean isInGroup(String group, ChannelContext channelContext) {
SetWithLock setWithLock = channelContext.getGroups();
if (setWithLock == null) {
return false;
}
Set set = setWithLock.getObj();
if (set == null) {
return false;
}
return set.contains(group);
}
/**
*
* @param channelContext
* @param remark
*/
public static void remove(ChannelContext channelContext, String remark) {
remove(channelContext, remark, null);
}
/**
* 和close方法对应,只不过不再进行重连等维护性的操作
* @param channelContext
* @param remark
* @param closeCode
*/
public static void remove(ChannelContext channelContext, String remark, CloseCode closeCode) {
remove(channelContext, null, remark, closeCode);
}
/**
* 和close方法对应,只不过不再进行重连等维护性的操作
* @param channelContext
* @param throwable
* @param remark
*/
public static void remove(ChannelContext channelContext, Throwable throwable, String remark) {
remove(channelContext, throwable, remark, (CloseCode) null);
}
/**
* 和close方法对应,只不过不再进行重连等维护性的操作
* @param channelContext
* @param throwable
* @param remark
* @param closeCode
*/
public static void remove(ChannelContext channelContext, Throwable throwable, String remark, CloseCode closeCode) {
close(channelContext, throwable, remark, true, closeCode);
}
/**
* 和close方法对应,只不过不再进行重连等维护性的操作
* @param tioConfig
* @param clientIp
* @param clientPort
* @param throwable
* @param remark
*/
public static void remove(TioConfig tioConfig, String clientIp, Integer clientPort, Throwable throwable,
String remark) {
remove(tioConfig, clientIp, clientPort, throwable, remark, (CloseCode) null);
}
/**
* 删除clientip和clientPort为指定值的连接
* @param tioConfig
* @param clientIp
* @param clientPort
* @param throwable
* @param remark
* @param closeCode
*/
public static void remove(TioConfig tioConfig, String clientIp, Integer clientPort, Throwable throwable,
String remark, CloseCode closeCode) {
ChannelContext channelContext = tioConfig.clientNodes.find(clientIp, clientPort);
remove(channelContext, throwable, remark, closeCode);
}
/**
* 删除clientip为指定值的所有连接
* @param serverTioConfig
* @param ip
* @param remark
*/
public static void remove(ServerTioConfig serverTioConfig, String ip, String remark) {
remove(serverTioConfig, ip, remark, (CloseCode) null);
}
/**
* 删除clientip为指定值的所有连接
* @param serverTioConfig
* @param ip
* @param remark
* @param closeCode
*/
public static void remove(ServerTioConfig serverTioConfig, String ip, String remark, CloseCode closeCode) {
SetWithLock setWithLock = serverTioConfig.ips.clients(serverTioConfig, ip);
if (setWithLock == null) {
return;
}
setWithLock.handle(new ReadLockHandler>() {
@Override
public void handler(Set set) {
for (ChannelContext channelContext : set) {
Tio.remove(channelContext, remark, closeCode);
}
}
});
}
/**
* 发送消息到指定ChannelContext
* @param channelContext
* @param packet
* @author tanyaowu
*/
public static Boolean send(ChannelContext channelContext, Packet packet) {
return send(channelContext, packet, null, null);
}
/**
*
* @param channelContext
* @param packet
* @param countDownLatch
* @param packetSendMode
* @return
* @author tanyaowu
*/
private static Boolean send(final ChannelContext channelContext, Packet packet, CountDownLatch countDownLatch,
PacketSendMode packetSendMode) {
try {
if (packet == null || channelContext == null) {
if (countDownLatch != null) {
countDownLatch.countDown();
}
return false;
}
if (channelContext.isVirtual) {
if (countDownLatch != null) {
countDownLatch.countDown();
}
return true;
}
if (channelContext.isClosed || channelContext.isRemoved) {
if (countDownLatch != null) {
countDownLatch.countDown();
}
if (channelContext != null) {
log.info("can't send data, {}, isClosed:{}, isRemoved:{}", channelContext, channelContext.isClosed,
channelContext.isRemoved);
}
return false;
}
if (channelContext.tioConfig.packetConverter != null) {
Packet packet1 = channelContext.tioConfig.packetConverter.convert(packet, channelContext);
if (packet1 == null) {
if (log.isInfoEnabled()) {
log.info("convert后为null,表示不需要发送", channelContext, packet.logstr());
}
return true;
}
packet = packet1;
}
boolean isSingleBlock = countDownLatch != null && packetSendMode == PacketSendMode.SINGLE_BLOCK;
boolean isAdded = false;
if (countDownLatch != null) {
Meta meta = new Meta();
meta.setCountDownLatch(countDownLatch);
packet.setMeta(meta);
}
if (channelContext.tioConfig.useQueueSend) {
isAdded = channelContext.sendRunnable.addMsg(packet);
} else {
isAdded = channelContext.sendRunnable.sendPacket(packet);
}
if (!isAdded) {
if (countDownLatch != null) {
countDownLatch.countDown();
}
return false;
}
if (channelContext.tioConfig.useQueueSend) {
channelContext.sendRunnable.execute();
}
if (isSingleBlock) {
long timeout = 10;
try {
Boolean awaitFlag = countDownLatch.await(timeout, TimeUnit.SECONDS);
if (!awaitFlag) {
log.error("{}, 阻塞发送超时, timeout:{}s, packet:{}", channelContext, timeout, packet.logstr());
}
} catch (InterruptedException e) {
log.error(e.toString(), e);
}
Boolean isSentSuccess = packet.getMeta().getIsSentSuccess();
return isSentSuccess;
} else {
return true;
}
} catch (Throwable e) {
log.error(channelContext + ", " + e.toString(), e);
return false;
}
}
/**
* 发送到指定的ip和port
* @param tioConfig
* @param ip
* @param port
* @param packet
* @author tanyaowu
*/
public static Boolean send(TioConfig tioConfig, String ip, int port, Packet packet) {
return send(tioConfig, ip, port, packet, false);
}
/**
* 发送到指定的ip和port
* @param tioConfig
* @param ip
* @param port
* @param packet
* @param isBlock
* @return
* @author tanyaowu
*/
private static Boolean send(TioConfig tioConfig, String ip, int port, Packet packet, boolean isBlock) {
ChannelContext channelContext = tioConfig.clientNodes.find(ip, port);
if (channelContext != null) {
if (isBlock) {
return bSend(channelContext, packet);
} else {
return send(channelContext, packet);
}
} else {
log.info("{}, can find channelContext by {}:{}", tioConfig.getName(), ip, port);
return false;
}
}
public static void sendToAll(TioConfig tioConfig, Packet packet) {
sendToAll(tioConfig, packet, null);
}
/**
* 发消息到所有连接
* @param tioConfig
* @param packet
* @param channelContextFilter
* @author tanyaowu
*/
public static void sendToAll(TioConfig tioConfig, Packet packet, ChannelContextFilter channelContextFilter) {
sendToAll(tioConfig, packet, channelContextFilter, false);
}
/**
*
* @param tioConfig
* @param packet
* @param channelContextFilter
* @param isBlock
* @author tanyaowu
*/
private static Boolean sendToAll(TioConfig tioConfig, Packet packet, ChannelContextFilter channelContextFilter,
boolean isBlock) {
try {
SetWithLock setWithLock = tioConfig.connections;
if (setWithLock == null) {
log.debug("{}, 没有任何连接", tioConfig.getName());
return false;
}
Boolean ret = sendToSet(tioConfig, setWithLock, packet, channelContextFilter, isBlock);
return ret;
} finally {
}
}
/**
* 发消息给指定业务ID
* @param tioConfig
* @param bsId
* @param packet
* @return
* @author tanyaowu
*/
public static Boolean sendToBsId(TioConfig tioConfig, String bsId, Packet packet) {
return sendToBsId(tioConfig, bsId, packet, false);
}
/**
* 发消息给指定业务ID
* @param tioConfig
* @param bsId
* @param packet
* @param isBlock
* @return
* @author tanyaowu
*/
private static Boolean sendToBsId(TioConfig tioConfig, String bsId, Packet packet, boolean isBlock) {
ChannelContext channelContext = Tio.getByBsId(tioConfig, bsId);
if (channelContext == null) {
return false;
}
if (isBlock) {
return bSend(channelContext, packet);
} else {
return send(channelContext, packet);
}
}
/**
* 发消息到组
* @param tioConfig
* @param group
* @param packet
* @author tanyaowu
*/
public static void sendToGroup(TioConfig tioConfig, String group, Packet packet) {
sendToGroup(tioConfig, group, packet, null);
}
/**
* 发消息到组
* @param tioConfig
* @param group
* @param packet
* @param channelContextFilter
* @author tanyaowu
*/
public static void sendToGroup(TioConfig tioConfig, String group, Packet packet,
ChannelContextFilter channelContextFilter) {
sendToGroup(tioConfig, group, packet, channelContextFilter, false);
}
/**
* 发消息到组
* @param tioConfig
* @param group
* @param packet
* @param channelContextFilter
* @param isBlock
* @return
*/
private static Boolean sendToGroup(TioConfig tioConfig, String group, Packet packet,
ChannelContextFilter channelContextFilter, boolean isBlock) {
try {
SetWithLock setWithLock = tioConfig.groups.clients(tioConfig, group);
if (setWithLock == null) {
log.debug("{}, 组[{}]不存在", tioConfig.getName(), group);
return false;
}
Boolean ret = sendToSet(tioConfig, setWithLock, packet, channelContextFilter, isBlock);
return ret;
} finally {
}
}
/**
* 发消息给指定ChannelContext id
* @param channelContextId
* @param packet
* @author tanyaowu
*/
public static Boolean sendToId(TioConfig tioConfig, String channelContextId, Packet packet) {
return sendToId(tioConfig, channelContextId, packet, false);
}
/**
* 发消息给指定ChannelContext id
* @param channelContextId
* @param packet
* @param isBlock
* @return
* @author tanyaowu
*/
private static Boolean sendToId(TioConfig tioConfig, String channelContextId, Packet packet, boolean isBlock) {
ChannelContext channelContext = Tio.getChannelContextById(tioConfig, channelContextId);
if (channelContext == null) {
return false;
}
if (isBlock) {
return bSend(channelContext, packet);
} else {
return send(channelContext, packet);
}
}
/**
* 发送到指定ip对应的集合
* @param tioConfig
* @param ip
* @param packet
* @author: tanyaowu
*/
public static void sendToIp(TioConfig tioConfig, String ip, Packet packet) {
sendToIp(tioConfig, ip, packet, null);
}
/**
* 发送到指定ip对应的集合
* @param tioConfig
* @param ip
* @param packet
* @param channelContextFilter
* @author: tanyaowu
*/
public static void sendToIp(TioConfig tioConfig, String ip, Packet packet,
ChannelContextFilter channelContextFilter) {
sendToIp(tioConfig, ip, packet, channelContextFilter, false);
}
/**
* 发送到指定ip对应的集合
* @param tioConfig
* @param ip
* @param packet
* @param channelContextFilter
* @param isBlock
* @return
* @author: tanyaowu
*/
private static Boolean sendToIp(TioConfig tioConfig, String ip, Packet packet,
ChannelContextFilter channelContextFilter, boolean isBlock) {
try {
SetWithLock setWithLock = tioConfig.ips.clients(tioConfig, ip);
if (setWithLock == null) {
log.info("{}, 没有ip为[{}]的对端", tioConfig.getName(), ip);
return false;
}
Boolean ret = sendToSet(tioConfig, setWithLock, packet, channelContextFilter, isBlock);
return ret;
} finally {
}
}
/**
* 发消息到指定集合
* @param tioConfig
* @param setWithLock
* @param packet
* @param channelContextFilter
* @author tanyaowu
*/
public static void sendToSet(TioConfig tioConfig, SetWithLock setWithLock, Packet packet,
ChannelContextFilter channelContextFilter) {
sendToSet(tioConfig, setWithLock, packet, channelContextFilter, false);
}
/**
* 发消息到指定集合
* @param tioConfig
* @param setWithLock
* @param packet
* @param channelContextFilter
* @param isBlock
* @author tanyaowu
*/
private static Boolean sendToSet(TioConfig tioConfig, SetWithLock setWithLock, Packet packet,
ChannelContextFilter channelContextFilter, boolean isBlock) {
boolean releasedLock = false;
Lock lock = setWithLock.readLock();
lock.lock();
try {
Set set = setWithLock.getObj();
if (set.size() == 0) {
log.debug("{}, 集合为空", tioConfig.getName());
return false;
}
CountDownLatch countDownLatch = null;
if (isBlock) {
countDownLatch = new CountDownLatch(set.size());
}
int sendCount = 0;
for (ChannelContext channelContext : set) {
if (channelContextFilter != null) {
boolean isfilter = channelContextFilter.filter(channelContext);
if (!isfilter) {
if (isBlock) {
countDownLatch.countDown();
}
continue;
}
}
sendCount++;
if (isBlock) {
send(channelContext, packet, countDownLatch, PacketSendMode.GROUP_BLOCK);
} else {
send(channelContext, packet, null, null);
}
}
lock.unlock();
releasedLock = true;
if (sendCount == 0) {
return false;
}
if (isBlock) {
try {
long timeout = sendCount / 5;
timeout = Math.max(timeout, 10);// timeout < 10 ? 10 : timeout;
boolean awaitFlag = countDownLatch.await(timeout, TimeUnit.SECONDS);
if (!awaitFlag) {
log.error("{}, 同步群发超时, size:{}, timeout:{}, packet:{}", tioConfig.getName(), setWithLock.getObj().size(),
timeout, packet.logstr());
return false;
} else {
return true;
}
} catch (InterruptedException e) {
log.error(e.toString(), e);
return false;
} finally {
}
} else {
return true;
}
} catch (Throwable e) {
log.error(e.toString(), e);
return false;
} finally {
if (!releasedLock) {
lock.unlock();
}
}
}
/**
* 发消息到指定token
* @param tioConfig
* @param token
* @param packet
* @return
* @author tanyaowu
*/
public static Boolean sendToToken(TioConfig tioConfig, String token, Packet packet) {
return sendToToken(tioConfig, token, packet, false);
}
/**
* 发消息给指定token
* @param tioConfig
* @param token
* @param packet
* @param isBlock
* @author tanyaowu
*/
private static Boolean sendToToken(TioConfig tioConfig, String token, Packet packet, boolean isBlock) {
SetWithLock setWithLock = tioConfig.tokens.find(tioConfig, token);
try {
if (setWithLock == null) {
return false;
}
ReadLock readLock = setWithLock.readLock();
readLock.lock();
try {
Set set = setWithLock.getObj();
boolean ret = false;
for (ChannelContext channelContext : set) {
boolean singleRet = false;
// 不要用 a = a || b(),容易漏执行后面的函数
if (isBlock) {
singleRet = bSend(channelContext, packet);
} else {
singleRet = send(channelContext, packet);
}
if (singleRet) {
ret = true;
}
}
return ret;
} catch (Throwable e) {
log.error(e.getMessage(), e);
} finally {
readLock.unlock();
}
return false;
} finally {
}
}
/**
* 发消息给指定用户
* @param tioConfig
* @param userid
* @param packet
* @author tanyaowu
*/
public static Boolean sendToUser(TioConfig tioConfig, String userid, Packet packet) {
return sendToUser(tioConfig, userid, packet, false);
}
/**
* 发消息给指定用户
* @param tioConfig
* @param userid
* @param packet
* @param isBlock
* @author tanyaowu
*/
private static Boolean sendToUser(TioConfig tioConfig, String userid, Packet packet, boolean isBlock) {
SetWithLock setWithLock = tioConfig.users.find(tioConfig, userid);
try {
if (setWithLock == null) {
return false;
}
ReadLock readLock = setWithLock.readLock();
readLock.lock();
try {
Set set = setWithLock.getObj();
boolean ret = false;
for (ChannelContext channelContext : set) {
boolean singleRet = false;
// 不要用 a = a || b(),容易漏执行后面的函数
if (isBlock) {
singleRet = bSend(channelContext, packet);
} else {
singleRet = send(channelContext, packet);
}
if (singleRet) {
ret = true;
}
}
return ret;
} catch (Throwable e) {
log.error(e.getMessage(), e);
} finally {
readLock.unlock();
}
return false;
} finally {
}
}
/**
* 解绑业务id
* @param channelContext
* @author tanyaowu
*/
public static void unbindBsId(ChannelContext channelContext) {
channelContext.tioConfig.bsIds.unbind(channelContext);
}
/**
* 与所有组解除解绑关系
* @param channelContext
* @author tanyaowu
*/
public static void unbindGroup(ChannelContext channelContext) {
channelContext.tioConfig.groups.unbind(channelContext);
}
/**
* 与指定组解除绑定关系
* @param group
* @param channelContext
* @author tanyaowu
*/
public static void unbindGroup(String group, ChannelContext channelContext) {
channelContext.tioConfig.groups.unbind(group, channelContext);
}
/**
* 将某用户从组中解除绑定
* @param tioConfig
* @param userid
* @param group
*/
public static void unbindGroup(TioConfig tioConfig, String userid, String group) {
SetWithLock setWithLock = Tio.getByUserid(tioConfig, userid);
if (setWithLock != null) {
setWithLock.handle(new ReadLockHandler>() {
@Override
public void handler(Set set) {
for (ChannelContext channelContext : set) {
Tio.unbindGroup(group, channelContext);
}
}
});
}
}
/**
* 解除channelContext绑定的token
* @param channelContext
* @author tanyaowu
*/
public static void unbindToken(ChannelContext channelContext) {
channelContext.tioConfig.tokens.unbind(channelContext);
}
/**
* 解除token
* @param tioConfig
* @param token
*/
public static void unbindToken(TioConfig tioConfig, String token) {
tioConfig.tokens.unbind(tioConfig, token);
}
// org.tio.core.TioConfig.ipBlacklist
/**
* 解除channelContext绑定的userid
* @param channelContext
* @author tanyaowu
*/
public static void unbindUser(ChannelContext channelContext) {
channelContext.tioConfig.users.unbind(channelContext);
}
/**
* 解除userid的绑定。一般用于多地登录,踢掉前面登录的场景
* @param tioConfig
* @param userid
* @author: tanyaowu
*/
public static void unbindUser(TioConfig tioConfig, String userid) {
tioConfig.users.unbind(tioConfig, userid);
}
private Tio() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy