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.packet.sip.SipParseException;
import io.pkts.packet.sip.Transport;
import io.pkts.packet.sip.address.impl.SipURIImpl;
import io.pkts.packet.sip.header.impl.ParametersSupport;
import io.pkts.packet.sip.impl.SipParser;
import io.pkts.packet.sip.impl.SipUserHostInfo;
import java.io.IOException;
import java.util.Optional;
import static io.pkts.packet.sip.impl.PreConditions.assertArgument;
import static io.pkts.packet.sip.impl.PreConditions.assertNotEmpty;
import static io.pkts.packet.sip.impl.PreConditions.assertNotNull;
import static io.pkts.packet.sip.impl.PreConditions.checkIfNotEmpty;
/**
* @author [email protected]
*
*/
public interface SipURI extends URI {
/**
* Get the user portion of this URI.
*
* @return the user portion of this URI or an empty optional if there is no
* user portion
*/
Optional getUser();
/**
* Get the host portion of this URI.
*
* @return
*/
Buffer getHost();
/**
* Get the port. If the port isn't set then -1 (negative one) will be
* returned.
*
* @return
*/
int getPort();
@Override
default SipURI toSipURI() {
return this;
}
/**
* Set the port.
*
* If you specify -1 (negative one), then no port will be included in the final SIP URI.
* However, if you explicitly set the port to something, then it will be included in the final
* result.
*
* @param port
* @return
*/
// void setPort(int port);
/**
* Check whether this is a sips URI.
*
* @return true if this indeed is a sips URI, false otherwise.
*/
boolean isSecure();
/**
* Same as {@link #getParameter("transport")}
*
* @return
* @throws SipParseException
*/
Optional getTransportParam() throws SipParseException;
/**
* Get the user parameter. This is the same as {@link #getParameter("user")}
*
* @return
* @throws SipParseException
*/
Optional getUserParam() throws SipParseException;
/**
* Get the ttl parameter. This is the same as {@link #getParameter("ttl")}
*
* @return the value of the TTL parameter or -1 (negative one) if it is not set.
* @throws SipParseException
*/
int getTTLParam() throws SipParseException;
/**
* Get the maddr parameter. This is the same as {@link #getParameter("maddr")}
*
* @return
* @throws SipParseException
*/
Optional getMAddrParam() throws SipParseException;
/**
* Get the method parameter. This is the same as {@link #getParameter("method")}
*
* @return
* @throws SipParseException
*/
Optional getMethodParam() throws SipParseException;
/**
* Get the value of the named parameter. If the named parameter is a so-called flag parameter,
* then the value returned will be an empty {@link Buffer}, which can be checked with
* {@link Buffer#isEmpty()} or {@link Buffer#capacity()}, which will return zero. As with any
* empty {@link Buffer}, if you do {@link Buffer#toString()} you will be getting an empty
* {@link String} back, which would be yet another way to check for a flag parameter.
*
* @param name the name of the parameter we are looking for.
* @return the value of the named parameter or null if there is no such parameter. If the named
* parameter is a flag parameter, then an empty buffer will be returned.
* @throws SipParseException in case anything goes wrong while extracting the parameter.
* @throws IllegalArgumentException in case the name is null.
*/
Optional getParameter(Buffer name) throws SipParseException, IllegalArgumentException;
/**
* Same as {@link #getParameter(Buffer)}.
*
* @param name
* @return
* @throws SipParseException in case anything goes wrong while extracting the parameter.
* @throws IllegalArgumentException in case the name is null.
*/
Optional getParameter(String name) throws SipParseException, IllegalArgumentException;
/**
* Sets the value of the specified parameter. If there already is a parameter with the same name
* its value will be overridden.
*
* A value of null or a zero length buffer means that this parameter is a flag parameter
*
* @param name the name of the parameter
* @param value the value of the parameter or null if you just want to set a flag parameter
* @return the previous value or null if there were none associated with this parameter name
* @throws SipParseException in case anything goes wrong when setting the parameter.
* @throws IllegalArgumentException in case the name is null or empty.
*/
// void setParameter(Buffer name, Buffer value) throws SipParseException, IllegalArgumentException;
/**
*
* @param name
* @param value
* @throws SipParseException
* @throws IllegalArgumentException
*/
// void setParameter(String name, String value) throws SipParseException, IllegalArgumentException;
/**
*
* @param name
* @param value
* @throws SipParseException
* @throws IllegalArgumentException
*/
// void setParameter(Buffer name, int value) throws SipParseException, IllegalArgumentException;
/**
*
* @param name
* @param value
* @throws SipParseException
* @throws IllegalArgumentException
*/
// void setParameter(String name, int value) throws SipParseException, IllegalArgumentException;
/**
* See rules for comparing URI's in RFC3261 section 19.1.4.
*
* @param o
* @return
*/
@Override
boolean equals(final Object o);
@Override
SipURI clone();
@Override
Builder copy();
/**
* Frame a sip or sips-uri, which according to RFC3261 is:
*
*
*
* Remember though that all these frame-functions will only do a basic
* verification that all things are ok so just because this function return
* without an exception doesn't mean that you actually framed a valid URI.
* Everything is done lazily so things may blow up later.
*
* Also note that this function assumes that someone else has already determined the boundaries for this
* sip(s)-uri and as such, this function does not expect '<' etc.
*
* @param buffer
* @return
* @throws SipParseException
* @throws IOException
* @throws IndexOutOfBoundsException
*/
static SipURI frame(final Buffer buffer) throws SipParseException, IndexOutOfBoundsException, IOException {
final Buffer original = buffer.slice();
final int originalIndex = buffer.getReaderIndex();
// Determine if the URI begins with sip: or sips:, or throw a meaningful error message if not
final boolean isSips;
try {
isSips = SipParser.isSips(buffer);
} catch (final SipParseException e) {
throw new SipParseException(e.getErrorOffset() - 1, "SIP URI must start with sip: or sips:");
}
// Parse and validate the user/host portion
final SipUserHostInfo userHost;
final int userHostStartIndex = buffer.getReaderIndex();
try {
userHost = SipParser.consumeUserInfoHostPort(buffer);
} catch (final SipParseException e) {
// Re-throw the exception with the same message, but index adjusted for its position within
// the entire URI.
throw new SipParseException(userHostStartIndex + e.getErrorOffset(), e.getTemplate(), e);
}
// Validate the port number
final Buffer port = userHost.getPort();
if (port != null) {
try {
port.parseToInt();
} catch (final NumberFormatException e) {
throw new SipParseException(0, "The SIP URI had a port but it was not an integer: \"" + port.toString()
+ "\"");
}
}
return new SipURIImpl(isSips, userHost.getUser(), userHost.getHost(), port, buffer, original);
}
static SipURI frame(final String buffer) throws SipParseException, IndexOutOfBoundsException, IOException {
assertNotEmpty(buffer, "Cannot frame a null or empty string into a SIP URI");
return SipURI.frame(Buffers.wrap(buffer));
}
static Builder with() {
return new Builder();
}
static Builder builder() {
return new Builder();
}
/**
* Create a new builder based where the user portion has been specified.
*
* Note, even though the user portion of a SIP URI isn't mandatory it will be
* checked for empty or null by this method. The reason for this is simply
* if you call a method called "withUser" then it is assumed you actually do
* want the user portion to be present. If this is not what you want, simply
* call another "withXXX" method.
*
* @param user
* @return
*/
static Builder withUser(final String user) {
final Builder builder = new Builder();
return builder.withUser(user);
}
static Builder withUser(final Buffer user) {
final Builder builder = new Builder();
return builder.withUser(user);
}
static Builder withHost(final String host) {
final Builder builder = new Builder();
return builder.withHost(host);
}
static Builder withParameters(final Buffer params) {
final ParametersSupport paramSupport = new ParametersSupport(params);
return new Builder(paramSupport);
}
static Builder withHost(final Buffer host) {
final Builder builder = new Builder();
return builder.withHost(host);
}
/**
* Create a new {@link Builder} based on the {@link SipURI}.
*
*
*
user
*
host
*
port
*
transport
*
schema (sip or sips)
*
*
* Any other parameter will be ignored.
*
* @param uri
* @return
*/
static Builder withTemplate(final SipURI uri) {
final Builder b = new Builder();
b.withUser(uri.getUser().orElse(null));
b.withHost(uri.getHost());
b.withPort(uri.getPort());
b.withSecure(uri.isSecure());
uri.getTransportParam().ifPresent(t -> b.withParameter(SipParser.TRANSPORT, t.toBuffer()));
return b;
}
class Builder extends URI.Builder {
private Buffer user;
private Buffer host;
private Buffer port;
private boolean isSecure;
private ParametersSupport paramSupport;
/**
* The final size of the buffer. We keep track of this so we at the end
* can allocate a final buffer to which we will write all the various
* parts to this single buffer.
*
* Note, we start counting at 4 because by default the scheme is "sip", which
* will be 4 long including the ':' (colon, as in "sip:").
*/
private int size = 4;
private Builder() {
this(new ParametersSupport(null));
}
private Builder(final ParametersSupport params) {
this.paramSupport = params;
}
/**
*
* @param user
* @return
*/
public Builder withUser(final Buffer user) {
if (user != null && !user.isEmpty()) {
// note that we must subtract the previous capacity of the user portion.
// the +1 is for the '@' sign that we will write into the buffer if there
// indeed is a user portion in this URI.
size += user.capacity() + 1 - (this.user != null ? this.user.capacity() + 1 : 0);
this.user = user.slice();
} else {
size -= this.user != null ? this.user.capacity() + 1 : 0;
this.user = null;
}
return this;
}
/**
*
* @param user
* @return
*/
public Builder withUser(final String user) {
if (checkIfNotEmpty(user)) {
withUser(Buffers.wrap(user));
}
return this;
}
/**
* Specify the host. The host portion of a {@link SipURI} is mandatory so
*
* @param host
* @return
*/
public Builder withHost(final Buffer host) throws SipParseException {
assertNotNull(host, "Host cannot be null");
size += host.capacity() - (this.host != null ? this.host.capacity() : 0);
this.host = host.slice();
return this;
}
public Builder withHost(final String host) throws SipParseException {
assertNotEmpty(host, "Host cannot be null or the empty string");
return withHost(Buffers.wrap(host));
}
public Builder withTransport(final Transport transport) throws SipParseException {
assertNotNull(transport, "Transport cannot be null or empty");
this.paramSupport.setParameter(SipParser.TRANSPORT, transport.toBuffer());
return this;
}
public Builder withTransport(final Buffer transport) throws SipParseException {
// will check so that it is actually ok
Transport.of(transport);
this.paramSupport.setParameter(SipParser.TRANSPORT, transport);
return this;
}
public Builder withTransport(final String transport) throws SipParseException {
// will check so that it is actually ok
Transport.of(transport);
this.paramSupport.setParameter(SipParser.TRANSPORT, Buffers.wrap(transport));
return this;
}
public Builder withParameter(final Buffer name, final Buffer value) throws SipParseException,
IllegalArgumentException {
this.paramSupport.setParameter(name, value);
return this;
}
public Builder withParameter(final String name, final String value) throws SipParseException,
IllegalArgumentException {
this.paramSupport.setParameter(name, value);
return this;
}
public Builder withParameter(final String name, final int value) throws SipParseException,
IllegalArgumentException {
this.paramSupport.setParameter(Buffers.wrap(name), Buffers.wrap(value));
return this;
}
public Builder withParameter(final Buffer name, final int value) throws SipParseException,
IllegalArgumentException {
this.paramSupport.setParameter(name, Buffers.wrap(value));
return this;
}
/**
* Wipe out all parameters. 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() {
this.paramSupport = new ParametersSupport(null);
return this;
}
/**
* Mark this {@link SipURI} as a secure sip address, i.e. "sips". Same as calling
* {@link #secure(true)}
*
* @return
*/
public Builder secure() {
if (!this.isSecure) {
this.isSecure = true;
++size;
}
return this;
}
/**
* Mark this {@link SipURI} as a secure sip address, i.e. "sips" or as a non-secure, i.e.
* "sip"
*
* @return
*/
public Builder withSecure(final boolean secure) {
if (secure == this.isSecure) {
return this;
}
if (secure && !this.isSecure) {
++size;
} else {
--size;
}
this.isSecure = secure;
return this;
}
/**
* Set the port. Specify -1 (negative one) means that we should use the default port, as in
* we won't include the port at all in the resulting buffer. However, if you explicitly set
* the port to 5060 then it will be included in the final buffer..
*
* @param port
* @return
*/
public Builder withPort(final int port) throws SipParseException {
assertArgument(port > 0 || port == -1, "Port must be greater than zero or negative one (use default)");
if (port == -1) {
return withPort(null);
} else {
return withPort(Buffers.wrap(port));
}
}
/**
* Specify the port as a buffer.
* @param port if null the port will be reset.
* @return
* @throws SipParseException in case the port is
*/
public Builder withPort(final Buffer port) throws SipParseException {
if (port != null) {
try {
assertArgument(port.parseToInt() > 0, "Port must be greater than zero or null (use default)");
} catch (final IOException e) {
e.printStackTrace();
}
}
if (this.port != null) {
size -= this.port.capacity() + 1;
}
if (port == null) {
this.port = null;
} else {
this.port = port;
size += this.port.capacity() + 1;
}
return this;
}
/**
* Convenience method for removing the port from this SIP URI. Same as
* {@link io.pkts.packet.sip.address.SipURI.Builder#withPort(null)}
*
* @return
* @throws SipParseException
*/
public Builder withNoPort() throws SipParseException {
return withPort(null);
}
/**
* Use UDP as the transport.
*
* @return
*/
public Builder useUDP() {
this.paramSupport.setParameter(SipParser.TRANSPORT, SipParser.UDP);
return this;
}
/**
* Use TCP as the transport.
*
* @return
*/
public Builder useTCP() {
this.paramSupport.setParameter(SipParser.TRANSPORT, SipParser.TCP);
return this;
}
/**
* Use TLS as the transport.
*
* @return
*/
public Builder useTLS() {
this.paramSupport.setParameter(SipParser.TRANSPORT, SipParser.TLS);
return this;
}
/**
* Use SCTP as the transport.
*
* @return
*/
public Builder useSCTP() {
this.paramSupport.setParameter(SipParser.TRANSPORT, SipParser.SCTP);
return this;
}
/**
* Use WebSocket as the transport.
*
* @return
*/
public Builder useWS() {
this.paramSupport.setParameter(SipParser.TRANSPORT, SipParser.WS);
return this;
}
public Builder useWSS() {
this.paramSupport.setParameter(SipParser.TRANSPORT, SipParser.WSS);
return this;
}
public boolean hasParameters() {
return this.paramSupport.hasParameters();
}
/**
* Construct a {@link SipURI}.
*
* @return
* @throws SipParseException in case mandatory parameters, such as {@link #host(Buffer)} is
* missing or if other aspects of constructing the {@link SipURI} fails.
*/
public SipURI build() throws SipParseException {
assertNotEmpty(this.host, "Host cannot be empty");
final Buffer scheme = isSecure ? SipParser.SCHEME_SIPS_COLON : SipParser.SCHEME_SIP_COLON;
final Buffer params = this.paramSupport.toBuffer();
if (params != null) {
size += params.capacity();
}
final Buffer uri = Buffers.createBuffer(size);
transferbytes(uri, params);
return new SipURIImpl(this.isSecure, this.user, this.host, port, params, uri);
}
private void transferbytes(final Buffer dst, final Buffer params) {
if (this.isSecure) {
SipParser.SCHEME_SIPS_COLON.getBytes(0, dst);
} else {
SipParser.SCHEME_SIP_COLON.getBytes(0, dst);
}
if (this.user != null) {
this.user.getBytes(0, dst);
dst.write(SipParser.AT);
}
this.host.getBytes(0, dst);
if (this.port != null) {
dst.write(SipParser.COLON);
this.port.getBytes(0, dst);
}
params.getBytes(0, dst);
}
}
}