?? ppg.java
字號:
package push;import javax.servlet.*;import javax.servlet.http.*;import java.net.*;import java.io.*;import java.util.StringTokenizer;/** * <code>PPG</code> class implements some push proxy gateway (PPG) functionality * for the purposes of this example only. This simple PPG is targeted to be used * in conjunction with WAP toolkit, and IPv4 type client addressing. * */public final class PPG extends HttpServlet { /* xml version */ private final static String XML_VERSION = "<?xml version=\"1.0\"?>"; /* Push Access Protocol (PAP) document type */ private final static String PAP_DOCTYPE = "<!DOCTYPE pap PUBLIC \"-//WAPFORUM//DTD PAP 1.0//EN\" \"http://www.wapforum.org/DTD/pap_1.0.dtd\" >"; /* content type of the push request multipart body */ private final static String CONTENT_TYPE = "multipart/related; boundary=multipart-boundary; type=\"application/xml\""; /* * WAP Push connection less service (client side). The registered port * number. */ private static final int connectionlessPushPort = 2948; private static int transactionId = 0; /** * <code>doPost</code> * * @param request * a <code>HttpServletRequest</code> value * @param response * a <code>HttpServletResponse</code> value * @exception ServletException * if an error occurs * @exception IOException * if an error occurs */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String clientAddress = null; String pushId = null; int resultCode = 1001; // accepted for processing try { // first, check the content type which should be "multipart/related" String contentType = request.getHeader("content-type"); StringTokenizer st = new StringTokenizer(contentType, ";"); String token = st.nextToken(); String boundary = null; if (!token.equalsIgnoreCase("multipart/related")) throw new Exception("wrong content type"); // finds the boundary string while (st.hasMoreTokens()) { token = st.nextToken().trim(); if (token.startsWith("boundary=")) { boundary = token.substring(9); break; } } if (boundary == null) throw new Exception("no multipart boundary"); boundary = "--" + boundary; String endBoundary = boundary + "--"; StringBuffer messageContent = new StringBuffer(); BufferedReader in = request.getReader(); String line; int i = 0; boolean startContent = false; System.out.println("boundary=" + boundary); // extract message content part while ((line = in.readLine()) != null) { if (line.equals(boundary)) ++i; else if (line.equals(endBoundary)) break; if (i == 1) { // PAP control entity int j = line.indexOf("address-value="); if (j >= 0) { clientAddress = line.substring(j + 15, line.indexOf( '"', j + 17)); } j = line.indexOf("push-id="); if (j >= 0) { pushId = line.substring(j + 9, line .indexOf('"', j + 11)); } } else if (i == 2) { // PAP content entity if (startContent) messageContent.append(line); else if (line.trim().equals("")) // end of headers startContent = true; else if (line.toLowerCase().startsWith("content-type:")) contentType = line.substring(13).trim(); } } if ((i = clientAddress.indexOf("/TYPE=IPv4")) == -1) { resultCode = 2002; // address error throw new Exception( "This PPG can handle only IPv4 type addresses"); } clientAddress = clientAddress.substring(clientAddress .indexOf("WAPPUSH=") + 8, i); if (clientAddress == null) { resultCode = 2002; // address error throw new Exception("Client address is not known"); } System.out.println("clientAddress: " + clientAddress); System.out.println("pushId: " + pushId); System.out.println("message content: " + messageContent); unitPushRequest(clientAddress, messageContent.toString().trim(), contentType); } catch (Exception e) { System.err.println(e); if (resultCode < 2000) resultCode = 2000; // bad message } // start writing the result response.setStatus(202); // accepted response.setContentType("application/xml"); PrintWriter out = response.getWriter(); out.println(XML_VERSION); out.println(PAP_DOCTYPE); out.println("<pap product-name=\"MobileZoo PPG\">"); out.println(" <push-response push-id=\"" + pushId + "\">"); out.println(" <response result"); out.println(" code=\"" + resultCode + "\""); out.println(" desc=\"" + resultCodeDesc(resultCode) + "\">"); out.println(" </response-result>"); out.println(" </push-response>"); out.println("</pap>"); } /** * Returns description of a PAP result response code * * @param code * an <code>int</code> value * @return a <code>String</code> value */ private static String resultCodeDesc(int code) { switch (code) { case 1001: return "Accepted for Processing"; case 2000: return "Bad Request"; case 2002: return "Address Error"; } return "Unknown result code"; } /** * <code>unitPushRequest</code> generates a connectionless mode Push request * * @param clientAddress * a <code>String</code> value * @param messageContent * a <code>String</code> value * @param contentType * a <code>String</code> value * @exception Exception * if an error occurs */ private void unitPushRequest(String clientAddress, String messageContent, String contentType) throws Exception { ByteArrayOutputStream content = new ByteArrayOutputStream(); contentType = encodeContent(messageContent, content, contentType); int wspContentType = encodeContentType(contentType); transactionId %= 127; byte[] wspPdu = wspPduPUSH(transactionId++, wspContentType, content .toByteArray()); sendData(clientAddress, connectionlessPushPort, wspPdu, wspPdu.length); } /** * A simplified "WBXML encoder". It handles only SI content type, and only * href attribute within SI content (others ignored). No well-formedness nor * validity checks are performed during the encoding. * * @param messageContent * a <code>String</code> value * @param content * a <code>ByteArrayOutputStream</code> value * @param contentType * a <code>String</code> value * @return a <code>String</code> value */ private static String encodeContent(String messageContent, ByteArrayOutputStream content, String contentType) throws Exception { if (contentType.startsWith("text/vnd.wap.si")) { int i = messageContent.indexOf("href=\"http://"); if (i > 0) { try { final byte[] bytes1 = { 0x0, 0x5, 0x4, 0x0, 0x45, (byte) 0xc6, 0xc, 0x3 }; final byte[] bytes2 = { 0x0, 0x7, 0x1, 0x3 }; final byte[] bytes3 = { 0x0, 0x1, 0x1 }; String href = messageContent.substring(i + 13, messageContent.indexOf("\"", i + 14)); String message = messageContent.substring(messageContent .indexOf(">", i + 15) + 1, messageContent.indexOf( "</indication>", i + 16)); content.write(bytes1); content.write(href.getBytes()); content.write(bytes2); content.write(message.trim().getBytes()); content.write(bytes3); return "application/vnd.wap.sic"; } catch (Exception e) { content.reset(); } } } content.write(messageContent.getBytes()); return contentType; } /** * <code>encodeContentType</code> encodes mime type (cf. WSP specification * WAP-203-WSP 4-May-2000) * * @param contentType * a <code>String</code> value * @return an <code>int</code> value */ private static int encodeContentType(String contentType) throws Exception { contentType = contentType.toLowerCase(); if (contentType.startsWith("text/vnd.wap.wml")) return 0x88; else if (contentType.startsWith("text/vnd.wap.si")) return 0xAD; else if (contentType.startsWith("text/vnd.wap.sl")) return 0xAF; else if (contentType.startsWith("application/vnd.wap.wmlc")) return 0x94; else if (contentType.startsWith("application/vnd.wap.sic")) return 0xAE; else if (contentType.startsWith("applicavtion/vnd.wap.slc")) return 0xB0; throw new Exception("unsupported content type:" + contentType); } // WSP PDU Type Assigments // Table 34 (page 94) in WSP specification WAP-203-WSP 4-May-2000 private static final int WSP_PUSH = 0x06; /** * Generate WSP PUSH PDU (note: only partial functionality provided) * * @param tid * an <code>int</code> value * @param contentType * an <code>int</code> value * @param content * a <code>byte[]</code> value * @return a <code>byte[]</code> value * @exception Exception * if an error occurs */ private static byte[] wspPduPUSH(int tid, int contentType, byte[] content) throws Exception { ByteArrayOutputStream data = new ByteArrayOutputStream(); data.write(tid); data.write(WSP_PUSH); data.write(1); // contenttype size + headers size data.write(contentType); data.write(content); return data.toByteArray(); } /** * <code>sendData</code> sends data to given address and port using UDP * datagram socket * * @param addressStr * a <code>String</code> value * @param port * an <code>int</code> value * @param data * a <code>byte[]</code> value * @param dataSize * an <code>int</code> value * @return an <code>int</code> value * @exception Exception * if an error occurs */ private static int sendData(String addressStr, int port, final byte[] data, int dataSize) throws Exception { if (dataSize <= 0) return 0; InetAddress addr = InetAddress.getByName(addressStr); System.out.println("sendData addr = " + addr.getHostAddress() + "; port = " + port + "; data_size = " + dataSize); DatagramSocket s = new DatagramSocket(); // s.setSoTimeout(1000); DatagramPacket packet = new DatagramPacket(data, dataSize, addr, port); s.send(packet); int nBytes = packet.getLength(); if (dataSize != nBytes) System.err .println("warning: not all bytes of a datagram are sent to socket!?"); s.close(); return nBytes; }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -