📄 relayconnection.java
字号:
* Package-private method to dispatch the request based on content type. * * @param in the input stream to read from. * @param out the output stream to write to. * @param contentType the content type of the request. * @exception APIException if the content type is unrecognized. * @exception IOException generated by stream operations. * */ synchronized static Response dispatchInternal( InputStream in, String contentType, MessageListener messageListener ) throws IOException, SOAPException, MessageProcessingException, MessagingException, ContentException, APIException { if( contentType == null || contentType.length() == 0 ) throw new APIException( "no-content-type-header" ); Response response = null; if( contentType.startsWith( "text/xml" ) ) { // message is DeliveryReport or ReadReply SOAPParser parser = new SOAPParser( in ); String transactionID = parser.getEnvelope() .getHeader() .getValue( SOAPConsts.MM7TransactionIDParameterName ); SOAPMethod method = parser.getEnvelope() .getBody() .getMethod(); if( method.getName().equals( SOAPConsts.MM7DeliveryReportReqMethodName ) ) { DeliveryReport dr = new DeliveryReport( method ); response = messageListener.processDeliveryReport( dr ); if( response != null ) { // check if response is one of DeliveryReportResponse/FaultResponse if( response.getClass() != DeliveryReportResponse.class && response.getClass() != FaultResponse.class ) throw new APIException( ErrorCode.SERVER_ERROR, "incorrect-delivery-report-response-class" ); response.setTransactionID( transactionID ); response.setNamespace( dr.getNamespace() ); } } else if( method.getName().equals( SOAPConsts.MM7ReadReplyReqMethodName ) ) { ReadReply rr = new ReadReply( method ); response = messageListener.processReadReply( rr ); if( response != null ) { // check if response is one of ReadReplyResponse/FaultResponse if( response.getClass() != ReadReplyResponse.class && response.getClass() != FaultResponse.class ) throw new APIException( ErrorCode.SERVER_ERROR, "incorrect-read-reply-response-class" ); response.setTransactionID( transactionID ); response.setNamespace( rr.getNamespace() ); } } else { throw new APIException( ErrorCode.UNSUPPORTED_OPERATION, "unknown-mm7-method", method.getName() ); } } else if( contentType.startsWith( "multipart/related" ) ) { InputStreamDataSource ds = new InputStreamDataSource( in, contentType ); MimeMultipart multipart = new MimeMultipart( ds ); DeliverRequest dr = new DeliverRequest( multipart ); response = messageListener.processDeliverRequest( dr ); if( response != null ) { // check if response is one of DeliverResponse/FaultResponse if( response.getClass() != DeliverResponse.class && response.getClass() != FaultResponse.class ) throw new APIException( ErrorCode.SERVER_ERROR, "incorrect-deliver-response-class" ); response.setTransactionID( dr.getTransactionID() ); response.setNamespace( dr.getNamespace() ); } } else { throw new APIException( "unexpected-content-type", contentType ); } return response; } /** * This method is used to create a socket. If the socket is required to be secure, * it creates an SSL socket and does SSL handshake which included key exchange * and server certificate verification. * * @return the socket created. * @exception APIException if there is an io error or if the host is unknown or * if there is an error validating the server certificate. */ private Socket createSocket() throws APIException { try { if( url.getProtocol().equals( "http" ) ) { Socket socket = new Socket( url.getHost(), url.getPort() ); socket.setSoTimeout( 2*60*1000 ); return socket; } else if( url.getProtocol().equals( "https" ) ) { SSLSocketFactory factory = ( SSLSocketFactory ) SSLSocketFactory.getDefault(); SSLSocket sslSocket = ( SSLSocket ) factory.createSocket( url.getHost(), url.getPort() ); sslSocket.setUseClientMode( true ); String[] cipherSuites = { "SSL_RSA_WITH_3DES_EDE_CBC_SHA" }; sslSocket.setEnabledCipherSuites( cipherSuites ); sslSocket.startHandshake(); X509Certificate[] certs = sslSocket.getSession() .getPeerCertificateChain(); X509Certificate peerCertificate = certs[0]; peerCertificate.checkValidity(); String peerName = peerCertificate.getSubjectDN() .getName(); String peerCommonName = getCommonName( peerName ); if( !weakCN ) { if( ! peerCommonName.equals( url.getHost() ) ) { throw new APIException( "cn-mismatch", "[" + peerCommonName + " != " + url.getHost() + "]" ); } } else { if( ! subDomainMatch( peerCommonName, url.getHost() ) ) { throw new APIException( "cn-mismatch", "[" + peerCommonName + " != " + url.getHost() + "]" ); } } return sslSocket; } else throw new APIException( "unknown-protocol", url.getProtocol() ); } catch( UnknownHostException uhe ) { throw new APIException( "cannot-create-socket", url.getHost() + ":" + url.getPort() ); } catch( IOException ioe ) { throw new APIException( "cannot-create-socket", url.getHost() + ":" + url.getPort() ); } catch( CertificateExpiredException cee ) { throw new APIException( ErrorCode.SERVER_ERROR, "certificate-expired", url.getHost() + ":" + url.getPort() ); } catch( CertificateNotYetValidException cnyv ) { throw new APIException( ErrorCode.SERVER_ERROR, "certificate-not-yet-valid", url.getHost() + ":" + url.getPort() ); } } /** * This method is used to retrieve the common name of the peer * * @param peerName the peer name from the certificate. * @throws APIException if common name cannot be found. * @return the peer common name from the peer name. * */ private static String getCommonName( String peerName ) throws APIException { if( peerName == null ) return null; int index = peerName.indexOf( "CN=" ); if( index != -1 ) { index += 3; int commaIndex = peerName.indexOf( ',', index ); if( commaIndex != -1 ) { return peerName.substring( index, commaIndex ); } } throw new APIException( ErrorCode.SERVER_ERROR, "no-cn-in-cert" ); } /** * This method is used to check if the last two elements of the domain name * of the host we are trying to connect to and the peer common name from the * certificate match. * * @param peerCommonName the peer common name from the certificate. * @param hostName the name of the host we are trying to connect to. * @return true if they match, false otherwise. * */ private static boolean subDomainMatch( String peerCommonName, String hostName ) { String peerSubDomain = null; String hostSubDomain = null; int lastDot = peerCommonName.lastIndexOf( '.' ); if( lastDot != -1 ) { int lastButOneDot = peerCommonName.lastIndexOf( '.', lastDot - 1 ); if( lastButOneDot != -1 ) { peerSubDomain = peerCommonName.substring( lastButOneDot + 1 ); } } lastDot = hostName.lastIndexOf( '.' ); if( lastDot != -1 ) { int lastButOneDot = hostName.lastIndexOf( '.', lastDot - 1 ); if( lastButOneDot != -1 ) { hostSubDomain = hostName.substring( lastButOneDot + 1 ); } } return ( peerSubDomain != null && hostSubDomain != null && peerSubDomain.equals( hostSubDomain ) ); } /** * This method writes the request to the socket using the authHeaderValue as the value * for the HTTP Authorization header. * * @param request the request object that needs to be written. * @param socket the socket to write to. * @param authHeaderValue the value to be used for Authorization header. * @return the HTTP response code. * @exception APIException if there is an IO error, SOAP exception creating the soap packet * from the request object or if there is no response from server. * */ private int writeMessage( Request request, Socket socket, String authHeaderValue ) throws APIException, ContentException { try { OutputStream outStr = socket.getOutputStream(); outStr.write( ("POST " + url.getPath() + " HTTP/1.0\r\n" ).getBytes() ); outStr.write( ("SOAPAction: \"\"\r\n" ).getBytes() ); if( logger.isDebugEnabled() ) { logger.debug( "[Begin Outgoing Request to Relay]\r\n" ); logger.debug( "POST " + url.getPath() + " HTTP/1.0\r\n" ); logger.debug( "SOAPAction: \"\"\r\n" ); } if( authHeaderValue != null ) { outStr.write( ("Authorization: " + authHeaderValue + "\r\n" ).getBytes() ); if( logger.isDebugEnabled() ) { logger.debug( "Authorization: " + authHeaderValue + "\r\n" ); } } else if( url.getProtocol().equals( "https" ) ) { authHeaderValue = "Basic " + Base64.encodeString( userName + ":" + password ); outStr.write( ("Authorization: " + authHeaderValue + "\r\n" ).getBytes() ); if( logger.isDebugEnabled() ) { logger.debug( "Authorization: " + authHeaderValue + "\r\n" ); } } request.writeTo( outStr ); outStr.flush(); if( logger.isDebugEnabled() ) { logger.debug( "[End Outgoing Request to Relay]" ); } return getHTTPResponseCode( socket.getInputStream() ); } catch( IOException ioe ) { throw new APIException( "io-exception-writing-to-socket", ioe.getMessage() ); } catch( SOAPException se ) { throw new APIException( se.getMessage() ); } } /** * This method is used to get a single line from the input stream. * * @param inStream the input stream to read from. * @return the string read from the input stream. * @exception APIException if there is an io error or if there is no response from server. * */ private static String getLine( InputStream inStream ) throws APIException { StringBuffer line = new StringBuffer(); try { for( ; ; ) { int byteRead = inStream.read(); if( byteRead == -1 ) break; if( ( char ) byteRead == '\r' ) { int newByteRead = inStream.read(); if( newByteRead == -1 ) break; if( ( char ) newByteRead == '\n' ) { return line.toString(); } break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -