diff --git a/pom.xml b/pom.xml index 5a95fbcc..68328396 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.sonic sonic-agent - v1.2.0-beta1 + v1.2.0-beta2 jar @@ -35,15 +35,22 @@ Java-WebSocket 1.5.2 - + - org.springframework.boot - spring-boot-starter-actuator + io.netty + netty-all + 4.1.52.Final - + - org.springframework.boot - spring-boot-starter-amqp + org.jboss.marshalling + jboss-marshalling + 2.0.10.Final + + + org.jboss.marshalling + jboss-marshalling-serial + 2.0.10.Final diff --git a/src/main/java/com/sonic/agent/AgentApplication.java b/src/main/java/com/sonic/agent/AgentApplication.java index d4c964ee..055ef3ce 100644 --- a/src/main/java/com/sonic/agent/AgentApplication.java +++ b/src/main/java/com/sonic/agent/AgentApplication.java @@ -1,16 +1,30 @@ package com.sonic.agent; +import com.sonic.agent.tools.SpringTool; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; /** * @author ZhouYiXun * @des Agent端启动类 * @date 2021/08/16 19:26 */ +@Import(SpringTool.class) @SpringBootApplication public class AgentApplication { + @Value("${sonic.agent.port}") + private int port; + public static void main(String[] args) { SpringApplication.run(AgentApplication.class, args); } + + @Bean + public TomcatServletWebServerFactory servletContainer(){ + return new TomcatServletWebServerFactory(port) ; + } } diff --git a/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java b/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java index 9024f7b7..628e0a84 100644 --- a/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java +++ b/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java @@ -11,6 +11,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -25,13 +26,14 @@ * @des * @date 2021/10/29 0:28 */ +@ConditionalOnProperty(value = "modules.webview.enable", havingValue = "true") @Configuration public class RemoteDebugDriver { private static final Logger logger = LoggerFactory.getLogger(RemoteDebugDriver.class); private static String chromePath; public static int port = 0; public static WebDriver webDriver; - @Value("${sonic.chrome.path}") + @Value("${modules.webview.chrome-driver-path}") private String path; @Bean @@ -58,6 +60,7 @@ public ServletRegistrationBean proxyServletRegistration() { @Bean @DependsOn(value = "setChromePath") public static void startChromeDriver() { + logger.info("开启webview相关功能"); try { DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); ChromeOptions chromeOptions = new ChromeOptions(); diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java index 3bcc0fb9..a899b0cd 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java @@ -5,6 +5,7 @@ import com.sonic.agent.tools.DownImageTool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; @@ -18,7 +19,8 @@ * @des ADB工具类 * @date 2021/08/16 19:26 */ -@DependsOn({"androidThreadPoolInit", "rabbitMsgInit"}) +@ConditionalOnProperty(value = "modules.android.enable", havingValue = "true") +@DependsOn({"androidThreadPoolInit", "nettyMsgInit"}) @Component public class AndroidDeviceBridgeTool { private static final Logger logger = LoggerFactory.getLogger(AndroidDeviceBridgeTool.class); @@ -26,6 +28,7 @@ public class AndroidDeviceBridgeTool { private static AndroidDeviceStatusListener androidDeviceStatusListener = new AndroidDeviceStatusListener(); public AndroidDeviceBridgeTool() { + logger.info("开启安卓相关功能"); init(); } @@ -369,7 +372,7 @@ public static void pushToCamera(IDevice iDevice, String url) { * @des 开启miniCap服务 * @date 2021/8/16 20:04 */ - public static void startMiniCapServer(IDevice iDevice, int quality, int screen, Session session) throws AdbCommandRejectedException, IOException, SyncException, TimeoutException { + public static void startMiniCapServer(IDevice iDevice, String quality, int screen, Session session) throws AdbCommandRejectedException, IOException, SyncException, TimeoutException { //先删除原有路径下的文件,防止上次出错后停止,再次打开会报错的情况 executeCommand(iDevice, "rm -rf /data/local/tmp/minicap*"); //获取cpu信息 @@ -386,11 +389,18 @@ public static void startMiniCapServer(IDevice iDevice, int quality, int screen, //给文件权限 executeCommand(iDevice, "chmod 777 /data/local/tmp/" + miniCapFileName); String size = getScreenSize(iDevice); - String vSize = Integer.parseInt(size.substring(0, size.indexOf("x"))) / 2 + "x" + Integer.parseInt(size.substring(size.indexOf("x") + 1)) / 2; + String vSize; + int q = 80; + if (quality.equals("fixed")) { + vSize = size; + q = 40; + } else { + vSize = "800x800"; + } try { //开始启动 - iDevice.executeShellCommand(String.format("LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/%s -Q " + quality + " -P %s@%s/%d", - miniCapFileName, size, vSize, screen), new IShellOutputReceiver() { + iDevice.executeShellCommand(String.format("LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/%s -Q %d -S -P %s@%s/%d", + miniCapFileName, q, size, vSize, screen), new IShellOutputReceiver() { @Override public void addOutput(byte[] bytes, int i, int i1) { String res = new String(bytes, i, i1); diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java index 79260752..053c4300 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java @@ -3,8 +3,7 @@ import com.alibaba.fastjson.JSONObject; import com.sonic.agent.interfaces.DeviceStatus; import com.sonic.agent.maps.AndroidDeviceManagerMap; -import com.sonic.agent.rabbitmq.RabbitMQThread; -import com.sonic.agent.tools.AgentTool; +import com.sonic.agent.netty.NettyThreadPool; /** * @author ZhouYiXun @@ -26,7 +25,7 @@ public static void send(String udId, String status) { deviceDetail.put("msg", "deviceDetail"); deviceDetail.put("udId", udId); deviceDetail.put("status", status); - RabbitMQThread.send(deviceDetail); + NettyThreadPool.send(deviceDetail); } /** diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceStatusListener.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceStatusListener.java index cc07fc2e..25c26c88 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceStatusListener.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceStatusListener.java @@ -5,8 +5,7 @@ import com.android.ddmlib.IDevice; import com.sonic.agent.interfaces.PlatformType; import com.sonic.agent.maps.AndroidDeviceManagerMap; -import com.sonic.agent.rabbitmq.RabbitMQThread; -import com.sonic.agent.tools.AgentTool; +import com.sonic.agent.netty.NettyThreadPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +36,7 @@ private void send(IDevice device) { deviceDetail.put("size", AndroidDeviceBridgeTool.getScreenSize(device)); deviceDetail.put("cpu", device.getProperty(IDevice.PROP_DEVICE_CPU_ABI)); deviceDetail.put("manufacturer", device.getProperty(IDevice.PROP_DEVICE_MANUFACTURER)); - RabbitMQThread.send(deviceDetail); + NettyThreadPool.send(deviceDetail); } @Override diff --git a/src/main/java/com/sonic/agent/bridge/ios/LibIMobileDeviceTool.java b/src/main/java/com/sonic/agent/bridge/ios/LibIMobileDeviceTool.java index 815acaea..83cc329e 100644 --- a/src/main/java/com/sonic/agent/bridge/ios/LibIMobileDeviceTool.java +++ b/src/main/java/com/sonic/agent/bridge/ios/LibIMobileDeviceTool.java @@ -2,13 +2,14 @@ import com.alibaba.fastjson.JSONObject; import com.sonic.agent.maps.IOSDeviceManagerMap; -import com.sonic.agent.rabbitmq.RabbitMQThread; +import com.sonic.agent.netty.NettyThreadPool; import com.sonic.agent.tools.ProcessCommandTool; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; @@ -17,7 +18,8 @@ import java.io.LineNumberReader; import java.util.List; -@DependsOn({"iOSThreadPoolInit", "rabbitMsgInit"}) +@ConditionalOnProperty(value = "modules.ios.enable", havingValue = "true") +@DependsOn({"iOSThreadPoolInit", "nettyMsgInit"}) @Component public class LibIMobileDeviceTool { private static final Logger logger = LoggerFactory.getLogger(LibIMobileDeviceTool.class); @@ -27,6 +29,7 @@ public LibIMobileDeviceTool() { } public static void init() { + logger.info("开启iOS相关功能"); if (!System.getProperty("os.name").contains("Mac")) { logger.info("iOS设备监听已关闭"); return; @@ -67,7 +70,7 @@ public static void sendDisConnectStatus(String udId) { deviceStatus.put("serialNum", udId); deviceStatus.put("status", "DISCONNECTED"); logger.info("iOS设备:" + udId + " 下线!"); - RabbitMQThread.send(deviceStatus); + NettyThreadPool.send(deviceStatus); IOSDeviceManagerMap.getMap().remove(udId); // wdaKill(udid); // relayKill(udid); @@ -87,7 +90,7 @@ public static void sendOnlineStatus(String udId) { deviceStatus.put("cpu", getCpuByUdId(udId)); deviceStatus.put("manufacturer", "APPLE"); logger.info("iOS设备:" + udId + " 上线!"); - RabbitMQThread.send(deviceStatus); + NettyThreadPool.send(deviceStatus); IOSDeviceManagerMap.getMap().remove(udId); } diff --git a/src/main/java/com/sonic/agent/netty/MarshallingCodeCFactory.java b/src/main/java/com/sonic/agent/netty/MarshallingCodeCFactory.java new file mode 100644 index 00000000..9a33038a --- /dev/null +++ b/src/main/java/com/sonic/agent/netty/MarshallingCodeCFactory.java @@ -0,0 +1,26 @@ +package com.sonic.agent.netty; + +import io.netty.handler.codec.marshalling.*; +import org.jboss.marshalling.MarshallerFactory; +import org.jboss.marshalling.Marshalling; +import org.jboss.marshalling.MarshallingConfiguration; + +public final class MarshallingCodeCFactory { + public static MarshallingDecoder buildMarshallingDecoder() { + final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial"); + final MarshallingConfiguration configuration = new MarshallingConfiguration(); + configuration.setVersion(5); + UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration); + MarshallingDecoder decoder = new MarshallingDecoder(provider, 10*1024*1024); + return decoder; + } + + public static MarshallingEncoder buildMarshallingEncoder() { + final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial"); + final MarshallingConfiguration configuration = new MarshallingConfiguration(); + configuration.setVersion(5); + MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration); + MarshallingEncoder encoder = new MarshallingEncoder(provider); + return encoder; + } +} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/netty/NettyClient.java b/src/main/java/com/sonic/agent/netty/NettyClient.java new file mode 100644 index 00000000..f168e79b --- /dev/null +++ b/src/main/java/com/sonic/agent/netty/NettyClient.java @@ -0,0 +1,68 @@ +package com.sonic.agent.netty; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import java.util.concurrent.TimeUnit; + +@Component +public class NettyClient implements ApplicationRunner { + private final Logger logger = LoggerFactory.getLogger(NettyClient.class); + private NioEventLoopGroup group = new NioEventLoopGroup(4); + private Channel channel; + private Bootstrap bootstrap; + @Value("${sonic.server.transport-port}") + private int serverPort; + @Value("${sonic.server.host}") + private String serverHost; + @Value("${sonic.agent.port}") + private int agentPort; + @Value("${sonic.agent.host}") + private String agentHost; + @Value("${sonic.agent.key}") + private String key; + @Value("${spring.version}") + private String version; + + @Override + public void run(ApplicationArguments args) { + group = new NioEventLoopGroup(); + bootstrap = new Bootstrap() + .group(group) + .option(ChannelOption.TCP_NODELAY, true) + .channel(NioSocketChannel.class) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder()); + socketChannel.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder()); + socketChannel.pipeline().addLast(new SecurityHandler(NettyClient.this, key, agentHost, agentPort, version)); + } + }); + doConnect(); + } + + protected void doConnect() { + if (channel != null && channel.isActive()) { + return; + } + ChannelFuture future = bootstrap.connect(serverHost, serverPort); + future.addListener((ChannelFutureListener) futureListener -> { + if (futureListener.isSuccess()) { + channel = futureListener.channel(); + } else { + logger.info("连接到服务器{}:{}失败!10s后重连...", serverHost, serverPort); + futureListener.channel().eventLoop().schedule(() -> doConnect(), 10, TimeUnit.SECONDS); + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java new file mode 100644 index 00000000..7eee6ae6 --- /dev/null +++ b/src/main/java/com/sonic/agent/netty/NettyClientHandler.java @@ -0,0 +1,126 @@ +package com.sonic.agent.netty; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.android.ddmlib.IDevice; +import com.sonic.agent.automation.AndroidStepHandler; +import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; +import com.sonic.agent.bridge.ios.LibIMobileDeviceTool; +import com.sonic.agent.interfaces.PlatformType; +import com.sonic.agent.maps.AndroidPasswordMap; +import com.sonic.agent.maps.HandlerMap; +import com.sonic.agent.tests.AndroidTests; +import com.sonic.agent.tools.SpringTool; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.websocket.Session; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class NettyClientHandler extends ChannelInboundHandlerAdapter { + private final Logger logger = LoggerFactory.getLogger(NettyClientHandler.class); + private static Map sessionMap = new ConcurrentHashMap(); + private NettyClient nettyClient; + public static Channel channel = null; + private AndroidTests androidTests = SpringTool.getBean(AndroidTests.class); + + public NettyClientHandler(NettyClient nettyClient, Channel channel) { + this.nettyClient = nettyClient; + this.channel = channel; + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + logger.info("Agent:{} 连接到服务器 {} 成功!", ctx.channel().localAddress(), ctx.channel().remoteAddress()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + JSONObject jsonObject = JSON.parseObject((String) msg); + logger.info("Agent:{} 收到服务器 {} 消息: {}", ctx.channel().localAddress(), ctx.channel().remoteAddress(), jsonObject); + NettyThreadPool.cachedThreadPool.execute(() -> { + switch (jsonObject.getString("msg")) { + case "reboot": + if (jsonObject.getInteger("platform") == PlatformType.ANDROID) { + IDevice rebootDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(jsonObject.getString("udId")); + if (rebootDevice != null) { + AndroidDeviceBridgeTool.reboot(rebootDevice); + } + } + if (jsonObject.getInteger("platform") == PlatformType.IOS) { + if (LibIMobileDeviceTool.getDeviceList().contains(jsonObject.getString("udId"))) { + LibIMobileDeviceTool.reboot(jsonObject.getString("udId")); + } + } + break; + case "heartBeat": + JSONObject heartBeat = new JSONObject(); + heartBeat.put("msg", "heartBeat"); + heartBeat.put("status", "alive"); + NettyThreadPool.send(heartBeat); + break; + case "runStep": + if (jsonObject.getInteger("pf") == PlatformType.ANDROID) { + AndroidPasswordMap.getMap().put(jsonObject.getString("udId") + , jsonObject.getString("pwd")); + AndroidStepHandler androidStepHandler = HandlerMap.getAndroidMap().get(jsonObject.getString("sessionId")); + androidStepHandler.resetResultDetailStatus(); + androidStepHandler.setGlobalParams(jsonObject.getJSONObject("gp")); + List steps = jsonObject.getJSONArray("steps").toJavaList(JSONObject.class); + for (JSONObject step : steps) { + try { + androidStepHandler.runStep(step); + } catch (Throwable e) { + break; + } + } + androidStepHandler.sendStatus(); + } + break; + case "suite": + JSONObject device = jsonObject.getJSONObject("device"); + if (AndroidDeviceBridgeTool.getIDeviceByUdId(device.getString("udId")) != null) { + AndroidPasswordMap.getMap().put(device.getString("udId") + , device.getString("password")); + try { + androidTests.run(jsonObject); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + //取消本次测试 + JSONObject subResultCount = new JSONObject(); + subResultCount.put("rid", jsonObject.getInteger("rid")); + NettyThreadPool.send(subResultCount); + } + break; + } + }); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + logger.info("服务器: {} 发生异常 {}", ctx.channel().remoteAddress(), cause.fillInStackTrace()); + ctx.close(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + logger.info("服务器: {} 连接断开", ctx.channel().remoteAddress()); + NettyThreadPool.isPassSecurity = false; + if (channel != null) { + channel.close(); + } + channel = null; + nettyClient.doConnect(); + } + + public static Map getMap() { + return sessionMap; + } +} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/netty/NettyThreadPool.java b/src/main/java/com/sonic/agent/netty/NettyThreadPool.java new file mode 100644 index 00000000..1b4a311d --- /dev/null +++ b/src/main/java/com/sonic/agent/netty/NettyThreadPool.java @@ -0,0 +1,63 @@ +package com.sonic.agent.netty; + +import com.alibaba.fastjson.JSONObject; +import com.sonic.agent.tools.AgentTool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; + +@Configuration +public class NettyThreadPool { + private final Logger logger = LoggerFactory.getLogger(NettyThreadPool.class); + private static LinkedBlockingQueue dataQueue; + public static ExecutorService cachedThreadPool; + public static boolean isPassSecurity = false; + private static Future read = null; + + @Bean + public void nettyMsgInit() { + cachedThreadPool = Executors.newCachedThreadPool(); + dataQueue = new LinkedBlockingQueue<>(); + } + + public static void send(JSONObject jsonObject) { + dataQueue.offer(jsonObject); + } + + public static void readQueue() { + if (read != null) { + isPassSecurity = false; + while (!read.isDone()) { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + isPassSecurity = true; + read = cachedThreadPool.submit(() -> { + while (isPassSecurity) { + try { + if (NettyClientHandler.channel != null) { + if (!dataQueue.isEmpty()) { + JSONObject m = dataQueue.poll(); + m.put("agentId", AgentTool.agentId); + NettyClientHandler.channel.writeAndFlush(m.toJSONString()); + } + } else { + Thread.sleep(10000); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } +} diff --git a/src/main/java/com/sonic/agent/netty/SecurityHandler.java b/src/main/java/com/sonic/agent/netty/SecurityHandler.java new file mode 100644 index 00000000..ce9f1fb8 --- /dev/null +++ b/src/main/java/com/sonic/agent/netty/SecurityHandler.java @@ -0,0 +1,76 @@ +package com.sonic.agent.netty; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.sonic.agent.tools.AgentTool; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SecurityHandler extends ChannelInboundHandlerAdapter { + private final Logger logger = LoggerFactory.getLogger(SecurityHandler.class); + private NettyClient nettyClient; + public static Channel channel = null; + private String key; + private String version; + private String host; + private int port; + + public SecurityHandler(NettyClient nettyClient, String key, String host, int port, String version) { + this.nettyClient = nettyClient; + this.key = key; + this.host = host; + this.port = port; + this.version = version; + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + logger.info("Agent:{} 请求连接到服务器 {} !", ctx.channel().localAddress(), ctx.channel().remoteAddress()); + JSONObject auth = new JSONObject(); + auth.put("msg", "auth"); + auth.put("key", key); + ctx.channel().writeAndFlush(auth.toJSONString()); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + JSONObject jsonMsg = JSON.parseObject((String) msg); + logger.info("Agent:{} 收到服务器 {} 返回验证消息: {}", ctx.channel().localAddress(), ctx.channel().remoteAddress(), jsonMsg); + if (jsonMsg.getString("msg") != null && jsonMsg.getString("msg").equals("auth") && jsonMsg.getString("result").equals("pass")) { + logger.info("服务器认证通过!"); + logger.info("当前sonic-agent版本为:" + version); + AgentTool.agentId = jsonMsg.getInteger("id"); + ctx.pipeline().remove(SecurityHandler.class); + channel = ctx.channel(); + JSONObject agentInfo = new JSONObject(); + agentInfo.put("msg", "agentInfo"); + agentInfo.put("agentId", jsonMsg.getInteger("id")); + agentInfo.put("port", port); + agentInfo.put("version", version); + agentInfo.put("systemType", System.getProperty("os.name")); + agentInfo.put("host", host); + channel.writeAndFlush(agentInfo.toJSONString()); + NettyThreadPool.readQueue(); + ctx.pipeline().addLast(new NettyClientHandler(nettyClient, channel)); + } else { + logger.info("服务器认证不通过!"); + NettyThreadPool.isPassSecurity = false; + ctx.close(); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + logger.info("Agent: {} 发生异常 {}", ctx.channel().remoteAddress(), cause.getMessage()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + logger.info("Agent: {} 连接断开", ctx.channel().remoteAddress()); + NettyThreadPool.isPassSecurity = false; + ctx.close(); + } +} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/rabbitmq/RabbitListenerConfig.java b/src/main/java/com/sonic/agent/rabbitmq/RabbitListenerConfig.java deleted file mode 100644 index b9143466..00000000 --- a/src/main/java/com/sonic/agent/rabbitmq/RabbitListenerConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.sonic.agent.rabbitmq; - -import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer; -import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.converter.MappingJackson2MessageConverter; -import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory; -import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory; - -/** - * @author ZhouYiXun - * @des rabbitmq监听配置 - * @date 2021/8/23 19:26 - */ -@Configuration -public class RabbitListenerConfig implements RabbitListenerConfigurer { - @Override - public void configureRabbitListeners(RabbitListenerEndpointRegistrar rabbitListenerEndpointRegistrar) { - rabbitListenerEndpointRegistrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory()); - } - - @Bean - MessageHandlerMethodFactory messageHandlerMethodFactory() { - DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory(); - messageHandlerMethodFactory.setMessageConverter(mappingJackson2MessageConverter()); - return messageHandlerMethodFactory; - } - - @Bean - public MappingJackson2MessageConverter mappingJackson2MessageConverter() { - return new MappingJackson2MessageConverter(); - } -} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/rabbitmq/RabbitMQThread.java b/src/main/java/com/sonic/agent/rabbitmq/RabbitMQThread.java deleted file mode 100644 index 9b3ab65c..00000000 --- a/src/main/java/com/sonic/agent/rabbitmq/RabbitMQThread.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.sonic.agent.rabbitmq; - -import com.alibaba.fastjson.JSONObject; -import com.sonic.agent.tools.AgentTool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; - -@Component -public class RabbitMQThread { - private static LinkedBlockingQueue msgQueue; - public static ExecutorService cachedThreadPool; - public static boolean isPass = false; - @Autowired - private RabbitTemplate rabbitTemplate; - - @Bean - public void rabbitMsgInit() { - cachedThreadPool = Executors.newCachedThreadPool(); - msgQueue = new LinkedBlockingQueue<>(); - } - - public static void send(JSONObject jsonObject) { - msgQueue.offer(jsonObject); - } - - @Bean - public void sendToRabbitMQ() { - cachedThreadPool.submit(() -> { - while (true) { - if (!isPass) { - Thread.sleep(5000); - continue; - } - try { - if (!msgQueue.isEmpty()) { - JSONObject m = msgQueue.poll(); - m.put("agentId", AgentTool.agentId); - rabbitTemplate.convertAndSend("DataExchange", "data" - , m); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - } -} diff --git a/src/main/java/com/sonic/agent/rabbitmq/RabbitQueueConfig.java b/src/main/java/com/sonic/agent/rabbitmq/RabbitQueueConfig.java deleted file mode 100644 index d4785165..00000000 --- a/src/main/java/com/sonic/agent/rabbitmq/RabbitQueueConfig.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.sonic.agent.rabbitmq; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.core.*; -import org.springframework.amqp.rabbit.connection.ConnectionFactory; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -@Configuration -public class RabbitQueueConfig { - private final Logger logger = LoggerFactory.getLogger(RabbitQueueConfig.class); - private String queueId; - @Value("${sonic.agent.key}") - private String key; - - @Bean - public String queueId() { - queueId = UUID.randomUUID().toString(); - return queueId; - } - - @Bean("MsgDirectExchange") - public DirectExchange MsgDirectExchange() { - return new DirectExchange("MsgDirectExchange", true, false); - } - - @Bean("MsgQueue") - public Queue MsgQueue() { - return new Queue("MsgQueue-" + key, true); - } - - @Bean("TaskDirectExchange") - public DirectExchange TaskDirectExchange() { - return new DirectExchange("TaskDirectExchange", true, false); - } - - @Bean("TaskQueue") - public Queue TaskQueue() { - Map params = new HashMap<>(); - params.put("x-message-ttl", 1000 * 60 * 5); - params.put("x-dead-letter-exchange", "MsgDirectExchange"); - params.put("x-dead-letter-routing-key", key); - return QueueBuilder.durable("TaskQueue-" + key).withArguments(params).build(); - } - - @Bean - public Binding bindingMsgDirect(@Qualifier("MsgQueue") Queue queue, - @Qualifier("MsgDirectExchange") DirectExchange exchange) { - return BindingBuilder.bind(queue).to(exchange).with(key); - } - - @Bean - public Binding bindingTaskDirect(@Qualifier("TaskQueue") Queue queue, - @Qualifier("TaskDirectExchange") DirectExchange exchange) { - return BindingBuilder.bind(queue).to(exchange).with(key); - } - - @Bean - public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { - RabbitTemplate rabbitTemplate = new RabbitTemplate(); - rabbitTemplate.setConnectionFactory(connectionFactory); - rabbitTemplate.setMandatory(true); - rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter()); - rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> { - if (!ack) { - logger.error("ConfirmCallback: 相关数据:" + correlationData + "\n" + - "确认情况:" + false + "\n" + - "原因:" + cause); - } - }); - - rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> - logger.info("ConfirmCallback: 消息:" + message + "\n" + - "回应码:" + replyCode + "\n" + - "回应信息:" + replyText + "\n" + - "交换机:" + exchange + "\n" + - "路由键:" + routingKey)); - - return rabbitTemplate; - } - -} diff --git a/src/main/java/com/sonic/agent/receiver/MsgReceiver.java b/src/main/java/com/sonic/agent/receiver/MsgReceiver.java deleted file mode 100644 index aa0e8182..00000000 --- a/src/main/java/com/sonic/agent/receiver/MsgReceiver.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.sonic.agent.receiver; - -import com.alibaba.fastjson.JSONObject; -import com.android.ddmlib.IDevice; -import com.rabbitmq.client.Channel; -import com.sonic.agent.automation.AndroidStepHandler; -import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; -import com.sonic.agent.bridge.android.AndroidDeviceThreadPool; -import com.sonic.agent.bridge.ios.LibIMobileDeviceTool; -import com.sonic.agent.interfaces.PlatformType; -import com.sonic.agent.maps.AndroidPasswordMap; -import com.sonic.agent.maps.HandlerMap; -import com.sonic.agent.rabbitmq.RabbitMQThread; -import com.sonic.agent.tests.AndroidTests; -import com.sonic.agent.tools.AgentTool; -import com.sonic.agent.tools.GetWebStartPort; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.io.IOException; -import java.util.*; - -/** - * @author ZhouYiXun - * @des - * @date 2021/9/16 18:40 - */ -@Component -public class MsgReceiver { - @Value("${spring.version}") - private String version; - @Value("${sonic.agent.host}") - private String host; - @Autowired - private AndroidTests androidTests; - private final Logger logger = LoggerFactory.getLogger(MsgReceiver.class); - - @RabbitListener(queues = "MsgQueue-${sonic.agent.key}") - public void process(JSONObject jsonObject, Channel channel, Message message) { - logger.info("MsgReceiver消费者收到消息 : " + jsonObject.toString()); - long deliveryTag = message.getMessageProperties().getDeliveryTag(); - AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { - switch (jsonObject.getString("msg")) { - case "auth": - logger.info("当前sonic-agent版本为:" + version); - AgentTool.agentId = jsonObject.getInteger("id"); - RabbitMQThread.isPass = true; - JSONObject agentInfo = new JSONObject(); - agentInfo.put("msg", "agentInfo"); - agentInfo.put("port", GetWebStartPort.getTomcatPort()); - agentInfo.put("version", version); - agentInfo.put("systemType", System.getProperty("os.name")); - agentInfo.put("host", host); - RabbitMQThread.send(agentInfo); - try { - channel.basicAck(deliveryTag, true); - } catch (IOException e) { - e.printStackTrace(); - } - break; - case "reboot": - if (jsonObject.getInteger("platform") == PlatformType.ANDROID) { - IDevice rebootDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(jsonObject.getString("udId")); - if (rebootDevice != null) { - AndroidDeviceBridgeTool.reboot(rebootDevice); - } - } - if (jsonObject.getInteger("platform") == PlatformType.IOS) { - if (LibIMobileDeviceTool.getDeviceList().contains(jsonObject.getString("udId"))) { - LibIMobileDeviceTool.reboot(jsonObject.getString("udId")); - } - } - try { - channel.basicAck(deliveryTag, true); - } catch (IOException e) { - e.printStackTrace(); - } - break; - case "runStep": - if (jsonObject.getInteger("pf") == PlatformType.ANDROID) { - AndroidPasswordMap.getMap().put(jsonObject.getString("udId") - , jsonObject.getString("pwd")); - AndroidStepHandler androidStepHandler = HandlerMap.getAndroidMap().get(jsonObject.getString("sessionId")); - androidStepHandler.resetResultDetailStatus(); - androidStepHandler.setGlobalParams(jsonObject.getJSONObject("gp")); - List steps = jsonObject.getJSONArray("steps").toJavaList(JSONObject.class); - for (JSONObject step : steps) { - try { - androidStepHandler.runStep(step); - } catch (Throwable e) { - break; - } - } - androidStepHandler.sendStatus(); - } - try { - channel.basicAck(deliveryTag, true); - } catch (IOException e) { - e.printStackTrace(); - } - break; - case "suite": - JSONObject device = jsonObject.getJSONObject("device"); - if (AndroidDeviceBridgeTool.getIDeviceByUdId(device.getString("udId")) != null) { - AndroidPasswordMap.getMap().put(device.getString("udId") - , device.getString("password")); - try { - androidTests.run(channel, deliveryTag, jsonObject); - } catch (Exception e) { - e.printStackTrace(); - try { - channel.basicReject(deliveryTag, true); - } catch (IOException ioException) { - ioException.printStackTrace(); - } - } - } else { - //取消本次测试 - JSONObject subResultCount = new JSONObject(); - subResultCount.put("rid", jsonObject.getInteger("rid")); - RabbitMQThread.send(subResultCount); - try { - channel.basicAck(deliveryTag, true); - } catch (IOException e) { - e.printStackTrace(); - } - } - break; - } - }); - } -} diff --git a/src/main/java/com/sonic/agent/tests/AndroidTests.java b/src/main/java/com/sonic/agent/tests/AndroidTests.java index 1193c9ec..4b6d3c23 100644 --- a/src/main/java/com/sonic/agent/tests/AndroidTests.java +++ b/src/main/java/com/sonic/agent/tests/AndroidTests.java @@ -2,7 +2,6 @@ import com.alibaba.fastjson.JSONObject; import com.android.ddmlib.IDevice; -import com.rabbitmq.client.Channel; import com.sonic.agent.automation.AndroidStepHandler; import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; import com.sonic.agent.bridge.android.AndroidDeviceLocalStatus; @@ -13,8 +12,6 @@ import org.bytedeco.javacv.FrameRecorder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -31,12 +28,10 @@ @Component public class AndroidTests { private final Logger logger = LoggerFactory.getLogger(AndroidTests.class); - @Autowired - private RabbitTemplate rabbitTemplate; @Value("${sonic.agent.key}") private String key; - public void run(Channel channel, long tag, JSONObject jsonObject) throws IOException { + public void run(JSONObject jsonObject) throws IOException { AndroidStepHandler androidStepHandler = new AndroidStepHandler(); List steps = jsonObject.getJSONArray("steps").toJavaList(JSONObject.class); int rid = jsonObject.getInteger("rid"); @@ -45,7 +40,6 @@ public void run(Channel channel, long tag, JSONObject jsonObject) throws IOExcep JSONObject gp = jsonObject.getJSONObject("gp"); androidStepHandler.setGlobalParams(gp); androidStepHandler.setTestMode(cid, rid, udId, DeviceStatus.TESTING, ""); - channel.basicAck(tag, true); int wait = jsonObject.getInteger("wait"); if (!AndroidDeviceLocalStatus.startTest(udId)) { androidStepHandler.waitDevice(wait + 1); @@ -56,7 +50,7 @@ public void run(Channel channel, long tag, JSONObject jsonObject) throws IOExcep } else { //延时队列 jsonObject.put("wait", wait); - rabbitTemplate.convertAndSend("TaskDirectExchange", key, jsonObject); +// rabbitTemplate.convertAndSend("TaskDirectExchange", key, jsonObject); logger.info("进入延时队列:" + jsonObject); } return; @@ -131,29 +125,6 @@ public void run(Channel channel, long tag, JSONObject jsonObject) throws IOExcep } continue; } -// File logDec = new File("test-output/log"); -// if (!logDec.exists()) { -// logDec.mkdirs(); -// } - //写入logcat -// File logcatFile = new File(logDec + File.separator + Calendar.getInstance().getTimeInMillis() + "_" + udId + ".log"); -// FileOutputStream logFileOut = null; -// try { -// logFileOut = new FileOutputStream(logcatFile); -// } catch (FileNotFoundException e) { -// logger.error(e.getMessage()); -// } -// FileOutputStream finalLogFileOut = logFileOut; - //添加监听 -// androidStepHandler.getAndroidDriver().addLogcatMessagesListener((msg) -> { -// try { -// finalLogFileOut.write((msg + "\n").getBytes(StandardCharsets.UTF_8)); -// } catch (IOException e) { -// logger.error(e.getMessage()); -// } -// }); - //开始广播 -// androidStepHandler.getAndroidDriver().startLogcatBroadcast("localhost", AppiumServer.service.getUrl().getPort()); Future miniCapPro = null; AtomicReference> imgList = new AtomicReference<>(new ArrayList<>()); AtomicReference banner = new AtomicReference<>(new String[24]); @@ -168,30 +139,15 @@ public void run(Channel channel, long tag, JSONObject jsonObject) throws IOExcep MiniCapTool miniCapTool = new MiniCapTool(); miniCapPro = miniCapTool.start(udId, banner, imgList, "high", -1, null); } - //两分钟录一次 - try { - Thread.sleep(120000); - } catch (InterruptedException e) { - logger.error(e.getMessage()); + int w = 0; + while (w < 10 && (!runStep.isDone())) { + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + logger.error(e.getMessage()); + } + w++; } - //移除监听 -// androidStepHandler.getAndroidDriver().removeAllLogcatListeners(); - //移除logcat广播 -// androidStepHandler.getAndroidDriver().stopLogcatBroadcast(); - //关闭流 -// if (logFileOut != null) { -// try { -// logFileOut.close(); -// } catch (IOException e) { -// logger.error(e.getMessage()); -// } -// } - //处理logcat日志 -// if (isFail.get()) { -// androidStepHandler.log.sendSelfLog(logcatFile.getName(), UploadTools.upload(logcatFile, "logFiles")); -// } else { -// logcatFile.delete(); -// } //处理录像 if (isSupportRecord) { if (androidStepHandler.getStatus() == 3) { diff --git a/src/main/java/com/sonic/agent/tools/GetWebStartPort.java b/src/main/java/com/sonic/agent/tools/GetWebStartPort.java deleted file mode 100644 index 460ab5bf..00000000 --- a/src/main/java/com/sonic/agent/tools/GetWebStartPort.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sonic.agent.tools; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.web.context.WebServerInitializedEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.stereotype.Component; - -@Component -public class GetWebStartPort implements ApplicationListener { - private final Logger logger = LoggerFactory.getLogger(GetWebStartPort.class); - - private static int serverPort = 0; - - public static int getTomcatPort(){ - return serverPort; - } - - @Override - public void onApplicationEvent(WebServerInitializedEvent event) { - serverPort = event.getWebServer().getPort(); - logger.info("tomcat开启端口: {}", serverPort); - } -} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/tools/LaunchTool.java b/src/main/java/com/sonic/agent/tools/LaunchTool.java index 518bd0b4..06d2c3e0 100644 --- a/src/main/java/com/sonic/agent/tools/LaunchTool.java +++ b/src/main/java/com/sonic/agent/tools/LaunchTool.java @@ -1,14 +1,9 @@ package com.sonic.agent.tools; -import com.alibaba.fastjson.JSONObject; import com.sonic.agent.automation.AppiumServer; import com.sonic.agent.automation.RemoteDebugDriver; -import com.sonic.agent.rabbitmq.RabbitMQThread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.context.annotation.DependsOn; @@ -17,28 +12,17 @@ import javax.annotation.PreDestroy; @Component -@DependsOn("rabbitMsgInit") +@DependsOn("nettyMsgInit") public class LaunchTool implements ApplicationRunner { private final Logger logger = LoggerFactory.getLogger(LaunchTool.class); - @Autowired - private RabbitTemplate rabbitTemplate; - @Value("${sonic.agent.key}") - private String key; @Override public void run(ApplicationArguments args) { AppiumServer.start(); - JSONObject auth = new JSONObject(); - auth.put("msg", "auth"); - auth.put("key", key); - rabbitTemplate.convertAndSend("DataExchange", "data", auth); } @PreDestroy public void destroy() throws InterruptedException { - JSONObject agentOffLine = new JSONObject(); - agentOffLine.put("msg", "offLine"); - RabbitMQThread.send(agentOffLine); RemoteDebugDriver.close(); AppiumServer.close(); Thread.sleep(3000); diff --git a/src/main/java/com/sonic/agent/tools/LogTool.java b/src/main/java/com/sonic/agent/tools/LogTool.java index be154f67..db9fddbb 100644 --- a/src/main/java/com/sonic/agent/tools/LogTool.java +++ b/src/main/java/com/sonic/agent/tools/LogTool.java @@ -4,7 +4,7 @@ import com.sonic.agent.interfaces.DeviceStatus; import com.sonic.agent.interfaces.StepType; import com.sonic.agent.maps.WebSocketSessionMap; -import com.sonic.agent.rabbitmq.RabbitMQThread; +import com.sonic.agent.netty.NettyThreadPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,7 +56,7 @@ public void send(JSONObject message) { */ private void sendToServer(JSONObject message) { message.put("time", new Date()); - RabbitMQThread.send(message); + NettyThreadPool.send(message); } /** diff --git a/src/main/java/com/sonic/agent/tools/MiniCapTool.java b/src/main/java/com/sonic/agent/tools/MiniCapTool.java index 350b391a..d124e776 100644 --- a/src/main/java/com/sonic/agent/tools/MiniCapTool.java +++ b/src/main/java/com/sonic/agent/tools/MiniCapTool.java @@ -33,18 +33,6 @@ public class MiniCapTool { public Future start(String udId, AtomicReference banner, AtomicReference> imgList, String pic, int tor, Session session) { Queue dataQueue = new LinkedBlockingQueue<>(); IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId); - int qua = 0; - switch (pic) { - case "low": - qua = 10; - break; - case "middle": - qua = 30; - break; - case "high": - qua = 60; - break; - } int s; if (tor == -1) { s = AndroidDeviceBridgeTool.getScreen(AndroidDeviceBridgeTool.getIDeviceByUdId(udId)); @@ -66,12 +54,12 @@ public Future start(String udId, AtomicReference banner, AtomicRefe c = 270; break; } - int finalQua = qua; +// int finalQua = qua; int finalC = c; Future miniCapPro = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> { try { - AndroidDeviceBridgeTool.startMiniCapServer(iDevice, finalQua, finalC, session); + AndroidDeviceBridgeTool.startMiniCapServer(iDevice, pic, finalC, session); } catch (AdbCommandRejectedException e) { e.printStackTrace(); } catch (IOException e) { @@ -231,6 +219,7 @@ public Future start(String udId, AtomicReference banner, AtomicRefe count++; break; case "middle": + case "fixed": count += 2; break; case "high": diff --git a/src/main/java/com/sonic/agent/tools/ScrcpyTool.java b/src/main/java/com/sonic/agent/tools/ScrcpyTool.java index ac4f02fc..7836a335 100644 --- a/src/main/java/com/sonic/agent/tools/ScrcpyTool.java +++ b/src/main/java/com/sonic/agent/tools/ScrcpyTool.java @@ -4,18 +4,51 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; public class ScrcpyTool { - public static void main(String[] args) throws IOException { - Socket capSocket; + private static final int BUFFER_SIZE = 1024 * 1024; + private static final int READ_BUFFER_SIZE = 1024 * 5; + + public static void main(String[] args) throws IOException, InterruptedException { + Socket capSocket = new Socket("localhost", 8666); OutputStream outputStream; InputStream inputStream; - capSocket = new Socket("localhost", 8666); outputStream = capSocket.getOutputStream(); inputStream = capSocket.getInputStream(); - outputStream.write(0); +// outputStream.write(0); + + int readLength; + int naluIndex = 0; + byte[] buffer = new byte[BUFFER_SIZE]; + int bufferLength = 0; while (capSocket.isConnected()) { - System.out.println(inputStream.read()); + readLength = inputStream.read(buffer, bufferLength, READ_BUFFER_SIZE); +// System.out.println(inputStream.read()); + System.out.println(readLength); + if(readLength>0) { + System.out.println(readLength); + bufferLength += readLength; + System.out.println(readLength); + for (int i = 5; i < bufferLength - 4; i++) { + if (buffer[i] == 0x00 && + buffer[i + 1] == 0x00 && + buffer[i + 2] == 0x00 && + buffer[i + 3] == 0x01 + ){ + naluIndex = i; + + byte[] naluBuffer = new byte[naluIndex]; + System.arraycopy(buffer, 0, naluBuffer, 0, naluIndex); +// dataQueue.add(naluBuffer); + bufferLength -= naluIndex; + System.arraycopy(buffer, naluIndex, buffer, 0, bufferLength); + i = 5; + } + } + + } } } diff --git a/src/main/java/com/sonic/agent/tools/SpringTool.java b/src/main/java/com/sonic/agent/tools/SpringTool.java new file mode 100644 index 00000000..9b0a44fe --- /dev/null +++ b/src/main/java/com/sonic/agent/tools/SpringTool.java @@ -0,0 +1,28 @@ +package com.sonic.agent.tools; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +public final class SpringTool implements ApplicationContextAware { + private static ApplicationContext applicationContext = null; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (SpringTool.applicationContext == null) { + SpringTool.applicationContext = applicationContext; + } + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static Object getBean(String name) { + return getApplicationContext().getBean(name); + } + + public static T getBean(Class clazz){ + return getApplicationContext().getBean(clazz); + } +} \ No newline at end of file diff --git a/src/main/java/com/sonic/agent/tools/UploadTools.java b/src/main/java/com/sonic/agent/tools/UploadTools.java index 75dacba9..9b6ddf44 100644 --- a/src/main/java/com/sonic/agent/tools/UploadTools.java +++ b/src/main/java/com/sonic/agent/tools/UploadTools.java @@ -28,8 +28,10 @@ @Component public class UploadTools { private final static Logger logger = LoggerFactory.getLogger(UploadTools.class); - @Value("${sonic.folder.url}") - private String url; + @Value("${sonic.server.host}") + private String host; + @Value("${sonic.server.folder-port}") + private String port; private static String baseUrl; private static RestTemplate restTemplate; @@ -37,7 +39,7 @@ public class UploadTools { @Autowired public void setRestTemplate(RestTemplate restTemplate) { UploadTools.restTemplate = restTemplate; - baseUrl = url; + baseUrl = "http://" + host + ":" + port + "/api/folder"; } public static String upload(File uploadFile, String type) { diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index ef40a048..74787a45 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -16,17 +16,12 @@ import com.sonic.agent.interfaces.DeviceStatus; import com.sonic.agent.maps.HandlerMap; import com.sonic.agent.maps.WebSocketSessionMap; -import com.sonic.agent.rabbitmq.RabbitMQThread; +import com.sonic.agent.netty.NettyThreadPool; import com.sonic.agent.tools.MiniCapTool; import com.sonic.agent.tools.PortTool; import com.sonic.agent.tools.ProcessCommandTool; import com.sonic.agent.tools.UploadTools; import org.openqa.selenium.OutputType; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.remote.DesiredCapabilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -39,15 +34,11 @@ import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; -import java.net.UnknownHostException; -import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicReference; @Component @@ -435,7 +426,7 @@ public void onMessage(String message, Session session) throws InterruptedExcepti jsonDebug.put("pwd", msg.getString("pwd")); jsonDebug.put("sessionId", session.getId()); jsonDebug.put("caseId", msg.getInteger("caseId")); - RabbitMQThread.send(jsonDebug); + NettyThreadPool.send(jsonDebug); } break; } @@ -452,12 +443,12 @@ private void sendText(Session session, String message) { } private void exit(Session session) { + AndroidDeviceLocalStatus.finish(udIdMap.get(session).getSerialNumber()); try { HandlerMap.getAndroidMap().get(session.getId()).closeAndroidDriver(); } catch (Exception e) { e.printStackTrace(); } finally { - AndroidDeviceLocalStatus.finish(udIdMap.get(session).getSerialNumber()); HandlerMap.getAndroidMap().remove(session.getId()); } List has = webViewForwardMap.get(udIdMap.get(session)); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 952985e7..fe483f04 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,37 +1,26 @@ -server: - port: 7777 - -spring: - application: - name: sonic-agent - rabbitmq: +sonic: + agent: + host: localhost + port: 7777 + key: 29002272-4659-4808-a804-08ce3388b136 + server: host: localhost - port: 5672 - username: sonic - password: sonic - virtual-host: sonic - listener: - simple: - acknowledge-mode: manual - publisher-confirm-type: correlated - publisher-returns: true + folder-port: 8094 + transport-port: 8095 + +modules: + android: + enable: true + ios: + enable: true + webview: + enable: true + chrome-driver-path: C:\Program Files\Google\Chrome\Application\chromedriver.exe logging: file: - name: logs/${spring.application.name}.log + name: logs/sonic-agent.log logback: rollingpolicy: clean-history-on-start: true max-history: 3 - -sonic: - modules: - android: true - ios: true - chrome: - path: C:\Program Files\Google\Chrome\Application\chromedriver.exe - folder: - url: http://localhost:8094/api/folder - agent: - host: 127.0.0.1 - key: 29002272-4659-4808-a804-08ce3388b136 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 411c3d11..31879ee6 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -1,47 +1,39 @@ -server: - #Agent服务的端口,可以自行更改 - port: 7777 - -spring: - application: - name: apex-agent - rabbitmq: - #rabbitMQ的host地址(如果用体验版的mq,这个host改为部署体验版机器的ip) +sonic: + agent: + # 替换为部署Agent机器的ipv4 host: localhost - #如果用体验版的mq,这里是5673 - port: 5673 - #MQ的用户名 - username: guest - #MQ的密码 - password: guest - #MQ的vHost - virtual-host: / - listener: - simple: - acknowledge-mode: manual - publisher-confirm-type: correlated - publisher-returns: true + # 替换为Agent服务的端口,可以自行更改 + port: 7777 + # 替换为前端新增Agent生成的key + key: 29002272-4659-4808-a804-08ce3388b136 + server: + # 如果跨网段,这个host改成后端的port + host: localhost + # 如果跨网段,这个port改成后端文件中心的port(一般不变) + folder-port: 8094 + # 如果跨网段,这个port改成后端传输中心的port(一般不变) + transport-port: 8095 + +modules: + # 安卓模块配置 + android: + enable: true + # iOS模块配置 + ios: + enable: true + # 在线webView调试模块配置 + webview: + enable: true + # Agent机器上的chrome浏览器的driver路径,可以去http://npm.taobao.org/mirrors/chromedriver/下载 + chrome-driver-path: C:\Program Files\Google\Chrome\Application\chromedriver.exe +# Agent日志管理,一般不需要更改,可根据自己需要配置 logging: file: - name: logs/${spring.application.name}.log + #日志路径 + name: logs/sonic-agent.log logback: rollingpolicy: clean-history-on-start: true + #保留天数 max-history: 3 - -sonic: - modules: - android: true - ios: true - chrome: - # Agent机器上的chrome浏览器的driver路径,可以去http://npm.taobao.org/mirrors/chromedriver/下载 - path: C:\Program Files\Google\Chrome\Application\chromedriver.exe - folder: - # 如果跨网段,这个host和port改成后端的host和port - url: http://localhost:8094/api/folder - agent: - # 替换为部署Agent机器的ipv4 - host: 127.0.0.1 - # 替换为前端新增Agent生成的key - key: 29002272-4659-4808-a804-08ce3388b136