/** * Constructor - takes a datagram packet and a stack structure Extracts the address of the other * from the datagram packet and stashes away the pointer to the passed stack structure. * * @param packet is the UDP Packet that contains the request. * @param sipStack stack is the shared SipStack structure * @param notifier Channel notifier (not very useful for UDP). */ public UDPMessageChannel( Datagram packet, SIPMessageStack sipStack, MessageProcessor messageProcessor) { incomingPacket = packet; stack = sipStack; this.messageProcessor = messageProcessor; myAddress = sipStack.getHostAddress(); myPort = messageProcessor.getPort(); Thread mythread = new Thread(this, "UDPMessageChannelThread"); mythread.start(); }
/** * Constructor - gets called from the SIPMessageStack class with a socket on accepting a new * client. All the processing of the message is done here with the stack being freed up to handle * new connections. The sock input is the socket that is returned from the accept. Global data * that is shared by all threads is accessible in the Server structure. * * @param sock Socket from which to read and write messages. The socket is already connected (was * created as a result of an accept). * @param sipStack the SIP Stack * @param channelNotifier Notifier (optional) that gets called when the channel is opened or * closed. */ protected TCPMessageChannel( SocketConnection sock, SIPMessageStack sipStack, TCPMessageProcessor msgProcessor) throws IOException { stack = sipStack; mySock = sock; myAddress = sipStack.getHostAddress(); peerAddress = sock.getAddress(); myClientInputStream = sock.openInputStream(); myClientOutputStream = sock.openOutputStream(); if (LogWriter.needsLogging) { LogWriter.logMessage("Creating new TCPMessageChannel " + this); LogWriter.logMessage( LogWriter.TRACE_DEBUG, "Channel parameters: " + "stack: " + stack + "\n" + "processor: " + msgProcessor + "\n" + "localAddress: " + myAddress + "\n" + "peerAddress: " + peerAddress + "\n" + "IS " + myClientInputStream + " Socket " + mySock); } stack.ioHandler.putSocket( stack.ioHandler.makeKey(mySock.getAddress(), mySock.getPort()), mySock, myClientOutputStream, myClientInputStream); mythread = new Thread(this, "TCPMessageChannel - incoming connection"); this.tcpMessageProcessor = msgProcessor; this.myPort = this.tcpMessageProcessor.getPort(); // Bug report by Vishwashanti Raj Kadiayl super.messageProcessor = msgProcessor; mythread.start(); }
/** * Constructor. We create one of these when we send out a message. * * @param targetAddr internet address of the place where we want to send messages. * @param port target port (where we want to send the message). * @param stack our SIP Stack. */ public UDPMessageChannel( String targetAddr, int port, SIPMessageStack sipStack, UDPMessageProcessor processor) { if (LogWriter.needsLogging) LogWriter.logMessage( LogWriter.TRACE_DEBUG, "DEBUG, UDPMessageChannel, UDPMessageChannel()," + " Creating message channel on " + targetAddr + "/" + port); stack = sipStack; this.peerPort = port; this.peerAddress = targetAddr; this.messageProcessor = processor; this.myPort = processor.getPort(); this.myAddress = sipStack.getHostAddress(); this.peerProtocol = "UDP"; }
/** * Constructor - connects to the given inet address. Acknowledgement -- Lamine Brahimi (IBM * Zurich) sent in a bug fix for this method. A thread was being uncessarily created. * * @param inetAddr inet address to connect to. * @param sipStack is the sip stack from which we are created. * @throws IOException if we cannot connect. */ protected TLSMessageChannel( InetAddress inetAddr, int port, SIPMessageStack sipStack, TLSMessageProcessor messageProcessor) throws IOException { if (LogWriter.needsLogging) { sipStack.logWriter.logMessage("creating new TLSMessageChannel "); sipStack.logWriter.logStackTrace(); } this.peerAddress = inetAddr; this.peerPort = port; this.myPort = messageProcessor.getPort(); this.peerProtocol = "TLS"; this.stack = sipStack; this.tlsMessageProcessor = messageProcessor; this.myAddress = sipStack.getHostAddress(); // Bug report by Vishwashanti Raj Kadiayl this.key = MessageChannel.getKey(peerAddress, peerPort, "TLS"); super.messageProcessor = messageProcessor; }
/** * Constructor - gets called from the SIPStack class with a socket on accepting a new client. All * the processing of the message is done here with the stack being freed up to handle new * connections. The sock input is the socket that is returned from the accept. Global data that is * shared by all threads is accessible in the Server structure. * * @param sock Socket from which to read and write messages. The socket is already connected (was * created as a result of an accept). * @param sipStack Ptr to SIP Stack */ protected TLSMessageChannel( SSLSocket sock, SIPMessageStack sipStack, TLSMessageProcessor msgProcessor) throws IOException { if (LogWriter.needsLogging) { sipStack.logWriter.logMessage("creating new TLSMessageChannel "); sipStack.logWriter.logStackTrace(); } mySock = sock; peerAddress = mySock.getInetAddress(); myAddress = sipStack.getHostAddress(); myClientInputStream = mySock.getInputStream(); myClientOutputStream = mySock.getOutputStream(); mythread = new Thread(this); mythread.setDaemon(true); mythread.setName("TLSMessageChannelThread"); // Stash away a pointer to our stack structure. stack = sipStack; this.tlsMessageProcessor = msgProcessor; this.myPort = this.tlsMessageProcessor.getPort(); // Bug report by Vishwashanti Raj Kadiayl super.messageProcessor = msgProcessor; // Can drop this after response is sent potentially. mythread.start(); }
/** * Constructor - connects to the given inet address. Acknowledgement -- Lamine Brahimi (IBM * Zurich) sent in a bug fix for this method. A thread was being unnecessarily created. * * @param inetAddr inet address to connect to. * @param sipStack is the sip stack from which we are created. * @param messageProcessor to whom a parsed message is passed * @throws IOException if we cannot connect. */ protected TCPMessageChannel( String inetAddr, int port, SIPMessageStack sipStack, TCPMessageProcessor messageProcessor) throws IOException { this.peerAddress = inetAddr; this.peerPort = port; this.myPort = messageProcessor.getPort(); this.peerProtocol = "TCP"; this.stack = sipStack; this.tcpMessageProcessor = messageProcessor; this.myAddress = sipStack.getHostAddress(); // Bug report by Vishwashanti Raj Kadiayl super.messageProcessor = messageProcessor; this.key = "TCP" + ":" + stack.ioHandler.makeKey(peerAddress, peerPort); if (LogWriter.needsLogging) LogWriter.logMessage( "Created new TCP Message Channel " + this + " with key " + key + "\nprocessor: " + messageProcessor); }
/** * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser errors). * * @param sipMessage Mesage to process (this calls the application for processing the message). */ public void processMessage(SIPMessage sipMessage) throws Exception { try { if (sipMessage.getFrom() == null || // sipMessage.getFrom().getTag() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeq() == null || sipMessage.getViaHeaders() == null) { String badmsg = sipMessage.encode(); if (LogWriter.needsLogging) { stack.logWriter.logMessage("bad message " + badmsg); stack.logWriter.logMessage(">>> Dropped Bad Msg"); } stack.logBadMessage(badmsg); return; } ViaList viaList = sipMessage.getViaHeaders(); // For a request // first via header tells where the message is coming from. // For response, this has already been recorded in the outgoing // message. if (sipMessage instanceof SIPRequest) { Via v = (Via) viaList.first(); if (v.hasPort()) { this.peerPort = v.getPort(); } else this.peerPort = 5061; this.peerProtocol = v.getTransport(); try { this.peerAddress = mySock.getInetAddress(); // Check to see if the received parameter matches // the peer address and tag it appropriately. // Bug fix by [email protected] // Should record host address not host name // bug fix by Joost Yervante Damand if (!v.getSentBy().getInetAddress().equals(this.peerAddress)) { v.setParameter(Via.RECEIVED, this.peerAddress.getHostAddress()); // @@@ hagai v.setParameter(Via.RPORT, new Integer(this.peerPort).toString()); } } catch (java.net.UnknownHostException ex) { // Could not resolve the sender address. if (LogWriter.needsLogging) { stack.logWriter.logMessage("Rejecting message -- could not resolve Via Address"); } return; } catch (java.text.ParseException ex) { InternalErrorHandler.handleException(ex); } // Use this for outgoing messages as well. if (!this.isCached) { ((TLSMessageProcessor) this.messageProcessor).cacheMessageChannel(this); this.isCached = true; String key = IOHandler.makeKey(mySock.getInetAddress(), this.peerPort); stack.ioHandler.putSocket(key, mySock); } } // Foreach part of the request header, fetch it and process it long receptionTime = System.currentTimeMillis(); // if (sipMessage instanceof SIPRequest) { // This is a request - process the request. SIPRequest sipRequest = (SIPRequest) sipMessage; // Create a new sever side request processor for this // message and let it handle the rest. if (LogWriter.needsLogging) { stack.logWriter.logMessage("----Processing Message---"); } // Check for reasonable size - reject message // if it is too long. if (stack.getMaxMessageSize() > 0 && sipRequest.getSize() + (sipRequest.getContentLength() == null ? 0 : sipRequest.getContentLength().getContentLength()) > stack.getMaxMessageSize()) { SIPResponse sipResponse = sipRequest.createResponse(SIPResponse.MESSAGE_TOO_LARGE); byte[] resp = sipResponse.encodeAsBytes(); this.sendMessage(resp, false); throw new Exception("Message size exceeded"); } ServerRequestInterface sipServerRequest = stack.newSIPServerRequest(sipRequest, this); sipServerRequest.processRequest(sipRequest, this); if (this.stack.serverLog.needsLogging(ServerLog.TRACE_MESSAGES)) { if (sipServerRequest.getProcessingInfo() == null) { stack.serverLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), false, receptionTime); } else { this.stack.serverLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), sipServerRequest.getProcessingInfo(), false, receptionTime); } } } else { SIPResponse sipResponse = (SIPResponse) sipMessage; // This is a response message - process it. // Check the size of the response. // If it is too large dump it silently. if (stack.getMaxMessageSize() > 0 && sipResponse.getSize() + (sipResponse.getContentLength() == null ? 0 : sipResponse.getContentLength().getContentLength()) > stack.getMaxMessageSize()) { if (LogWriter.needsLogging) this.stack.logWriter.logMessage("Message size exceeded"); return; } ServerResponseInterface sipServerResponse = stack.newSIPServerResponse(sipResponse, this); sipServerResponse.processResponse(sipResponse, this); } } finally { } }
/** * Gets invoked by the parser as a callback on successful message parsing (i.e. no parser errors). * * @param sipMessage Mesage to process (this calls the application for processing the message). */ public void processMessage(Message sipMessage) { if (!stack.isAlive()) { if (LogWriter.needsLogging) LogWriter.logMessage( LogWriter.TRACE_DEBUG, "MsgChannel " + this + " is dropping message as the stack is closing"); return; // drop messages when closing, avoid Exceptions } try { if (LogWriter.needsLogging) LogWriter.logMessage( "[TCPMessageChannel]-> Processing incoming message: " + sipMessage.getFirstLine()); if (sipMessage.getFromHeader() == null || sipMessage.getTo() == null || sipMessage.getCallId() == null || sipMessage.getCSeqHeader() == null || sipMessage.getViaHeaders() == null) { String badmsg = sipMessage.encode(); if (LogWriter.needsLogging) { ServerLog.logMessage("bad message " + badmsg); ServerLog.logMessage(">>> Dropped Bad Msg"); } stack.logBadMessage(badmsg); return; } ViaList viaList = sipMessage.getViaHeaders(); // For a request // first via header tells where the message is coming from. // For response, this has already been recorded in the outgoing // message. if (sipMessage instanceof Request) { ViaHeader v = (ViaHeader) viaList.first(); if (v.hasPort()) { viaPort = v.getPort(); } else { viaPort = SIPMessageStack.DEFAULT_PORT; } this.peerProtocol = v.getTransport(); try { if (peerPort == -1) peerPort = mySock.getPort(); this.peerAddress = mySock.getAddress(); // Log this because it happens when the remote host identifies // as a FQDN but this is not resolvable to an IP by the OS. // S40 doesn't have DNS settings, for instance, so if the APN // is not able to resolve all the addresses of the SIP/IMS core, // this problem will appear. if (peerAddress == null && LogWriter.needsLogging) LogWriter.logMessage( LogWriter.TRACE_EXCEPTION, "WARNING! Socket.getAddress() returned 'null'!!!"); // Be warned, the host comparison may fail if socket.getAddress() // returns a domain name as the Via Host will be a numeric IP. // FIXME: No idea. Doing a DNS lookup or reverse DNS lookup // can be misleading because they can be non-matching, that is, // DNS(peerAddressName) != ReverseDNS(peerAddressIP) if (v.hasParameter(ViaHeader.RPORT) || !v.getHost().equals(this.peerAddress)) { if (LogWriter.needsLogging) LogWriter.logMessage( LogWriter.TRACE_MESSAGES, "WARNING! \"Received\" parameter " + "has been temporarily disabled. Response will be sent to topmost Via Host: " + v.getHost()); this.peerAddress = v.getHost(); // if (LogWriter.needsLogging) // LogWriter.logMessage(LogWriter.TRACE_MESSAGES, "Adding // \"received\" parameter" + // " to incoming request with value: " + peerAddress + // " because it doesn't match the Via host " + v.getHost()); // v.setParameter(ViaHeader.RECEIVED, this.peerAddress); } if (v.hasParameter(ViaHeader.RPORT)) v.setParameter(ViaHeader.RPORT, Integer.toString(this.peerPort)); /* * If socket is invalid, close it because it is useless and dangerous. * Also if we ran out of slots for new sockets, as this could prevent * incoming connections from being accepted. */ if (mySock.getAddress() == null || (stack.maxConnections != -1 && tcpMessageProcessor.getNumConnections() >= stack.maxConnections)) { stack.ioHandler.disposeSocket(mySock, myClientInputStream, myClientOutputStream); mySock = null; myClientInputStream = null; myClientOutputStream = null; if (stack.maxConnections != -1) { synchronized (tcpMessageProcessor) { tcpMessageProcessor.decreaseNumConnections(); tcpMessageProcessor.notify(); } } } // reuse socket even for outgoing requests else if (!this.isCached) { ((TCPMessageProcessor) this.messageProcessor).cacheMessageChannel(this); String key = "TCP" + ":" + stack.ioHandler.makeKey(peerAddress, peerPort); stack.ioHandler.putSocket(key, mySock, myClientOutputStream, myClientInputStream); } } catch (IOException e) { e.printStackTrace(); } } // System.out.println("receiver address = " + receiverAddress); // For each part of the request header, fetch it and process it long receptionTime = System.currentTimeMillis(); if (sipMessage instanceof Request) { // This is a request - process the request. Request sipRequest = (Request) sipMessage; // Create a new sever side request processor for this // message and let it handle the rest. if (LogWriter.needsLogging) { LogWriter.logMessage("----Processing Message---"); } // TODO: check maximum size of request SIPServerRequestInterface sipServerRequest = stack.newSIPServerRequest(sipRequest, this); if (sipServerRequest != null) { try { sipServerRequest.processRequest(sipRequest, this); ServerLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), false, receptionTime); } catch (SIPServerException ex) { ServerLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), ex.getMessage(), false, receptionTime); handleException(ex); } } else { if (LogWriter.needsLogging) LogWriter.logMessage("Dropping request -- null sipServerRequest"); } } else { // This is a response message - process it. Response sipResponse = (Response) sipMessage; // TODO: check maximum size of the response SIPServerResponseInterface sipServerResponse = stack.newSIPServerResponse(sipResponse, this); if (LogWriter.needsLogging) LogWriter.logMessage("got a response interface " + sipServerResponse); try { // Responses with no ClienTransaction associated will not be processed // as they may cause a NPE in the EventScanner thread. if (sipServerResponse != null) sipServerResponse.processResponse(sipResponse, this); else { if (LogWriter.needsLogging) { LogWriter.logMessage("null sipServerResponse!"); } } } catch (SIPServerException ex) { // An error occured processing the message -- just log it. ServerLog.logMessage( sipMessage, getPeerAddress().toString() + ":" + getPeerPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), ex.getMessage(), false, receptionTime); // Ignore errors while processing responses?? } } } catch (Exception ee) { if (stack.isAlive()) { throw new RuntimeException(ee.getClass() + ":" + ee.getMessage()); } // else ignore exceptions } finally { // this.tcpMessageProcessor.useCount --; } }
/** * Actually process the parsed SIP message. * * @param sipMessage */ public void processMessage(Message sipMessage) { if (sipMessage instanceof Request) { Request sipRequest = (Request) sipMessage; // This is a request - process it. SIPServerRequestInterface sipServerRequest = stack.newSIPServerRequest(sipRequest, this); // Drop it if there is no request returned if (sipServerRequest == null) { if (LogWriter.needsLogging) { LogWriter.logMessage("Null request interface returned"); } return; } try { if (LogWriter.needsLogging) LogWriter.logMessage( "About to process " + sipRequest.getFirstLine() + "/" + sipServerRequest); sipServerRequest.processRequest(sipRequest, this); if (LogWriter.needsLogging) LogWriter.logMessage( "Done processing " + sipRequest.getFirstLine() + "/" + sipServerRequest); // So far so good -- we will commit this message if // all processing is OK. if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) { if (sipServerRequest.getProcessingInfo() == null) { ServerLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), false, new Long(receptionTime).toString()); } else { ServerLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), sipServerRequest.getProcessingInfo(), false, new Long(receptionTime).toString()); } } } catch (SIPServerException ex) { if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) { ServerLog.logMessage( sipMessage, sipRequest.getViaHost() + ":" + sipRequest.getViaPort(), stack.getHostAddress() + ":" + stack.getPort(this.getTransport()), ex.getMessage(), false, new Long(receptionTime).toString()); } handleException(ex); } } else { // Handle a SIP Response message. Response sipResponse = (Response) sipMessage; SIPServerResponseInterface sipServerResponse = stack.newSIPServerResponse(sipResponse, this); try { if (sipServerResponse != null) { sipServerResponse.processResponse(sipResponse, this); // Normal processing of message. } else { if (LogWriter.needsLogging) { LogWriter.logMessage("null sipServerResponse!"); } } } catch (SIPServerException ex) { if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) { this.logResponse(sipResponse, receptionTime, ex.getMessage() + "-- Dropped!"); } ServerLog.logException(ex); } } }