1/*
2 * Copyright (C) 2009 Google Inc.  All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.polo.pairing;
18
19import com.google.polo.exception.NoConfigurationException;
20import com.google.polo.exception.PoloException;
21import com.google.polo.pairing.message.ConfigurationAckMessage;
22import com.google.polo.pairing.message.ConfigurationMessage;
23import com.google.polo.pairing.message.EncodingOption;
24import com.google.polo.pairing.message.OptionsMessage.ProtocolRole;
25import com.google.polo.pairing.message.PairingRequestAckMessage;
26import com.google.polo.pairing.message.PairingRequestMessage;
27import com.google.polo.pairing.message.PoloMessage.PoloMessageType;
28import com.google.polo.wire.PoloWireInterface;
29
30import java.io.IOException;
31
32/**
33 * Pairing session state machine implementation for a server.
34 */
35public class ServerPairingSession extends PairingSession {
36  /**
37   * Optional server name.
38   */
39  private final String mServerName;
40
41  public ServerPairingSession(PoloWireInterface protocol,
42      PairingContext context) {
43    this(protocol, context, null);
44  }
45
46  public ServerPairingSession(PoloWireInterface protocol,
47      PairingContext context, String serverName) {
48    super(protocol, context);
49    mServerName = serverName;
50  }
51
52  @Override
53  protected void doInitializationPhase() throws PoloException, IOException {
54    logDebug("Waiting for PairingRequest...");
55    PairingRequestMessage request = (PairingRequestMessage)
56        getNextMessage(PoloMessageType.PAIRING_REQUEST);
57
58    logDebug("Requested service to pair: " + request.getServiceName());
59    mServiceName = request.getServiceName();
60
61    if (request.hasClientName()) {
62      logDebug("Client name: " + request.getClientName());
63      mPeerName = request.getClientName();
64    } else {
65      mPeerName = null;
66    }
67
68    logDebug("Sending PairingRequestAck ...");
69    PairingRequestAckMessage ack = new PairingRequestAckMessage(mServerName);
70    sendMessage(ack);
71
72    logDebug("Waiting for Options ...");
73    // Nothing to do with these; the client is responsible for intersecting
74    // our options with its, and proposing a valid configuration.
75    getNextMessage(PoloMessageType.OPTIONS);
76
77    logDebug("Sending Options...");
78    sendMessage(mLocalOptions);
79  }
80
81  @Override
82  protected void doConfigurationPhase() throws PoloException, IOException {
83    logDebug("Waiting for Configuration...");
84    setConfiguration((ConfigurationMessage) getNextMessage(
85        PoloMessageType.CONFIGURATION));
86
87    // Verify the configuration
88    EncodingOption encoding = mSessionConfig.getEncoding();
89
90    if (getLocalRole() == ProtocolRole.DISPLAY_DEVICE) {
91      if (!mLocalOptions.supportsOutputEncoding(encoding)) {
92        throw new NoConfigurationException("Cannot support requested  " +
93            "output encoding: " + encoding.getType());
94      }
95    } else if (getLocalRole() == ProtocolRole.INPUT_DEVICE) {
96      if (!mLocalOptions.supportsInputEncoding(encoding)) {
97        throw new NoConfigurationException("Cannot support requested " +
98            "input encoding: " + encoding.getType());
99      }
100    } else {
101      throw new IllegalStateException(); // should never happen
102    }
103
104    // Configuration accepted
105    logDebug("Sending ConfigurationAck...");
106    sendMessage(new ConfigurationAckMessage());
107  }
108
109  /**
110   * Returns {@code true} if server name is set.
111   */
112  public boolean hasServerName() {
113    return mServerName != null;
114  }
115
116  /**
117   * Returns {@code true} if client name is set.
118   */
119  public boolean hasClientName() {
120    return hasPeerName();
121  }
122
123  /**
124   * Returns server name, or {@code null} if not set.
125   */
126  public String getServerName() {
127    return mServerName;
128  }
129
130  /**
131   * Returns client name, or {@code null} if not set.
132   */
133  public String getClientName() {
134    return getPeerName();
135  }
136}
137