<commit_before>/*
*  
* This file is part of BlueScale.
*
* BlueScale is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* BlueScale is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
* 
* You should have received a copy of the GNU Affero General Public License
* along with BlueScale.  If not, see <http://www.gnu.org/licenses/>.
* 
* Copyright <NAME> 2010
* 
* 
* Please contact us at www.BlueScaleSoftware.com
*
*/
package com.bss.telco.jainsip

import javax.sip._
import javax.sip.address._
import javax.sip.header._
import javax.sip.message._
import javax.sdp.MediaDescription
import javax.sdp.SdpException
import javax.sdp.SdpFactory
import javax.sdp.SdpParseException
import javax.sdp.SessionDescription
import javax.sdp.MediaDescription
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.stack.ServerLog;

import java.util._
import java.net.InetAddress
import scala.actors.Actor 
import com.bss.telco._
import com.bss.telco.jainsip._ 
import com.bss.telco.api._  
import com.bss.util._

protected[jainsip] class JainSipInternal(telco:SipTelcoServer,
										val ip:String, 
										val port:Int,
										val destIp:String, 
										val destPort:Int) extends SipListener 
														 //with LogHelper
														 {
   
    val sipFactory = SipFactory.getInstance()
	sipFactory.setPathName("gov.nist")
	val properties = new Properties()
	val transport = "udp"

	def debug(s:String) {
		println(s)
	}
	def log(s:String) {
			println(s)
	}

	def error(s:String) {
		println(s)
	}
	
 
    properties.setProperty("javax.sip.STACK_NAME", "BSSJainSip"+this.hashCode())//name with hashcode so we can have multiple instances started in one VM
	properties.setProperty("javax.sip.OUTBOUND_PROXY", destIp +  ":" + destPort + "/"+ transport)
	properties.setProperty("gov.nist.javax.sip.DEBUG_LOG","log/debug_log" + port + ".log.txt") //FIXME
	properties.setProperty("gov.nist.javax.sip.SERVER_LOG","log/server_log" + port + ".log.txt")
	properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS","false")
	properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR")
	properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", "10")	
    properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false") 
 
	val sipStack = sipFactory.createSipStack(properties)
	//sipStack.asInstanceOf[SipStackImpl].getServerLog().setTraceLevel(ServerLog.TRACE_NONE)
    debug("createSipStack " + sipStack)
	val headerFactory 	= sipFactory.createHeaderFactory()
	val addressFactory = sipFactory.createAddressFactory()
	val messageFactory = sipFactory.createMessageFactory()
	val udpListeningPoint = sipStack.createListeningPoint(ip, port, transport)
	val sipProvider = sipStack.createSipProvider(udpListeningPoint)
 
	val inviteCreator = new InviteCreator(this)
	sipProvider.addSipListener(this)
  
	 
	override def processRequest(requestEvent:RequestEvent) {
		val request = requestEvent.getRequest()
		val serverTransactionId = requestEvent.getServerTransaction()

		 request.getMethod() match {
		  case Request.INVITE 	=> processInvite(requestEvent)
		  case Request.ACK 		=> processAck(requestEvent, requestEvent.getRequest())
		  case Request.BYE 		=> processBye(requestEvent, requestEvent.getRequest(), requestEvent.getServerTransaction())
		  case Request.REGISTER => processRegister(requestEvent)
		  case Request.CANCEL 	=> println("processCancel(requestEvent, serverTransactionId)") //TODO: handle cancels...may be too late for most things but we can try to cancel.
		  case _ =>/*serverTransactionId.sendResponse( messageFactory.createResponse( 202, request ) )
					// send one back
					val prov = requestEvent.getSource()
					val refer = requestEvent.getDialog().createRequest("REFER")
					requestEvent.getDialog().sendRequest( prov.getNewClientTransaction(refer) )
					*/
		 }		 
	}
	
	def processRegister(requestEvent:RequestEvent) {
		val r = requestEvent.getRequest()
		printHeaders(requestEvent.getRequest())
		sendRegisterResponse(200, requestEvent)
    }
 
	def processNewRequest(requestEvent: RequestEvent, f:(RequestEvent)=>Unit) =
		requestEvent.getServerTransaction() match {
		  case null => { val transaction = requestEvent.getSource().asInstanceOf[SipProvider].getNewServerTransaction(requestEvent.getRequest())
					 
		  				}
		 
		  case _ => error("request event that's not null...this shouldn't happen")
			  }
	
  
	def processInvite(requestEvent: RequestEvent) {
		debug("request for " + requestEvent.getRequest())	
		val request = requestEvent.getRequest()
		Option(requestEvent.getServerTransaction) match {
			case Some(transaction) => 	val conn = telco.getConnection(getCallId(request))
			                            conn.execute( ()=>{
											conn.serverTx = Some(transaction)
											SdpHelper.addMediaTo(conn.localSdp, SdpHelper.getSdp(request.getRawContent()) )					
											sendResponse(200, conn, request.getRawContent()) 
										})
			
			case None => 	    val transaction = requestEvent.getSource().asInstanceOf[SipProvider].getNewServerTransaction(request)
								transaction.sendResponse(messageFactory.createResponse(Response.RINGING,request) )
								val destination = parseToHeader(request.getRequestURI().toString())
								val conn = new JainSipConnection(getCallId(request), destination, "", INCOMING(), telco)
                                conn.execute( ()=>{
                                	conn.contactHeader = Some(request.getHeader("contact").asInstanceOf[ContactHeader]) 
                                    conn.serverTx = Some(transaction)
								    conn.dialog = Some( transaction.getDialog() ) //FIXME: we may not need to store this...
                                    //TOOD: make sure it defaults to alerting
									conn.setConnectionid(getCallId(request))
									telco.addConnection(conn) //(getCallId(request), conn)
									SdpHelper.addMediaTo(conn.localSdp, SdpHelper.getSdp(request.getRawContent()))
									telco.fireIncoming(conn) 
								})
		}
		
	}
	
	def sendRegisterResponse(responseCode:Int, requestEvent:RequestEvent) = {
    	//LETS DO THIS MORE SCALA STYLE
		val response = messageFactory.createResponse(responseCode, requestEvent.getRequest() ) //transaction.getRequest())
		response.addHeader( requestEvent.getRequest().getHeader("Contact"))
		requestEvent.getServerTransaction().sendResponse(response)
	}
 
	//TODO: deal with dead transactions...
	def sendResponse(responseCode:Int, conn:JainSipConnection, content:Array[Byte] ) = 
	    conn.serverTx match {
            case Some(tx)=> 	val response = messageFactory.createResponse(responseCode,conn.serverTx.get.getRequest)
		                        response.getHeader(ToHeader.NAME).asInstanceOf[ToHeader].setTag("4321")  //FIXME
		                        response.addHeader(headerFactory.createContactHeader(addressFactory.createAddress("sip:" + ip + ":"+port)))
                            	if ( null != content ) response.setContent(content,headerFactory.createContentTypeHeader("application", "sdp"))
		                        tx.sendResponse(response)
            case None => println("Error, ServerTX not found for conn " + conn)
	    }
	 
	
	
    
	private def processBye(requestEvent: RequestEvent, request:Request, transaction:ServerTransaction) {
		transaction.sendResponse(messageFactory.createResponse(200, request))
		val conn = telco.getConnection(getCallId(request))
		conn.execute(()=>{
			conn.setState(VERSIONED_UNCONNECTED( transaction.getBranchId() ))
			telco.removeConnection(conn)
		})
	}<commit_msg>took out tags in the header for now, will redo soon<commit_after>/*
*  
* This file is part of BlueScale.
*
* BlueScale is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* BlueScale is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
* 
* You should have received a copy of the GNU Affero General Public License
* along with BlueScale.  If not, see <http://www.gnu.org/licenses/>.
* 
* Copyright <NAME> 2010
* 
* 
* Please contact us at www.BlueScaleSoftware.com
*
*/
package com.bss.telco.jainsip

import javax.sip._
import javax.sip.address._
import javax.sip.header._
import javax.sip.message._
import javax.sdp.MediaDescription
import javax.sdp.SdpException
import javax.sdp.SdpFactory
import javax.sdp.SdpParseException
import javax.sdp.SessionDescription
import javax.sdp.MediaDescription
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.stack.ServerLog;

import java.util._
import java.net.InetAddress
import scala.actors.Actor 
import com.bss.telco._
import com.bss.telco.jainsip._ 
import com.bss.telco.api._  
import com.bss.util._

protected[jainsip] class JainSipInternal(telco:SipTelcoServer,
										val ip:String, 
										val port:Int,
										val destIp:String, 
										val destPort:Int) extends SipListener 
														 //with LogHelper
														 {
   
    val sipFactory = SipFactory.getInstance()
	sipFactory.setPathName("gov.nist")
	val properties = new Properties()
	val transport = "udp"

	def debug(s:String) {
		println(s)
	}
	def log(s:String) {
			println(s)
	}

	def error(s:String) {
		println(s)
	}
	
 
    properties.setProperty("javax.sip.STACK_NAME", "BSSJainSip"+this.hashCode())//name with hashcode so we can have multiple instances started in one VM
	properties.setProperty("javax.sip.OUTBOUND_PROXY", destIp +  ":" + destPort + "/"+ transport)
	properties.setProperty("gov.nist.javax.sip.DEBUG_LOG","log/debug_log" + port + ".log.txt") //FIXME
	properties.setProperty("gov.nist.javax.sip.SERVER_LOG","log/server_log" + port + ".log.txt")
	properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS","false")
	properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR")
	properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", "10")	
    properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "false") 
 
	val sipStack = sipFactory.createSipStack(properties)
	//sipStack.asInstanceOf[SipStackImpl].getServerLog().setTraceLevel(ServerLog.TRACE_NONE)
    debug("createSipStack " + sipStack)
	val headerFactory 	= sipFactory.createHeaderFactory()
	val addressFactory = sipFactory.createAddressFactory()
	val messageFactory = sipFactory.createMessageFactory()
	val udpListeningPoint = sipStack.createListeningPoint(ip, port, transport)
	val sipProvider = sipStack.createSipProvider(udpListeningPoint)
 
	val inviteCreator = new InviteCreator(this)
	sipProvider.addSipListener(this)
  
	 
	override def processRequest(requestEvent:RequestEvent) {
		val request = requestEvent.getRequest()
		val serverTransactionId = requestEvent.getServerTransaction()

		 request.getMethod() match {
		  case Request.INVITE 	=> processInvite(requestEvent)
		  case Request.ACK 		=> processAck(requestEvent, requestEvent.getRequest())
		  case Request.BYE 		=> processBye(requestEvent, requestEvent.getRequest(), requestEvent.getServerTransaction())
		  case Request.REGISTER => processRegister(requestEvent)
		  case Request.CANCEL 	=> println("processCancel(requestEvent, serverTransactionId)") //TODO: handle cancels...may be too late for most things but we can try to cancel.
		  case _ =>/*serverTransactionId.sendResponse( messageFactory.createResponse( 202, request ) )
					// send one back
					val prov = requestEvent.getSource()
					val refer = requestEvent.getDialog().createRequest("REFER")
					requestEvent.getDialog().sendRequest( prov.getNewClientTransaction(refer) )
					*/
		 }		 
	}
	
	def processRegister(requestEvent:RequestEvent) {
		val r = requestEvent.getRequest()
		printHeaders(requestEvent.getRequest())
		sendRegisterResponse(200, requestEvent)
    }
 
	def processNewRequest(requestEvent: RequestEvent, f:(RequestEvent)=>Unit) =
		requestEvent.getServerTransaction() match {
		  case null => { val transaction = requestEvent.getSource().asInstanceOf[SipProvider].getNewServerTransaction(requestEvent.getRequest())
					 
		  				}
		 
		  case _ => error("request event that's not null...this shouldn't happen")
			  }
	
  
	def processInvite(requestEvent: RequestEvent) {
		debug("request for " + requestEvent.getRequest())	
		val request = requestEvent.getRequest()
		Option(requestEvent.getServerTransaction) match {
			case Some(transaction) => 	val conn = telco.getConnection(getCallId(request))
			                            conn.execute( ()=>{
											conn.serverTx = Some(transaction)
											SdpHelper.addMediaTo(conn.localSdp, SdpHelper.getSdp(request.getRawContent()) )					
											sendResponse(200, conn, request.getRawContent()) 
										})
			
			case None => 	    val transaction = requestEvent.getSource().asInstanceOf[SipProvider].getNewServerTransaction(request)
								transaction.sendResponse(messageFactory.createResponse(Response.RINGING,request) )
								val destination = parseToHeader(request.getRequestURI().toString())
								val conn = new JainSipConnection(getCallId(request), destination, "", INCOMING(), telco)
                                conn.execute( ()=>{
                                	conn.contactHeader = Some(request.getHeader("contact").asInstanceOf[ContactHeader]) 
                                    conn.serverTx = Some(transaction)
								    conn.dialog = Some( transaction.getDialog() ) //FIXME: we may not need to store this...
                                    //TOOD: make sure it defaults to alerting
									conn.setConnectionid(getCallId(request))
									telco.addConnection(conn) //(getCallId(request), conn)
									SdpHelper.addMediaTo(conn.localSdp, SdpHelper.getSdp(request.getRawContent()))
									telco.fireIncoming(conn) 
								})
		}
		
	}
	
	def sendRegisterResponse(responseCode:Int, requestEvent:RequestEvent) = {
    	//LETS DO THIS MORE SCALA STYLE
		val response = messageFactory.createResponse(responseCode, requestEvent.getRequest() ) //transaction.getRequest())
		response.addHeader( requestEvent.getRequest().getHeader("Contact"))
		requestEvent.getServerTransaction().sendResponse(response)
	}
 
	//TODO: deal with dead transactions...
	def sendResponse(responseCode:Int, conn:JainSipConnection, content:Array[Byte] ) = 
	    conn.serverTx match {
            case Some(tx)=> 	val response = messageFactory.createResponse(responseCode,conn.serverTx.get.getRequest)
		                        //response.getHeader(ToHeader.NAME).asInstanceOf[ToHeader].setTag("4321")  //FIXME
		                        response.addHeader(headerFactory.createContactHeader(addressFactory.createAddress("sip:" + ip + ":"+port)))
                            	if ( null != content ) response.setContent(content,headerFactory.createContentTypeHeader("application", "sdp"))
		                        tx.sendResponse(response)
            case None => println("Error, ServerTX not found for conn " + conn)
	    }
	 
	
	
    
	private def processBye(requestEvent: RequestEvent, request:Request, transaction:ServerTransaction) {
		transaction.sendResponse(messageFactory.createResponse(200, request))
		val conn = telco.getConnection(getCallId(request))
		conn.execute(()=>{
			conn.setState(VERSIONED_UNCONNECTED( transaction.getBranchId() ))
			telco.removeConnection(conn)
		})
	}
{'fraction_non_alphanumeric': 0.10727800201816347, 'fraction_numerical': 0.0029011099899091826, 'mean_word_length': 3.7320202924500148, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4221995', 'n_tokens_mistral': 5249, 'n_tokens_neox': 4590, 'n_words': 960}