Exemplo n.º 1
0
  /**
   * @param remote Indicates who "generated" <code>code</code>.<br>
   *     <code>true</code> means that this endpoint received the <code>code</code> from the other
   *     endpoint.<br>
   *     false means this endpoint decided to send the given code,<br>
   *     <code>remote</code> may also be true if this endpoint started the closing handshake since
   *     the other endpoint may not simply echo the <code>code</code> but close the connection the
   *     same time this endpoint does do but with an other <code>code</code>. <br>
   */
  protected synchronized void closeConnection(int code, String message, boolean remote) {
    if (readystate == READYSTATE.CLOSED) {
      return;
    }

    if (key != null) {
      // key.attach( null ); //see issue #114
      key.cancel();
    }
    if (channel != null) {
      try {
        channel.close();
      } catch (IOException e) {
        wsl.onWebsocketError(this, e);
      }
    }
    try {
      this.wsl.onWebsocketClose(this, code, message, remote);
    } catch (RuntimeException e) {
      wsl.onWebsocketError(this, e);
    }
    if (draft != null) draft.reset();
    handshakerequest = null;

    readystate = READYSTATE.CLOSED;
    this.outQueue.clear();
  }
Exemplo n.º 2
0
 private void open(Handshakedata d) {
   if (DEBUG) System.out.println("open using draft: " + draft.getClass().getSimpleName());
   readystate = READYSTATE.OPEN;
   try {
     wsl.onWebsocketOpen(this, d);
   } catch (RuntimeException e) {
     wsl.onWebsocketError(this, e);
   }
 }
Exemplo n.º 3
0
 private void close(int code, String message, boolean remote) {
   if (readystate != READYSTATE.CLOSING && readystate != READYSTATE.CLOSED) {
     if (readystate == READYSTATE.OPEN) {
       if (code == CloseFrame.ABNORMAL_CLOSE) {
         assert (remote == false);
         readystate = READYSTATE.CLOSING;
         flushAndClose(code, message, false);
         return;
       }
       if (draft.getCloseHandshakeType() != CloseHandshakeType.NONE) {
         try {
           if (!remote) {
             try {
               wsl.onWebsocketCloseInitiated(this, code, message);
             } catch (RuntimeException e) {
               wsl.onWebsocketError(this, e);
             }
           }
           sendFrame(new CloseFrameBuilder(code, message));
         } catch (InvalidDataException e) {
           wsl.onWebsocketError(this, e);
           flushAndClose(CloseFrame.ABNORMAL_CLOSE, "generated frame is invalid", false);
         }
       }
       flushAndClose(code, message, remote);
     } else if (code == CloseFrame.FLASHPOLICY) {
       assert (remote);
       flushAndClose(CloseFrame.FLASHPOLICY, message, true);
     } else {
       flushAndClose(CloseFrame.NEVER_CONNECTED, message, false);
     }
     if (code == CloseFrame.PROTOCOL_ERROR) // this endpoint found a PROTOCOL_ERROR
     flushAndClose(code, message, remote);
     readystate = READYSTATE.CLOSING;
     tmpHandshakeBytes = null;
     return;
   }
 }
Exemplo n.º 4
0
  protected synchronized void flushAndClose(int code, String message, boolean remote) {
    if (flushandclosestate) {
      return;
    }
    closecode = code;
    closemessage = message;
    closedremotely = remote;

    flushandclosestate = true;

    wsl.onWriteDemand(
        this); // ensures that all outgoing frames are flushed before closing the connection
    try {
      wsl.onWebsocketClosing(this, code, message, remote);
    } catch (RuntimeException e) {
      wsl.onWebsocketError(this, e);
    }
    if (draft != null) draft.reset();
    handshakerequest = null;
  }
Exemplo n.º 5
0
  public void startHandshake(ClientHandshakeBuilder handshakedata)
      throws InvalidHandshakeException {
    assert (readystate != READYSTATE.CONNECTING) : "shall only be called once";

    // Store the Handshake Request we are about to send
    this.handshakerequest = draft.postProcessHandshakeRequestAsClient(handshakedata);

    // Notify Listener
    try {
      wsl.onWebsocketHandshakeSentAsClient(this, this.handshakerequest);
    } catch (InvalidDataException e) {
      // Stop if the client code throws an exception
      throw new InvalidHandshakeException("Handshake data rejected by client.");
    } catch (RuntimeException e) {
      wsl.onWebsocketError(this, e);
      throw new InvalidHandshakeException("rejected because of" + e);
    }

    // Send
    write(draft.createHandshake(this.handshakerequest, role));
  }
Exemplo n.º 6
0
  private void decodeFrames(ByteBuffer socketBuffer) {

    List<Framedata> frames;
    try {
      frames = draft.translateFrame(socketBuffer);
      for (Framedata f : frames) {
        if (DEBUG) System.out.println("matched frame: " + f);
        Opcode curop = f.getOpcode();
        boolean fin = f.isFin();

        if (curop == Opcode.CLOSING) {
          int code = CloseFrame.NOCODE;
          String reason = "";
          if (f instanceof CloseFrame) {
            CloseFrame cf = (CloseFrame) f;
            code = cf.getCloseCode();
            reason = cf.getMessage();
          }
          if (readystate == READYSTATE.CLOSING) {
            // complete the close handshake by disconnecting
            closeConnection(code, reason, true);
          } else {
            // echo close handshake
            if (draft.getCloseHandshakeType() == CloseHandshakeType.TWOWAY)
              close(code, reason, true);
            else flushAndClose(code, reason, false);
          }
          continue;
        } else if (curop == Opcode.PING) {
          wsl.onWebsocketPing(this, f);
          continue;
        } else if (curop == Opcode.PONG) {
          wsl.onWebsocketPong(this, f);
          continue;
        } else if (!fin || curop == Opcode.CONTINUOUS) {
          if (curop != Opcode.CONTINUOUS) {
            if (current_continuous_frame_opcode != null)
              throw new InvalidDataException(
                  CloseFrame.PROTOCOL_ERROR, "Previous continuous frame sequence not completed.");
            current_continuous_frame_opcode = curop;
          } else if (fin) {
            if (current_continuous_frame_opcode == null)
              throw new InvalidDataException(
                  CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started.");
            current_continuous_frame_opcode = null;
          } else if (current_continuous_frame_opcode == null) {
            throw new InvalidDataException(
                CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence was not started.");
          }
          try {
            wsl.onWebsocketMessageFragment(this, f);
          } catch (RuntimeException e) {
            wsl.onWebsocketError(this, e);
          }

        } else if (current_continuous_frame_opcode != null) {
          throw new InvalidDataException(
              CloseFrame.PROTOCOL_ERROR, "Continuous frame sequence not completed.");
        } else if (curop == Opcode.TEXT) {
          try {
            wsl.onWebsocketMessage(this, Charsetfunctions.stringUtf8(f.getPayloadData()));
          } catch (RuntimeException e) {
            wsl.onWebsocketError(this, e);
          }
        } else if (curop == Opcode.BINARY) {
          try {
            wsl.onWebsocketMessage(this, f.getPayloadData());
          } catch (RuntimeException e) {
            wsl.onWebsocketError(this, e);
          }
        } else {
          throw new InvalidDataException(
              CloseFrame.PROTOCOL_ERROR, "non control or continious frame expected");
        }
      }
    } catch (InvalidDataException e1) {
      wsl.onWebsocketError(this, e1);
      close(e1);
      return;
    }
  }
Exemplo n.º 7
0
  /**
   * Returns whether the handshake phase has is completed. In case of a broken handshake this will
   * be never the case.
   */
  private boolean decodeHandshake(ByteBuffer socketBufferNew) {
    ByteBuffer socketBuffer;
    if (tmpHandshakeBytes.capacity() == 0) {
      socketBuffer = socketBufferNew;
    } else {
      if (tmpHandshakeBytes.remaining() < socketBufferNew.remaining()) {
        ByteBuffer buf =
            ByteBuffer.allocate(tmpHandshakeBytes.capacity() + socketBufferNew.remaining());
        tmpHandshakeBytes.flip();
        buf.put(tmpHandshakeBytes);
        tmpHandshakeBytes = buf;
      }

      tmpHandshakeBytes.put(socketBufferNew);
      tmpHandshakeBytes.flip();
      socketBuffer = tmpHandshakeBytes;
    }
    socketBuffer.mark();
    try {
      if (draft == null) {
        HandshakeState isflashedgecase = isFlashEdgeCase(socketBuffer);
        if (isflashedgecase == HandshakeState.MATCHED) {
          try {
            write(ByteBuffer.wrap(Charsetfunctions.utf8Bytes(wsl.getFlashPolicy(this))));
            close(CloseFrame.FLASHPOLICY, "");
          } catch (InvalidDataException e) {
            close(
                CloseFrame.ABNORMAL_CLOSE,
                "remote peer closed connection before flashpolicy could be transmitted",
                true);
          }
          return false;
        }
      }
      HandshakeState handshakestate = null;

      try {
        if (role == Role.SERVER) {
          if (draft == null) {
            for (Draft d : knownDrafts) {
              d = d.copyInstance();
              try {
                d.setParseMode(role);
                socketBuffer.reset();
                Handshakedata tmphandshake = d.translateHandshake(socketBuffer);
                if (tmphandshake instanceof ClientHandshake == false) {
                  flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false);
                  return false;
                }
                ClientHandshake handshake = (ClientHandshake) tmphandshake;
                handshakestate = d.acceptHandshakeAsServer(handshake);
                if (handshakestate == HandshakeState.MATCHED) {
                  resourceDescriptor = handshake.getResourceDescriptor();
                  ServerHandshakeBuilder response;
                  try {
                    response = wsl.onWebsocketHandshakeReceivedAsServer(this, d, handshake);
                  } catch (InvalidDataException e) {
                    flushAndClose(e.getCloseCode(), e.getMessage(), false);
                    return false;
                  } catch (RuntimeException e) {
                    wsl.onWebsocketError(this, e);
                    flushAndClose(CloseFrame.NEVER_CONNECTED, e.getMessage(), false);
                    return false;
                  }
                  write(
                      d.createHandshake(
                          d.postProcessHandshakeResponseAsServer(handshake, response), role));
                  draft = d;
                  open(handshake);
                  return true;
                }
              } catch (InvalidHandshakeException e) {
                // go on with an other draft
              }
            }
            if (draft == null) {
              close(CloseFrame.PROTOCOL_ERROR, "no draft matches");
            }
            return false;
          } else {
            // special case for multiple step handshakes
            Handshakedata tmphandshake = draft.translateHandshake(socketBuffer);
            if (tmphandshake instanceof ClientHandshake == false) {
              flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false);
              return false;
            }
            ClientHandshake handshake = (ClientHandshake) tmphandshake;
            handshakestate = draft.acceptHandshakeAsServer(handshake);

            if (handshakestate == HandshakeState.MATCHED) {
              open(handshake);
              return true;
            } else {
              close(CloseFrame.PROTOCOL_ERROR, "the handshake did finaly not match");
            }
            return false;
          }
        } else if (role == Role.CLIENT) {
          draft.setParseMode(role);
          Handshakedata tmphandshake = draft.translateHandshake(socketBuffer);
          if (tmphandshake instanceof ServerHandshake == false) {
            flushAndClose(CloseFrame.PROTOCOL_ERROR, "wrong http function", false);
            return false;
          }
          ServerHandshake handshake = (ServerHandshake) tmphandshake;
          handshakestate = draft.acceptHandshakeAsClient(handshakerequest, handshake);
          if (handshakestate == HandshakeState.MATCHED) {
            try {
              wsl.onWebsocketHandshakeReceivedAsClient(this, handshakerequest, handshake);
            } catch (InvalidDataException e) {
              flushAndClose(e.getCloseCode(), e.getMessage(), false);
              return false;
            } catch (RuntimeException e) {
              wsl.onWebsocketError(this, e);
              flushAndClose(CloseFrame.NEVER_CONNECTED, e.getMessage(), false);
              return false;
            }
            open(handshake);
            return true;
          } else {
            close(CloseFrame.PROTOCOL_ERROR, "draft " + draft + " refuses handshake");
          }
        }
      } catch (InvalidHandshakeException e) {
        close(e);
      }
    } catch (IncompleteHandshakeException e) {
      if (tmpHandshakeBytes.capacity() == 0) {
        socketBuffer.reset();
        int newsize = e.getPreferedSize();
        if (newsize == 0) {
          newsize = socketBuffer.capacity() + 16;
        } else {
          assert (e.getPreferedSize() >= socketBuffer.remaining());
        }
        tmpHandshakeBytes = ByteBuffer.allocate(newsize);

        tmpHandshakeBytes.put(socketBufferNew);
        // tmpHandshakeBytes.flip();
      } else {
        tmpHandshakeBytes.position(tmpHandshakeBytes.limit());
        tmpHandshakeBytes.limit(tmpHandshakeBytes.capacity());
      }
    }
    return false;
  }