Sending packets to Minecraft PE - ios

I'm working at application that works with Minecraft PE servers. I am currently at the position of creating the handshake with the server. Looking at this page http://wiki.vg/Protocol I understand that the status ping works as follows:
C->S : Handshake State=1
C->S : Request
S->C : Response
C->S : Ping
S->C : Pong
C is client and S is server. But I don't understand what bytes/data/hex I need to send. I use https://github.com/robbiehanson/CocoaAsyncSocket to connect and here is the code:
error = nil;
BOOL successs = [self.clientSocket connectToHost:self.serverData[#"host"] onPort:[self.serverData[#"port"] intValue] error:&error];
if (successs)
{
[self.clientSocket writeData:data withTimeout:-1 tag:1];
}

Related

TCP connection issue by using BlueSocket framework on IOS

Getting error of "Error code: -9989(0x-2705), Connection refused" by using BlueSocket framework and connecting between Mac and IOS.
Here is the logic:
I am treating Mac as a server:
// making TCP IPV4 socket
try self.listenSocket = Socket.create(family: .inet, type: .stream, proto: .tcp)
// start lisening port of 8888
try socket.listen(on: self.port)
// accept client connection when there is
let newSocket = try socket.acceptClientConnection()
// keep opening and reading data ....
iPhone as a client:
self.socket = try Socket.create(family: .inet)
try self.socket?.connect(to: ip, port: 8888)
try self.socket?.setReadTimeout(value: readWriteTimeOut)
try self.socket?.setWriteTimeout(value: readWriteTimeOut)
self.socket?.readBufferSize = Socket.SOCKET_MAXIMUM_SSL_READ_BUFFER_SIZE
client first time connect with the server works fine.
after the server receives data, client-side automatically closes the socket.
client tries to connect the server again to send back data by using same code above.
Then error displays!
I think by default when the server-side uses socket.listen, it has SO_REUSEADDR set to true
Need suggestions on how to resolve this issue. Thanks!
Just need to make sure while loop for socket.acceptClientConnection() is opening all the time....

How to serve a remote file (taken from a remote SMB server) to certain requests

I'm trying to serve a video file as response when certain request hits the server (server running on a mobile app). eg: someone goes to http://mylocalip:8080/video, and I want to serve him with a video.
This video file can be stored locally, or can be external. I started trying to serve a file located on a SMB server, so I tried using this code to get the file from the server and returning it (I know it's waiting for the whole file to read instead of reading and sending chunks, but should work right?):
webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
print("########\n########Request: \(request)")
let webrequested:GCDWebServerRequest = request;
let urlcita:String = String(webrequested.URL)
print("URL of requests\(urlcita)")
if urlcita.rangeOfString("videosmb") != nil{
print("It's a video SMB request")
//Test fake SMB file predefined. Read File using KxSMB
let route:String = "smb://192.168.1.205/ServidorAH/video.avi";
let extensFile:NSString = (route as NSString).pathExtension
let contentype = GCDWebServerGetMimeTypeForExtension(extensFile as String);
print("Content type MIME \(contentype)")
//Open SMB file using KxSMB
let authcredentials = KxSMBAuth.smbAuthWorkgroup("", username: "Guest", password: "");
let provider = KxSMBProvider.sharedSmbProvider()!
let archivoes = provider.fetchAtPath(route, auth: authcredentials)
//Switch to manually end the reading when switched to true. In the future will send chunks of data until the end, instead of reading the whole file first.
var interruptor:Bool = false
//Response Stream block
let responseStream: GCDWebServerStreamedResponse = GCDWebServerStreamedResponse(contentType: contentype, asyncStreamBlock: { completionBlock in
if (interruptor == true)
{
print("Test: End of reading")
completionBlock(NSData(), nil);
}
if archivoes!.isKindOfClass(NSError){
//It can not find the file, SMB error, so empty NSDATA to completion block
let errorcito:NSError = archivoes as! NSError
print("Error obteniendo archivo SMB: \(errorcito.localizedDescription)");
completionBlock(NSData(), nil);
}else{
print("Archivo SMB adecuado \(archivoes)")
let datos:NSData = archivoes!.readDataToEndOfFile()
//Print lenght of data (to check the size of the file)
print("Data lenght \(datos.length)")
//Set switch to true, so the next call will send an empty daya completion block
interruptor = true
//Send data chunk (in this case everything)
completionBlock(datos, nil);
}
})
return responseStream
}else{
//Default response
return GCDWebServerDataResponse(HTML:"<html><body><p>Hello World<br></p></body></html>")
}
However, I can't make it work. I always get a broken pipe error, and the web player accessing the web server (browsing from the mac and iOS too) doesn't play anything. I've also tried using an embeded iOS player to log the response (KxMovie). I get something like this:
[DEBUG] Did open connection on socket 19
[DEBUG] Connection received 177 bytes on socket 19
[DEBUG] Connection on socket 19 preflighting request "GET /videosmb" with 177 bytes body
[DEBUG] Connection on socket 19 processing request "GET /videosmb" with 177 bytes body
[DEBUG] Did connect
[DEBUG] Did start background task
[DEBUG] Connection sent 175 bytes on socket 19
...
Using a local player (KxMovie) from inside the App, here appears to be reading the file headers and it gets the right file size and dimensions of the video. However it doesn't play and it ends saying it reached the end of the video (without playing it). Just after that, WebServer shows an error:
...
[ERROR] Error while writing to socket 19: Broken pipe (32)
[DEBUG] Did close connection on socket 19
[VERBOSE] [fe80::cd0:28cd:3a37:b871%en1:8080] fe80::cd0:28cd:3a37:b871%en1:50109 200 "GET /videosmb" (177 | 175)
[DEBUG] Did disconnect
[DEBUG] Did end background task
Given the fact this is the first time I'm dealing with SMB servers, I though that maybe I was doing something wrong with the SMB part, so I decided to go for a simplified method just for testing.
This time I tried to serve a simple mp4 file stored on a remote webserver (not SMB). It didn't work either.
Finally I tried to serve a local file included in the main Bundle of the App, and the same happened: nothing. Here is the code:
webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
print("########\n########Request: \(request)")
let webrequested:GCDWebServerRequest = request;
let url:String = String(webrequested.URL)
print("URL of request: \(url)")
if url.rangeOfString("video") != nil{
print("It's a video request")
let rutalocalita = (NSBundle.mainBundle()).pathForResource("video", ofType: "avi")
let datos = NSData(contentsOfFile: rutalocalita!)!
print("video size: \(datos.length)")
return GCDWebServerDataResponse(data: datos, contentType: "video/avi")
}else{
//Default Response: Simple web
return GCDWebServerDataResponse(HTML:"<html><body><p>Hello World<br></p></body></html>")
}
})
This is what the log looks like:
[DEBUG] Did open connection on socket 19
[DEBUG] Connection received 177 bytes on socket 19
[DEBUG] Connection on socket 19 preflighting request "GET /video" with 177 bytes body
[DEBUG] Connection on socket 19 processing request "GET /video" with 177 bytes body
[DEBUG] Did connect
[DEBUG] Did start background task
[myCUSTOMDebug] Read 13584902 b. I'm going to send the response back to the request.
[DEBUG] Connection sent 173 bytes on socket 19
...
Here the local Playing I'm using inside the app to track the response, is able to read things like:
header='HTTP/1.1 200 OK'
2015-10-17 17:51:41.571 videotvtest[262:14252] http_code=200
2015-10-17 17:51:41.571 videotvtest[262:14252] header='Cache-Control: no-cache'
2015-10-17 17:51:41.571 videotvtest[262:14252] header='Content-Length: 13584902'
2015-10-17 17:51:41.572 videotvtest[262:14252] header='Content-Type: video/avi'
2015-10-17 17:51:41.572 videotvtest[262:14252] header='Connection: Close'
2015-10-17 17:51:41.573 videotvtest[262:14252] header='Server: GCDWebServer'
...
[ERROR] Error while writing to socket 19: Broken pipe (32)
[DEBUG] Did close connection on socket 19
[VERBOSE] [fe80::cd0:28cd:3a37:b871%en1:8080] fe80::cd0:28cd:3a37:b871%en1:50155 200 "GET /video" (177 | 173)
netbios_ns_send_name_query, name query sent for '*'.
[DEBUG] Did disconnect
[DEBUG] Did end background task
I'm playing around with tvOS and Xcode 7 for this, but I guess it should be ok if I'm able to show a regular HTML response... so I'm sure I'm missing something, or maybe I missed some framework when installing WebServer (I'm not using pods)?
Thanks in advance
If you want to serve a video file that can play in the browser using the video tag, at least on Chrome and Safari, you need to implement HTTP range requests.
GCDWebServer automatically implement range support if you use GCDWebServerFileResponse. If you use another type of response you would need to implement it yourself based on the byteRange property of the incoming GCDWebServerRequest. You should copy-paste the logic from GCDWebServerFileResponse.m.

LuaSocket (UDP) not receiving datagrams

I'm experimenting with LuaSocket for a project I'm working on. I've chosen UDP as my protocol.
Looking for docs and tutorials online, I've attempted to create a client-server pair for testing and learning.
According to what I've read, the following code should work. However, only the server seems to be working properly. The client sends a message, but it will not receive the reply from the server.
Thank you for any help anyone can provide.
Server:
-- Server
#!/usr/bin/env lua5.1
local socket = require("socket")
udp = socket.udp()
udp:setsockname("*", 53474)
udp:settimeout(0)
while true do
data, ip, port = udp:receivefrom()
if data then
print("Received: ", data, ip, port)
udp:sendto(data, ip, port)
end
socket.sleep(0.01)
end
Client:
-- Client
#!/usr/bin/env lua5.1
local socket = require("socket")
udp = socket.udp()
udp:setpeername("127.0.0.1", 53474)
udp:settimeout(0)
udp:send("Data!")
data = udp:receive()
if data then
print("Received: ", data)
end
The timeout value you set is 0, which causes the client timeout every time.
To fix it, give it a positive timeout value:
udp:settimeout(1)
Or set it to nil or a negative value, so it blocks indefinitely:
udp:settimeout()
or
udp:settimeout(-1)

Creating sockaddr_in for CocoaAsyncSocket Getting Invalid IPv4 address

I'm having trouble connecting to a Java socket server. I know the server is working because I connect via a Java socket. I'm using the CocoaAsyncSocket library to make a client connection from an iOS device. I've tried the following,
[socket connectToHost:#"XXX.XXX.X.XXX" onPort:9090 error:&err]
method but the server never sees the client connect and the client (CocoaAsyncSocket) thinks its connected. So thats no good, then I realized there was another connection method available.
So I'm thinking I should be using the connectToAddress method instead. I've used this post as a reference for my current code but I'm still getting an error and I'm not sure why. The only difference from my version and the suggested version is for the length they use sa_len and I was getting a error and xCode wanted to switch it to sin_len, so I did. I'm really new to direct socket connections so bear with me.
GCDAsyncSocket *socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
struct sockaddr_in ip4addr;
ip4addr.sin_family = AF_INET;
ip4addr.sin_port = htons(9090);
inet_pton(AF_INET, "XXX.XXX.X.XXX", &ip4addr.sin_addr);
NSData *discoveryHost = [NSData dataWithBytes:&ip4addr length:ip4addr.sin_len];
NSError *err = nil;
if (![socket connectToAddress:discoveryHost error:&err])
{
NSLog(#"I CANNOT CONNECT!");
}
else
{
NSLog(#"IM CONNECTED!");
}
The connection fails and the error is,
Error Domain=GCDAsyncSocketErrorDomain Code=2 "A valid IPv4 or IPv6 address was not given" UserInfo=0x8bac880 {NSLocalizedDescription=A valid IPv4 or IPv6 address was not given}
I changed
NSData *discoveryHost = [NSData dataWithBytes:&ip4addr length:ip4addr.sin_len];
to
NSData *discoveryHost = [NSData dataWithBytes:&ip4addr length:sizeof(ip4addr)];
and it fixed that error I was getting. However, the reason I wasn't able to connect via the connectToHost method was due to my server socket code. I have two server sockets accepting connections. I commented out the second and it worked just fine. I'm guessing it was due to the thread being locked by the second socket or something.

i get a tftp timeout from vxworks

I wrote some code on VxWorks to download a file from a TFTP server using tftpLib but the get gives me a timeout:
ERR [TFTP] tftpSend:479: Transfer Timed Out.
ERR [TFTP] tftpGet:1077: File transfer error.
Error has occurred: 4915207
which isn't right as the host is reachable:
ping("3.94.213.53",3)
Pinging 3.94.213.53 (3.94.213.53) with 64 bytes of data:
Reply from 3.94.213.53 bytes=64 ttl=63 seq=0 time<1ms
Reply from 3.94.213.53 bytes=64 ttl=63 seq=1 time<1ms
Reply from 3.94.213.53 bytes=64 ttl=63 seq=2 time<1ms
and when I do this from the Linux shell, it works just as expected:
tftp -r "artifacts/ngfm.bin" -g 3.94.213.53
What might be the problem here?
The get section of my code looks like:
pFile = fopen("flash:/ngfm.bin","wb");
if (pFile != NULL) {
/* Get file from TFTP server and write it to the file descriptor */
if (OK == (status = tftpGet (pTftpDesc, pFilename, pFile, TFTP_CLIENT))) {
printf("tftpGet() successful\n");
} else {
printf("Error has occurred: %d\n", errno); // errno is where the error is stored
}
} else {
printf("Bad file pointer pFile");
}
edit:
The code I have above the get portion is:
/*Initiate TFTP session*/
if ((pTftpDesc = tftpInit ()) == NULL)
printf("Error on tftpInit()\n");
/*connect to TFTP host and set transfer mode*/
if ((tftpPeerSet (pTftpDesc, pHost, port) == ERROR) ||
(tftpModeSet (pTftpDesc, pMode) == ERROR)) {
(void) tftpQuit (pTftpDesc);
printf("Error on tftpPeerSet()\n");
return ERROR;
}
I believe your problem is caused by lack of calling of tftpModeSet - http://www.vxdev.com/docs/vx55man/vxworks/ref/tftpLib.html#tftpModeSet
So add:
tftpModeSet(pTftpDesc, "binary");
This will prevent your binary file from causing the stream to die off on the first \n
Okay, turns out that TFTP is a no go in my situation.
I hooked up Wireshark and saw that my client is getting through to the server just fine on port 69. I previously have also made sure that I have port forwarding on port 69 setup in my iptable rules properly. Now I just read this on Wikipedia:
Data transfer is initiated on port 69, but the data transfer ports are
chosen independently by the sender and receiver during initialization
of the connection. The ports are chosen at random according to the
parameters of the networking stack, typically from the range of
ephemeral ports
i.e. TFTP won't work for me because I need NAT and it has to be secure. I'll need to go with a protocol that's connection orriented, ftp e.g.
I found that the standar VxWorks library also contains ftpLib.h (http://www.vxdev.com/docs/vx55man/vxworks/ref/ftpLib.html#ftpLs) that will hopefully resolve my NAT issues as FTP works with connection based TCP.

Resources