How can i send packages on a Minecraft Client (With Fabricmc) and receive it on a Bukkit Server? - bukkit

I'm a Chinese secondary school student,so my written English may not very well.
How can i send packages (like some words) on a Minecraft Client (Use a Fabricmc Mod to send) and receive it on the bukkit server on MC Multiplayer?

This is done using what's known as the 'plugin messaging channel'. Take a look at this Fabricmc wiki to read about client networking (messaging). See this Spigot wiki on the plugin server-side messaging channel; ignore that this wiki talks a lot about bungee, it's just because that's a common use case. You can make your own channel.
The code below is copied from said wikis and is very much pseudo-code:
Client
Sending from the client
PacketByteBuf buf = PacketByteBufs.create();
buf.writeBlockPos(target);
ServerPlayNetworking.send((ServerPlayerEntity) user, TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, buf);
Receiving on the client
ClientPlayNetworking.registerGlobalReceiver(TutorialNetworkingConstants.HIGHLIGHT_PACKET_ID, (client, handler, buf, responseSender) -> {
client.execute(() -> {
// Everything in this lambda is run on the render thread
ClientBlockHighlighting.highlightBlock(client, target);
});
});
Where you see TutorialNetworkingConstants.HIGHL..., that's the Identifier for the channel.
Server (Spigot/Bukkit)
Sending from the server
player.sendPluginMessage(this, "YourChannelName", out.toByteArray());
Receiving on the server
#Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
if (!channel.equals("YourChannelName")) {
return;
}
ByteArrayDataInput in = ByteStreams.newDataInput(message);
String data = in.readUTF();
...
Take a thorough read of those tutorials, they should cover all you need to know. Just be sure to unregister your channels on both the client and server.

Related

How to use libmosquitto to make a request and get response using MQTT v5?

I'm trying to use libmosquitto to make a request (publish to a 'test/topic' topic) and I want to get a response based on the client (sender) id. So that means the client will publish to 'test/topic' and it will automatically subscribe 'test/topic/<client_id>'
The server has already subscribed on 'test/topic' and when it becomes the message, it will send a response (publish) to 'test/topic/<client_id>', which the client subscribed to receive that response in the first place.
The challenge here is how do I get the <client_id>, right. I already done this in python and js, where the client will send metadata or properties in the payload, which the server can unpack to get the client_id. However, I'm using C++ now and it's frustrating because I can't figure out how to get these properties.
Here is an example of how to do this in python. I just want to do the same with c++
I'm using the libmosquitto as I mentionned. I don't even have an example to show because I didn't find how to do this. There is literally no example on how to do this with the mosquitto c++ lib (which is confusing since mosquitto is a famous lib I guess).
I hope someone had a similar problem or can post an example for c++ and mosquitto lib. Thanks in advance.
When in doubt, look at the tests:
const char *my_client_id = ...;
mosquitto_property *proplist = NULL;
mosquitto_property_add_string_pair(&proplist, MQTT_PROP_USER_PROPERTY, "client_id", my_client_id);
mosquitto_publish_v5(mosq, &sent_mid, "test/topic", strlen("message"), "message", 0, false, proplist);
mosquitto_property_free_all(&proplist);
Since you asked in the comments, you can retrieve these properties from published messages by first setting an on_message callback using mosquitto_message_v5_callback_set and the implementing it like so:
void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message, const mosquitto_property *props) {
std::string topic{message->topic};
if (topic == "test/topic") {
const char *client_id = nullptr;
mosquitto_property_read_string_pair(props, MQTT_PROP_USER_PROPERTY, nullptr, &client_id, false);
if (client_id) {
/* client_id contains a client id. */
}
}

Apache Thrift for just processing, not server

I hope I don't have misunderstood the Thrift concept, but what I see from (example) questions like this, this framework is composed by different modular layers that can be enabled or disabled.
I'm mostly interesed in the "IDL part" of Thrift, so that I can create a common interface between my C++ code and an external Javascript application. I would like to call C++ functions using JS, with Binary data transmission, and I've already used the compiler for this.
But both my C++ (the server) and JS (client) application already exchange data using a C++ Webserver with Websockets support, it is not provided by Thrift.
So I was thinking to setup the following items:
In JS (already done):
TWebSocketTransport to send data to my "Websocket server" (with host ws://xxx.xxx.xxx.xxx)
TBinaryProtocol to encapsulate the data (using this JS implementation)
The compiled Thrift JS library with the correspondent C++ functions to call (done with the JS compiler)
In C++ (partial):
TBinaryProtocol to encode/decode the data
A TProcessor with handler to get the data from the client and process it
For now, the client is already able to sent requests to my websocket server, I see receiving them in binary form and I just need Thrift to:
Decode the input
Call the appropriate C++ function
Encode the output
My webserver will send the response to the client. So no "Thrift server" is needed here. I see there is the TProcessor->process() function, I'm trying to use it when I receive the binary data but it needs an in/out TProtocol. No problem here... but in order to create the TBinaryProtocol I also need a TTransport! If no Thrift server is expected... what Transport should I use?
I tried to set TTransport to NULL in TBinaryProtocol constructor, but once I use it it gives nullptr exception.
Code is something like:
Init:
boost::shared_ptr<MySDKServiceHandler> handler(new MySDKServiceHandler());
thriftCommandProcessor = boost::shared_ptr<TProcessor>(new MySDKServiceProcessor(handler));
thriftInputProtocol = boost::shared_ptr<TBinaryProtocol>(new TBinaryProtocol(TTransport???));
thriftOutputProtocol = boost::shared_ptr<TBinaryProtocol>(new TBinaryProtocol(TTransport???));
When data arrives:
this->thriftInputProtocol->writeBinary(input); // exception here
this->thriftCommandProcessor->process(this->thriftInputProtocol, this->thriftOutputProtocol, NULL);
this->thriftOutputProtocol->readBinary(output);
I've managed to do it using the following components:
// create the Processor using my compiled Thrift class (from IDL)
boost::shared_ptr<MySDKServiceHandler> handler(new MySDKServiceHandler());
thriftCommandProcessor = boost::shared_ptr<TProcessor>(new ThriftSDKServiceProcessor(handler));
// Transport is needed, I use the TMemoryBuffer so everything is kept in local memory
boost::shared_ptr<TTransport> transport(new apache::thrift::transport::TMemoryBuffer());
// my client/server data is based on binary protocol. I pass the transport to it
thriftProtocol = boost::shared_ptr<TProtocol>(new TBinaryProtocol(transport, 0, 0, false, false));
/* .... when the message arrives through my webserver */
void parseMessage(const byte* input, const int input_size, byte*& output, int& output_size)
{
// get the transports to write and read Thrift data
boost::shared_ptr<TTransport> iTr = this->thriftProtocol->getInputTransport();
boost::shared_ptr<TTransport> oTr = this->thriftProtocol->getOutputTransport();
// "transmit" my data to Thrift
iTr->write(input, input_size);
iTr->flush();
// make the Thrift work using the Processor
this->thriftCommandProcessor->process(this->thriftProtocol, NULL);
// the output transport (oTr) contains the called procedure result
output = new byte[MAX_SDK_WS_REPLYSIZE];
output_size = oTr->read(output, MAX_SDK_WS_REPLYSIZE);
}
My webserver will send the response to the client. So no "Thrift server" is needed here. I see there is the TProcessor->process() function, I'm trying to use it when I receive the binary data but it needs an in/out TProtocol. No problem here... but in order to create the TBinaryProtocol I also need a TTransport! If no Thrift server is expected... what Transport should I use?
The usual pattern is to store the bits somewhere and use that buffer or data stream as the input, same for the output. For certain languages there is a TStreamTransport available, for C++ the TBufferBase class looks promising to me.

Websocket broadcasting not working

I have an issue with my websocket.
I have recently switched my server from PHP to c++ side, and used the POCO library, i used exactly this script:
WebSocketServer.cpp
For the one client side in c++ i used a snipet i found here on stackoverflow:
WebSocketClient.cpp
I modified the client a bit, first it sends a default message as soon as i connect to the server.
I wrapped the whole thing with an Update function from my main app, that I am constantly able to recieve messages:
void CLeagueStats :: Update( ) {
if(m_Connected) {
string msg = Recv( );
if(msg != "") {
//handleIncomingMsg( msg );
}
} else if(GetTime() - LastReconnectTime > 90 || LastReconnectTime == 0) {
Connect( );
}
}
string CLeagueStats :: Recv( ) {
char receiveBuff[256];
int flags=0;
int rlen=m_psock->receiveFrame(receiveBuff,256,flags);
CONSOLE_Print("Recv: "+string(receiveBuff));
return string(receiveBuff);
}
I have now written a totally simple javascript client which is initalizing on page load:
<script type="text/javascript">
var ip_port = 'localhost:9980';
var ohc;
if (typeof (MozWebSocket) == 'function')
ohc = new MozWebSocket('ws://' + ip_port);
else
ohc = new WebSocket('ws://' + ip_port);
var self = this;
setTimeout(function() {
self.ohc.send("hey");
}, 500);
</script>
The server log includes both messages:
C++ App:
WebSocket connection established. Frame received (length=5, flags=0x81).
Javascript:
WebSocket connection established. Frame received (length=3, flags=0x81).
But the log from the C++ App does send the connection message and recieve it back, but i dont get the message from the js-client:
[Websocket] Connecting to websocket.
[Websocket] Send: hello
[Websocket] Recv: hello
Why this happen?
Isn't the snippet form the servercode directly sending the message back to all clients?
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
app.logger().information(Poco::format("Frame received (length=%d, flags=0x%x).", n,unsigned(flags)));
ws.sendFrame(buffer, n, flags);
Is there anything wrong with the code?
I am not a situation to reproduce the environment but I had a similar issue using Python and IOS web sockets. Every other technology we used was working in with Python Sockets flawlessly but IOS web socket had problem. After many days later we find out that IOS web socket does not send a communication ender (EOM) that Python can process. So the we had to handle different IOS sockets different.
I have checked WebSocket flags 81 so it is text and frame is finish. But I would suggest you to check from Developer Tools of browser to see what is recieved over the socket connection from Network Tab.
I may be problem of End of Message did not understood by javascript WebSocket. If you see the data hello on developer tools then it would be easy to handle with situation. However if you don't see any message coming then the problem is most probably from C++ code.
In attachment you can see how Chrome shows the socket data transactions. Keep in mind that clicking on the connection on the left list will update the transactions they are not live.
Hope this helps you.
If not go deeper using tcpdump or similar sowftware to be sure if they really sent and got by two sides.

How do I duplicate certificate authentication (Mumble (c/c++)) in Python?

Alright so, before I really get into this post, I am going to have to warn you that this might not be an easy fix. Whoever reads and is able to reply to this post must know a lot of c/c++, and at least some python to be able to answer the question I have above.
Basically, I have a connection method from Mumble (a VOIP client), that connects to a server and sends it an SSL certificate for authentication purposes. I also have a Python script that connects to the same Mumble VOIP server, but I don't send a certificate.
I need to modify my existing code to send a certificate, as the current Mumble client does.
--
Here is the C++ code that seems to send a certificate:
ServerHandler::ServerHandler() {
MumbleSSL::addSystemCA();
{
QList<QSslCipher> pref;
foreach(QSslCipher c, QSslSocket::defaultCiphers()) {
if (c.usedBits() < 128)
continue;
pref << c;
}
if (pref.isEmpty())
qFatal("No ciphers of at least 128 bit found");
QSslSocket::setDefaultCiphers(pref);
}
void ServerHandler::run() {
qbaDigest = QByteArray();
QSslSocket *qtsSock = new QSslSocket(this);
qtsSock->setPrivateKey(g.s.kpCertificate.second);
qtsSock->setLocalCertificate(g.s.kpCertificate.first.at(0));
QList<QSslCertificate> certs = qtsSock->caCertificates();
certs << g.s.kpCertificate.first;
qtsSock->setCaCertificates(certs);
cConnection = ConnectionPtr(new Connection(this, qtsSock));
qtsSock->setProtocol(QSsl::TlsV1);
qtsSock->connectToHostEncrypted(qsHostName, usPort);
void ServerHandler::serverConnectionConnected() {
tConnectionTimeoutTimer->stop();
qscCert = cConnection->peerCertificateChain();
qscCipher = cConnection->sessionCipher();
if (! qscCert.isEmpty()) {
const QSslCertificate &qsc = qscCert.last();
qbaDigest = sha1(qsc.publicKey().toDer());
bUdp = Database::getUdp(qbaDigest);
} else {
bUdp = true;
}
QStringList tokens = Database::getTokens(qbaDigest);
foreach(const QString &qs, tokens)
mpa.add_tokens(u8(qs));
QMap<int, CELTCodec *>::const_iterator i;
for (i=g.qmCodecs.constBegin(); i != g.qmCodecs.constEnd(); ++i)
mpa.add_celt_versions(i.key());
sendMessage(mpa);
--
And alas, this is what I do to connect to it right now (in python):
try:
self.socket.connect(self.host)
except:
print self.threadName,"Couldn't connect to server"
return
self.socket.setblocking(0)
print self.threadName,"connected to server"
--
Soo... what do I need to do more to my Python source to connect to servers that require a certificate? Because my source currently connects just fine to any mumble server with requirecert set to false. I need it to work on all servers, as this will be used on my own server (which ironically enough, has requirecerts on.)
I can pregenerate the certificate as a .p12 or w/e type file, so I don't need the program to generate the cert. I just need it to send the cert as the server wants it (as is done in the c++ I posted).
Please help me really soon! If you need more info, message me again.
Stripped out all irrelevant code, now it's just the code that deals with ssl.
From the C++ code it looks like you simply need to have ssl support and negotiate with the correct certification file and encrypt the payload with the correct private key. Those certifications and privates keys are most likely stored in your original program somewhere. If there are non-standard Authorities that the C++ might be loading up you'll need to find out where to put those root authorities in your python installation, or make sure python simply ignores those issues, which is less secure.
In python you can create a socket, like above, except with urllib. This library has support for HTTPs and providing the certification and private keys. URLOpener
Example Usage:
opener = urllib.URLopener(key_file = 'mykey.key', cert_file = 'mycert.cer')
self.socket = opener.open(url)
You'll probably need to make it more robust with the appropriate error checking and such, but hopefully this info will help you out.

Growl Notifications from a Web Server

I notice that Growl allows for the possibility of Growl notifications from a website. Has anyone tried implementing this?
If so, what form did it take? Did you implement multi user support? And, can you provide any code examples (C# or Objective-C would preferable but I'm not that fussed)?
Rich
There are GNTP (Growl Network Transport Protocol) bindings for various languages, a list of bindings can be found here - these allow you to send notifications from, say, a PHP script.
I wouldn't trust Growl's UDP system directly, but rather write a server that receives and stores notifications (maybe as a tiny web app), and a local script that routinely grabs any new messages via HTTP and Growls them. Not complicated at all, will be more reliable than UDP, and can queue up messages when your Growl'ing machine is powered-off or unreachable. Shouldn't take long to implement
Basically, server.php in pseudo-PHP (which could use Net_Growl):
<?php
if($_GET['action'] == "store"){
$title = $_POST['title'];
$message = $_POST['message'];
$password = sha1($_POST['password']);
if($password == "..."){
store_in_database(sanitise($title), sanitise($message);
}
} else {
print(json_encode(get_notifications_from_database()));
mark_notifications_as_read();
}
?>
client.py in pseudo-Python (which could use gntp):
while 1:
time.sleep(60):
data = urllib.urlopen("http://myserver.com/server.php?action=get&password=blah").read()
for line in data:
notif = json.decode(line)
growl.alert(notif['title'], notif['message'])