public void dump(PrintWriter out) { out.println("SpdyConnection open=" + channels.size() + " outQ:" + outQueue.size()); for (SpdyStream str : channels.values()) { str.dump(out); } out.println(); }
public SpdyStream get(String host, String url) { SpdyStream sch = new SpdyStream(this); sch.getRequest().addHeader("host", host); sch.getRequest().addHeader("url", url); sch.send(); return sch; }
// Framing error or shutdown- close all streams. public void abort(String msg) { System.err.println(msg); inClosed = true; List<Integer> ch = new ArrayList<>(channels.keySet()); for (Integer i : ch) { SpdyStream stream = channels.remove(i); if (stream != null) { stream.onReset(); } } }
@Override public void receive(final SpdyStream stream) throws IOException { List<String> requestHeaders = stream.getRequestHeaders(); String path = null; for (int i = 0; i < requestHeaders.size(); i += 2) { String s = requestHeaders.get(i); if ("url".equals(s)) { path = requestHeaders.get(i + 1); break; } } if (path == null) { // TODO: send bad request error throw new AssertionError(); } File file = new File(baseDirectory + path); if (file.exists() && !file.isDirectory()) { serveFile(stream, file); } else { send404(stream, path); } }
private void send404(SpdyStream stream, String path) throws IOException { List<String> responseHeaders = Arrays.asList( "status", "404", "version", "HTTP/1.1", "content-type", "text/plain"); OutputStream out = stream.reply(responseHeaders); String text = "Not found: " + path; out.write(text.getBytes("UTF-8")); out.close(); }
private void serveFile(SpdyStream stream, File file) throws IOException { InputStream in = new FileInputStream(file); byte[] buffer = new byte[8192]; OutputStream out = stream.reply( Arrays.asList( "status", "200", "version", "HTTP/1.1", "content-type", contentType(file))); int count; while ((count = in.read(buffer)) != -1) { out.write(buffer, 0, count); } out.close(); }
/** * Process a SPDY connection. Called in the input thread, should not block. * * @throws IOException */ protected int handleFrame() throws IOException { if (inFrame.c) { switch (inFrame.type) { case TYPE_SETTINGS: { int cnt = inFrame.readInt(); for (int i = 0; i < cnt; i++) { inFrame.readByte(); inFrame.read24(); inFrame.readInt(); } // TODO: save/interpret settings break; } case TYPE_GOAWAY: { int lastStream = inFrame.readInt(); log.info("GOAWAY last=" + lastStream); // Server will shut down - but will keep processing the current requests, // up to lastStream. If we sent any new ones - they need to be canceled. abort("GO_AWAY", lastStream); goAway = lastStream; return CLOSE; } case TYPE_RST_STREAM: { inFrame.streamId = inFrame.read32(); int errCode = inFrame.read32(); if (SpdyContext.debug) { trace( "> RST " + inFrame.streamId + " " + ((errCode < RST_ERRORS.length) ? RST_ERRORS[errCode] : Integer.valueOf(errCode))); } SpdyStream sch; synchronized (channels) { sch = channels.remove(Integer.valueOf(inFrame.streamId)); } // if RST stream is for a closed channel - we can ignore. if (sch != null) { sch.onReset(); } inFrame = null; break; } case TYPE_SYN_STREAM: { SpdyStream ch = getSpdyContext().getStream(this); synchronized (channels) { channels.put(Integer.valueOf(inFrame.streamId), ch); } try { ch.onCtlFrame(inFrame); inFrame = null; } catch (Throwable t) { log.log(Level.SEVERE, "Error parsing head SYN_STREAM", t); abort("Error reading headers " + t); return CLOSE; } spdyContext.onStream(this, ch); break; } case TYPE_SYN_REPLY: { SpdyStream sch; synchronized (channels) { sch = channels.get(Integer.valueOf(inFrame.streamId)); } if (sch == null) { abort("Missing channel"); return CLOSE; } try { sch.onCtlFrame(inFrame); inFrame = null; } catch (Throwable t) { log.info("Error parsing head SYN_STREAM" + t); abort("Error reading headers " + t); return CLOSE; } break; } case TYPE_PING: { SpdyFrame oframe = getSpdyContext().getFrame(); oframe.type = TYPE_PING; oframe.c = true; oframe.append32(inFrame.read32()); oframe.pri = 0x80; send(oframe, null); break; } } } else { // Data frame SpdyStream sch; synchronized (channels) { sch = channels.get(Integer.valueOf(inFrame.streamId)); } if (sch == null) { abort("Missing channel"); return CLOSE; } sch.onDataFrame(inFrame); synchronized (channels) { if (sch.finRcvd && sch.finSent) { channels.remove(Integer.valueOf(inFrame.streamId)); } } inFrame = null; } return LONG; }