Live Sequence Protocol for Java
Implementation of LSP in Java language
 Todos Classes Namespaces Arquivos Funções Variáveis
LspServer.java
Vá para a documentação deste arquivo.
1 package lsp;
2 
3 import java.io.IOException;
4 import java.net.SocketAddress;
5 import java.nio.ByteBuffer;
6 import java.util.concurrent.ConcurrentHashMap;
7 import java.util.concurrent.ConcurrentMap;
8 import java.util.concurrent.atomic.AtomicInteger;
9 
15 public class LspServer {
17  private final ConcurrentMap<Short, LspConnection> connectionPool = new ConcurrentHashMap<>(16);
18 
25  private final ConcurrentMap<Long, LspConnection> connectedSockets = new ConcurrentHashMap<>(16);
26 
27  // Variáveis de controle do servidor
28  private final AtomicInteger idCounter = new AtomicInteger();
29  private volatile boolean active = true;
30  private volatile boolean markClosed;
31 
32  /* Parâmetros do servidor */
33  private final LspParams params;
34 
35  /* Socket LSP */
36  private final LspSocket lspSocket;
37  private final int port;
38 
39  public LspServer(int port, LspParams params) throws IOException {
40  this.lspSocket = new LspSocketImpl(port);
41  this.port = this.lspSocket.getPort();
42  this.params = params == null ? LspParams.defaultParams() : params;
43  }
44 
55  public Pack read() {
56  checkActive();
57  return lspSocket.receive();
58  }
59 
66  public void write(Pack pack) {
67  checkActive();
68 
69  final LspConnection conn = connectionPool.get(pack.getConnId());
70  if (conn == null || conn.isClosed()) {
71  throw new ClosedConnectionException(pack.getConnId());
72  }
73 
74  lspSocket.send(pack);
75  conn.incSendMissing();
76  }
77 
87  public void closeConn(short connId) {
88  checkActive();
89 
90  final LspConnection conn = connectionPool.get(connId);
91  if (conn == null) {
92  throw new ClosedConnectionException(connId);
93  }
94 
95  // Marca a conexão como fechada e se não há mensagens para serem
96  // enviadas, encerra a conexão formalmente e remove da lista de conexões
97  // e do conjunto de sockets.
98  conn.close(false);
99  if (conn.getSendMissing() == 0) {
100  realCloseConn(connId, conn);
101  return;
102  }
103 
104  while (!conn.isInterrupted()) {
105  try {
106  Thread.sleep(params.getEpoch());
107  } catch (InterruptedException e) {
108  return;
109  }
110  }
111  }
112 
113  private void realCloseConn(short connId, final LspConnection conn) {
114  conn.close();
115  connectionPool.remove(connId);
116  connectedSockets.remove(conn.getSockId());
117  }
118 
123  public void closeAll() {
124  // Marca servidor como fechado para novas entradas
125  this.markClosed = true;
126 
127  // Marca todas as conexões como fechadas (em paralelo)
128  for (final LspConnection conn : connectionPool.values()) {
129  new Thread() {
130  public void run() {
131  conn.close(false);
132  };
133  }.start();
134  }
135 
136  // Aguarda o pool de conexão se esvaziar
137  while (!connectionPool.isEmpty()) {
138  try {
139  Thread.sleep(params.getEpoch());
140  } catch (InterruptedException e) {
141  break;
142  }
143  }
144 
145  // Marca servidor como inativo e fecha socket lsp
146  this.active = false;
147  this.lspSocket.close();
148 
149  // Limpeza de memória
150  this.connectionPool.clear();
151  this.connectedSockets.clear();
152  }
153 
154  private void checkActive() {
155  if (!active || markClosed)
156  throw new ClosedConnectionException();
157  }
158 
159  public int getPort() {
160  return this.port;
161  }
162 
163  private Short newConnId() {
164  synchronized (idCounter) {
165  // Se a quantidade de conexões já é o máximo suportado não vale a
166  // pena pesquisar por um id livre
167  if (connectionPool.size() == 65535) {
168  return null;
169  }
170 
171  // Pesquisa por um id livre
172  while (true) {
173  final short id = (short) idCounter.incrementAndGet();
174  if (id == 0) {
175  continue;
176  }
177  if (!connectionPool.containsKey(id)) {
178  return id;
179  }
180  }
181  }
182  }
183 
184  private final class LspSocketImpl extends LspSocket {
185  LspSocketImpl(final int port) throws IOException {
186  super(port);
187  }
188 
189  @Override
190  boolean isActive() {
191  return active;
192  }
193 
194  @Override
195  void dgramReceiveConnect(final SocketAddress sockAddr, final ByteBuffer buf) {
196  // Somente serão aceitos pedidos de conexão bem formados, isto é,
197  // aqueles em que Connection ID e Sequence Number são iguais a zero
198  if (buf.getInt() == 0) {
199  final long sockId = LspConnection.uniqueSockId(sockAddr);
200 
201  // A abertura de novas conexões é feita a seguir. A condição
202  // garante não abrir nova conexão se esta já está aberta
203  LspConnection conn = connectedSockets.get(sockId);
204  if (conn == null) {
205  // Verifica se há espaço no pool para mais conexões
206  final Short newId = newConnId();
207  if (newId == null) {
208  return;
209  }
210 
211  ServerTriggers triggers = new ServerTriggers();
212 
213  // Adicionando a conexão ao pool de conexão
214  conn = new LspConnection(newId, sockId, sockAddr, params, triggers);
215  connectionPool.put(newId, conn);
216  connectedSockets.put(sockId, conn);
217  dgramSendAck(conn, (short) 0);
218 
219  // Adicionando referência da conexão associada a triggers
220  triggers.bindedConn = conn;
221  }
222 
223  // Mesmo recebendo o pedido de conexão do mesmo socket remoto,
224  // deve ser avisado que a conexão recebeu uma mensagem.
225  else {
226  conn.received();
227  }
228  }
229  }
230 
231  LspConnection usedConnection(short connId) {
232  return connectionPool.get(connId);
233  }
234  }
235 
236  private final class ServerTriggers implements ConnectionTriggers {
237  public LspConnection bindedConn;
238 
239  @Override
240  public void doEpochActions() {
241  Helpers.resendData(lspSocket, bindedConn);
242  Helpers.resendAck(lspSocket, bindedConn);
243  }
244 
245  @Override
246  public void doCloseConnection() {
247  realCloseConn(bindedConn.getId(), bindedConn);
248  }
249  }
250 }
Serviço de entrada e saída de pacotes.
Definition: LspSocket.java:26
Representa uma conexão LSP.
short getConnId()
Definition: Pack.java:12
Pack read()
Lê dados da fila de entrada do servidor.
Definition: LspServer.java:55
void closeConn(short connId)
Encerra uma conexão com o identificador connId.
Definition: LspServer.java:87
LspServer(int port, LspParams params)
Definition: LspServer.java:39
final void dgramSendAck(final LspConnection conn, final short seqNum)
Definition: LspSocket.java:283
void closeAll()
Encerra todas as conexões ativas e a atividade do servidor.
Definition: LspServer.java:123
void write(Pack pack)
Envia dados para um determinado cliente.
Definition: LspServer.java:66
int getSendMissing()
Número de mensagens na fila, mas faltam enviar.
Servidor LSP.
Definition: LspServer.java:15