Package gov.nist.javax.sip.stack

Source Code of gov.nist.javax.sip.stack.NioWebSocketMessageChannel

/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain.  As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
package gov.nist.javax.sip.stack;

import gov.nist.core.CommonLogger;
import gov.nist.core.Host;
import gov.nist.core.HostPort;
import gov.nist.core.LogWriter;
import gov.nist.core.StackLogger;
import gov.nist.javax.sip.header.RecordRoute;
import gov.nist.javax.sip.message.SIPMessage;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.channels.SocketChannel;
import java.text.ParseException;

import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.ContactHeader;
import javax.sip.header.RecordRouteHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;

public class NioWebSocketMessageChannel extends NioTcpMessageChannel{

  private static StackLogger logger = CommonLogger
      .getLogger(NioWebSocketMessageChannel.class);
 
  private WebSocketCodec codec = new WebSocketCodec(true, true);
 
  boolean readingHttp = true;
  String httpInput = "";
 
  public static NioWebSocketMessageChannel create(
      NioWebSocketMessageProcessor nioTcpMessageProcessor,
      SocketChannel socketChannel) throws IOException {
    NioWebSocketMessageChannel retval = (NioWebSocketMessageChannel) channelMap.get(socketChannel);
    if (retval == null) {
      retval = new NioWebSocketMessageChannel(nioTcpMessageProcessor,
          socketChannel);
      channelMap.put(socketChannel, retval);
    }
    return retval;
  }
 
  protected NioWebSocketMessageChannel(NioTcpMessageProcessor nioTcpMessageProcessor,
      SocketChannel socketChannel) throws IOException {
    super(nioTcpMessageProcessor, socketChannel);

    messageProcessor = nioTcpMessageProcessor;
    myClientInputStream = socketChannel.socket().getInputStream();
  }
 
  @Override
  protected void sendMessage(final byte[] msg, final boolean isClient) throws IOException {
    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      logger.logDebug("sendMessage isClient  = " + isClient + " this = " + this);
    }
    lastActivityTimeStamp = System.currentTimeMillis();
   
    NIOHandler nioHandler = ((NioTcpMessageProcessor) messageProcessor).nioHandler;
    if(this.socketChannel != null && this.socketChannel.isConnected() && this.socketChannel.isOpen()) {
      nioHandler.putSocket(NIOHandler.makeKey(this.peerAddress, this.peerPort), this.socketChannel);
    }
    sendWrapped(msg, this.peerAddress, this.peerPort, isClient);
  }
 
  protected void sendNonWebSocketMessage(byte[] msg, boolean isClient) throws IOException {

    if (logger.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
      logger.logDebug("sendMessage isClient  = " + isClient + " this = " + this);
    }
    lastActivityTimeStamp = System.currentTimeMillis();
   
    NIOHandler nioHandler = ((NioTcpMessageProcessor) messageProcessor).nioHandler;
    if(this.socketChannel != null && this.socketChannel.isConnected() && this.socketChannel.isOpen()) {
      nioHandler.putSocket(NIOHandler.makeKey(this.peerAddress, this.peerPort), this.socketChannel);
    }
    super.sendTCPMessage(msg, this.peerAddress, this.peerPort, isClient);
  }

  private byte[] wrapBufferIntoWebSocketFrame(byte[] buffer) {
    try {
      return WebSocketCodec.encode(buffer, 0, true);
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return null;
  }

  public void sendWrapped(byte message[], InetAddress receiverAddress,
      int receiverPort, boolean retry) throws IOException {
    message = wrapBufferIntoWebSocketFrame(message);
    super.sendTCPMessage(message, receiverAddress, receiverPort, retry);
  }
 
  @Override
  public void sendMessage(final byte message[], final InetAddress receiverAddress,
      final int receiverPort, final boolean retry) throws IOException {
    sendWrapped(message, receiverAddress, receiverPort, retry);
  }

  public NioWebSocketMessageChannel(InetAddress inetAddress, int port,
      SIPTransactionStack sipStack,
      NioTcpMessageProcessor nioTcpMessageProcessor) throws IOException {
    super(inetAddress, port, sipStack, nioTcpMessageProcessor);
  }
 
  @Override
  protected void addBytes(byte[] bytes) throws Exception {
    String s = new String(bytes);
    if(readingHttp) {
      httpInput += s;
      if(s.endsWith("\r\n") || s.endsWith("\n")) {
        readingHttp = false;
        byte[] response = new WebSocketHttpHandshake().createHttpResponse(s);
        sendNonWebSocketMessage(response, false);
      }
    } else if(!readingHttp) {
      ByteArrayInputStream bios = new ByteArrayInputStream(bytes);
      byte[] decodedMsg = null;
      do {
        decodedMsg = codec.decode(bios);
        if(decodedMsg == null) {
          return; // the codec can't parse a full websocket frame, we will try again when have more data
        }
        nioParser.addBytes(decodedMsg);
        logger.logDebug("Nio websocket bytes were added " + decodedMsg.length);
      } while (decodedMsg != null);
     
    }
  }
 
  @Override
  public String getTransport() {
    return "WS";
  }

  @Override
  public void onNewSocket(byte[] message) {
    super.onNewSocket(message);
   
  }
 
    /**
     * Call back method. When the parser finshes parsing a message let the channel see it and decide
     * if it want to create some address mappings (for Websocket or otherwise).
     *
     * @param message
     * @throws Exception
     */
  @Override
    public void processMessage(SIPMessage message) throws Exception {
      if(message instanceof Request) {
        Request request = (Request) message;
        if(request.getMethod().equals(Request.REGISTER)) {
          ContactHeader contact = (ContactHeader) request.getHeader(ContactHeader.NAME);
          URI uri = contact.getAddress().getURI();
          if(uri.isSipURI()) {
            SipURI sipUri = (SipURI) uri;
            String host = sipUri.getHost();
            NioTcpMessageProcessor processor = (NioTcpMessageProcessor) this.messageProcessor;
            HostPort hostPort = new HostPort();
            hostPort.setHost(new Host(host));
            hostPort.setPort(5060);
            processor.assignChannelToDestination(hostPort, this);
          }
        }
        ContactHeader contact = (ContactHeader)message.getHeader(ContactHeader.NAME);
          RecordRouteHeader rr = (RecordRouteHeader)message.getHeader(RecordRouteHeader.NAME);
          ViaHeader via = message.getTopmostViaHeader();
         
          if(rr == null) {
            if(contact != null) {
              rewriteUri((SipURI) contact.getAddress().getURI());
            }
          } else {
            rewriteUri((SipURI) rr.getAddress().getURI()); // not needed but just in case some clients does it
          }
         
          String viaHost = via.getHost();
          if(viaHost.endsWith(".invalid")) {
            via.setHost(getPeerAddress());
            via.setPort(getPeerPort());
          }
      } else {
        ContactHeader contact = (ContactHeader)message.getHeader(ContactHeader.NAME);
          if(contact != null) {
            rewriteUri((SipURI) contact.getAddress().getURI());
          }
      }
     
    super.processMessage(message);
    }
 
  public void rewriteUri(SipURI uri) {
    try {
      String uriHost = uri.getHost();
      if(uriHost.endsWith(".invalid")) {
        uri.setHost(getPeerAddress());
      }
    } catch (ParseException e) {
      logger.logError("Cant parse address", e);
    }
    uri.setPort(getPeerPort());
  }

}
TOP

Related Classes of gov.nist.javax.sip.stack.NioWebSocketMessageChannel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.