PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/VeyoHealth/dcm4che-2.0.27/dcm4che-audit/src/main/java/org/dcm4che2/audit/log4j/net/SyslogAppender2.java

https://bitbucket.org/masoudn/veyohealth
Java | 912 lines | 670 code | 195 blank | 47 comment | 50 complexity | 24b30d10b6f755585c2ca7ab8e321044 MD5 | raw file
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is part of dcm4che, an implementation of DICOM(TM) in
  15. * Java(TM), hosted at http://sourceforge.net/projects/dcm4che.
  16. *
  17. * The Initial Developer of the Original Code is
  18. * Gunter Zeilinger, Huetteldorferstr. 24/10, 1150 Vienna/Austria/Europe.
  19. * Portions created by the Initial Developer are Copyright (C) 2008
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * See listed authors below.
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. package org.dcm4che2.audit.log4j.net;
  39. import java.io.BufferedOutputStream;
  40. import java.io.ByteArrayOutputStream;
  41. import java.io.IOException;
  42. import java.io.OutputStream;
  43. import java.lang.management.ManagementFactory;
  44. import java.net.DatagramPacket;
  45. import java.net.DatagramSocket;
  46. import java.net.InetAddress;
  47. import java.net.InetSocketAddress;
  48. import java.net.Socket;
  49. import java.net.SocketAddress;
  50. import java.net.SocketException;
  51. import java.net.UnknownHostException;
  52. import java.security.KeyStore;
  53. import java.util.Calendar;
  54. import java.util.Locale;
  55. import java.util.StringTokenizer;
  56. import java.util.TimeZone;
  57. import javax.net.SocketFactory;
  58. import javax.net.ssl.SSLContext;
  59. import javax.net.ssl.SSLSocket;
  60. import org.apache.log4j.AppenderSkeleton;
  61. import org.apache.log4j.Level;
  62. import org.apache.log4j.spi.ErrorCode;
  63. import org.apache.log4j.spi.LoggingEvent;
  64. import org.dcm4che2.audit.util.SSLUtils;
  65. /**
  66. * @author Gunter Zeilinger <gunterze@gmail.com>
  67. *
  68. * @version $Revision$ $Date$
  69. * @since Nov 25, 2009
  70. */
  71. public class SyslogAppender2 extends AppenderSkeleton {
  72. private enum Facility {
  73. KERN, // 0 kernel messages
  74. USER, // 1 user-level messages
  75. MAIL, // 2 mail system
  76. DAEMON, // 3 system daemons
  77. AUTH, // 4 security/authorization messages
  78. SYSLOG, // 5 messages generated internally by syslogd
  79. LPR, // 6 line printer subsystem
  80. NEWS, // 7 network news subsystem
  81. UUCP, // 8 UUCP subsystem
  82. CRON, // 9 clock daemon
  83. AUTHPRIV, // 10 security/authorization messages
  84. FTP, // 11 FTP daemon
  85. NTP, // 12 NTP subsystem
  86. AUDIT, // 13 log audit
  87. ALERT, // 14 log alert
  88. CRON2, // 15 clock daemon (note 2)
  89. LOCAL0, // 16 local use 0 (local0)
  90. LOCAL1, // 17 local use 1 (local1)
  91. LOCAL2, // 18 local use 2 (local2)
  92. LOCAL3, // 19 local use 3 (local3)
  93. LOCAL4, // 20 local use 4 (local4)
  94. LOCAL5, // 21 local use 5 (local5)
  95. LOCAL6, // 22 local use 6 (local6)
  96. LOCAL7 // 23 local use 7 (local7)
  97. }
  98. private enum Severity {
  99. EMERGENCY, // 0 Emergency: system is unusable
  100. ALERT, // 1 Alert: action must be taken immediately
  101. CRITICAL, // 2 Critical: critical conditions
  102. ERROR, // 3 Error: error conditions
  103. WARNING, // 4 Warning: warning conditions
  104. NOTICE, // 5 Notice: normal but significant condition
  105. INFORMATIONAL, // 6 Informational: informational messages
  106. DEBUG // 7 Debug: debug-level messages
  107. }
  108. private enum Protocol {
  109. UDP {
  110. @Override
  111. void init(SyslogAppender2 app) {
  112. app.initDatagramSocket();
  113. }
  114. @Override
  115. void send(SyslogAppender2 app) throws IOException {
  116. app.sendDatagramPacket();
  117. }
  118. @Override
  119. void close(SyslogAppender2 app) {
  120. app.closeDatagramSocket();
  121. }
  122. },
  123. TCP {
  124. @Override
  125. void init(SyslogAppender2 app) {
  126. app.initSocketFactory();
  127. }
  128. @Override
  129. void send(SyslogAppender2 app) throws IOException {
  130. app.writeToSocket();
  131. }
  132. @Override
  133. void close(SyslogAppender2 app) {
  134. app.closeSocket();
  135. }
  136. };
  137. abstract void init(SyslogAppender2 app);
  138. abstract void send(SyslogAppender2 app) throws IOException;
  139. abstract void close(SyslogAppender2 app);
  140. }
  141. private String host = "localhost";
  142. private int port = 514;
  143. private String bindAddress = "0.0.0.0";
  144. private int localPort = 0;
  145. private Protocol protocol = Protocol.UDP;
  146. private int sendBuffer = 0;
  147. private int tcpConnectTimeout = 300;
  148. private int tcpRetryInterval = 60000;
  149. private boolean tcpNoDelay = true;
  150. private boolean tlsEnabled = false;
  151. private String tlsProtocol = "TLSv1";
  152. private String[] tlsCiphers = { "TLS_RSA_WITH_AES_128_CBC_SHA" };
  153. private String keyStoreFile;
  154. private char[] keyStorePass;
  155. private char[] keyPass;
  156. private String keyStoreType = "JKS";
  157. private String trustStoreFile;
  158. private char[] trustStorePass;
  159. private String trustStoreType = "JKS";
  160. private Facility syslogFacility = Facility.AUTHPRIV;
  161. private Severity fatalSeverity = Severity.EMERGENCY;
  162. private Severity errorSeverity = Severity.ERROR;
  163. private Severity warnSeverity = Severity.WARNING;
  164. private Severity infoSeverity = Severity.NOTICE;
  165. private Severity debugSeverity = Severity.DEBUG;
  166. private String applicationName;
  167. private String messageID;
  168. private boolean timestampInUTC = false;
  169. private boolean prefixMessageWithBOM = true;
  170. private String hostName;
  171. private String processID;
  172. private Calendar calendar;
  173. private Buffer buf = new Buffer();
  174. private SocketAddress bindaddr;
  175. private SocketAddress addr;
  176. private DatagramSocket ds;
  177. private SocketFactory socketFactory;
  178. private Socket sock;
  179. private OutputStream sockout;
  180. private long retryConnectAt;
  181. public String getHost() {
  182. return host;
  183. }
  184. public void setHost(String host) {
  185. this.host = host;
  186. }
  187. public int getPort() {
  188. return port;
  189. }
  190. public void setPort(int port) {
  191. this.port = port;
  192. }
  193. public String getBindAddress() {
  194. return bindAddress;
  195. }
  196. public void setBindAddress(String bindAddress) {
  197. this.bindAddress = bindAddress;
  198. }
  199. public int getLocalPort() {
  200. return localPort;
  201. }
  202. public void setLocalPort(int localPort) {
  203. this.localPort = localPort;
  204. }
  205. public String getProtocol() {
  206. return protocol.toString();
  207. }
  208. public void setProtocol(String protocol) {
  209. this.protocol = Protocol.valueOf(protocol.toUpperCase());
  210. }
  211. public int getSendBuffer() {
  212. return sendBuffer;
  213. }
  214. public void setSendBuffer(int sendBuffer) {
  215. this.sendBuffer = sendBuffer;
  216. }
  217. public int getTcpConnectTimeout() {
  218. return tcpConnectTimeout;
  219. }
  220. public void setTcpConnectTimeout(int tcpConnectTimeout) {
  221. this.tcpConnectTimeout = tcpConnectTimeout;
  222. }
  223. public int getTcpRetryInterval() {
  224. return tcpRetryInterval;
  225. }
  226. public void setTcpRetryInterval(int tcpRetryInterval) {
  227. this.tcpRetryInterval = tcpRetryInterval;
  228. }
  229. public boolean isTcpNoDelay() {
  230. return tcpNoDelay;
  231. }
  232. public void setTcpNoDelay(boolean tcpNoDelay) {
  233. this.tcpNoDelay = tcpNoDelay;
  234. }
  235. public boolean isTlsEnabled() {
  236. return tlsEnabled;
  237. }
  238. public void setTlsEnabled(boolean tlsEnabled) {
  239. this.tlsEnabled = tlsEnabled;
  240. }
  241. public String getTlsProtocol() {
  242. return tlsProtocol;
  243. }
  244. public void setTlsProtocol(String tlsProtocol) {
  245. this.tlsProtocol = tlsProtocol;
  246. }
  247. public String getTlsCiphers() {
  248. return toString(tlsCiphers);
  249. }
  250. public void setTlsCiphers(String tlsCiphers) {
  251. this.tlsCiphers = split(tlsCiphers);
  252. }
  253. private static String toString(String[] ss) {
  254. if (ss.length == 0)
  255. return "";
  256. if (ss.length == 1)
  257. return ss[0];
  258. int iMax = ss.length - 1;
  259. StringBuilder b = new StringBuilder();
  260. for (int i = 0; ; i++) {
  261. b.append(String.valueOf(ss[i]));
  262. if (i == iMax)
  263. return b.toString();
  264. b.append(", ");
  265. }
  266. }
  267. private static String[] split(String s) {
  268. StringTokenizer stk = new StringTokenizer(s, " ,");
  269. int count = stk.countTokens();
  270. if (count == 0)
  271. throw new IllegalArgumentException(s);
  272. String[] ss = new String[count];
  273. for (int i = 0; i < ss.length; i++)
  274. ss[i] = stk.nextToken();
  275. return ss;
  276. }
  277. public String getKeyStoreFile() {
  278. return keyStoreFile;
  279. }
  280. public void setKeyStoreFile(String keyStoreFile) {
  281. this.keyStoreFile = keyStoreFile;
  282. }
  283. public String getKeyStorePass() {
  284. return new String(keyStorePass);
  285. }
  286. public void setKeyStorePass(String keyStorePass) {
  287. this.keyStorePass = keyStorePass.toCharArray();
  288. }
  289. public String getKeyPass() {
  290. return new String(keyPass);
  291. }
  292. public void setKeyPass(String keyPass) {
  293. this.keyPass = keyPass.toCharArray();
  294. }
  295. public String getKeyStoreType() {
  296. return keyStoreType;
  297. }
  298. public void setKeyStoreType(String keyStoreType) {
  299. this.keyStoreType = keyStoreType;
  300. }
  301. public String getTrustStoreFile() {
  302. return trustStoreFile;
  303. }
  304. public void setTrustStoreFile(String trustStoreFile) {
  305. this.trustStoreFile = trustStoreFile;
  306. }
  307. public String getTrustStorePass() {
  308. return new String(trustStorePass);
  309. }
  310. public void setTrustStorePass(String trustStorePass) {
  311. this.trustStorePass = trustStorePass.toCharArray();
  312. }
  313. public String getTrustStoreType() {
  314. return trustStoreType;
  315. }
  316. public void setTrustStoreType(String trustStoreType) {
  317. this.trustStoreType = trustStoreType;
  318. }
  319. public String getSyslogFacility() {
  320. return syslogFacility.toString();
  321. }
  322. public void setSyslogFacility(String facility) {
  323. this.syslogFacility = Facility.valueOf(facility.toUpperCase());
  324. }
  325. public String getFatalSeverity() {
  326. return fatalSeverity.toString();
  327. }
  328. public void setFatalSeverity(String severity) {
  329. this.fatalSeverity = Severity.valueOf(severity.toUpperCase());
  330. }
  331. public String getErrorSeverity() {
  332. return errorSeverity.toString();
  333. }
  334. public void setErrorSeverity(String severity) {
  335. this.errorSeverity = Severity.valueOf(severity.toUpperCase());
  336. }
  337. public String getWarnSeverity() {
  338. return warnSeverity.toString();
  339. }
  340. public void setWarnSeverity(String severity) {
  341. this.warnSeverity = Severity.valueOf(severity.toUpperCase());
  342. }
  343. public String getInfoSeverity() {
  344. return infoSeverity.toString();
  345. }
  346. public void setInfoSeverity(String severity) {
  347. this.infoSeverity = Severity.valueOf(severity.toUpperCase());
  348. }
  349. public String getDebugSeverity() {
  350. return debugSeverity.toString();
  351. }
  352. public void setDebugSeverity(String severity) {
  353. this.debugSeverity = Severity.valueOf(severity.toUpperCase());
  354. }
  355. public String getHostName() {
  356. return hostName;
  357. }
  358. public void setHostName(String hostname) {
  359. this.hostName = hostname.length() > 0 ? hostname : null;
  360. }
  361. public String getApplicationName() {
  362. return applicationName;
  363. }
  364. public void setApplicationName(String applicationName) {
  365. this.applicationName = applicationName;
  366. }
  367. public String getMessageID() {
  368. return messageID;
  369. }
  370. public void setMessageID(String messageID) {
  371. this.messageID = messageID;
  372. }
  373. public boolean isTimestampInUTC() {
  374. return timestampInUTC;
  375. }
  376. public void setTimestampInUTC(boolean timestampInUTC) {
  377. this.timestampInUTC = timestampInUTC;
  378. }
  379. public boolean isPrefixMessageWithBOM() {
  380. return prefixMessageWithBOM;
  381. }
  382. public void setPrefixMessageWithBOM(boolean prefixMessageWithBOM) {
  383. this.prefixMessageWithBOM = prefixMessageWithBOM;
  384. }
  385. @Override
  386. public void activateOptions() {
  387. initCalendar();
  388. initProcessID();
  389. initHostName();
  390. initConnection();
  391. }
  392. private void initCalendar() {
  393. calendar = timestampInUTC
  394. ? Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ENGLISH)
  395. : Calendar.getInstance(Locale.ENGLISH);
  396. }
  397. private void initProcessID() {
  398. String s = ManagementFactory.getRuntimeMXBean().getName();
  399. int atPos = s.indexOf('@');
  400. processID = atPos > 0 ? s.substring(0, atPos) : s;
  401. }
  402. private void initHostName() {
  403. if (hostName == null)
  404. try {
  405. hostName = InetAddress.getLocalHost().getCanonicalHostName();
  406. } catch (UnknownHostException e) {
  407. errorHandler.error("Failed to detect local host name", e,
  408. ErrorCode.GENERIC_FAILURE);
  409. }
  410. }
  411. private void initConnection() {
  412. bindaddr = new InetSocketAddress(bindAddress, localPort);
  413. addr = new InetSocketAddress(host, port);
  414. protocol.init(this);
  415. }
  416. @Override
  417. protected void append(LoggingEvent event) {
  418. try {
  419. buf.reset();
  420. writeHeader(event);
  421. writeSP();
  422. writeStructuredData();
  423. writeSP();
  424. if (prefixMessageWithBOM)
  425. writeBOM();
  426. writeString(event.getRenderedMessage());
  427. protocol.send(this);
  428. } catch (IOException e) {
  429. errorHandler.error("Failed to emit message by " + protocol
  430. + " connection to " + host + ":" + port, e,
  431. ErrorCode.WRITE_FAILURE, event);
  432. }
  433. }
  434. private void writeHeader(LoggingEvent event) {
  435. writePRI(event.getLevel());
  436. writeVersion();
  437. writeSP();
  438. writeTimeStamp(event.timeStamp);
  439. writeSP();
  440. writeString(hostName);
  441. writeSP();
  442. writeString(applicationName);
  443. writeSP();
  444. writeString(processID);
  445. writeSP();
  446. writeString(messageID);
  447. }
  448. private void writeVersion() {
  449. buf.write('1');
  450. }
  451. private void writeStructuredData() {
  452. writeNIL(); // no structured data
  453. }
  454. private void writeSP() {
  455. buf.write(' ');
  456. }
  457. private void writeNIL() {
  458. buf.write('-');
  459. }
  460. private void writePRI(Level level) {
  461. buf.write('<');
  462. writeNumber(buf, prival(level));
  463. buf.write('>');
  464. }
  465. private int prival(Level level) {
  466. return (syslogFacility.ordinal() << 3) | severityOf(level).ordinal();
  467. }
  468. private Severity severityOf(Level level) {
  469. if (level.isGreaterOrEqual(Level.FATAL)) {
  470. return fatalSeverity ;
  471. } else if (level.isGreaterOrEqual(Level.ERROR)) {
  472. return errorSeverity;
  473. } else if (level.isGreaterOrEqual(Level.WARN)) {
  474. return warnSeverity;
  475. } else if (level.isGreaterOrEqual(Level.INFO)) {
  476. return infoSeverity;
  477. } else {
  478. return debugSeverity;
  479. }
  480. }
  481. private void writeTimeStamp(long time) {
  482. calendar.setTimeInMillis(time);
  483. writeNumber(buf, calendar.get(Calendar.YEAR), 4);
  484. buf.write('-');
  485. writeNumber(buf, calendar.get(Calendar.MONTH) + 1, 2);
  486. buf.write('-');
  487. writeNumber(buf, calendar.get(Calendar.DAY_OF_MONTH), 2);
  488. buf.write('T');
  489. writeNumber(buf, calendar.get(Calendar.HOUR_OF_DAY), 2);
  490. buf.write(':');
  491. writeNumber(buf, calendar.get(Calendar.MINUTE), 2);
  492. buf.write(':');
  493. writeNumber(buf, calendar.get(Calendar.SECOND), 2);
  494. buf.write('.');
  495. writeNumber(buf, calendar.get(Calendar.MILLISECOND), 3);
  496. if (timestampInUTC)
  497. buf.write('Z');
  498. else
  499. writeTimezone((calendar.get(Calendar.ZONE_OFFSET)
  500. + calendar.get(Calendar.DST_OFFSET)) / 60000);
  501. }
  502. private void writeTimezone(int tzoff) {
  503. if (tzoff < 0) {
  504. tzoff = -tzoff;
  505. buf.write('-');
  506. } else {
  507. buf.write('+');
  508. }
  509. int hh = tzoff / 60;
  510. int mm = tzoff - (hh << 6) + (hh << 2) ; // mm = tzoff - hh * 60
  511. writeNumber(buf, hh, 2);
  512. buf.write(':');
  513. writeNumber(buf, mm, 2);
  514. }
  515. private void writeString(String s) {
  516. if (s == null)
  517. writeNIL();
  518. else
  519. try {
  520. buf.write(s.getBytes("UTF-8"));
  521. } catch (IOException e) {
  522. throw new AssertionError(e);
  523. }
  524. }
  525. private void writeNumber(OutputStream out, int d) {
  526. writeNumber(out, d, stringSize(d));
  527. }
  528. private static int stringSize(int d) {
  529. if (d < 10)
  530. return 1;
  531. if (d < 100)
  532. return 2;
  533. if (d < 1000)
  534. return 3;
  535. if (d < 10000)
  536. return 4;
  537. d /= 10000;
  538. int n = 5;
  539. while (d > 9) {
  540. d /= 10;
  541. n++;
  542. }
  543. return n;
  544. }
  545. private void writeNumber(OutputStream out, int d, int w) {
  546. int q, n;
  547. switch (w) {
  548. case 4:
  549. writeDigit(out, q = d / 1000);
  550. d -= (q << 10) - (q << 4) - (q << 3); // d -= q * 1000
  551. //$FALL-THROUGH$
  552. case 3:
  553. writeDigit(out, q = d / 100);
  554. d -= (q << 7) + (q << 2) - (q << 5); // d -= q * 100
  555. //$FALL-THROUGH$
  556. case 2:
  557. writeDigit(out, q = d / 10);
  558. d -= (q << 3) + (q << 1); // d -= q * 10
  559. //$FALL-THROUGH$
  560. case 1:
  561. writeDigit(out, d);
  562. break;
  563. default:
  564. n = 10000;
  565. w -= 4;
  566. while (--w > 0)
  567. n = (n << 3) + (n << 1); // n *= 10
  568. while (n > 1) {
  569. writeDigit(out, q = d / n);
  570. d -= q * n;
  571. n /= 10;
  572. }
  573. writeDigit(out, d);
  574. }
  575. }
  576. private static final int[] DIGITS = {
  577. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
  578. private void writeDigit(OutputStream out, int d) {
  579. try {
  580. out.write(DIGITS[d]);
  581. } catch (IOException e) {
  582. // should never happen because writes always in byte buffer
  583. throw new AssertionError(e);
  584. }
  585. }
  586. private void writeBOM() {
  587. buf.write(0xEF);
  588. buf.write(0xBB);
  589. buf.write(0xBF);
  590. }
  591. @Override
  592. public void close() {
  593. synchronized (this) {
  594. if (closed)
  595. return;
  596. closed = true;
  597. }
  598. protocol.close(this);
  599. }
  600. @Override
  601. public boolean requiresLayout() {
  602. return false;
  603. }
  604. private class Buffer extends ByteArrayOutputStream {
  605. void writeTo(DatagramSocket ds) throws IOException {
  606. ds.send(new DatagramPacket(buf, count, addr));
  607. }
  608. }
  609. private void initDatagramSocket() {
  610. try {
  611. this.ds = new DatagramSocket(bindaddr);
  612. } catch (SocketException e) {
  613. errorHandler.error("Failed to create datagram socket bound to "
  614. + bindaddr, e, ErrorCode.GENERIC_FAILURE);
  615. return;
  616. }
  617. if (sendBuffer > 0)
  618. try {
  619. ds.setSendBufferSize(sendBuffer);
  620. } catch (SocketException e) {
  621. errorHandler.error("Failed to set SO_SNDBUF option to "
  622. + sendBuffer + " for datagram socket " + ds,
  623. e, ErrorCode.GENERIC_FAILURE);
  624. }
  625. }
  626. private void sendDatagramPacket() throws IOException {
  627. if (buf != null)
  628. buf.writeTo(ds);
  629. }
  630. private void closeDatagramSocket() {
  631. ds.close();
  632. ds = null;
  633. }
  634. private void initSocketFactory() {
  635. if (tlsEnabled)
  636. try {
  637. socketFactory = getSSLContext().getSocketFactory();
  638. } catch (Exception e) {
  639. errorHandler.error(
  640. "Failed to configure TLS context from key store "
  641. + keyStoreFile + " and trust store " + trustStoreFile,
  642. e, ErrorCode.GENERIC_FAILURE);
  643. }
  644. else
  645. socketFactory = SocketFactory.getDefault();
  646. }
  647. private SSLContext getSSLContext() throws Exception {
  648. KeyStore keystore = SSLUtils.loadKeyStore(
  649. keyStoreFile, keyStorePass, keyStoreType);
  650. KeyStore truststore = SSLUtils.loadKeyStore(
  651. trustStoreFile, trustStorePass, trustStoreType);
  652. return SSLUtils.getSSLContext(keystore, keyPass, truststore, null);
  653. }
  654. private void writeToSocket() throws IOException {
  655. if (socketFactory == null)
  656. return;
  657. if (sock != null) {
  658. try {
  659. doWriteToSocket();
  660. return;
  661. } catch (IOException e) {
  662. close();
  663. retryConnectAt = 0;
  664. }
  665. }
  666. if (retryConnectAt > 0
  667. && retryConnectAt > System.currentTimeMillis()) {
  668. return;
  669. }
  670. try {
  671. connect();
  672. } catch (IOException e) {
  673. retryConnectAt = System.currentTimeMillis()
  674. + tcpRetryInterval;
  675. throw e;
  676. }
  677. doWriteToSocket();
  678. }
  679. private void connect() throws IOException {
  680. Socket tmp = null;
  681. try {
  682. tmp = socketFactory.createSocket();
  683. tmp.setTcpNoDelay(tcpNoDelay);
  684. if (sendBuffer > 0)
  685. tmp.setSendBufferSize(sendBuffer);
  686. tmp.bind(bindaddr);
  687. if (tmp instanceof SSLSocket) {
  688. SSLSocket sslsock = (SSLSocket) tmp;
  689. sslsock.setEnabledProtocols(new String[] { tlsProtocol });
  690. sslsock.setEnabledCipherSuites(tlsCiphers);
  691. }
  692. tmp.connect(addr, tcpConnectTimeout);
  693. if (tmp instanceof SSLSocket) {
  694. SSLSocket sslsock = (SSLSocket) tmp;
  695. sslsock.startHandshake();
  696. }
  697. sockout = new BufferedOutputStream(tmp.getOutputStream());
  698. sock = tmp;
  699. tmp = null;
  700. } finally {
  701. if (tmp != null)
  702. try { tmp.close(); } catch (Exception ignore) { /* ignore */ }
  703. }
  704. }
  705. private void doWriteToSocket() throws IOException {
  706. writeNumber(sockout, buf.size());
  707. sockout.write(' ');
  708. buf.writeTo(sockout);
  709. sockout.flush();
  710. }
  711. private void closeSocket() {
  712. try { sockout.close(); } catch (Exception ignore) { /* ignore */ }
  713. try { sock.close(); } catch (Exception ignore) { /* ignore */ }
  714. sockout = null;
  715. sock = null;
  716. }
  717. }