Skip to content
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

RPC client should send pool ID on connection #846

Merged
merged 9 commits into from
Jul 13, 2017
Merged

Conversation

buger
Copy link
Member

@buger buger commented Jun 30, 2017

Now we generate pool ID to unique identify Gateway instance, so MDCB
can use it instead of API address.

It is implemented on TCP level, by overriding Dial function. Once we
have connection object, we write handshake “register” message, so Sink
can distinguish legacy clients from new ones. Next, we send the length of ID
(max 256, or single byte), and the third message is ID itself.

Note that tests include simple MDCB mock, which shows how we read the ID and apply it.

Part of https://github.com/TykTechnologies/tyk-sink/pull/11

Now hybrid and mdcb clients can use secured connection.
Added new boolean options to “slave_options” section: `use_ssl` and
`ssl_insecure_skip_verify`

MDCB part TykTechnologies/tyk-sink#10
Now we generate pool ID to unique identify Gateway instance, so MDCB
can use it instead of API address.

It is implemented on TCP level, by overriding Dial function. Once we
have connection object, we write handshake “register” message, so Sink
can distinguish legacy clients from new ones. Next we send length of ID
(max 256, or single byte), and third message is ID itself.
@buger buger requested a review from lonelycode June 30, 2017 08:08
// Let gorpc handle it
if err != nil {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the doc:

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered.

So you could get n, err == 4, nil for example.

I believe you want io.ReadFull, which will make sure n == 8, even if multiple Read calls are necessary:

ReadFull reads exactly len(buf) bytes from r into buf.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you don't actually check that the string here is? It would also be more readable if you didn't hard-code the number 8 here, like:

const want = "register"
handshake := make([]byte, len(want))
[...]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If client wrote 8 bytes on the wire, it will be always possible to read them in 1 single read. If it is not possible, it means that client wrote less than 8 bytes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we should introduce const for this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I misunderstood what ReadFull does, you are right we can re-use it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly - if the client wrote less, you want to error, not accept it :)

}

type customListener struct {
L net.Listener
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you make this an embedded field, you could avoid defining ListenAddr and Close and just use Addr and Close from net.Listener.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that I can't just embedd the field, because I need to override Accept function. Also ListenAddr is a go-rpc function, and this is actually is not net.Listener but gorpc.Listener interface, which differs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can override methods from an embedded field - that's exactly what embedding is for. But you're right, I assumed the two interfaces were the same.


conn.Write([]byte("register"))
conn.Write([]byte{byte(len(RPCClientSingletonConnectionID))})
conn.Write([]byte(RPCClientSingletonConnectionID))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this sends register, the length as a byte, and the ID itself? I assume the first two are so that we can change this "protocol" in the future more easily.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this is perhaps a bit silly, but I would add something like:

if len(RPCClientSingletonConnectionID) > 255 {
    panic("RPCClientSingletonConnectionID is too long")
}

The silent overflow is a bit scary, even if we're sure that we won't touch this very often.

Copy link
Member Author

@buger buger Jun 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the first two are so that we can change this "protocol" in the future more easily.

Exactly

The silent overflow is a bit scary, even if we're sure that we won't touch this very often.

Good point, because if we would like to change protocol, we for sure forgot about this limitation.


if err != nil {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same ReadFull comment as above

_, err = c.Read(idLenBuf)
if err != nil {
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the ReadFull thing applies here because you're only reading one byte, but you might as well do it out of consistency.

@ilijabojanovic
Copy link
Member

@buger approved for merge

@buger buger changed the base branch from mdcb_ssl to master July 12, 2017 17:55
If we decide to change length of the UUID in future it can never be more
then 1 byte length
OnConnect called for each client in pool, and needs to be guarded
@buger buger merged commit cf8ceb0 into master Jul 13, 2017
@buger buger deleted the mdcb_register_refactoring branch July 13, 2017 12:55
buger added a commit that referenced this pull request Jul 13, 2017
Now we generate pool ID to unique identify Gateway instance, so MDCB
can use it instead of API address.

It is implemented on TCP level, by overriding Dial function. Once we
have a connection object, we write handshake “proto2” message, so Sink
can distinguish legacy clients from new ones. Next, we send the length of ID
(max 256, or single byte), and the third message is ID itself.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants