Exemplo n.º 1
0
func (caller *endpoint) Invite(callee *endpoint) error {
	// Starting a dialog.
	callid := "thisisacall" + string(caller.dialogIx)
	tagString := fmt.Sprintf("tag.%s.%s", caller.username, caller.host)
	branch := "z9hG4bK.callbranch.INVITE"
	caller.dialog.callId = callid
	caller.dialog.from_tag = base.String{tagString}
	caller.dialog.currentTx = txInfo{}
	caller.dialog.currentTx.branch = branch

	invite := base.NewRequest(
		base.INVITE,
		&base.SipUri{
			User: &callee.username,
			Host: callee.host,
		},
		"SIP/2.0",
		[]base.SipHeader{
			Via(caller, branch),
			To(callee, caller.dialog.to_tag),
			From(caller, caller.dialog.from_tag),
			Contact(caller),
			CSeq(caller.dialog.cseq, base.INVITE),
			CallId(callid),
			ContentLength(0),
		},
		"",
	)
	caller.dialog.cseq += 1

	log.Info("Sending: %v", invite.Short())
	tx := caller.tm.Send(invite, fmt.Sprintf("%v:%v", callee.host, callee.port))
	caller.dialog.currentTx.tx = transaction.Transaction(tx)
	for {
		select {
		case r := <-tx.Responses():
			log.Info("Received response: %v", r.Short())
			log.Debug("Full form:\n%v\n", r.String())
			// Get To tag if present.
			tag, ok := r.Headers("To")[0].(*base.ToHeader).Params.Get("tag")
			if ok {
				caller.dialog.to_tag = tag.(base.String)
			}

			switch {
			case r.StatusCode >= 300:
				// Call setup failed.
				return fmt.Errorf("callee sent negative response code %v.", r.StatusCode)
			case r.StatusCode >= 200:
				// Ack 200s manually.
				log.Info("Sending Ack")
				tx.Ack()
				return nil
			}
		case e := <-tx.Errors():
			log.Warn(e.Error())
			return e
		}
	}
}
Exemplo n.º 2
0
func (caller *endpoint) nonInvite(callee *endpoint, method base.Method) error {
	caller.dialog.currentTx.branch = "z9hG4bK.callbranch." + string(method)
	request := base.NewRequest(
		method,
		&base.SipUri{
			User: &callee.username,
			Host: callee.host,
		},
		"SIP/2.0",
		[]base.SipHeader{
			Via(caller, caller.dialog.currentTx.branch),
			To(callee, caller.dialog.to_tag),
			From(caller, caller.dialog.from_tag),
			Contact(caller),
			CSeq(caller.dialog.cseq, method),
			CallId(caller.dialog.callId),
			ContentLength(0),
		},
		"",
	)
	caller.dialog.cseq += 1

	log.Info("Sending: %v", request.Short())
	tx := caller.tm.Send(request, fmt.Sprintf("%v:%v", callee.host, callee.port))
	caller.dialog.currentTx.tx = transaction.Transaction(tx)
	for {
		select {
		case r := <-tx.Responses():
			log.Info("Received response: %v", r.Short())
			log.Debug("Full form:\n%v\n", r.String())
			switch {
			case r.StatusCode >= 300:
				// Failure (or redirect).
				return fmt.Errorf("callee sent negative response code %v.", r.StatusCode)
			case r.StatusCode >= 200:
				// Success.
				log.Info("Successful transaction")
				return nil
			}
		case e := <-tx.Errors():
			log.Warn(e.Error())
			return e
		}
	}
}
Exemplo n.º 3
0
// Send an automatic ACK.
func (tx *ClientTransaction) Ack() {
	ack := base.NewRequest(base.ACK,
		tx.origin.Recipient,
		tx.origin.SipVersion,
		[]base.SipHeader{},
		"")

	// Copy headers from original request.
	// TODO: Safety
	base.CopyHeaders("From", tx.origin, ack)
	base.CopyHeaders("Call-Id", tx.origin, ack)
	base.CopyHeaders("Route", tx.origin, ack)
	cseq := tx.origin.Headers("CSeq")[0].Copy()
	cseq.(*base.CSeq).MethodName = base.ACK
	ack.AddHeader(cseq)
	via := tx.origin.Headers("Via")[0].Copy()
	ack.AddHeader(via)

	// Copy headers from response.
	base.CopyHeaders("To", tx.lastResp, ack)

	// Send the ACK.
	tx.transport.Send(tx.dest, ack)
}
Exemplo n.º 4
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
}
Exemplo n.º 5
0
func TestMassUDP(t *testing.T) {
	NUM_MSGS := 10000
	from, _ := NewManager("udp")
	to, _ := NewManager("udp")
	to.Listen(fmt.Sprintf("%s:%d", alice.host, alice.port))
	receiver := to.GetChannel()

	receivedIDs := make([]int, 0)
	result := make(chan bool)

	go func() {
	recvloop:
		for {
			select {
			case msg, ok := <-receiver:
				if !ok {
					break recvloop
				}
				id, _ := strconv.ParseInt(msg.GetBody(), 10, 32)
				receivedIDs = append(receivedIDs, int(id))
				if len(receivedIDs) >= NUM_MSGS {
					break recvloop
				}
			case <-time.After(time.Second / 10):
				break recvloop
			}
		}

		if !(len(receivedIDs) == NUM_MSGS) {
			t.Errorf("Error - received an unexpected number of messages: %d", len(receivedIDs))
		} else {
			seenSet := make(map[int]bool)
			for _, val := range receivedIDs {
				if _, match := seenSet[val]; match {
					t.Errorf("Duplicate message received: %d", val)
				}
				seenSet[val] = true
			}
			if len(seenSet) != NUM_MSGS {
				t.Errorf("Unexpected number of messages received: %d", len(seenSet))
			}
		}
		result <- true
	}()

	go func() {
		uri := base.SipUri{User: base.String{"alice"}, Host: "127.0.0.1", Port: nil, UriParams: base.NewParams(), Headers: base.NewParams()}
		for ii := 1; ii <= NUM_MSGS; ii++ {
			from.Send(fmt.Sprintf("%s:%d", alice.host, alice.port),
				base.NewRequest(base.ACK, &uri, "SIP/2.0",
					[]base.SipHeader{base.ContentLength(len(fmt.Sprintf("%d", ii)))},
					fmt.Sprintf("%d", ii)))

			if ii%100 == 0 {
				<-time.After(time.Millisecond)
			}
		}
	}()

	_ = <-result
	return
}