mirror of https://github.com/axmolengine/axmol.git
Merge pull request #5477 from heliclei/console-upload-file
CCConsole:support file upload via telnet console
This commit is contained in:
commit
b363751b1a
|
@ -105,6 +105,7 @@ static bool isFloat( std::string myString ) {
|
|||
// Check the entire string was consumed and if either failbit or badbit is set
|
||||
return iss.eof() && !iss.fail();
|
||||
}
|
||||
|
||||
// helper free functions
|
||||
|
||||
// dprintf() is not defined in Android
|
||||
|
@ -281,7 +282,7 @@ Console::Console()
|
|||
{ "texture", "Flush or print the TextureCache info. Args: [flush | ] ", std::bind(&Console::commandTextures, this, std::placeholders::_1, std::placeholders::_2) },
|
||||
{ "director", "director commands, type -h or [director help] to list supported directives", std::bind(&Console::commandDirector, this, std::placeholders::_1, std::placeholders::_2) },
|
||||
{ "touch", "simulate touch event via console, type -h or [touch help] to list supported directives", std::bind(&Console::commandTouch, this, std::placeholders::_1, std::placeholders::_2) },
|
||||
|
||||
{ "upload", "upload file. Args: [filename filesize]", std::bind(&Console::commandUpload, this, std::placeholders::_1, std::placeholders::_2) },
|
||||
};
|
||||
|
||||
;
|
||||
|
@ -753,6 +754,22 @@ void Console::commandTouch(int fd, const std::string& args)
|
|||
}
|
||||
}
|
||||
|
||||
void Console::commandUpload(int fd, const std::string& args)
|
||||
{
|
||||
auto argv = split(args,' ');
|
||||
if(argv.size() == 2)
|
||||
{
|
||||
_upload_file_name = argv[0];
|
||||
_upload_file_size = std::atoi(argv[1].c_str());
|
||||
_file_uploading = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char msg[] = "upload: invalid arguments.\n";
|
||||
send(fd, msg, sizeof(msg) - 1, 0);
|
||||
}
|
||||
|
||||
}
|
||||
bool Console::parseCommand(int fd)
|
||||
{
|
||||
char buf[512];
|
||||
|
@ -832,6 +849,48 @@ ssize_t Console::readline(int fd, char* ptr, int maxlen)
|
|||
return n;
|
||||
}
|
||||
|
||||
ssize_t Console::readfile(int fd, std::string& file_name, int file_size)
|
||||
{
|
||||
ssize_t n, rc;
|
||||
char c;
|
||||
|
||||
auto sharedFileUtils = FileUtils::getInstance();
|
||||
|
||||
std::string writablePath = sharedFileUtils->getWritablePath();
|
||||
std::string fileName = writablePath+file_name;
|
||||
|
||||
FILE* fp = fopen(fileName.c_str(), "wb");
|
||||
if(!fp)
|
||||
{
|
||||
const char err[] = "can't create file!\n";
|
||||
send(fd, err, sizeof(err),0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if (fp)
|
||||
// {
|
||||
// size_t ret = fwrite(szBuf, 1, strl6en(szBuf), fp);
|
||||
// CCASSERT(ret != 0, "fwrite function returned zero value");
|
||||
// fclose(fp);
|
||||
// if (ret != 0)
|
||||
// log("Writing file to writable path succeed.");
|
||||
// }
|
||||
|
||||
for( n=0; n<file_size; n++ ) {
|
||||
if( (rc = recv(fd, &c, 1, 0)) ==1 ) {
|
||||
fwrite(&c, 1, 1, fp);
|
||||
} else if( rc == 0 ) {
|
||||
return 0;
|
||||
} else if( errno == EINTR ) {
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return n;
|
||||
}
|
||||
|
||||
void Console::addClient()
|
||||
{
|
||||
struct sockaddr client;
|
||||
|
@ -910,10 +969,21 @@ void Console::loop()
|
|||
/* data from client */
|
||||
std::vector<int> to_remove;
|
||||
for(const auto &fd: _fds) {
|
||||
if(FD_ISSET(fd,©_set)) {
|
||||
if( ! parseCommand(fd) ) {
|
||||
if(FD_ISSET(fd,©_set))
|
||||
{
|
||||
if(!_file_uploading)
|
||||
{
|
||||
if( ! parseCommand(fd) )
|
||||
{
|
||||
to_remove.push_back(fd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
readfile(fd, _upload_file_name, _upload_file_size);
|
||||
_file_uploading = false;
|
||||
|
||||
}
|
||||
if(--nready <= 0)
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
protected:
|
||||
void loop();
|
||||
ssize_t readline(int fd, char *buf, int maxlen);
|
||||
ssize_t readfile(int fd, std::string &file_name, int file_size);
|
||||
bool parseCommand(int fd);
|
||||
|
||||
void addClient();
|
||||
|
@ -115,6 +116,7 @@ protected:
|
|||
void commandProjection(int fd, const std::string &args);
|
||||
void commandDirector(int fd, const std::string &args);
|
||||
void commandTouch(int fd, const std::string &args);
|
||||
void commandUpload(int fd, const std::string &args);
|
||||
// file descriptor: socket, console, etc.
|
||||
int _listenfd;
|
||||
int _maxfd;
|
||||
|
@ -126,6 +128,10 @@ protected:
|
|||
bool _running;
|
||||
bool _endThread;
|
||||
|
||||
bool _file_uploading;
|
||||
ssize_t _upload_file_size;
|
||||
std::string _upload_file_name;
|
||||
|
||||
std::map<std::string, Command> _commands;
|
||||
|
||||
// strings generated by cocos2d sent to the remote console
|
||||
|
|
|
@ -24,17 +24,21 @@
|
|||
|
||||
#include "ConsoleTest.h"
|
||||
#include "../testResource.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#include <WS2tcpip.h>
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//
|
||||
// EaseSpriteDemo
|
||||
// ConsoleTest
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
|
||||
|
@ -42,8 +46,8 @@ static int sceneIdx = -1;
|
|||
|
||||
static std::function<Layer*()> createFunctions[] =
|
||||
{
|
||||
CL(ConsoleTCP),
|
||||
CL(ConsoleCustomCommand),
|
||||
CL(ConsoleUploadFile),
|
||||
};
|
||||
|
||||
#define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0]))
|
||||
|
@ -126,37 +130,6 @@ void ConsoleTestScene::runThisTest()
|
|||
Director::getInstance()->replaceScene(this);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//
|
||||
// ConsoleTCP
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
|
||||
ConsoleTCP::ConsoleTCP()
|
||||
{
|
||||
_console = Director::getInstance()->getConsole();
|
||||
}
|
||||
|
||||
ConsoleTCP::~ConsoleTCP()
|
||||
{
|
||||
}
|
||||
|
||||
void ConsoleTCP::onEnter()
|
||||
{
|
||||
BaseTestConsole::onEnter();
|
||||
_console->listenOnTCP(5678);
|
||||
}
|
||||
|
||||
std::string ConsoleTCP::title() const
|
||||
{
|
||||
return "Console TCP";
|
||||
}
|
||||
|
||||
std::string ConsoleTCP::subtitle() const
|
||||
{
|
||||
return "telnet localhost 5678";
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//
|
||||
|
@ -166,6 +139,7 @@ std::string ConsoleTCP::subtitle() const
|
|||
|
||||
ConsoleCustomCommand::ConsoleCustomCommand()
|
||||
{
|
||||
_console = Director::getInstance()->getConsole();
|
||||
static struct Console::Command commands[] = {
|
||||
{"hello", "This is just a user generated command", [](int fd, const std::string& args) {
|
||||
const char msg[] = "how are you?\nArguments passed: ";
|
||||
|
@ -184,7 +158,6 @@ ConsoleCustomCommand::~ConsoleCustomCommand()
|
|||
void ConsoleCustomCommand::onEnter()
|
||||
{
|
||||
BaseTestConsole::onEnter();
|
||||
_console->listenOnTCP(5678);
|
||||
}
|
||||
|
||||
std::string ConsoleCustomCommand::title() const
|
||||
|
@ -196,3 +169,162 @@ std::string ConsoleCustomCommand::subtitle() const
|
|||
{
|
||||
return "telnet localhost 5678";
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
//
|
||||
// ConsoleUploadFile
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
|
||||
ConsoleUploadFile::ConsoleUploadFile()
|
||||
{
|
||||
srand (time(NULL));
|
||||
int _id = rand()%100000;
|
||||
char buf[32];
|
||||
sprintf(buf, "%d", _id);
|
||||
_target_file_name = std::string("grossini") + buf;
|
||||
|
||||
_src_file_path = FileUtils::getInstance()->fullPathForFilename(s_pathGrossini);
|
||||
_thread = std::thread( &ConsoleUploadFile::uploadFile, this);
|
||||
}
|
||||
|
||||
void ConsoleUploadFile::onEnter()
|
||||
{
|
||||
BaseTestConsole::onEnter();
|
||||
|
||||
}
|
||||
|
||||
ConsoleUploadFile::~ConsoleUploadFile()
|
||||
{
|
||||
_thread.join();
|
||||
}
|
||||
void ConsoleUploadFile::uploadFile()
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp;
|
||||
int sfd, s, j;
|
||||
|
||||
/* Obtain address(es) matching host/port */
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */
|
||||
hints.ai_socktype = SOCK_STREAM; /* stream socket */
|
||||
hints.ai_flags = 0;
|
||||
hints.ai_protocol = 0; /* Any protocol */
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2),&wsaData);
|
||||
#endif
|
||||
|
||||
s = getaddrinfo("localhost", "5678", &hints, &result);
|
||||
if (s != 0)
|
||||
{
|
||||
CCLOG("ConsoleUploadFile: getaddrinfo error");
|
||||
return;
|
||||
}
|
||||
|
||||
/* getaddrinfo() returns a list of address structures.
|
||||
Try each address until we successfully connect(2).
|
||||
If socket(2) (or connect(2)) fails, we (close the socket
|
||||
and) try the next address. */
|
||||
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
sfd = socket(rp->ai_family, rp->ai_socktype,
|
||||
rp->ai_protocol);
|
||||
if (sfd == -1)
|
||||
continue;
|
||||
|
||||
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||
break; /* Success */
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||
closesocket(sfd);
|
||||
#else
|
||||
close(sfd);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rp == NULL) { /* No address succeeded */
|
||||
CCLOG("ConsoleUploadFile: could not connect!");
|
||||
return;
|
||||
}
|
||||
|
||||
freeaddrinfo(result); /* No longer needed */
|
||||
|
||||
|
||||
FILE* fp = fopen(_src_file_path.c_str(), "rb");
|
||||
if(!fp)
|
||||
{
|
||||
CCLOG("ConsoleUploadFile: could not open file %s", _src_file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
//read file size
|
||||
fseek(fp, 0, SEEK_END);
|
||||
int size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
char sb[32];
|
||||
sprintf(sb, "%d", size);
|
||||
std::string tmp = "upload";
|
||||
|
||||
tmp += " ";
|
||||
tmp += _target_file_name;
|
||||
tmp += " ";
|
||||
tmp += sb;
|
||||
tmp += "\n";
|
||||
char cmd[512];
|
||||
|
||||
strcpy(cmd, tmp.c_str());
|
||||
send(sfd,cmd,strlen(cmd),0);
|
||||
|
||||
// allocate memory to contain the whole file:
|
||||
char* buffer = (char*) malloc (sizeof(char)*size);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
CCLOG("ConsoleUploadFile: memory allocate error!");
|
||||
return;
|
||||
}
|
||||
|
||||
// copy the file into the buffer:
|
||||
int ret = fread(buffer, 1, size, fp);
|
||||
if (ret != size)
|
||||
{
|
||||
CCLOG("ConsoleUploadFile: read file: %s error!",_src_file_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
//send to console socket
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
send(sfd, &buffer[i], 1, 0);
|
||||
}
|
||||
|
||||
// terminate
|
||||
fclose (fp);
|
||||
free (buffer);
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||
closesocket(sfd);
|
||||
WSACleanup();
|
||||
#else
|
||||
close(sfd);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
std::string ConsoleUploadFile::title() const
|
||||
{
|
||||
return "Console UploadFile";
|
||||
}
|
||||
|
||||
std::string ConsoleUploadFile::subtitle() const
|
||||
{
|
||||
auto sharedFileUtils = FileUtils::getInstance();
|
||||
|
||||
std::string writablePath = sharedFileUtils->getWritablePath();
|
||||
|
||||
return "file uploaded to:" + writablePath + _target_file_name;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,31 +45,13 @@ public:
|
|||
void backCallback(Ref* sender) override;
|
||||
};
|
||||
|
||||
class ConsoleTCP : public BaseTestConsole
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(ConsoleTCP);
|
||||
|
||||
void onEnter() override;
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
|
||||
protected:
|
||||
ConsoleTCP();
|
||||
virtual ~ConsoleTCP();
|
||||
|
||||
cocos2d::Console *_console;
|
||||
|
||||
private:
|
||||
CC_DISALLOW_COPY_AND_ASSIGN(ConsoleTCP);
|
||||
};
|
||||
|
||||
class ConsoleCustomCommand : public BaseTestConsole
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(ConsoleCustomCommand);
|
||||
|
||||
void onEnter() override;
|
||||
virtual void onEnter() override;
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
|
||||
|
@ -82,6 +64,27 @@ private:
|
|||
CC_DISALLOW_COPY_AND_ASSIGN(ConsoleCustomCommand);
|
||||
};
|
||||
|
||||
class ConsoleUploadFile : public BaseTestConsole
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(ConsoleUploadFile);
|
||||
|
||||
virtual void onEnter() override;
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
|
||||
protected:
|
||||
ConsoleUploadFile();
|
||||
virtual ~ConsoleUploadFile();
|
||||
|
||||
void uploadFile();
|
||||
std::string _src_file_path;
|
||||
std::string _target_file_name;
|
||||
std::thread _thread;
|
||||
private:
|
||||
CC_DISALLOW_COPY_AND_ASSIGN(ConsoleUploadFile);
|
||||
};
|
||||
|
||||
class ConsoleTestScene : public TestScene
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue