PageRenderTime 71ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/freecs-1.3.20100406/src/freecs/core/ConnectionBuffer.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 363 lines | 293 code | 28 blank | 42 comment | 139 complexity | db65bdd030b62da135dd99e989ca1249 MD5 | raw file
  1. /**
  2. * Copyright (C) 2003 Manfred Andres
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. package freecs.core;
  19. import freecs.*;
  20. import freecs.content.*;
  21. import freecs.interfaces.*;
  22. import freecs.util.ObjectBuffer;
  23. import java.nio.ByteBuffer;
  24. import java.nio.channels.SelectionKey;
  25. import java.nio.channels.SocketChannel;
  26. import freecs.util.TrafficMonitor;
  27. import java.net.InetAddress;
  28. /**
  29. * gets attached to the keys reading from a nonblocking channel
  30. * stores the raw request in a buffer. if the request is finished, parse gets
  31. * called which in turn decides which requestobject to use for this requst
  32. * and suplies this RequestObject to the next available RequestEvaluator
  33. */
  34. public class ConnectionBuffer {
  35. private volatile User u;
  36. private int src;
  37. private ByteBuffer buf;
  38. private ByteBuffer tBuf = null;
  39. public ByteBuffer rBuf = ByteBuffer.allocate (Server.srv.READBUFFER_SIZE);
  40. private SelectionKey sk;
  41. private String ts;
  42. private ObjectBuffer writeBuffer = new ObjectBuffer (Server.srv.INITIAL_RESPONSE_QUEUE);
  43. private volatile boolean valid=true;
  44. public Connection conn;
  45. private StringBuffer lsb = new StringBuffer();
  46. private static final int GET = 1;
  47. private static final int POST= 2;
  48. private int reqType = 0;
  49. private int so = 0;
  50. private int cStart = -1;
  51. private int cLength = -1;
  52. public volatile IRequest currentRequest;
  53. private boolean reading=false;
  54. private volatile long closeWhen=System.currentTimeMillis() + Server.srv.KEEP_ALIVE_TIMEOUT;
  55. public ConnectionBuffer (int src) {
  56. this.src = src;
  57. buf = ByteBuffer.allocate(Server.srv.READBUFFER_SIZE);
  58. if (Server.TRACE_CREATE_AND_FINALIZE)
  59. Server.log (this, "++++++++++++++++++++++++++++++++++++++++CREATE", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
  60. }
  61. /**
  62. * appends to the incomplete request and checks if it has completed
  63. * if the request is complete, it will be returned. NULL will be returned
  64. * on the other hand.
  65. * FIXME: has to get more modular to support different protocols
  66. * @return IRequst The full request || null if incomplete
  67. */
  68. public IRequest append () throws Exception {
  69. boolean parse = false;
  70. synchronized (this) {
  71. reading=true;
  72. rBuf.flip();
  73. if (this.buf.remaining () < rBuf.remaining ()) {
  74. ByteBuffer tbuf = ByteBuffer.allocate (this.buf.position () + rBuf.remaining ());
  75. this.buf.flip ();
  76. tbuf.put(this.buf);
  77. this.buf = tbuf;
  78. }
  79. this.buf.put(rBuf);
  80. rBuf.clear ();
  81. if (reqType == 0 && this.buf.position () > 4) {
  82. if (this.buf.get(0) == 'P' && this.buf.get(1) == 'O' && this.buf.get(2) == 'S' && this.buf.get(3) == 'T') {
  83. reqType = POST;
  84. } else if (this.buf.get(0) == 'G' && this.buf.get(1) == 'E' && this.buf.get(2) == 'T') {
  85. reqType = GET;
  86. } else {
  87. this.addLog("HEADER-INVALID");
  88. this.invalidate();
  89. reading=false;
  90. return null;
  91. }
  92. }
  93. if (reqType == GET) {
  94. if (this.buf.position() > 4096) {
  95. this.addLog("HEADER>4096bytes");
  96. this.invalidate();
  97. reading=false;
  98. return null;
  99. }
  100. if (this.buf.position () > 10
  101. && this.buf.get (this.buf.position () - 4) == '\r'
  102. && this.buf.get (this.buf.position () - 3) == '\n'
  103. && this.buf.get (this.buf.position () - 2) == '\r'
  104. && this.buf.get (this.buf.position () - 1) == '\n') {
  105. parse = true;
  106. }
  107. } else if (reqType == POST) {
  108. if (cLength == -1) {
  109. for (; so < this.buf.position () - 15; so++) {
  110. if (so > 4096
  111. || (this.buf.get(so) == '\r'
  112. && this.buf.get(so+1) == '\n'
  113. && this.buf.get(so+2) == '\r'
  114. && this.buf.get(so+3) == '\n')) {
  115. this.addLog("HEADER-INVALID");
  116. this.invalidate();
  117. reading=false;
  118. return null;
  119. }
  120. if (this.buf.get(so) == 'C' && this.buf.get(so+1) == 'o'
  121. && this.buf.get(so+2) == 'n' && this.buf.get(so+3) == 't'
  122. && this.buf.get(so+4) == 'e' && this.buf.get(so+5) == 'n'
  123. && this.buf.get(so+6) == 't' && this.buf.get(so+7) == '-'
  124. && (this.buf.get(so+8) == 'L' || this.buf.get(so+8) == 'l')
  125. && this.buf.get(so+9) == 'e' && this.buf.get(so+10) == 'n'
  126. && this.buf.get(so+11) == 'g' && this.buf.get(so+12) == 't'
  127. && this.buf.get(so+13) == 'h' && this.buf.get(so+14) == ':') {
  128. int cso = so + 14;
  129. if (cso >= this.buf.capacity ()) return null;
  130. while ((this.buf.get(cso) < 48 || this.buf.get(cso) > 57)) {
  131. if (cso >= this.buf.capacity ()) return null;
  132. cso++;
  133. }
  134. StringBuffer sb = new StringBuffer ();
  135. while (this.buf.get(cso) >= 48 && this.buf.get(cso) <= 57) {
  136. if (cso >= this.buf.capacity ()) return null;
  137. sb.append ((char) this.buf.get(cso));
  138. cso++;
  139. }
  140. so = cso;
  141. cLength = Integer.parseInt (sb.toString ());
  142. break;
  143. }
  144. }
  145. }
  146. if (cLength != -1) {
  147. for (; cStart == -1 && so < this.buf.position () - 4; so++) {
  148. if (so > 4096) {
  149. this.addLog("HEADER>4096bytes");
  150. this.invalidate();
  151. reading=false;
  152. return null;
  153. }
  154. if (this.buf.get(so) == '\r'
  155. && this.buf.get(so+1) == '\n'
  156. && this.buf.get(so+2) == '\r'
  157. && this.buf.get(so+3) == '\n') {
  158. cStart = so + 4;
  159. break;
  160. }
  161. }
  162. if (cStart != -1) {
  163. if ((this.buf.position () - cStart) > cLength) {
  164. int diff = this.buf.position () - cStart - cLength;
  165. tBuf = ByteBuffer.allocate (diff);
  166. for (int pos = this.buf.position () - diff; pos < this.buf.position (); pos++) {
  167. tBuf.put (this.buf.get (pos));
  168. }
  169. this.buf.position(cStart + cLength);
  170. parse=true;
  171. } else if ((this.buf.position () - cStart) == cLength) {
  172. parse=true;
  173. }
  174. }
  175. }
  176. }
  177. }
  178. if (parse)
  179. return parse();
  180. return null;
  181. }
  182. /**
  183. * hands over this buffer to the requestparser-threads which take care of parsing the request
  184. * @return IRequest The IRequest-object containing the request
  185. */
  186. public IRequest parse () throws Exception {
  187. // FIXME: when we install another protocol we have to check here for the type of protocol
  188. IRequest req = null;
  189. synchronized (this) {
  190. this.buf.flip ();
  191. try {
  192. req = new HTTPRequest(buf, this);
  193. } catch (Exception e) {
  194. reset();
  195. throw e;
  196. }
  197. reading=false;
  198. }
  199. try {
  200. req.parse ();
  201. Connection conn = req.getConnectionObject();
  202. if (!conn.isDirectlyConnected) {
  203. InetAddress ia = ((SocketChannel) sk.channel ()).socket().getInetAddress ();
  204. if (ia != null) {
  205. TrafficMonitor.tm.markAsProxy (ia);
  206. }
  207. }
  208. /* } catch (Exception e) {
  209. Server.debug (this, "parse: ", e, Server.MSG_ERROR, Server.LVL_MAJOR);
  210. throw e; */
  211. } finally {
  212. reset ();
  213. }
  214. return req;
  215. }
  216. private synchronized void reset () {
  217. if (buf.capacity () != Server.srv.READBUFFER_SIZE) {
  218. buf = ByteBuffer.allocate (Server.srv.READBUFFER_SIZE);
  219. } else {
  220. buf.clear ();
  221. }
  222. if (tBuf != null) {
  223. buf.put (tBuf);
  224. tBuf = null;
  225. }
  226. cStart = -1;
  227. cLength= -1;
  228. reqType= 0;
  229. so = 0;
  230. valid=true;
  231. reading=false;
  232. }
  233. public void setTemplateSet (String ts) {
  234. this.ts = ts;
  235. }
  236. public String getTemplateSet () {
  237. return ts;
  238. }
  239. public void setUser (User u) {
  240. this.u = u;
  241. }
  242. public User getUser () {
  243. return u;
  244. }
  245. /**
  246. * returns the SocketChannel of this requestbuffer
  247. */
  248. public SelectionKey getKey () {
  249. return sk;
  250. }
  251. public void setKey (SelectionKey sk) {
  252. if (!CentralSelector.isSkValid(sk)) {
  253. Server.log(this, "setKey: tryed to set invalid key", Server.MSG_STATE, Server.LVL_VERBOSE);
  254. return;
  255. }
  256. this.sk=sk;
  257. conn = new Connection (sk);
  258. }
  259. public void addToWrite (Object ic) {
  260. if (!CentralSelector.isSkValid(sk)) {
  261. Server.log (this, "addToWrite: selection-key isn't valid anymore", Server.MSG_STATE, Server.LVL_VERBOSE);
  262. return;
  263. }
  264. synchronized (this) {
  265. if (writeBuffer.isFull ()) {
  266. int newSize = writeBuffer.capacity () + Server.srv.INITIAL_RESPONSE_QUEUE;
  267. if (newSize > Server.srv.MAX_RESPONSE_QUEUE) {
  268. Server.log(this, "addToWrite: write-queue would be bigger than specified for " + toString(), Server.MSG_STATE, Server.LVL_MINOR);
  269. return;
  270. }
  271. Server.log(this, "addToWrite: Expanding write-queue for " + toString(), Server.MSG_STATE, Server.LVL_MINOR);
  272. writeBuffer.resizeTo(newSize);
  273. }
  274. writeBuffer.put(ic);
  275. }
  276. writeToLog();
  277. Responder.res.addToWrite((SocketChannel) sk.channel(), this);
  278. }
  279. public ObjectBuffer getWriteQueue () {
  280. return writeBuffer;
  281. }
  282. public void updateKeepAliveTimeout () {
  283. if (isMessageFrame)
  284. return;
  285. closeWhen = System.currentTimeMillis() + Server.srv.KEEP_ALIVE_TIMEOUT;
  286. }
  287. public long getKeepAliveTimeout(long ts) {
  288. if (isMessageFrame || reading)
  289. return -1;
  290. return closeWhen;
  291. }
  292. public void invalidate() {
  293. valid=false;
  294. }
  295. public boolean isValid() {
  296. return valid;
  297. }
  298. private volatile boolean isMessageFrame = false;
  299. public void setIsMessageFrame(boolean b) {
  300. // Server.log("changed state to message-frame-state", Server.MSG_STATE, Server.LVL_MAJOR);
  301. isMessageFrame=b;
  302. }
  303. public void addLog (String str) {
  304. lsb.append (" ");
  305. lsb.append (str);
  306. }
  307. public void writeToLog () {
  308. if (lsb.length() < 1)
  309. return;
  310. if (conn!=null && conn.peerAddress != null)
  311. lsb.insert(0, conn.peerAddress.getHostAddress());
  312. else if (conn != null)
  313. lsb.insert(0, conn.toString());
  314. else
  315. lsb.insert(0, "undefined");
  316. Server.log ("OK", lsb.toString (), Server.MSG_TRAFFIC, Server.LVL_MINOR);
  317. lsb = new StringBuffer();
  318. }
  319. public void logError (String reason) {
  320. lsb.append (" REASON: ");
  321. lsb.append (reason);
  322. if (conn != null && conn.peerAddress != null)
  323. lsb.insert (0, conn.peerAddress.getHostAddress());
  324. else if (conn != null)
  325. lsb.insert (0, conn.toString());
  326. else
  327. lsb.insert (0, "undefined");
  328. Server.log ("FAILED", lsb.toString (), Server.MSG_TRAFFIC, Server.LVL_MAJOR);
  329. lsb = new StringBuffer();
  330. }
  331. public void finalize() {
  332. if (Server.TRACE_CREATE_AND_FINALIZE)
  333. Server.log(this, "----------------------------------------FINALIZED", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
  334. }
  335. }