Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
*
*/
package io.pkts.packet.sip.address;
import io.pkts.buffer.Buffer;
import io.pkts.buffer.Buffers;
import io.pkts.buffer.ByteNotFoundException;
import io.pkts.packet.sip.SipParseException;
import io.pkts.packet.sip.address.impl.AddressImpl;
import io.pkts.packet.sip.impl.SipParser;
import java.io.IOException;
import static io.pkts.packet.sip.impl.PreConditions.assertArgument;
import static io.pkts.packet.sip.impl.PreConditions.assertNotNull;
import static io.pkts.packet.sip.impl.PreConditions.ifNull;
/**
* Represents an address and like everything else, it is an immutable class.
*
* @author [email protected]
*/
public interface Address {
/**
* Get the display name of this {@link Address} or an empty buffer if it is
* not set.
*
* @return
*/
Buffer getDisplayName();
/**
* Get the {@link URI} of this {@link Address}.
*
* @return the {@link URI}
* @throws SipParseException
*/
URI getURI() throws SipParseException;
/**
* Get the {@link Address} as a raw buffer.
*
* @return
*/
Buffer toBuffer();
void getBytes(Buffer dst);
/**
* An {@link Address} is an immutable object so if you wish to change something
* you have to create a copy of it.
*
* @return
*/
Builder copy();
static Address frame(final String buffer) throws SipParseException, IndexOutOfBoundsException, IOException {
return frame(Buffers.wrap(buffer));
}
/**
*
* Parses a SIP "name-addr" as defined by RFC3261 section 25.1:
*
*
*
* @param buffer
* @return
* @throws SipParseException
* @throws IOException
*/
static Address frame(final Buffer buffer) throws SipParseException, IndexOutOfBoundsException,
IOException {
SipParser.consumeWS(buffer);
final Buffer original = buffer.slice();
boolean doubleQuote = false;
if (buffer.peekByte() == SipParser.DQUOT) {
doubleQuote = true;
}
final Buffer displayName = SipParser.consumeDisplayName(buffer);
boolean leftAngleBracket = true;
// handle the case of an address that looks like:
// ""
// where the two double quotes is the ones that
// caused a problem. This checks for that case and
// consumes any potential white space that is left
// after the consumption of that weird display name
if (doubleQuote && displayName.isEmpty()) {
SipParser.consumeWS(buffer);
}
// if no display name, then there may be a '<' present
// and if so, consume it.
if (displayName.isEmpty() && buffer.peekByte() == SipParser.LAQUOT) {
buffer.readByte();
} else if (!displayName.isEmpty()) {
// if display name, we DO expect a '<'. Note, there may or may
// not be white space before the <
SipParser.consumeWS(buffer);
SipParser.expect(buffer, SipParser.LAQUOT);
} else {
leftAngleBracket = false;
}
// if there is no angle bracket then we are not protected
// by the '<' '>' construct so then we must actually break
// when we hit a ';' or a '?' since those would then be part
// of the header and not the URI
Buffer addrSpec = null;
if (!leftAngleBracket) {
try {
final int index = buffer.indexOf(1024, SipParser.SEMI, SipParser.QUESTIONMARK, SipParser.CR,
SipParser.LF);
if (index >= 0) {
final Buffer temp = buffer.readBytes(index - buffer.getReaderIndex());
addrSpec = SipParser.consumeAddressSpec(temp);
} else {
// none of the bytes we were looking for was found
// so we will just consume the entire buffer
addrSpec = SipParser.consumeAddressSpec(buffer);
}
} catch (final ByteNotFoundException e) {
throw new SipParseException(buffer.getReaderIndex(),
"Unable to parse the uri (addr-spec) portion of the address");
}
} else {
addrSpec = SipParser.consumeAddressSpec(buffer);
}
if (addrSpec == null) {
throw new SipParseException(buffer.getReaderIndex(), "Unable to find the name-addr portion");
}
if (displayName.isEmpty() && buffer.hasReadableBytes() && buffer.peekByte() == SipParser.RAQUOT) {
buffer.readByte();
} else if (!displayName.isEmpty()) {
// if display name, we DO expect a '>'
SipParser.expect(buffer, SipParser.RAQUOT);
}
final URI uri = URI.frame(addrSpec);
return new AddressImpl(original, displayName, uri);
}
static Builder builder() {
return new Builder();
}
static Builder withHost(final Buffer host) {
final Builder builder = new Builder();
return builder.withHost(assertNotNull(host, "host cannot be null"));
}
static Builder withHost(final String host) {
final Builder builder = new Builder();
return builder.withHost(assertNotNull(host, "host cannot be null"));
}
static Builder withURI(final URI uri) {
final Builder builder = new Builder();
builder.withURI(uri);
return builder;
}
class Builder {
private SipURI.Builder uriBuilder;
private Buffer displayName;
private Builder() {
// left empty intentionally
}
/**
* Use this user for the {@link SipURI} that will be part of this {@link Address}. See
* {@link #withHost(Buffer)} for more information.
*
* @param user
* @return
*/
public Builder withUser(final Buffer user) {
ensureURIBuilder().withUser(user);
return this;
}
public Builder withUser(final String user) {
ensureURIBuilder().withUser(user);
return this;
}
/**
* Use this port for the {@link SipURI} that will be part of this {@link Address}. See
* {@link #withHost(Buffer)} for more information.
*
* @param port
* @return
*/
public Builder withPort(final int port) {
ensureURIBuilder().withPort(port);
return this;
}
/**
* Set a parameter on the URI within the {@link Address} object.
*
* @param name
* @param value
* @return
* @throws SipParseException
* @throws IllegalArgumentException
*/
public Builder withURIParameter(final Buffer name, final Buffer value) throws SipParseException,
IllegalArgumentException {
ensureURIBuilder().withParameter(name, value);
return this;
}
/**
* Set a parameter on the URI within the {@link Address} object.
*
* @param name
* @param value
* @return
* @throws SipParseException
* @throws IllegalArgumentException
*/
public Builder withURIParameter(final String name, final String value) throws SipParseException,
IllegalArgumentException {
ensureURIBuilder().withParameter(name, value);
return this;
}
/**
* Set a parameter on the URI within the {@link Address} object.
*
* @param name
* @param value
* @return
* @throws SipParseException
* @throws IllegalArgumentException
*/
public Builder withURIParameter(final String name, final int value) throws SipParseException,
IllegalArgumentException {
ensureURIBuilder().withParameter(name, value);
return this;
}
/**
* Set a parameter on the URI within the {@link Address} object.
*
* @param name
* @param value
* @return
* @throws SipParseException
* @throws IllegalArgumentException
*/
public Builder withURIParameter(final Buffer name, final int value) throws SipParseException,
IllegalArgumentException {
ensureURIBuilder().withParameter(name, value);
return this;
}
/**
* Wipe out all parameters on the URI within the {@link Address} object.
*
* Useful if you e.g. create a copy of a SipURI but you want to remove any potential parameters that may be on the SIP URI.
*
* @return
*/
public Builder withNoParameters() {
ensureURIBuilder().withNoParameters();
return this;
}
/**
* Set UDP as the transport on the wrapped SIP URI (assuming this is a SIP URI that this
* {@link Address} object is indeed wrapping).
*
* @return
*/
public Builder withTransportUDP() {
ensureURIBuilder().useUDP();
return this;
}
/**
* Set TCP as the transport on the wrapped SIP URI (assuming this is a SIP URI that this
* {@link Address} object is indeed wrapping).
*
* @return
*/
public Builder withTransportTCP() {
ensureURIBuilder().useTCP();
return this;
}
/**
* Set TLS as the transport on the wrapped SIP URI (assuming this is a SIP URI that this
* {@link Address} object is indeed wrapping).
*
* @return
*/
public Builder withTransportTLS() {
ensureURIBuilder().useTLS();
return this;
}
/**
* Set SCTP as the transport on the wrapped SIP URI (assuming this is a SIP URI that this
* {@link Address} object is indeed wrapping).
*
* @return
*/
public Builder withTransportSCTP() {
ensureURIBuilder().useSCTP();
return this;
}
public Builder withTransport(final Buffer transport) throws SipParseException {
ensureURIBuilder().withTransport(transport);
return this;
}
public Builder withTransport(final String transport) throws SipParseException {
ensureURIBuilder().withTransport(transport);
return this;
}
/**
* Set WS as the transport on the wrapped SIP URI (assuming this is a SIP URI that this
* {@link Address} object is indeed wrapping).
*
* @return
*/
public Builder withTransportWS() {
ensureURIBuilder().useWS();
return this;
}
/**
* Set WSS as the transport on the wrapped SIP URI (assuming this is a SIP URI that this
* {@link Address} object is indeed wrapping).
*
* @return
*/
public Builder withTransportWSS() {
ensureURIBuilder().useWSS();
return this;
}
/**
* Use this host for the URI with this {@link Address}. This is a convenient way of creating
* an {@link Address} with a {@link SipURI} and is the same as:
*
*
* SipURI uri = SipURI.with().host(host).build();
* Address.with(uri);
*
*
* NOTE: you cannot specify a host and also specify a URI since those would conflict and an
* exception will occur at the time you try and {@link #build()} the address.
*
* @param host
* @return
*/
public Builder withHost(final Buffer host) {
ensureURIBuilder().withHost(host);
return this;
}
public Builder withHost(final String host) {
ensureURIBuilder().withHost(host);
return this;
}
public Builder withDisplayName(final Buffer displayName) {
this.displayName = ifNull(displayName, Buffers.EMPTY_BUFFER);
return this;
}
public Builder withDisplayName(final String displayName) {
this.displayName = Buffers.wrap(ifNull(displayName, ""));
return this;
}
private SipURI.Builder ensureURIBuilder() {
if (uriBuilder == null) {
uriBuilder = SipURI.builder();
}
return uriBuilder;
}
public Builder withURI(final URI uri) {
assertNotNull(uri, "URI cannot be null");
assertArgument(uri.isSipURI(), "Can only do SIP URIs right now");
uriBuilder = uri.toSipURI().copy();
return this;
}
public Address build() throws SipParseException {
final SipURI uri = uriBuilder.build();
final Buffer uriBuffer = uri.toBuffer();
int size = uriBuffer.capacity();
boolean doubleQuoteIt = false;
final boolean yesDisplayName = displayName != null && !displayName.isEmpty();
if (yesDisplayName) {
size += displayName.capacity() + 1; // +1 for space
if (doubleQuoteIt(displayName)) {
doubleQuoteIt = true;
size += 2; // because we will surround the display name with double quotes.
}
}
// we will only add the angle brackets if there is a display name and/or there
// are parameters on the URI. See RFC3261 section
final boolean yesAngleQuoteIt = yesDisplayName || uriBuilder.hasParameters();
if (yesAngleQuoteIt) {
size += 2;
}
final Buffer addressBuf = Buffers.createBuffer(size);
if (yesDisplayName) {
if (doubleQuoteIt) {
addressBuf.write(SipParser.DOUBLE_QOUTE);
displayName.getBytes(0, addressBuf);
addressBuf.write(SipParser.DOUBLE_QOUTE);
} else {
displayName.getBytes(0, addressBuf);
}
addressBuf.write(SipParser.SP);
}
if (yesAngleQuoteIt) {
addressBuf.write(SipParser.LAQUOT);
uriBuffer.getBytes(0, addressBuf);
addressBuf.write(SipParser.RAQUOT);
} else {
uriBuffer.getBytes(0, addressBuf);
}
return new AddressImpl(addressBuf, this.displayName, uri);
}
private boolean doubleQuoteIt(final Buffer buffer) {
try {
// Don't think a display name would be longer than 1k but if
// it is and there is a space after that 1k then this fails...
return buffer.indexOf(1024, SipParser.SP, SipParser.HTAB) != -1
&& buffer.getByte(0) != SipParser.DOUBLE_QOUTE;
} catch (final IOException e) {
// ignore, can't happen
return false;
}
}
}
}