001package ball.upnp.ssdp;
002/*-
003 * ##########################################################################
004 * UPnP/SSDP Implementation Classes
005 * $Id: SSDPMessage.java 5285 2020-02-05 04:23:21Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-upnp/trunk/src/main/java/ball/upnp/ssdp/SSDPMessage.java $
007 * %%
008 * Copyright (C) 2013 - 2020 Allen D. Ball
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 *      http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * ##########################################################################
022 */
023import java.net.DatagramPacket;
024import java.net.InetSocketAddress;
025import java.net.SocketException;
026import java.net.URI;
027import java.nio.charset.Charset;
028import org.apache.http.Header;
029import org.apache.http.HttpHeaders;
030import org.apache.http.HttpMessage;
031
032import static java.nio.charset.StandardCharsets.UTF_8;
033
034/**
035 * SSDP {@link HttpMessage} interface definition.
036 *
037 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
038 * @version $Revision: 5285 $
039 */
040public interface SSDPMessage extends HttpMessage {
041
042    /**
043     * SSDP {@link Charset}
044     */
045    public static final Charset CHARSET = UTF_8;
046
047    /**
048     * SSDP IPv4 broadcast address
049     */
050    public static final InetSocketAddress ADDRESS =
051        new InetSocketAddress("239.255.255.250", 1900);
052
053    /**
054     * SSDP message header name
055     */
056    public static final String
057        AL = "AL",
058        EXT = "EXT",
059        MAN = "MAN",
060        MX = "MX",
061        NT = "NT",
062        NTS = "NTS",
063        ST = "ST",
064        USN = "USN";
065
066    /**
067     * SSDP {@link #NTS} value
068     */
069    public static final String
070        SSDP_ALIVE = "ssdp:alive",
071        SSDP_BYEBYE = "ssdp:byebye";
072
073    /**
074     * HTTP cache control key
075     */
076    public static final String
077        MAX_AGE = "max-age";
078
079    /**
080     * {@link SSDPMessage} end-of-line sequence.
081     */
082    public static final String CRLF = "\r\n";
083
084    /**
085     * Method to get the service location.
086     *
087     * @return  The service location {@link URI}.
088     */
089    public default URI getLocation() {
090        Header header = getFirstHeader(HttpHeaders.LOCATION);
091
092        if (header == null) {
093            header = getFirstHeader(AL);
094        }
095
096        String value = (header != null) ? header.getValue() : null;
097
098        return (value != null) ? URI.create(value) : null;
099    }
100
101    /**
102     * Method to get the service type ({@value #ST}).
103     *
104     * @return  The service type {@link URI}.
105     */
106    public default URI getST() {
107        Header header = getFirstHeader(ST);
108        String value = (header != null) ? header.getValue() : null;
109
110        return (value != null) ? URI.create(value) : null;
111    }
112
113    /**
114     * Method to get the {@value #USN} {@link URI}.
115     *
116     * @return  The {@value #USN} {@link URI}.
117     */
118    public default URI getUSN() {
119        Header header = getFirstHeader(USN);
120        String value = (header != null) ? header.getValue() : null;
121
122        return (value != null) ? URI.create(value) : null;
123    }
124
125    /**
126     * Method to encode {@link.this} {@link SSDPMessage} to a
127     * {@link DatagramPacket}.
128     *
129     * @return  The {@link DatagramPacket}.
130     *
131     * @throws  SocketException
132     *                          If this {@link SSDPMessage} cannot be
133     *                          converted to a {@link DatagramPacket}.
134     *
135     * @see #ADDRESS
136     */
137    public default DatagramPacket toDatagramPacket() throws SocketException {
138        byte[] bytes = toString().getBytes(CHARSET);
139
140        return new DatagramPacket(bytes, 0, bytes.length, ADDRESS);
141    }
142}