giwrgos_

AuthServerCommunication

Nov 11th, 2019
267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.58 KB | None | 0 0
  1. package l2f.gameserver.network.loginservercon;
  2.  
  3. import l2f.gameserver.Config;
  4. import l2f.gameserver.ThreadPoolManager;
  5. import l2f.gameserver.network.GameClient;
  6. import l2f.gameserver.network.loginservercon.gspackets.AuthRequest;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9.  
  10. import java.io.IOException;
  11. import java.net.InetSocketAddress;
  12. import java.nio.ByteBuffer;
  13. import java.nio.ByteOrder;
  14. import java.nio.channels.CancelledKeyException;
  15. import java.nio.channels.SelectionKey;
  16. import java.nio.channels.Selector;
  17. import java.nio.channels.SocketChannel;
  18. import java.util.*;
  19. import java.util.concurrent.atomic.AtomicBoolean;
  20. import java.util.concurrent.locks.Lock;
  21. import java.util.concurrent.locks.ReadWriteLock;
  22. import java.util.concurrent.locks.ReentrantLock;
  23. import java.util.concurrent.locks.ReentrantReadWriteLock;
  24.  
  25. public class AuthServerCommunication extends Thread
  26. {
  27. private static final Logger _log = LoggerFactory.getLogger(AuthServerCommunication.class);
  28.  
  29. private static final AuthServerCommunication instance = new AuthServerCommunication();
  30.  
  31. public static final AuthServerCommunication getInstance()
  32. {
  33. return instance;
  34. }
  35.  
  36. private final Map<String, GameClient> waitingClients = new HashMap<String, GameClient>();
  37. private final Map<String, GameClient> authedClients = new HashMap<String, GameClient>();
  38.  
  39. private final ReadWriteLock lock = new ReentrantReadWriteLock();
  40. private final Lock readLock = lock.readLock();
  41. private final Lock writeLock = lock.writeLock();
  42.  
  43. private final ByteBuffer readBuffer = ByteBuffer.allocate(64 * 1024).order(ByteOrder.LITTLE_ENDIAN);
  44. private final ByteBuffer writeBuffer = ByteBuffer.allocate(64 * 1024).order(ByteOrder.LITTLE_ENDIAN);
  45.  
  46. private final Queue<SendablePacket> sendQueue = new ArrayDeque<SendablePacket>();
  47. private final Lock sendLock = new ReentrantLock();
  48.  
  49. private final AtomicBoolean isPengingWrite = new AtomicBoolean();
  50.  
  51. private SelectionKey key;
  52. private Selector selector;
  53.  
  54. private boolean shutdown;
  55. private boolean restart;
  56.  
  57. private AuthServerCommunication()
  58. {
  59. try
  60. {
  61. selector = Selector.open();
  62. }
  63. catch (IOException e)
  64. {
  65. _log.error("Error while creating Auth Server Communication!", e);
  66. }
  67. }
  68.  
  69. private void connect() throws IOException
  70. {
  71. _log.info("Connecting to authserver on " + Config.GAME_SERVER_LOGIN_HOST + ":" + Config.GAME_SERVER_LOGIN_PORT);
  72.  
  73. SocketChannel channel = SocketChannel.open();
  74. channel.configureBlocking(false);
  75.  
  76. key = channel.register(selector, SelectionKey.OP_CONNECT);
  77. channel.connect(new InetSocketAddress(Config.GAME_SERVER_LOGIN_HOST, Config.GAME_SERVER_LOGIN_PORT));
  78. }
  79.  
  80. public void sendPacket(SendablePacket packet)
  81. {
  82. if (isShutdown())
  83. return;
  84.  
  85. boolean wakeUp;
  86.  
  87. sendLock.lock();
  88. try
  89. {
  90. sendQueue.add(packet);
  91. wakeUp = enableWriteInterest();
  92. }
  93. catch (CancelledKeyException e)
  94. {
  95. return;
  96. }
  97. finally
  98. {
  99. sendLock.unlock();
  100. }
  101.  
  102. if (wakeUp)
  103. selector.wakeup();
  104. }
  105.  
  106. private boolean disableWriteInterest() throws CancelledKeyException
  107. {
  108. if (isPengingWrite.compareAndSet(true, false))
  109. {
  110. key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
  111. return true;
  112. }
  113. return false;
  114. }
  115.  
  116. private boolean enableWriteInterest() throws CancelledKeyException
  117. {
  118. if (!isPengingWrite.getAndSet(true))
  119. {
  120. key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
  121. return true;
  122. }
  123. return false;
  124. }
  125.  
  126. protected ByteBuffer getReadBuffer()
  127. {
  128. return readBuffer;
  129. }
  130.  
  131. protected ByteBuffer getWriteBuffer()
  132. {
  133. return writeBuffer;
  134. }
  135.  
  136. @Override
  137. public void run()
  138. {
  139. Set<SelectionKey> keys;
  140. Iterator<SelectionKey> iterator;
  141. SelectionKey key;
  142. int opts;
  143.  
  144. while (!shutdown)
  145. {
  146. restart = false;
  147.  
  148. try
  149. {
  150. loop: while(!isShutdown())
  151. {
  152. connect();
  153.  
  154. selector.select(5000L);
  155. keys = selector.selectedKeys();
  156. if (keys.isEmpty())
  157. throw new IOException("Connection timeout.");
  158.  
  159. iterator = keys.iterator();
  160.  
  161. try
  162. {
  163. while (iterator.hasNext())
  164. {
  165. key = iterator.next();
  166. iterator.remove();
  167.  
  168. opts = key.readyOps();
  169.  
  170. switch (opts)
  171. {
  172. case SelectionKey.OP_CONNECT:
  173. connect(key);
  174. break loop;
  175. }
  176. }
  177. }
  178. catch (CancelledKeyException e)
  179. {
  180. // Exit selector loop
  181. break;
  182. }
  183. }
  184.  
  185. loop: while(!isShutdown())
  186. {
  187. selector.select();
  188. keys = selector.selectedKeys();
  189. iterator = keys.iterator();
  190.  
  191. try
  192. {
  193. while (iterator.hasNext())
  194. {
  195. key = iterator.next();
  196. iterator.remove();
  197.  
  198. opts = key.readyOps();
  199.  
  200. switch (opts)
  201. {
  202. case SelectionKey.OP_WRITE:
  203. write(key);
  204. break;
  205. case SelectionKey.OP_READ:
  206. read(key);
  207. break;
  208. case SelectionKey.OP_READ | SelectionKey.OP_WRITE:
  209. write(key);
  210. read(key);
  211. break;
  212. }
  213. }
  214. }
  215. catch (CancelledKeyException e)
  216. {
  217. // Exit selector loop
  218. break loop;
  219. }
  220. }
  221. }
  222. catch (IOException e)
  223. {
  224. _log.error("AuthServer I/O error", e);
  225. }
  226.  
  227. close();
  228.  
  229. try
  230. {
  231. Thread.sleep(5000L);
  232. }
  233. catch (InterruptedException e)
  234. {
  235.  
  236. }
  237. }
  238. }
  239.  
  240. private void read(SelectionKey key) throws IOException
  241. {
  242. final SocketChannel channel = (SocketChannel) key.channel();
  243. final ByteBuffer buf = getReadBuffer();
  244. final int count = channel.read(buf);
  245. if (count == -1)
  246. throw new IOException("End of stream.");
  247.  
  248. if (count == 0)
  249. return;
  250.  
  251. buf.flip();
  252.  
  253. while (tryReadPacket(key, buf));
  254. }
  255.  
  256. private boolean tryReadPacket(SelectionKey key, ByteBuffer buf) throws IOException
  257. {
  258. int pos = buf.position();
  259. // проверяем, хватает ли нам байт для чтения заголовка и не пустого тела пакета
  260. if (buf.remaining() > 2)
  261. {
  262. // получаем ожидаемый размер пакета
  263. int size = buf.getShort() & 0xffff;
  264.  
  265. // проверяем корректность размера
  266. if (size <= 2){ throw new IOException("Incorrect packet size: <= 2"); }
  267.  
  268. //ожидаемый размер тела пакета
  269. size -= 2;
  270.  
  271. // проверяем, хватает ли байт на чтение тела
  272. if (size <= buf.remaining())
  273. {
  274. // apply limit
  275. int limit = buf.limit();
  276. buf.limit(pos + size + 2);
  277.  
  278. ReceivablePacket rp = PacketHandler.handlePacket(buf);
  279.  
  280. if (rp != null)
  281. {
  282. if (rp.read())
  283. ThreadPoolManager.getInstance().execute(rp);
  284. }
  285.  
  286. buf.limit(limit);
  287. buf.position(pos + size + 2);
  288.  
  289. // закончили чтение из буфера, почистим
  290. if (!buf.hasRemaining())
  291. {
  292. buf.clear();
  293. return false;
  294. }
  295.  
  296. return true;
  297. }
  298.  
  299. // не хватает данных на чтение тела пакета, сбрасываем позицию
  300. buf.position(pos);
  301. }
  302.  
  303. buf.compact();
  304.  
  305. return false;
  306. }
  307.  
  308. private void write(SelectionKey key) throws IOException
  309. {
  310. SocketChannel channel = (SocketChannel) key.channel();
  311. ByteBuffer buf = getWriteBuffer();
  312.  
  313. boolean done;
  314.  
  315. sendLock.lock();
  316. try
  317. {
  318. int i = 0;
  319. SendablePacket sp;
  320. while (i++ < 64 && (sp = sendQueue.poll()) != null)
  321. {
  322. final int headerPos = buf.position();
  323. buf.position(headerPos + 2);
  324.  
  325. sp.write();
  326. final int dataSize = buf.position() - headerPos - 2;
  327. if (dataSize == 0)
  328. {
  329. buf.position(headerPos);
  330. continue;
  331. }
  332.  
  333. // prepend header
  334. buf.position(headerPos);
  335. buf.putShort((short) (dataSize + 2));
  336. buf.position(headerPos + dataSize + 2);
  337. }
  338.  
  339. done = sendQueue.isEmpty();
  340. if (done)
  341. disableWriteInterest();
  342. }
  343. finally
  344. {
  345. sendLock.unlock();
  346. }
  347. buf.flip();
  348.  
  349. channel.write(buf);
  350.  
  351. if (buf.remaining() > 0)
  352. {
  353. buf.compact();
  354. done = false;
  355. }
  356. else
  357. {
  358. buf.clear();
  359. }
  360.  
  361. if (!done)
  362. {
  363. if (enableWriteInterest())
  364. selector.wakeup();
  365. }
  366. }
  367.  
  368. private void connect(SelectionKey key) throws IOException
  369. {
  370. final SocketChannel channel = (SocketChannel) key.channel();
  371. channel.finishConnect();
  372.  
  373. key.interestOps(key.interestOps() & ~SelectionKey.OP_CONNECT);
  374. key.interestOps(key.interestOps() | SelectionKey.OP_READ);
  375.  
  376. sendPacket(new AuthRequest());
  377. }
  378.  
  379. private void close()
  380. {
  381. restart = !shutdown;
  382.  
  383. sendLock.lock();
  384. try
  385. {
  386. sendQueue.clear();
  387. }
  388. finally
  389. {
  390. sendLock.unlock();
  391. }
  392.  
  393. readBuffer.clear();
  394. writeBuffer.clear();
  395.  
  396. isPengingWrite.set(false);
  397.  
  398. try
  399. {
  400. if (key != null)
  401. {
  402. key.channel().close();
  403. key.cancel();
  404. }
  405. }
  406. catch (IOException e)
  407. {}
  408.  
  409. writeLock.lock();
  410. try
  411. {
  412. waitingClients.clear();
  413. }
  414. finally
  415. {
  416. writeLock.unlock();
  417. }
  418. }
  419.  
  420. public void shutdown()
  421. {
  422. shutdown = true;
  423. selector.wakeup();
  424. }
  425.  
  426. public boolean isShutdown()
  427. {
  428. return shutdown || restart;
  429. }
  430.  
  431. public void restart()
  432. {
  433. restart = true;
  434. selector.wakeup();
  435. }
  436.  
  437. public GameClient addWaitingClient(GameClient client)
  438. {
  439. writeLock.lock();
  440. try
  441. {
  442. return waitingClients.put(client.getLogin(), client);
  443. }
  444. finally
  445. {
  446. writeLock.unlock();
  447. }
  448. }
  449.  
  450. public GameClient removeWaitingClient(String account)
  451. {
  452. writeLock.lock();
  453. try
  454. {
  455. return waitingClients.remove(account);
  456. }
  457. finally
  458. {
  459. writeLock.unlock();
  460. }
  461. }
  462.  
  463. public GameClient addAuthedClient(GameClient client)
  464. {
  465. writeLock.lock();
  466. try
  467. {
  468. return authedClients.put(client.getLogin(), client);
  469. }
  470. finally
  471. {
  472. writeLock.unlock();
  473. }
  474. }
  475.  
  476. public GameClient removeAuthedClient(String login)
  477. {
  478. writeLock.lock();
  479. try
  480. {
  481. return authedClients.remove(login);
  482. }
  483. finally
  484. {
  485. writeLock.unlock();
  486. }
  487. }
  488.  
  489. public GameClient getAuthedClient(String login)
  490. {
  491. readLock.lock();
  492. try
  493. {
  494. return authedClients.get(login);
  495. }
  496. finally
  497. {
  498. readLock.unlock();
  499. }
  500. }
  501.  
  502. public GameClient removeClient(GameClient client)
  503. {
  504. writeLock.lock();
  505. try
  506. {
  507. if (client.isAuthed())
  508. return authedClients.remove(client.getLogin());
  509. else
  510. return waitingClients.remove(client.getSessionKey());
  511. }
  512. finally
  513. {
  514. writeLock.unlock();
  515. }
  516. }
  517.  
  518. public String[] getAccounts()
  519. {
  520. readLock.lock();
  521. try
  522. {
  523. return authedClients.keySet().toArray(new String[authedClients.size()]);
  524. }
  525. finally
  526. {
  527. readLock.unlock();
  528. }
  529. }
  530. }
Advertisement
Add Comment
Please, Sign In to add comment