/minecraft_server/netapi/NetPacketThread.java

https://github.com/Clintonio/NetAPI · Java · 327 lines · 141 code · 30 blank · 156 comment · 19 complexity · 19be0a9e640b2310064c895cc135e5d8 MD5 · raw file

  1. package netapi;
  2. import netapi.packet.NetPacket;
  3. import netapi.packet.NetP2PPacket;
  4. import java.net.Socket;
  5. import java.net.SocketTimeoutException;
  6. import java.io.ObjectInputStream;
  7. import java.io.ObjectOutputStream;
  8. import java.io.BufferedInputStream;
  9. import java.io.IOException;
  10. import java.util.concurrent.ConcurrentLinkedQueue;
  11. import java.util.logging.Logger;
  12. /**
  13. * A thread that handles all packet handling
  14. * from server to client. A different build exists
  15. * for client and server
  16. *
  17. * @author Clinton Alexander
  18. * @version 0.1
  19. * @since 0.1
  20. */
  21. public class NetPacketThread extends Thread {
  22. /**
  23. * The current send queue
  24. *
  25. * @since 0.1
  26. */
  27. private ConcurrentLinkedQueue<NetPacket> sendQueue = new ConcurrentLinkedQueue<NetPacket>();
  28. /**
  29. * The output stream for this thread
  30. *
  31. * @since 0.1
  32. */
  33. private ObjectOutputStream oos = null;
  34. /**
  35. * The input stream for this thread
  36. *
  37. * @since 0.1
  38. */
  39. private ObjectInputStream ois = null;
  40. /**
  41. * Whether this current thread is alive
  42. *
  43. * @since 0.1
  44. */
  45. private boolean alive = true;
  46. /**
  47. * True if sender thread, false if receiver
  48. *
  49. * @since 0.1
  50. */
  51. private boolean sender = true;
  52. /**
  53. * Name of user sending data from this thread
  54. *
  55. * @since 0.1
  56. */
  57. private String senderName;
  58. /**
  59. * The logger we are logging with
  60. *
  61. * @since 0.1
  62. */
  63. private Logger log = Logger.getLogger("Minecraft");
  64. /**
  65. * The socket we are connected to
  66. *
  67. * @since 0.1
  68. */
  69. private Socket socket;
  70. /**
  71. * Called at creation of a new server
  72. *
  73. * @since 0.1
  74. * @throws IOException If cannot connect data stream
  75. * @param socket The socket we are connecte to
  76. * @param mode True if a sender thread, false if receiver
  77. */
  78. public NetPacketThread(Socket socket, boolean mode) {
  79. sender = mode;
  80. this.socket = socket;
  81. }
  82. /**
  83. * Called at creation of a new server
  84. *
  85. * @since 0.1
  86. * @param socket The socket we are connecte to
  87. * @param oos The sending data stream
  88. * @param mode True if a sender thread, false if receiver
  89. */
  90. public NetPacketThread(Socket socket, ObjectOutputStream oos) {
  91. sender = true;
  92. this.socket = socket;
  93. this.oos = oos;
  94. }
  95. /**
  96. * Called at creation of a new server
  97. *
  98. * @since 0.1
  99. * @param socket The socket we are connecte to
  100. * @param ois The receiving data stream
  101. * @param mode True if a sender thread, false if receiver
  102. */
  103. public NetPacketThread(Socket socket, ObjectInputStream ois) {
  104. sender = false;
  105. this.socket = socket;
  106. this.ois = ois;
  107. }
  108. //===============
  109. // Setters/ Adders
  110. //===============
  111. /**
  112. * Send the given packet
  113. *
  114. * @since 0.1
  115. * @param packet New packet to send
  116. */
  117. public void send(NetPacket packet) {
  118. sendQueue.add(packet);
  119. }
  120. /**
  121. * Set the username for sending data
  122. *
  123. * @since 0.1
  124. * @param username Username of this sender
  125. */
  126. public void setSenderName(String username) {
  127. this.senderName = username;
  128. }
  129. //===============
  130. // Data flow and execution
  131. //===============
  132. /**
  133. * Execution of this net thread
  134. *
  135. * @since 0.1
  136. */
  137. public void run() {
  138. try {
  139. if(!sender && (ois == null)) {
  140. log.info("(NetAPI) Packet reading thread opening");
  141. ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
  142. } else if(sender && (oos == null)) {
  143. log.info("(NetAPI) Packet writing thread opening");
  144. oos = new ObjectOutputStream(socket.getOutputStream());
  145. }
  146. while(alive) {
  147. if(sender) {
  148. sendNewPackets();
  149. } else {
  150. receiveNewPackets();
  151. }
  152. try {
  153. Thread.sleep(100);
  154. } catch (InterruptedException e) {
  155. // Ignore
  156. }
  157. }
  158. } catch (IOException e) {
  159. log.info("(NetAPI) Connection failed to stream " + e.getMessage());
  160. }
  161. log.info("(NetAPI) Closing packet thread");
  162. }
  163. /**
  164. * Send all new packets on the packet queue
  165. *
  166. * @since 0.1
  167. */
  168. private void sendNewPackets() {
  169. while(alive && (sendQueue.size() != 0)) {
  170. log.info("(NetAPI) Sending packet");
  171. NetPacket send = sendQueue.peek();
  172. try {
  173. oos.writeObject(send);
  174. sendQueue.poll();
  175. } catch (IOException e) {
  176. System.err.println("(NetAPI) Could not send packet: " + e.getMessage());
  177. }
  178. }
  179. }
  180. /**
  181. * Receive all new packets on the packet queue
  182. *
  183. * @since 0.1
  184. */
  185. private void receiveNewPackets() {
  186. log.info("(NetAPI) Packet thread in receive mode");
  187. Object in = null;
  188. try {
  189. while(alive) {
  190. try {
  191. in = ois.readObject();
  192. log.info("(NetAPI) Packet received");
  193. // P2P packets are ignored by the server
  194. if(in instanceof NetP2PPacket) {
  195. NetP2PPacket packet = (NetP2PPacket) in;
  196. log.info("(NetAPI) Received a P2P Packet: " + packet.getClass().getName());
  197. processP2PPacket(packet);
  198. // P2S packets are controlled by the server
  199. } else if(in instanceof NetPacket) {
  200. NetPacket packet = (NetPacket) in;
  201. processPacket(packet);
  202. }
  203. } catch (SocketTimeoutException e) {
  204. // Ignore
  205. }
  206. }
  207. } catch (IOException e) {
  208. log.info("(NetAPI) IOException in receiving: " + e.getMessage());
  209. } catch (ClassNotFoundException e) {
  210. log.info("(NetAPI) Could not find class: " + e.getMessage());
  211. }
  212. log.info("(NetAPI) Packet thread receving stopped");
  213. }
  214. /**
  215. * Process a regular packet
  216. *
  217. * @param packet Packet to handle
  218. */
  219. private void processPacket(NetPacket packet) {
  220. packet.setSender(senderName);
  221. NetPacketHandler[] handlers = NetAPI.getHandlers(packet);
  222. for(NetPacketHandler handler : handlers) {
  223. // To avoid a handler locking up the receiver thread
  224. // We will shove them into a temporary thread
  225. HandlerThread p = new HandlerThread(handler, packet);
  226. p.start();
  227. handler.handle(packet);
  228. }
  229. }
  230. /**
  231. * Process an incoming P2P packet and send it on to
  232. * any real peers
  233. *
  234. * @param packet Packet to send
  235. */
  236. private void processP2PPacket(NetP2PPacket packet) {
  237. packet.setSender(senderName);
  238. NetAPI.sendPacketToPlayers(packet);
  239. }
  240. //===============
  241. // Thread control methods
  242. //===============
  243. /**
  244. * Called at server close time
  245. *
  246. * @since 0.1
  247. */
  248. public void stopThread() {
  249. log.info("(NetAPI) Stopping net packet thread");
  250. alive = false;
  251. try {
  252. if(oos != null) {
  253. oos.close();
  254. }
  255. if(ois != null) {
  256. ois.close();
  257. }
  258. } catch (IOException e) {
  259. // Why the hell is that being thrown here? Doesn't matter.
  260. }
  261. }
  262. /**
  263. * A temporary packet handling thread to avoid locking the main
  264. * net packet thread
  265. *
  266. * @author Clinton Alexander
  267. * @since 0.1
  268. */
  269. private class HandlerThread extends Thread {
  270. /**
  271. * The handler for this thread
  272. *
  273. * @since 0.1
  274. */
  275. private NetPacketHandler handler;
  276. /**
  277. * The packet for this thread
  278. *
  279. * @since 0.1
  280. */
  281. private NetPacket packet;
  282. /**
  283. * Create the handler thread
  284. *
  285. * @since 0.1
  286. * @param handler Handler we are handling with
  287. * @param packet Packet to handler
  288. */
  289. public HandlerThread(NetPacketHandler handler, NetPacket packet) {
  290. this.packet = packet;
  291. this.handler = handler;
  292. }
  293. public void run() {
  294. handler.handle(packet);
  295. }
  296. }
  297. }