Example #1
0
func NewConn(baseConn net.Conn, output chan base.SipMessage) *connection {
	var isStreamed bool
	switch baseConn.(type) {
	case *net.UDPConn:
		isStreamed = false
	case *net.TCPConn:
		isStreamed = true
	case *tls.Conn:
		isStreamed = true
	default:
		log.Severe("Conn object %v is not a known connection type. Assume it's a streamed protocol, but this may cause messages to be rejected")
	}
	connection := connection{baseConn: baseConn, isStreamed: isStreamed}

	connection.parsedMessages = make(chan base.SipMessage)
	connection.parserErrors = make(chan error)
	connection.output = output
	connection.parser = parser.NewParser(connection.parsedMessages,
		connection.parserErrors,
		connection.isStreamed)

	go connection.read()
	go connection.pipeOutput()

	return &connection
}
Example #2
0
// Render params to a string.
// Note that this does not escape special characters, this should already have been done before calling this method.
func (p params) ToString(sep uint8) string {
	var buffer bytes.Buffer
	first := true

	for _, k := range p.Keys() {
		v, ok := p.Get(k)
		if !ok {
			log.Severe("Internal consistency error. Key %v present in param.Keys() but failed to Get()!", k)
			continue
		}

		if !first {
			buffer.WriteString(fmt.Sprintf("%c", sep))
		}
		first = false

		buffer.WriteString(fmt.Sprintf("%s", k))

		switch v := v.(type) {
		case String:
			if strings.ContainsAny(v.String(), c_ABNF_WS) {
				buffer.WriteString(fmt.Sprintf("=\"%s\"", v.String()))
			} else {
				buffer.WriteString(fmt.Sprintf("=%s", v.String()))
			}
		}
	}

	return buffer.String()
}
Example #3
0
func (udp *Udp) listen(conn *net.UDPConn) {
	log.Info("Begin listening for UDP on address %s", conn.LocalAddr())

	buffer := make([]byte, c_BUFSIZE)
	for {
		num, _, err := conn.ReadFromUDP(buffer)
		if err != nil {
			if udp.stop {
				log.Info("Stopped listening for UDP on %s", conn.LocalAddr)
				break
			} else {
				log.Severe("Failed to read from UDP buffer: " + err.Error())
				continue
			}
		}

		pkt := append([]byte(nil), buffer[:num]...)
		go func() {
			msg, err := parser.ParseMessage(pkt)
			if err != nil {
				log.Warn("Failed to parse SIP message: %s", err.Error())
			} else {
				udp.output <- msg
			}
		}()
	}
}
Example #4
0
// Copy a list of params.
func (p params) Copy() Params {
	dup := NewParams()
	for _, k := range p.Keys() {
		if v, ok := p.Get(k); ok {
			dup.Add(k, v)
		} else {
			log.Severe("Internal consistency error. Key %v present in param.Keys() but failed to Get()!", k)
		}
	}

	return dup
}
Example #5
0
func (tcp *Tcp) serve(listeningPoint *net.TCPListener) {
	log.Info("Begin serving TCP on address " + listeningPoint.Addr().String())

	for {
		baseConn, err := listeningPoint.Accept()
		if err != nil {
			log.Severe("Failed to accept TCP conn on address " + listeningPoint.Addr().String() + "; " + err.Error())
			continue
		}

		conn := NewConn(baseConn, tcp.output)
		log.Debug("Accepted new TCP conn %p from %s on address %s", &conn, conn.baseConn.RemoteAddr(), conn.baseConn.LocalAddr())
		tcp.connTable.Notify(baseConn.RemoteAddr().String(), conn)
	}
}
Example #6
0
func (tx *ServerTransaction) initNonInviteFSM() {
	// Define States

	// Trying
	server_state_def_trying := fsm.State{
		Index: server_state_trying,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_trying, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_proceeding, tx.act_respond},
			server_input_user_2xx:      {server_state_completed, tx.act_respond},
			server_input_user_300_plus: {server_state_completed, tx.act_respond},
		},
	}

	// Proceeding
	server_state_def_proceeding := fsm.State{
		Index: server_state_proceeding,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_proceeding, tx.act_respond},
			server_input_user_1xx:      {server_state_proceeding, tx.act_respond},
			server_input_user_2xx:      {server_state_completed, tx.act_final},
			server_input_user_300_plus: {server_state_completed, tx.act_final},
			server_input_transport_err: {server_state_terminated, tx.act_trans_err},
		},
	}

	// Completed
	server_state_def_completed := fsm.State{
		Index: server_state_completed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_completed, tx.act_respond},
			server_input_user_1xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_completed, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_completed, fsm.NO_ACTION},
			server_input_timer_h:       {server_state_terminated, tx.act_timeout},
			server_input_transport_err: {server_state_terminated, tx.act_trans_err},
		},
	}

	// Terminated
	server_state_def_terminated := fsm.State{
		Index: server_state_terminated,
		Outcomes: map[fsm.Input]fsm.Outcome{
			server_input_request:       {server_state_terminated, fsm.NO_ACTION},
			server_input_user_1xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_2xx:      {server_state_terminated, fsm.NO_ACTION},
			server_input_user_300_plus: {server_state_terminated, fsm.NO_ACTION},
			server_input_timer_h:       {server_state_terminated, fsm.NO_ACTION},
			server_input_delete:        {server_state_terminated, tx.act_delete},
		},
	}

	// Define FSM
	fsm, err := fsm.Define(
		server_state_def_trying,
		server_state_def_proceeding,
		server_state_def_completed,
		server_state_def_terminated,
	)
	if err != nil {
		log.Severe("Failed to define transaction FSM. Transaction will be dropped.")
		return
	}

	tx.fsm = fsm
}
Example #7
0
// Consume input lines one at a time, producing base.SipMessage objects and sending them down p.output.
func (p *parser) parse(requireContentLength bool) {
	var message base.SipMessage

	for {
		// Parse the StartLine.
		startLine, err := p.input.NextLine()

		if err != nil {
			log.Debug("Parser %p stopped", p)
			break
		}

		if isRequest(startLine) {
			method, recipient, sipVersion, err := parseRequestLine(startLine)
			message = base.NewRequest(method, recipient, sipVersion, []base.SipHeader{}, "")
			p.terminalErr = err
		} else if isResponse(startLine) {
			sipVersion, statusCode, reason, err := parseStatusLine(startLine)
			message = base.NewResponse(sipVersion, statusCode, reason, []base.SipHeader{}, "")
			p.terminalErr = err
		} else {
			p.terminalErr = fmt.Errorf("transmission beginning '%s' is not a SIP message", startLine)
		}

		if p.terminalErr != nil {
			p.terminalErr = fmt.Errorf("failed to parse first line of message: %s", p.terminalErr.Error())
			p.errs <- p.terminalErr
			break
		}

		// Parse the header section.
		// Headers can be split across lines (marked by whitespace at the start of subsequent lines),
		// so store lines into a buffer, and then flush and parse it when we hit the end of the header.
		var buffer bytes.Buffer
		headers := make([]base.SipHeader, 0)

		flushBuffer := func() {
			if buffer.Len() > 0 {
				newHeaders, err := p.parseHeader(buffer.String())
				if err == nil {
					headers = append(headers, newHeaders...)
				} else {
					log.Debug("Skipping header '%s' due to error: %s", buffer.String(), err.Error())
				}
				buffer.Reset()
			}
		}

		for {
			line, err := p.input.NextLine()

			if err != nil {
				log.Debug("Parser %p stopped", p)
				break
			}

			if len(line) == 0 {
				// We've hit the end of the header section.
				// Parse anything remaining in the buffer, then break out.
				flushBuffer()
				break
			}

			if !strings.Contains(c_ABNF_WS, string(line[0])) {
				// This line starts a new header.
				// Parse anything currently in the buffer, then store the new header line in the buffer.
				flushBuffer()
				buffer.WriteString(line)
			} else if buffer.Len() > 0 {
				// This is a continuation line, so just add it to the buffer.
				buffer.WriteString(" ")
				buffer.WriteString(line)
			} else {
				// This is a continuation line, but also the first line of the whole header section.
				// Discard it and log.
				log.Debug("Discarded unexpected continuation line '%s' at start of header block in message '%s'",
					line,
					message.Short())
			}
		}

		// Store the headers in the message object.
		for _, header := range headers {
			message.AddHeader(header)
		}

		var contentLength int

		// Determine the length of the body, so we know when to stop parsing this message.
		if p.streamed {
			// Use the content-length header to identify the end of the message.
			contentLengthHeaders := message.Headers("Content-Length")
			if len(contentLengthHeaders) == 0 {
				p.terminalErr = fmt.Errorf("Missing required content-length header on message %s", message.Short())
				p.errs <- p.terminalErr
				break
			} else if len(contentLengthHeaders) > 1 {
				var errbuf bytes.Buffer
				errbuf.WriteString("Multiple content-length headers on message ")
				errbuf.WriteString(message.Short())
				errbuf.WriteString(":\n")
				for _, header := range contentLengthHeaders {
					errbuf.WriteString("\t")
					errbuf.WriteString(header.String())
				}
				p.terminalErr = fmt.Errorf(errbuf.String())
				p.errs <- p.terminalErr
				break
			}

			contentLength = int(*(contentLengthHeaders[0].(*base.ContentLength)))
		} else {
			// We're not in streaming mode, so the Write method should have calculated the length of the body for us.
			contentLength = (<-p.bodyLengths.Out).(int)
		}

		// Extract the message body.
		body, err := p.input.NextChunk(contentLength)

		if err != nil {
			log.Debug("Parsed %p stopped", p)
			break
		}

		switch message.(type) {
		case *base.Request:
			message.(*base.Request).Body = body
		case *base.Response:
			message.(*base.Response).Body = body
		default:
			log.Severe("Internal error - message %s is neither a request type nor a response type", message.Short())
		}
		p.output <- message
	}

	if !p.streamed {
		// We're in unstreamed mode, so we created a bodyLengths ElasticChan which
		// needs to be disposed.
		close(p.bodyLengths.In)
	}
	return
}
Example #8
0
func (tx *ClientTransaction) initInviteFSM() {
	// Define Actions

	// Resend the request.
	act_resend := func() fsm.Input {
		tx.timer_a_time *= 2
		tx.timer_a.Reset(tx.timer_a_time)
		tx.resend()
		return fsm.NO_INPUT
	}

	// Just pass up the latest response.
	act_passup := func() fsm.Input {
		tx.passUp()
		return fsm.NO_INPUT
	}

	// Handle 300+ responses.
	// Pass up response and send ACK, start timer D.
	act_300 := func() fsm.Input {
		tx.passUp()
		tx.Ack()
		if tx.timer_d != nil {
			tx.timer_d.Stop()
		}
		tx.timer_d = time.AfterFunc(tx.timer_d_time, func() {
			tx.fsm.Spin(client_input_timer_d)
		})
		return fsm.NO_INPUT
	}

	// Send an ACK.
	act_ack := func() fsm.Input {
		tx.Ack()
		return fsm.NO_INPUT
	}

	// Send up transport failure error.
	act_trans_err := func() fsm.Input {
		tx.transportError()
		return client_input_delete
	}

	// Send up timeout error.
	act_timeout := func() fsm.Input {
		tx.timeoutError()
		return client_input_delete
	}

	// Pass up the response and delete the transaction.
	act_passup_delete := func() fsm.Input {
		tx.passUp()
		tx.Delete()
		return fsm.NO_INPUT
	}

	// Just delete the transaction.
	act_delete := func() fsm.Input {
		tx.Delete()
		return fsm.NO_INPUT
	}

	// Define States

	// Calling
	client_state_def_calling := fsm.State{
		Index: client_state_calling,
		Outcomes: map[fsm.Input]fsm.Outcome{
			client_input_1xx:           {client_state_proceeding, act_passup},
			client_input_2xx:           {client_state_terminated, act_passup_delete},
			client_input_300_plus:      {client_state_completed, act_300},
			client_input_timer_a:       {client_state_calling, act_resend},
			client_input_timer_b:       {client_state_terminated, act_timeout},
			client_input_transport_err: {client_state_terminated, act_trans_err},
		},
	}

	// Proceeding
	client_state_def_proceeding := fsm.State{
		Index: client_state_proceeding,
		Outcomes: map[fsm.Input]fsm.Outcome{
			client_input_1xx:      {client_state_proceeding, act_passup},
			client_input_2xx:      {client_state_terminated, act_passup_delete},
			client_input_300_plus: {client_state_completed, act_300},
			client_input_timer_a:  {client_state_proceeding, fsm.NO_ACTION},
			client_input_timer_b:  {client_state_proceeding, fsm.NO_ACTION},
		},
	}

	// Completed
	client_state_def_completed := fsm.State{
		Index: client_state_completed,
		Outcomes: map[fsm.Input]fsm.Outcome{
			client_input_1xx:           {client_state_completed, fsm.NO_ACTION},
			client_input_2xx:           {client_state_completed, fsm.NO_ACTION},
			client_input_300_plus:      {client_state_completed, act_ack},
			client_input_timer_d:       {client_state_terminated, act_delete},
			client_input_transport_err: {client_state_terminated, act_trans_err},
			client_input_timer_a:       {client_state_completed, fsm.NO_ACTION},
			client_input_timer_b:       {client_state_completed, fsm.NO_ACTION},
		},
	}

	// Terminated
	client_state_def_terminated := fsm.State{
		Index: client_state_terminated,
		Outcomes: map[fsm.Input]fsm.Outcome{
			client_input_1xx:      {client_state_terminated, fsm.NO_ACTION},
			client_input_2xx:      {client_state_terminated, fsm.NO_ACTION},
			client_input_300_plus: {client_state_terminated, fsm.NO_ACTION},
			client_input_timer_a:  {client_state_terminated, fsm.NO_ACTION},
			client_input_timer_b:  {client_state_terminated, fsm.NO_ACTION},
			client_input_delete:   {client_state_terminated, act_delete},
		},
	}

	fsm, err := fsm.Define(
		client_state_def_calling,
		client_state_def_proceeding,
		client_state_def_completed,
		client_state_def_terminated,
	)

	if err != nil {
		log.Severe("Failure to define INVITE client transaction fsm: %s", err.Error())
	}

	tx.fsm = fsm
}