Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
26 KB
Referenced Files
None
Subscribers
None
diff --git a/util/nacl/module.cpp b/util/nacl/module.cpp
index 06840dd2..9ee3d52f 100644
--- a/util/nacl/module.cpp
+++ b/util/nacl/module.cpp
@@ -1,127 +1,131 @@
#ifdef NACL
/* talks to chrome via the nacl stuff */
#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/module.h>
#include <ppapi/cpp/var.h>
#include <ppapi/cpp/dev/scriptable_object_deprecated.h>
#include <SDL/SDL.h>
#include <SDL/SDL_nacl.h>
#include <string>
#include "../../main.h"
#include "network-system.h"
#include "../funcs.h"
namespace nacl{
class PaintownScript: public pp::deprecated::ScriptableObject {
public:
virtual bool HasMethod(const pp::Var& method, pp::Var* exception);
virtual pp::Var Call(const pp::Var& method, const std::vector<pp::Var>& args,pp::Var* exception);
};
class PaintownInstance : public pp::Instance {
public:
explicit PaintownInstance(PP_Instance instance, pp::Core * core):
pp::Instance(instance),
core(core){
the_instance = this;
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
+ RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
}
virtual ~PaintownInstance() {}
static PaintownInstance * the_instance;
pp::Core * core;
static int launch(void * arg){
int argc = 1;
char * argv[1] = {"paintown"};
Global::debug(0) << "Run paintown main" << std::endl;
paintown_main(argc, argv);
return 0;
}
- bool HandleInputEvent(const PP_InputEvent& event){
- SDL_NACL_PushEvent(&event);
+ bool HandleInputEvent(const pp::InputEvent & event){
+ SDL_NACL_PushEvent((pp::InputEvent*) &event);
return true;
}
/* set up the viewport and run the game as usual */
void run(){
Nacl::NetworkSystem * system = new Nacl::NetworkSystem(the_instance, core);
Storage::setInstance(system);
SDL_NACL_SetInstance(pp_instance(), 640, 480);
int ok = SDL_Init(SDL_INIT_VIDEO |
SDL_INIT_AUDIO |
SDL_INIT_TIMER |
SDL_INIT_JOYSTICK |
SDL_INIT_NOPARACHUTE);
Global::debug(0) << "SDL Init: " << ok << std::endl;
Util::Thread::Id thread;
Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) launch, NULL);
Global::debug(0) << "Running thread " << thread << std::endl;
}
+ /*
virtual pp::Var GetInstanceObject(){
PaintownScript * object = new PaintownScript();
return pp::Var(this, object);
}
+ */
/* when the browser does paintownModule.postMessage('run') this will
* get executed.
*/
virtual void HandleMessage(const pp::Var& var_message){
if (!var_message.is_string()){
return;
}
std::string message = var_message.AsString();
if (message == "run"){
run();
}
}
};
PaintownInstance * PaintownInstance::the_instance;
bool PaintownScript::HasMethod(const pp::Var& method, pp::Var* exception){
if (!method.is_string()){
return false;
}
std::string name = method.AsString();
if (name == "run"){
return true;
}
return false;
}
pp::Var PaintownScript::Call(const pp::Var& method, const std::vector<pp::Var>& args,pp::Var* exception){
if (!method.is_string()){
return false;
}
std::string name = method.AsString();
if (name == "run"){
PaintownInstance::the_instance->run();
}
return pp::Var();
}
class PaintownModule : public pp::Module {
public:
PaintownModule() : pp::Module() {}
virtual ~PaintownModule() {}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new PaintownInstance(instance, core());
}
};
}
namespace pp{
Module * CreateModule(){
return new nacl::PaintownModule();
}
}
#endif
diff --git a/util/nacl/network-system.cpp b/util/nacl/network-system.cpp
index 0a6d2df5..94d34b84 100644
--- a/util/nacl/network-system.cpp
+++ b/util/nacl/network-system.cpp
@@ -1,804 +1,808 @@
#ifdef NACL
/* documentation for ppapi
* http://code.google.com/chrome/nativeclient/docs/reference/peppercpp/inherits.html
*/
/* issues with getting data
* 1. the function that starts the game is called from the main chrome thread
* which starts from a javascript call to module.PostMessage('run').
* ...
*
*/
#include <unistd.h>
#include <errno.h>
#include "network-system.h"
#include <sstream>
#include <fstream>
#include "../funcs.h"
#include "../debug.h"
#include <ppapi/c/pp_errors.h>
#include <ppapi/cpp/url_loader.h>
#include <ppapi/cpp/url_request_info.h>
#include <ppapi/cpp/url_response_info.h>
#include <ppapi/c/ppb_url_request_info.h>
#include <ppapi/cpp/completion_callback.h>
using std::string;
using std::map;
using std::vector;
using std::ostringstream;
using std::ifstream;
namespace Nacl{
static const char * CONTEXT = "nacl";
typedef Path::AbsolutePath AbsolutePath;
typedef Path::RelativePath RelativePath;
enum RequestType{
Exists
};
struct Request{
RequestType type;
AbsolutePath absolute;
RelativePath relative;
bool complete;
bool success;
};
Request operation;
struct NaclRequest{
virtual ~NaclRequest(){
}
virtual void start() = 0;
};
struct NaclRequestOpen: public NaclRequest {
NaclRequestOpen(pp::Instance * instance, const string & url, Manager * manager):
request(instance),
loader(instance),
url(url),
manager(manager){
request.SetURL(url);
request.SetMethod("GET");
// request.SetProperty(PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS, pp::Var((bool) PP_TRUE));
}
void start(){
Global::debug(2) << "Request open for url " << url << std::endl;
pp::CompletionCallback callback(&NaclRequestOpen::onFinish, this);
int32_t ok = loader.Open(request, callback);
Global::debug(2) << "Open " << ok << std::endl;
if (ok != PP_OK_COMPLETIONPENDING){
// Global::debug(0) << "Call on main thread" << std::endl;
// core->CallOnMainThread(0, callback, ok);
callback.Run(ok);
}
// Global::debug(1) << "Callback running" << std::endl;
}
static void onFinish(void * me, int32_t result){
NaclRequestOpen * self = (NaclRequestOpen*) me;
self->finish(result);
}
void finish(int32_t result);
pp::URLRequestInfo request;
pp::URLLoader loader;
string url;
Manager * manager;
};
struct NaclRequestExists: public NaclRequest {
NaclRequestExists(pp::Instance * instance, const string & url, Manager * manager):
request(instance),
loader(instance),
url(url),
manager(manager){
request.SetURL(url);
request.SetMethod("GET");
}
void start(){
pp::CompletionCallback callback(&NaclRequestExists::onFinish, this);
int32_t ok = loader.Open(request, callback);
if (ok != PP_OK_COMPLETIONPENDING){
callback.Run(ok);
}
}
static void onFinish(void * me, int32_t result){
NaclRequestExists * self = (NaclRequestExists*) me;
self->finish(result);
}
void finish(int32_t result);
pp::URLRequestInfo request;
pp::URLLoader loader;
string url;
Manager * manager;
};
class FileHandle{
public:
FileHandle():
buffer(NULL){
}
~FileHandle(){
delete[] buffer;
}
class Reader{
public:
static const int PAGE_SIZE = 1024 * 32;
struct Page{
Page():
buffer(NULL),
size(0),
next(NULL){
buffer = new char[PAGE_SIZE];
}
char * buffer;
int size;
Page * next;
~Page(){
delete[] buffer;
delete next;
}
};
Reader(pp::CompletionCallback finish, pp::URLLoader & loader, FileHandle * handle, pp::Core * core):
finish(finish),
loader(loader),
handle(handle),
core(core),
tries(0){
current = &page;
}
int getSize(){
Page * use = &page;
int total = 0;
while (use != NULL){
total += use->size;
use = use->next;
}
return total;
}
void copy(char * buffer){
Page * use = &page;
while (use != NULL){
memcpy(buffer, use->buffer, use->size);
buffer += use->size;
use = use->next;
}
}
void read(){
pp::CompletionCallback callback(&Reader::onRead, this);
if (current->size == PAGE_SIZE){
Page * next = new Page();
current->next = next;
current = next;
}
int32_t ok = loader.ReadResponseBody(current->buffer + current->size, PAGE_SIZE - current->size, callback);
if (ok != PP_OK_COMPLETIONPENDING){
callback.Run(ok);
}
}
static void onRead(void * self, int32_t result){
Reader * reader = (Reader*) self;
reader->didRead(result);
}
void didRead(int32_t result){
Global::debug(2) << "Read " << result << " bytes" << std::endl;
current->size += result;
if (result > 0){
tries = 0;
read();
} else {
if (tries >= 3){
handle->readDone(this);
} else {
tries += 1;
pp::CompletionCallback callback(&Reader::doRead, this);
core->CallOnMainThread((tries - 1) * 25, callback, 0);
}
}
}
static void doRead(void * self, int32_t result){
Reader * reader = (Reader*) self;
reader->read();
}
pp::CompletionCallback finish;
pp::URLLoader & loader;
Page page;
Page * current;
FileHandle * handle;
pp::Core * core;
int tries;
};
void readAll(pp::CompletionCallback finish, pp::Core * core, pp::URLLoader & loader){
reader = new Reader(finish, loader, this, core);
reader->read();
}
void readDone(Reader * reader){
length = reader->getSize();
Global::debug(2) << "Done reading, got " << length << " bytes" << std::endl;
position = 0;
buffer = new char[length];
reader->copy(buffer);
reader->finish.Run(0);
}
int read(void * buffer, size_t count){
size_t bytes = position + count < length ? count : (length - position);
memcpy(buffer, this->buffer + position, bytes);
position += bytes;
return bytes;
}
off_t seek(off_t offset, int whence){
switch (whence){
case SEEK_SET: {
position = offset;
break;
}
case SEEK_CUR: {
position += offset;
break;
}
case SEEK_END: {
position = length - offset;
break;
}
}
return position;
}
off_t position;
off_t length;
char * buffer;
Util::ReferenceCount<Reader> reader;
};
class Manager{
public:
Manager(pp::Instance * instance, pp::Core * core):
instance(instance),
core(core),
factory(this){
}
pp::Instance * instance;
pp::Core * core;
Util::ReferenceCount<NaclRequest> request;
pp::CompletionCallbackFactory<Manager> factory;
struct OpenFileData{
const char * path;
Util::ReferenceCount<FileHandle> file;
};
struct ExistsData{
const char * path;
bool exists;
};
OpenFileData openFileData;
ExistsData existsData;
Util::Thread::LockObject lock;
volatile bool done;
Util::ReferenceCount<FileHandle> openFile(const char * path){
Global::debug(1, CONTEXT) << "open " << path << std::endl;
Util::Thread::ScopedLock scoped(lock);
done = false;
openFileData.path = path;
pp::CompletionCallback callback(&Manager::doOpenFile, this);
core->CallOnMainThread(0, callback, 0);
lock.wait(done);
return openFileData.file;
}
bool exists(const string & path){
Global::debug(1, CONTEXT) << "exists " << path << std::endl;
Util::Thread::ScopedLock scoped(lock);
done = false;
existsData.exists = false;
existsData.path = path.c_str();
pp::CompletionCallback callback(&Manager::doExists, this);
core->CallOnMainThread(0, callback, 0);
lock.wait(done);
return existsData.exists;
}
static void doExists(void * self, int32_t result){
Manager * manager = (Manager*) self;
manager->continueExists();
}
void continueExists(){
request = new NaclRequestExists(instance, existsData.path, this);
request->start();
}
void success(NaclRequestExists & exists){
existsData.exists = true;
requestComplete();
}
void failure(NaclRequestExists & exists){
existsData.exists = false;
requestComplete();
}
/* called by the main thread */
static void doOpenFile(void * self, int32_t result){
Manager * manager = (Manager*) self;
manager->continueOpenFile();
}
void continueOpenFile(){
request = new NaclRequestOpen(instance, openFileData.path, this);
request->start();
}
void requestComplete(){
/* destroy request on the main thread */
request = NULL;
lock.lockAndSignal(done, true);
}
void success(NaclRequestOpen & open){
pp::URLResponseInfo info = open.loader.GetResponseInfo();
if (info.GetStatusCode() == 200){
- Global::debug(1) << "Opened file" << std::endl;
/*
int64_t received = 0;
int64_t total = 0;
if (open.loader.GetDownloadProgress(&received, &total)){
Global::debug(0) << "Downloaded " << received << " total " << total << std::endl;
}
*/
Util::ReferenceCount<FileHandle> handle = new FileHandle();
pp::CompletionCallback callback(&Manager::completeRead, this);
openFileData.file = handle;
handle->readAll(callback, core, open.loader);
/*
openFileData.file = nextFileDescriptor();
fileTable[openFileData.file] = new FileHandle(request.convert<NaclRequestOpen>());
readEntireFile(fileTable[openFileData.file]);
*/
} else {
Global::debug(1) << "Could not open file" << std::endl;
requestComplete();
}
}
static void completeRead(void * self, int32_t result){
Manager * manager = (Manager*) self;
manager->requestComplete();
}
void failure(NaclRequestOpen & open){
requestComplete();
}
};
void NaclRequestOpen::finish(int32_t result){
if (result == 0){
manager->success(*this);
} else {
manager->failure(*this);
}
}
void NaclRequestExists::finish(int32_t result){
if (result == 0){
pp::URLResponseInfo info = loader.GetResponseInfo();
if (info.GetStatusCode() == 200){
manager->success(*this);
} else {
manager->failure(*this);
}
} else {
manager->failure(*this);
}
}
NetworkSystem::NetworkSystem(pp::Instance * instance, pp::Core * core):
instance(instance),
core(core){
}
NetworkSystem::~NetworkSystem(){
}
AbsolutePath NetworkSystem::find(const RelativePath & path){
AbsolutePath all = Util::getDataPath2().join(path);
if (exists(all)){
return all;
}
throw Storage::NotFound(__FILE__, __LINE__, path.path());
}
RelativePath NetworkSystem::cleanse(const AbsolutePath & path){
string str = path.path();
if (str.find(Util::getDataPath2().path()) == 0){
str.erase(0, Util::getDataPath2().path().length());
} else if (str.find(userDirectory().path()) == 0){
str.erase(0, userDirectory().path().length());
}
return RelativePath(str);
}
bool NetworkSystem::exists(const RelativePath & path){
try{
AbsolutePath absolute = find(path);
return true;
} catch (const Storage::NotFound & found){
return false;
}
}
bool NetworkSystem::exists(const AbsolutePath & path){
Util::Thread::ScopedLock scoped(lock);
if (existsCache.find(path) != existsCache.end()){
return existsCache[path];
}
Manager manager(instance, core);
bool what = manager.exists(path.path());
existsCache[path] = what;
return what;
}
string NetworkSystem::readFileAsString(const AbsolutePath & path){
if (!exists(path)){
ostringstream fail;
fail << "Could not read " << path.path();
throw Filesystem::NotFound(__FILE__, __LINE__, fail.str());
}
ostringstream buffer;
ifstream input(path.path().c_str());
char stuff[1024];
while (input.good()){
input.read(stuff, sizeof(stuff) - 1);
stuff[sizeof(stuff) - 1] = '\0';
buffer << stuff;
}
return buffer.str();
}
static vector<string> split(string input, char splitter){
vector<string> all;
size_t found = input.find(splitter);
while (found != string::npos){
all.push_back(input.substr(0, found));
input.erase(0, found + 1);
found = input.find(splitter);
}
if (input.size() != 0){
all.push_back(input);
}
return all;
}
vector<AbsolutePath> NetworkSystem::readDirectory(const AbsolutePath & dataPath){
/* assume existence of 'directory.txt' in the given directory */
AbsolutePath fullPath = dataPath.join(RelativePath("directory.txt"));
string all = readFileAsString(fullPath);
vector<string> files = split(all, '\n');
vector<AbsolutePath> paths;
for (vector<string>::iterator it = files.begin(); it != files.end(); it++){
string what = *it;
paths.push_back(dataPath.join(RelativePath(what)));
}
return paths;
}
/* check if 'foo/bar/baz.txt' matches *.txt */
static bool matchFile(const AbsolutePath & path, const string & find, bool insensitive = false){
string file = path.getFilename().path();
unsigned int index = 0;
while (index < file.size()){
if (index >= find.size()){
return false;
}
if (find[index] == '*'){
return true;
}
if (insensitive){
if (tolower(find[index]) != tolower(file[index])){
return false;
}
} else {
if (find[index] != file[index]){
return false;
}
}
index += 1;
}
return true;
}
std::vector<AbsolutePath> NetworkSystem::getFiles(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive){
vector<AbsolutePath> files = readDirectory(dataPath);
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
if (matchFile(check, find)){
paths.push_back(check);
}
}
return paths;
}
std::vector<AbsolutePath> NetworkSystem::getFilesRecursive(const AbsolutePath & dataPath, const std::string & find, bool caseInsensitive){
vector<AbsolutePath> files = readDirectory(dataPath);
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
if (matchFile(check, find)){
paths.push_back(check);
}
vector<AbsolutePath> more = getFilesRecursive(check, find, caseInsensitive);
paths.insert(paths.end(), more.begin(), more.end());
}
return paths;
}
AbsolutePath NetworkSystem::configFile(){
return AbsolutePath("paintownrc");
}
AbsolutePath NetworkSystem::userDirectory(){
return AbsolutePath("paintown-user");
}
std::vector<AbsolutePath> NetworkSystem::findDirectories(const RelativePath & path){
vector<AbsolutePath> files = readDirectory(find(path));
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
try{
/* if we can read directory contents then its a directory */
vector<AbsolutePath> more = readDirectory(check);
paths.push_back(check);
} catch (const Filesystem::NotFound & fail){
}
}
return paths;
}
AbsolutePath NetworkSystem::findInsensitive(const RelativePath & path){
try{
/* try sensitive lookup first */
return find(path);
} catch (const Filesystem::NotFound & fail){
}
/* get the base directory */
AbsolutePath directory = find(path.getDirectory());
return lookupInsensitive(directory, path.getFilename());
}
AbsolutePath NetworkSystem::lookupInsensitive(const AbsolutePath & directory, const RelativePath & path){
vector<AbsolutePath> files = readDirectory(directory);
vector<AbsolutePath> paths;
for (vector<AbsolutePath>::iterator it = files.begin(); it != files.end(); it++){
AbsolutePath check = *it;
if (matchFile(check, path.path(), true)){
return check;
}
}
ostringstream out;
out << "Cannot find " << path.path() << " in " << directory.path();
throw Filesystem::NotFound(__FILE__, __LINE__, out.str());
}
int nextFileDescriptor(){
static int next = 3;
int n = next;
next += 1;
return n;
}
int NetworkSystem::libcOpen(const char * path, int mode, int params){
Manager manager(instance, core);
Util::ReferenceCount<FileHandle> handle = manager.openFile(path);
+ if (handle == NULL){
+ return -1;
+ }
Util::Thread::ScopedLock scoped(lock);
int file = nextFileDescriptor();
fileTable[file] = handle;
return file;
}
ssize_t NetworkSystem::libcRead(int fd, void * buffer, size_t count){
Util::Thread::ScopedLock scoped(lock);
if (fileTable.find(fd) == fileTable.end()){
return EBADF;
}
-
Util::ReferenceCount<FileHandle> handle = fileTable[fd];
+ if (handle == NULL){
+ Global::debug(0) << "Handle is null!!" << std::endl;
+ }
return handle->read(buffer, count);
}
int NetworkSystem::libcClose(int fd){
Util::Thread::ScopedLock scoped(lock);
if (fileTable.find(fd) == fileTable.end()){
return -1;
/* set errno to EBADF */
}
fileTable.erase(fileTable.find(fd));
return 0;
}
off_t NetworkSystem::libcLseek(int fd, off_t offset, int whence){
Global::debug(2, CONTEXT) << "seek fd " << fd << " offset " << offset << " whence " << whence << std::endl;
Util::Thread::ScopedLock scoped(lock);
if (fileTable.find(fd) == fileTable.end()){
return -1;
}
Util::ReferenceCount<FileHandle> handle = fileTable[fd];
return handle->seek(offset, whence);
}
}
/* NOTE FIXME Missing I/O in Native Client */
Nacl::NetworkSystem & getSystem(){
return (Nacl::NetworkSystem&) Storage::instance();
}
extern "C" {
/* http://sourceware.org/binutils/docs-2.21/ld/Options.html#index-g_t_002d_002dwrap_003d_0040var_007bsymbol_007d-261
* --wrap=symbol
* Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to __wrap_symbol. Any undefined reference to __real_symbol will be resolved to symbol.
*/
int __wrap_open(const char * path, int mode, int params){
return getSystem().libcOpen(path, mode, params);
}
ssize_t __wrap_read(int fd, void * buf, size_t count){
return getSystem().libcRead(fd, buf, count);
}
extern int __real_close(int fd);
int __wrap_close(int fd){
/* we may be given a file descriptor that we do not own, probably
* because some file descriptors are really tied to sockets so
* if we don't own the fd then pass it to the real close function.
*/
int ok = getSystem().libcClose(fd);
if (ok == -1){
return __real_close(fd);
}
return ok;
}
off_t __wrap_lseek(int fd, off_t offset, int whence){
return getSystem().libcLseek(fd, offset, whence);
}
int pipe (int filedes[2]){
return -1;
}
int mkdir (const char *filename, mode_t mode){
return -1;
}
int access(const char *filename, int how){
return -1;
}
char * getcwd (char *buffer, size_t size){
return NULL;
}
int lstat (const char *path, struct stat *buf){
return -1;
}
int rmdir (const char *filename){
return -1;
}
int chdir (const char *filename){
return -1;
}
int setuid (uid_t newuid){
return 0;
}
int seteuid (uid_t uid){
return 0;
}
uid_t geteuid (void){
return NULL;
}
int setgid (gid_t gid){
return 0;
}
gid_t getgid (void){
return NULL;
}
int setegid (gid_t gid){
return 0;
}
gid_t getegid (void){
return NULL;
}
char * getlogin (void){
return NULL;
}
uid_t getuid(void){
return NULL;
}
struct passwd * getpwuid (uid_t uid){
return NULL;
}
struct passwd * getpwnam (const char *name){
return NULL;
}
struct group * getgrnam(const char *name){
return NULL;
}
struct group * getgrgid(gid_t gid){
return NULL;
}
int link (const char *oldname, const char *newname){
return -1;
}
int unlink (const char *filename){
return -1;
}
int kill(pid_t pid, int sig){
return -1;
}
}
#endif

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:17 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68346
Default Alt Text
(26 KB)

Event Timeline