File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\jenkins\slaves\JnlpSlaveAgentProtocol2.java.html

1 package jenkins.slaves;
2
3 import hudson.Extension;
4 import hudson.TcpSlaveAgentListener.ConnectionFromCurrentPeer;
5 import hudson.Util;
6 import hudson.remoting.Channel;
7 import hudson.remoting.Engine;
8 import hudson.slaves.SlaveComputer;
9 import hudson.util.IOException2;
10 import jenkins.model.Jenkins;
11
12 import java.io.ByteArrayInputStream;
13 import java.io.IOException;
14 import java.io.PrintWriter;
15 import java.net.Socket;
16 import java.security.SecureRandom;
17 import java.util.Map.Entry;
18 import java.util.Properties;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.TimeoutException;
22 import java.util.logging.Logger;
23
24 /**
25 * {@link JnlpSlaveAgentProtocol} Version 2.
26 *
27 * <p>
28 * This protocol extends the version 1 protocol by adding a per-client cookie,
29 * so that we can detect a reconnection from the slave and take appropriate action,
30 * when the connection disappered without the master noticing.
31 *
32 * @author Kohsuke Kawaguchi
33 * @since 1.467
34 */
35 @Extension
36 public class JnlpSlaveAgentProtocol2 extends JnlpSlaveAgentProtocol {
37 @Override
38 public String getName() {
39 return "JNLP2-connect";
40 }
41
42 @Override
43 public void handle(Socket socket) throws IOException, InterruptedException {
44 new Handler2(socket).run();
45 }
46
47 protected static class Handler2 extends Handler {
48 public Handler2(Socket socket) throws IOException {
49 super(socket);
50 }
51
52 /**
53 * Handles JNLP slave agent connection request (v2 protocol)
54 */
55 @Override
56 protected void run() throws IOException, InterruptedException {
57 Properties request = new Properties();
58 request.load(new ByteArrayInputStream(in.readUTF().getBytes("UTF-8")));
59
60 final String nodeName = request.getProperty("Node-Name");
61
62 if(!SLAVE_SECRET.mac(nodeName).equals(request.getProperty("Secret-Key"))) {
63 error(out, "Unauthorized access");
64 return;
65 }
66
67 SlaveComputer computer = (SlaveComputer) Jenkins.getInstance().getComputer(nodeName);
68 if(computer==null) {
69 error(out, "No such slave: "+nodeName);
70 return;
71 }
72
73 Channel ch = computer.getChannel();
74 if(ch !=null) {
75 String c = request.getProperty("Cookie");
76 if (c!=null && c.equals(ch.getProperty(COOKIE_NAME))) {
77 // we think we are currently connected, but this request proves that it's from the party
78 // we are supposed to be communicating to. so let the current one get disconnected
79 LOGGER.info("Disconnecting "+nodeName+" as we are reconnected from the current peer");
80 try {
81 computer.disconnect(new ConnectionFromCurrentPeer()).get(15, TimeUnit.SECONDS);
82 } catch (ExecutionException e) {
83 throw new IOException2("Failed to disconnect the current client",e);
84 } catch (TimeoutException e) {
85 throw new IOException2("Failed to disconnect the current client",e);
86 }
87 } else {
88 error(out, nodeName + " is already connected to this master. Rejecting this connection.");
89 return;
90 }
91 }
92
93 out.println(Engine.GREETING_SUCCESS);
94
95 Properties response = new Properties();
96 String cookie = generateCookie();
97 response.put("Cookie",cookie);
98 writeResponseHeaders(out, response);
99
100 ch = jnlpConnect(computer);
101
102 ch.setProperty(COOKIE_NAME, cookie);
103 }
104
105 private void writeResponseHeaders(PrintWriter out, Properties response) {
106 for (Entry<Object, Object> e : response.entrySet()) {
107 out.println(e.getKey()+": "+e.getValue());
108 }
109 out.println(); // empty line to conclude the response header
110 }
111
112 private String generateCookie() {
113 byte[] cookie = new byte[32];
114 new SecureRandom().nextBytes(cookie);
115 return Util.toHexString(cookie);
116 }
117 }
118
119 private static final Logger LOGGER = Logger.getLogger(JnlpSlaveAgentProtocol2.class.getName());
120
121 private static final String COOKIE_NAME = JnlpSlaveAgentProtocol2.class.getName()+".cookie";
122 }
123