func (this *SIPResponse) CreateRequest(requestURI address.SipURI, via *header.Via, cseq *header.CSeq) *SIPRequest { newRequest := NewSIPRequest() method := cseq.GetMethod() newRequest.SetMethod(method) newRequest.SetRequestURI(requestURI) if (method == "ACK" || method == "CANCEL") && this.GetTopmostVia().GetBranch() != "" { // Use the branch id from the OK. //try { via.SetBranch(this.GetTopmostVia().GetBranch()) //} catch (ParseException ex) {} } newRequest.SetHeader(via) newRequest.SetHeader(cseq) for headerIterator := this.getHeaders().Front(); headerIterator != nil; headerIterator = headerIterator.Next() { nextHeader := headerIterator.Value.(header.Header) // Some headers do not belong in a Request .... if this.IsResponseHeader(nextHeader) { continue } if _, ok := nextHeader.(*header.ViaList); ok { continue } if _, ok := nextHeader.(*header.CSeq); ok { continue } if _, ok := nextHeader.(*header.ContentType); ok { continue } if _, ok := nextHeader.(*header.RecordRouteList); ok { continue } // if _, ok:=nextHeader.(*header.To); ok{ // nextHeader = nextHeader.clone(); // } // else if (nextHeader instanceof From) // nextHeader = (SIPHeader)nextHeader.clone(); // try { newRequest.AttachHeader2(nextHeader, false) // } catch(SIPDuplicateHeaderException e){ // e.printStackTrace(); // } } return newRequest }
/** * Generate (compute) a transaction ID for this SIP message. * @return A string containing the concatenation of various * portions of the From,To,Via and RequestURI portions * of this message as specified in RFC 2543: * All responses to a request contain the same values in * the Call-ID, CSeq, To, and From fields * (with the possible addition of a tag in the To field * (section 10.43)). This allows responses to be matched with requests. * Incorporates a bug fix for a bug sent in by Gordon Ledgard of * IPera for generating transactionIDs when no port is present in the * via header. * Incorporates a bug fix for a bug report sent in by Chris Mills * of Nortel Networks (converts to lower case when returning the * transaction identifier). * *@return a string that can be used as a transaction identifier * for this message. This can be used for matching responses and * requests (i.e. an outgoing request and its matching response have * the same computed transaction identifier). */ func (this *SIPMessage) GetTransactionId() string { var topVia *header.Via if this.GetViaHeaders().Len() > 0 { topVia = this.GetViaHeaders().Front().Value.(*header.Via) } // Have specified a branch Identifier so we can use it to identify // the transaction. BranchId is not case sensitive. // Branch Id prefix is not case sensitive. if topVia != nil && topVia.GetBranch() != "" && strings.Contains(strings.ToUpper(topVia.GetBranch()), strings.ToUpper(header.SIPConstants_BRANCH_MAGIC_COOKIE)) { // Bis 09 compatible branch assignment algorithm. // implies that the branch id can be used as a transaction // identifier. return strings.ToLower(topVia.GetBranch()) } else { // Old style client so construct the transaction identifier // from various fields of the request. var retval bytes.Buffer from := this.GetFrom().(*header.From) to := this.GetTo().(*header.To) hpFrom := from.GetUserAtHostPort() retval.WriteString(hpFrom + ":") if from.HasTag() { retval.WriteString(from.GetTag() + ":") } hpTo := to.GetUserAtHostPort() retval.WriteString(hpTo + ":") cid := this.callIdHeader.GetCallId() retval.WriteString(cid + ":") retval.WriteRune(rune(this.cSeqHeader.GetSequenceNumber())) retval.WriteString(":" + this.cSeqHeader.GetMethod()) if topVia != nil { retval.WriteString(":" + topVia.GetSentBy().String()) if !topVia.GetSentBy().HasPort() { retval.WriteString(":") retval.WriteRune(5060) } } hc := ToHexString([]byte(strings.ToLower(retval.String()))) if len(hc) < 32 { return hc } else { return hc[len(hc)-32 : len(hc)] } } // Convert to lower case -- bug fix as a result of a bug report // from Chris Mills of Nortel Networks. }
/** a parser for the essential part of the via header. */ func (this *ViaParser) ParseVia(v *header.Via) (ParseException error) { lexer := this.GetLexer() var protocolName, protocolVersion *core.Token // The protocol lexer.Match(TokenTypes_ID) if protocolName = lexer.GetNextToken(); protocolName.GetTokenValue() != "SIP" { return this.CreateParseException("Protcoal Not Supported error") } lexer.SPorHT() // consume the "/" lexer.Match('/') lexer.SPorHT() lexer.Match(TokenTypes_ID) lexer.SPorHT() if protocolVersion = lexer.GetNextToken(); protocolVersion.GetTokenValue() != "2.0" { return this.CreateParseException("Version Not Supported error") } lexer.SPorHT() // We consume the "/" lexer.Match('/') lexer.SPorHT() lexer.Match(TokenTypes_ID) lexer.SPorHT() transport := lexer.GetNextToken() lexer.SPorHT() protocol := header.NewProtocol() protocol.SetProtocolName(protocolName.GetTokenValue()) protocol.SetProtocolVersion(protocolVersion.GetTokenValue()) protocol.SetTransport(transport.GetTokenValue()) v.SetSentProtocol(protocol) // sent-By hnp := core.NewHostNameParserFromLexer(this.GetLexer()) var hostPort *core.HostPort if hostPort, ParseException = hnp.GetHostPort(); ParseException != nil { return ParseException } v.SetSentBy(hostPort) // Ignore blanks lexer.SPorHT() var la byte for la, _ = lexer.LookAheadK(0); la == ';'; la, _ = lexer.LookAheadK(0) { lexer.Match(';') lexer.SPorHT() var nameValue *core.NameValue if nameValue, ParseException = this.NameValue(); ParseException != nil { return ParseException } name := nameValue.GetName() nameValue.SetName(strings.ToLower(name)) v.SetParameterFromNameValue(nameValue) lexer.SPorHT() } if la, _ = lexer.LookAheadK(0); la == '(' { lexer.SelectLexer("charLexer") lexer.ConsumeK(1) var comment bytes.Buffer for { ch, _ := lexer.LookAheadK(0) if ch == ')' { lexer.ConsumeK(1) break } else if ch == '\\' { // Escaped character tok := lexer.GetNextToken() comment.WriteString(tok.GetTokenValue()) lexer.ConsumeK(1) tok = lexer.GetNextToken() comment.WriteString(tok.GetTokenValue()) lexer.ConsumeK(1) } else if ch == '\n' { break } else { comment.WriteByte(ch) lexer.ConsumeK(1) } } v.SetComment(comment.String()) } return nil }