use of won.owner.pojo.ServerSideConnectPayload in project webofneeds by researchstudio-sat.
the class ServerSideActionController method connectSockets.
// rsponses: 204 (no content) or 409 (conflict)
@RequestMapping(value = "/connect", method = RequestMethod.POST)
public ResponseEntity connectSockets(@RequestBody(required = true) ServerSideConnectPayload connectAction) {
String username = SecurityContextHolder.getContext().getAuthentication().getName();
// cannot use user object from context since hw doesn't know about created in
// this session atom,
// therefore, we have to retrieve the user object from the user repository
User user = userService.getByUsername(username);
if (user == null) {
return new ResponseEntity("Cannot process connect action: not logged in.", HttpStatus.FORBIDDEN);
}
if (StringUtils.isEmpty(connectAction.getFromSocket())) {
return new ResponseEntity("Cannot process connect action: from socket not specified.", HttpStatus.CONFLICT);
}
if (StringUtils.isEmpty(connectAction.getToSocket())) {
return new ResponseEntity("Cannot process connect action: to socket not specified.", HttpStatus.CONFLICT);
}
Set<UserAtom> atoms = user.getUserAtoms();
if (!(connectAction.isFromPending() || atoms.stream().anyMatch(atom -> connectAction.getFromSocket().startsWith(atom.getUri().toString())))) {
return new ResponseEntity("Cannot process connect action: from atom is not owned nor in pending.", HttpStatus.CONFLICT);
}
if (connectAction.isAutoOpen() && !(connectAction.isToPending() || atoms.stream().anyMatch(atom -> connectAction.getToSocket().startsWith(atom.getUri().toString())))) {
return new ResponseEntity("Cannot process connect autoOpen action: to atom is not owned nor in pending.", HttpStatus.CONFLICT);
}
serverSideActionService.connect(connectAction, SecurityContextHolder.getContext().getAuthentication());
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
use of won.owner.pojo.ServerSideConnectPayload in project webofneeds by researchstudio-sat.
the class ServerSideActionService method connect.
/**
* Connect the specified sockets, optionally waiting until the respective atoms
* have been created. Use the specified authentication for sending messages on
* behalf of the user the authentication was obtained from.
*/
public void connect(ServerSideConnectPayload connectAction, Authentication authentication) {
// a little bit of shared state for the actions we are creating:
if (StringUtils.isEmpty(connectAction.getFromSocket()) || StringUtils.isEmpty(connectAction.getToSocket())) {
throw new IllegalArgumentException("From and To Socket expected");
}
// we want to have 2 atoms before we can start connecting:
final AtomicInteger atomCounter = new AtomicInteger(0);
final AtomicBoolean connectSent = new AtomicBoolean(false);
final URI fromSocket = URI.create(connectAction.getFromSocket());
final String message = connectAction.getMessage();
final URI toSocket = URI.create(connectAction.getToSocket());
// count the sockets that are NOT pending (= the number of atoms that have
// already been created)
int atoms = 2;
if (connectAction.isFromPending()) {
atoms--;
}
if (connectAction.isToPending()) {
atoms--;
}
atomCounter.set(atoms);
final Function<Optional<WonMessage>, Collection<EventTriggeredAction<WonMessage>>> action = new Function<Optional<WonMessage>, Collection<EventTriggeredAction<WonMessage>>>() {
@Override
public Collection<EventTriggeredAction<WonMessage>> apply(Optional<WonMessage> msg) {
// process success responses for create
if (msg.isPresent() && atomCounter.get() < 2 && isResponseToCreateOfSockets(msg.get(), connectAction)) {
// we're processing a response event for the creation of one of our atoms.
atomCounter.incrementAndGet();
}
// event:
if (atomCounter.get() >= 2) {
// we have all the atoms we need for the connect.
if (connectSent.compareAndSet(false, true)) {
// we haven't sent the connect yet, do it now and register a new action
// waiting for the connect on the receiving end.
sendConnect(fromSocket, toSocket, message, authentication);
return Arrays.asList(new EventTriggeredAction<WonMessage>(String.format("Connect %s and %s: Expecting incoming connect from %s for %s", fromSocket, toSocket, fromSocket, toSocket), m -> isConnectFromSocketForSocket(m.get(), fromSocket, toSocket), this));
} else {
// receiving end. If so, send an open.
if (connectAction.isAutoOpen() && isConnectFromSocketForSocket(msg.get(), fromSocket, toSocket)) {
reactWithConnect(msg.get(), message, authentication);
// that's it - don't register any more actions
}
}
} else {
// for another create response
return Arrays.asList(new EventTriggeredAction<>(String.format("Connect %s and %s: Expecting response for create", fromSocket, toSocket), m -> m.isPresent() && isResponseToCreateOfSockets(m.get(), connectAction), this));
}
// none of the above - this is the last execution of this action.
return Collections.emptyList();
}
};
// add the action in such a way that it is triggered on add (with an empty
// Optional<WonMessage>)
this.actionContainer.addAction(new EventTriggeredAction<WonMessage>(String.format("Connect %s and %s", fromSocket, toSocket), action));
}
Aggregations