-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[INTERNAL][CORE] Prepares Stream access #653
base: master
Are you sure you want to change the base?
Conversation
c66a516
to
ecb5e10
Compare
This patch introduces new classes and interface. This is necessary to distinguish between plain stream connections and internal stuff. In general this patch is a whole rewrite of the DTM. It now manages two connection pools. One for packet connections and one for stream connections. In addition this commits adds Javadoc, TODOs and FIXMEs.
ecb5e10
to
76d49fc
Compare
@tobous can you just please have a look at the Javadoc and basically just the naming of the methods in the interfaces ? I guess the rest of this "commit" is not reviewable, however the whole logic of the DTM is tested with a bunch of test cases. |
@srossbach Yes, I can have a look at it. But I'm busy for the rest of the week, so I won't get to it (or at least finish it) before next Monday. |
He has not replied since 9 days, so I removed him as reviewer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got through everything but the DataTransfereManager (and its test). For that class, I am way out of my depth (and I have been reviewing for a while, so my concentration is fading). I will try the class again in the next couple of days.
* <p>It offers support for two connection types. | ||
* | ||
* <ol> | ||
* <li>Establishing a connection using {@link #connect(String, Object)} to establish a connection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the phrase "establish(ing) a connection" twice sounds a bit weird. But that is more of a nit-pick than a real complaint.
* @return <code>true</code> to accept the connection or <code>false</code> to reject the | ||
* connection. | ||
*/ | ||
public boolean connectionEstablished(IStreamConnection connection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The public
modifier is not needed for interface methods. Also, rename to better represent the "accepting/rejecting" nature?
public boolean connectionEstablished(IStreamConnection connection); | |
boolean checkIncomingConnection(IStreamConnection connection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is from a TCP (depends on the stream service) point of the the connection IS established, it occupies a port.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Then how about something along the lines of checkNewConnection(...)
?
try { | ||
listener.connectionClosed(connectionId, connection); | ||
accepted |= listener.connectionEstablished(connection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The or-assignment is not necessary as you break anyways when accepted is true, i.e. when you encounter true for the first time.
(Also, you could avoid the unnecessary assignments by checking first and only assigning if the listener returns true and then breaking. But it makes the logic harder to read, so I'm not sure whether it's really worth it.
accepted |= listener.connectionEstablished(connection); | |
accepted = listener.connectionEstablished(connection); |
* <p>Furthermore if a listener accepts the request every outstanding listener will <b>not</b> get | ||
* notified about this connection establishment. | ||
*/ | ||
public interface IStreamConnectionListener { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I understand what this class is needed for. Could you explain the use case to me? Was it added so that we don't have to blindly accept any incoming stream?
Furthermore, using the name "listener" is a bit confusing in combination with the implemented behavior. This "listener" is only used to accept or reject connections and doesn't really do anything with the passed connection. Furthermore, it only runs until a registered listener accepts the connection, meaning not all listeners have to be notified (as stated in the javadoc).
I am struggling with finding a good name, but I somewhat like the metaphor of a bouncer for incoming connections (which doesn't completely match as all "bouncers" have to "reject" the connection for it to actually be rejected).
public interface IStreamConnectionListener { | |
public interface IStreamConnectionBouncer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite simple and has to do with (D)DOS attacks. So imagine you open a socket (you can only accept 65535 connections). The first check after calling accept (see ServerSocket) is to do some mighty "magic" and close the connection just afterwards if the "magic" decided you shall not pass. Now it gets passes to the listener(s). If no listener is interested, should I keep the connection alive ? I guess not.
TBH the name is bad. It should be changed.
* A stream connection consists of an input and out stream. It up to the caller to gracefully | ||
* shutdown the connections. | ||
*/ | ||
public interface IStreamConnection extends IConnection { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this interface provide access to the streams but also direct access to some of their functionality (the timeout stuff)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because timeout stuff is session management, The connection only provides the "stream" but not the session you would put above it. To clearify things, we are talking about network sessions (see OSI layer), not about a Saros session.
|
||
private final Map<String, IConnection> pool = new HashMap<>(); | ||
|
||
ConnectionPool(final String name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, you want a pool for every connection type. You could also consider making the pool generic (<T extends IConnection>
) in order to better differentiate between the connection types and make the usage easier. It doesn't really make the class more complicated and would me you wouldn't have to cast the result from get
requests.
This would make the name somewhat unnecessary, but you could still keep it around for a better toString()
.
@@ -319,10 +320,10 @@ public void unblockOutgoingSessionPackets(JID jid) throws RemoteException { | |||
return; | |||
} | |||
|
|||
IByteStreamConnection connection = | |||
getDataTransferManager().getConnection(ISarosSession.SESSION_CONNECTION_ID, jid); | |||
IConnection connection = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The returned connection is a IPacketConnection
. Why not hold it as such? (This would also make the cast in l.336 unnecessary.)
Also, why do you check the type in the while loop in l.326? Can this check ever fail? Instead, you can just do a null-check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have basically two review modes.
Production = all the good stuff
Test Frameworks = just get this **** done.
However yes it seems that I did a refactor during multiple patches however this was already coded in such a bad way😆 after the first changes that I do not recognize any warnings here that may araised after the next refactoring steps.
* @author coezbek | ||
* @author jurke | ||
*/ | ||
@Component(module = "net") | ||
public class DataTransferManager implements IConnectionListener, IConnectionManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a new javadoc?
} | ||
|
||
private IByteStreamConnection connectInternal(String connectionID, JID peer) throws IOException { | ||
private IConnection connectInternal( | ||
final String id, final JID address, final boolean isPlainStream) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This solution using the Boolean to determine the return type is a bit ugly in my opinion. But using generics gets very ugly fast as far as I can tell, so this isn't an option either.
Would splitting this method into a stream and non-stream variant be a possibility without creating too much code duplication? The logic is kind of long/complicated, so I don't have a good overview.
for (ByteStream byteStream : establishedStreams) | ||
try { | ||
byteStream.close(); | ||
} catch (IOException e) { // ignore} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} catch (IOException e) { // ignore} | |
} catch (IOException e) { // ignore |
I currently have limited time. Will reply on friday, saturday, or sunday. |
This patch introduces an new class / interface which is just used for
the ITransmitter and IReceiver. This is necessary to distinguish between
plan stream connections and internal stuff.