initial drop

This commit is contained in:
Alex Yatskov 2011-08-28 08:45:42 -07:00
commit e9b8aa88c0
30 changed files with 3765 additions and 0 deletions

33
main.cpp Normal file
View File

@ -0,0 +1,33 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
using namespace metacall;
int main(int argc, char **argv) {
Client client;
return 0;
}

134
mc_binding-inl.hpp Normal file
View File

@ -0,0 +1,134 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
namespace metacall {
//
// Binding
//
template <typename R>
bool Binding::bind(const Token& token, R(*function)()) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor0p<R>(function);
return true;
}
return false;
}
template <typename R, typename P1>
bool Binding::bind(const Token& token, R(*function)(P1)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor1p<R, P1>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2>
bool Binding::bind(const Token& token, R(*function)(P1, P2)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor2p<R, P1, P2>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2, typename P3>
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor3p<R, P1, P2, P3>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2, typename P3, typename P4>
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor4p<R, P1, P2, P3, P4>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor5p<R, P1, P2, P3, P4, P5>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor6p<R, P1, P2, P3, P4, P5, P6>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor7p<R, P1, P2, P3, P4, P5, P6, P7>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor8p<R, P1, P2, P3, P4, P5, P6, P7, P8>(function);
return true;
}
return false;
}
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
bool Binding::bind(const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8, P9)) {
if (functors_.find(token) == functors_.end()) {
functors_[token] = new Functor9p<R, P1, P2, P3, P4, P5, P6, P7, P8, P9>(function);
return true;
}
return false;
}
}

69
mc_binding.cpp Normal file
View File

@ -0,0 +1,69 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
namespace metacall {
//
// Binding
//
Binding::~Binding() {
unbindAll();
}
Binding::CallResult Binding::call(const Token& token, Deserializer* args, Serializer* ret) const {
const FunctorMap::const_iterator iter = functors_.find(token);
if (iter == functors_.end()) {
return CALL_RESULT_UNBOUND_FUNC;
}
if (!iter->second->call(args, ret)) {
return CALL_RESULT_INVALID_ARGS;
}
return CALL_RESULT_SUCCESS;
}
void Binding::unbind(const Token& token) {
FunctorMap::iterator iter = functors_.find(token);
if (iter != functors_.end()) {
delete iter->second;
functors_.erase(iter);
}
}
void Binding::unbindAll() {
for (FunctorMap::iterator iter = functors_.begin(); iter != functors_.end(); ++iter) {
delete iter->second;
}
functors_.clear();
}
}

76
mc_binding.hpp Normal file
View File

@ -0,0 +1,76 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Binding
//
class Binding {
public:
enum CallResult {
CALL_RESULT_SUCCESS,
CALL_RESULT_INVALID_ARGS,
CALL_RESULT_UNBOUND_FUNC
};
~Binding();
template <typename R>
bool bind (const Token& token, R(*function)());
template <typename R, typename P1>
bool bind (const Token& token, R(*function)(P1));
template <typename R, typename P1, typename P2>
bool bind (const Token& token, R(*function)(P1, P2));
template <typename R, typename P1, typename P2, typename P3>
bool bind (const Token& token, R(*function)(P1, P2, P3));
template <typename R, typename P1, typename P2, typename P3, typename P4>
bool bind (const Token& token, R(*function)(P1, P2, P3, P4));
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5));
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6));
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7));
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8));
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
bool bind (const Token& token, R(*function)(P1, P2, P3, P4, P5, P6, P7, P8, P9));
CallResult call (const Token& token, Deserializer* args, Serializer* ret) const;
void unbind (const Token& token);
void unbindAll ();
private:
typedef std::map<unsigned, IFunctor*> FunctorMap;
FunctorMap functors_;
};
}

102
mc_buffer.cpp Normal file
View File

@ -0,0 +1,102 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_buffer.hpp"
namespace metacall {
//
// Buffer
//
Buffer::Buffer(const void* data, int count) {
setData(data, count);
}
Buffer::Buffer() {
}
void Buffer::addToBack(const void* data, int bytes) {
data_.insert(
data_.end(),
static_cast<const byte*>(data),
static_cast<const byte*>(data) + bytes
);
}
void Buffer::addToFront(const void* data, int bytes) {
data_.insert(
data_.begin(),
static_cast<const byte*>(data),
static_cast<const byte*>(data) + bytes
);
}
int Buffer::removeFromFront(void* data, int bytes) {
bytes = std::min(static_cast<size_t>(bytes), data_.size());
if (data != NULL) {
memcpy(data, &data_[0], bytes);
}
data_.erase(data_.begin(), data_.begin() + bytes);
return bytes;
}
int Buffer::removeFromBack(void* data, int bytes) {
bytes = std::min(static_cast<size_t>(bytes), data_.size());
if (data != NULL) {
memcpy(data, &data_[data_.size() - bytes], bytes);
}
data_.erase(data_.end() - bytes, data_.end());
return bytes;
}
void Buffer::clear() {
data_.clear();
}
void Buffer::setData(const void* data, int bytes) {
data_.assign(
static_cast<const byte*>(data),
static_cast<const byte*>(data) + bytes
);
}
const void* Buffer::data() const {
return &data_[0];
}
void* Buffer::data() {
return &data_[0];
}
int Buffer::bytes() const {
return data_.size();
}
}

56
mc_buffer.hpp Normal file
View File

@ -0,0 +1,56 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Buffer
//
class Buffer {
public:
Buffer(const void* data, int bytes);
Buffer();
void addToBack (const void* data, int bytes);
void addToFront (const void* data, int bytes);
int removeFromFront (void* data, int bytes);
int removeFromBack (void* data, int bytes);
void clear ();
void setData (const void* data, int bytes);
const void* data () const;
void* data ();
int bytes () const;
private:
std::vector<byte> data_;
};
}

97
mc_client.cpp Normal file
View File

@ -0,0 +1,97 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_client.hpp"
namespace metacall {
//
// Client
//
Client::Client() :
stream_(&socket_),
protocol_(&stream_, &binding_)
{
}
void Client::advance() {
if (!socket_.opened()) {
return;
}
if (socket_.connected()) {
protocol_.advance();
}
else {
disconnect();
}
}
bool Client::connect(const char name[], int port) {
disconnect();
socket_.open();
socket_.setNagle(false);
if (!socket_.connect(name, port)) {
disconnect();
return false;
}
socket_.setBlocking(false);
return true;
}
void Client::disconnect() {
protocol_.clearHandlers();
stream_.reset();
socket_.close();
}
bool Client::connected() const {
return socket_.connected();
}
const Protocol* Client::protocol() const {
return &protocol_;
}
Protocol* Client::protocol() {
return &protocol_;
}
const Binding* Client::binding() const {
return &binding_;
}
Binding* Client::binding() {
return &binding_;
}
}

58
mc_client.hpp Normal file
View File

@ -0,0 +1,58 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Client
//
class Client {
public:
Client();
void advance ();
bool connect (const char name[], int port);
void disconnect ();
bool connected () const;
const Protocol* protocol () const;
Protocol* protocol ();
const Binding* binding () const;
Binding* binding ();
private:
Socket socket_;
Stream stream_;
Binding binding_;
Protocol protocol_;
};
}

56
mc_common.hpp Normal file
View File

@ -0,0 +1,56 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Macros
//
#define IS_TRUE(x) ((x) != 0)
#define ASSERT assert
//
// Types
//
#ifdef _WIN32
typedef unsigned __int8 byte;
typedef unsigned __int16 word;
typedef unsigned __int32 dword;
typedef unsigned __int64 qword;
#else
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int dword;
typedef unsigned long int qword;
#endif
}

755
mc_functor.hpp Normal file
View File

@ -0,0 +1,755 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// IFunctor
//
class IFunctor {
public:
virtual bool call(Deserializer* args, Serializer* ret) const = 0;
};
//
// Functor0p
//
template <typename R>
class Functor0p : public IFunctor {
public:
typedef R(*F)();
Functor0p(F function) :
function_(function)
{
}
bool call(Deserializer*, Serializer* ret) const {
ret->write(function_());
return true;
}
private:
F function_;
};
template <>
class Functor0p<void> : public IFunctor {
public:
typedef void(*F)();
Functor0p(F function) :
function_(function)
{
}
bool call(Deserializer*, Serializer*) const {
function_();
return true;
}
private:
F function_;
};
//
// Functor1p
//
template <typename R, typename P1>
class Functor1p : public IFunctor {
public:
typedef R (*F)(P1);
Functor1p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
const bool success = args->read(&p1);
if (success) {
ret->write(function_(p1));
}
return success;
}
private:
F function_;
};
template <typename P1>
class Functor1p<void, P1> : public IFunctor {
public:
typedef void (*F)(P1);
Functor1p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
const bool success = args->read(&p1);
if (success) {
function_(p1);
}
return success;
}
private:
F function_;
};
//
// Functor2p
//
template <typename R, typename P1, typename P2>
class Functor2p : public IFunctor {
public:
typedef R (*F)(P1, P2);
Functor2p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
const bool success =
args->read(&p1) &&
args->read(&p2);
if (success) {
ret->write(function_(p1, p2));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2>
class Functor2p<void, P1, P2> : public IFunctor {
public:
typedef void (*F)(P1, P2);
Functor2p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
const bool success =
args->read(&p1) &&
args->read(&p2);
if (success) {
function_(p1, p2);
}
return success;
}
private:
F function_;
};
//
// Functor3p
//
template <typename R, typename P1, typename P2, typename P3>
class Functor3p : public IFunctor {
public:
typedef R (*F)(P1, P2, P3);
Functor3p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3);
if (success) {
ret->write(function_(p1, p2, p3));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2, typename P3>
class Functor3p<void, P1, P2, P3> : public IFunctor {
public:
typedef void (*F)(P1, P2, P3);
Functor3p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3);
if (success) {
function_(p1, p2, p3);
}
return success;
}
private:
F function_;
};
//
// Functor4p
//
template <typename R, typename P1, typename P2, typename P3, typename P4>
class Functor4p : public IFunctor {
public:
typedef R (*F)(P1, P2, P3, P4);
Functor4p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4);
if (success) {
ret->write(function_(p1, p2, p3, p4));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2, typename P3, typename P4>
class Functor4p<void, P1, P2, P3, P4> : public IFunctor {
public:
typedef void (*F)(P1, P2, P3, P4);
Functor4p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4);
if (success) {
function_(p1, p2, p3, p4);
}
return success;
}
private:
F function_;
};
//
// Functor5p
//
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
class Functor5p : public IFunctor {
public:
typedef R (*F)(P1, P2, P3, P4, P5);
Functor5p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5);
if (success) {
ret->write(function_(p1, p2, p3, p4, p5));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2, typename P3, typename P4, typename P5>
class Functor5p<void, P1, P2, P3, P4, P5> : public IFunctor {
public:
typedef void (*F)(P1, P2, P3, P4, P5);
Functor5p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5);
if (success) {
function_(p1, p2, p3, p4, p5);
}
return success;
}
private:
F function_;
};
//
// Functor6p
//
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
class Functor6p : public IFunctor {
public:
typedef R (*F)(P1, P2, P3, P4, P5, P6);
Functor6p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6);
if (success) {
ret->write(function_(p1, p2, p3, p4, p5, p6));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
class Functor6p<void, P1, P2, P3, P4, P5, P6> : public IFunctor {
public:
typedef void (*F)(P1, P2, P3, P4, P5, P6);
Functor6p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6);
if (success) {
function_(p1, p2, p3, p4, p5, p6);
}
return success;
}
private:
F function_;
};
//
// Functor7p
//
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
class Functor7p : public IFunctor {
public:
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7);
Functor7p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
typename StripConstRef<P7>::Type p7;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6) &&
args->read(&p7);
if (success) {
ret->write(function_(p1, p2, p3, p4, p5, p6, p7));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
class Functor7p<void, P1, P2, P3, P4, P5, P6, P7> : public IFunctor {
public:
typedef void (*F)(P1, P2, P3, P4, P5, P6, P7);
Functor7p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
typename StripConstRef<P7>::Type p7;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6) &&
args->read(&p7);
if (success) {
function_(p1, p2, p3, p4, p5, p6, p7);
}
return success;
}
private:
F function_;
};
//
// Functor8p
//
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
class Functor8p : public IFunctor {
public:
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7, P8);
Functor8p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
typename StripConstRef<P7>::Type p7;
typename StripConstRef<P8>::Type p8;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6) &&
args->read(&p7) &&
args->read(&p8);
if (success) {
ret->write(function_(p1, p2, p3, p4, p5, p6, p7, p8));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
class Functor8p<void, P1, P2, P3, P4, P5, P6, P7, P8> : public IFunctor {
public:
typedef void (*F)(P1, P2, P3, P4, P5, P6, P7, P8);
Functor8p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
typename StripConstRef<P7>::Type p7;
typename StripConstRef<P8>::Type p8;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6) &&
args->read(&p7) &&
args->read(&p8);
if (success) {
function_(p1, p2, p3, p4, p5, p6, p7, p8);
}
return success;
}
private:
F function_;
};
//
// Functor9p
//
template <typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
class Functor9p : public IFunctor {
public:
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
Functor9p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer* ret) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
typename StripConstRef<P7>::Type p7;
typename StripConstRef<P8>::Type p8;
typename StripConstRef<P9>::Type p9;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6) &&
args->read(&p7) &&
args->read(&p8) &&
args->read(&p9);
if (success) {
ret->write(function_(p1, p2, p3, p4, p5, p6, p7, p8, p9));
}
return success;
}
private:
F function_;
};
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
class Functor9p<void, P1, P2, P3, P4, P5, P6, P7, P8, P9> : public IFunctor {
public:
typedef void (*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
Functor9p(F function) :
function_(function)
{
}
bool call(Deserializer* args, Serializer*) const {
typename StripConstRef<P1>::Type p1;
typename StripConstRef<P2>::Type p2;
typename StripConstRef<P3>::Type p3;
typename StripConstRef<P4>::Type p4;
typename StripConstRef<P5>::Type p5;
typename StripConstRef<P6>::Type p6;
typename StripConstRef<P7>::Type p7;
typename StripConstRef<P8>::Type p8;
typename StripConstRef<P9>::Type p9;
const bool success =
args->read(&p1) &&
args->read(&p2) &&
args->read(&p3) &&
args->read(&p4) &&
args->read(&p5) &&
args->read(&p6) &&
args->read(&p7) &&
args->read(&p8) &&
args->read(&p9);
if (success) {
function_(p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
return success;
}
private:
F function_;
};
}

88
mc_meta.hpp Normal file
View File

@ -0,0 +1,88 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Meta
//
qword serialize (class Serializer*, ...);
qword deserialize (class Deserializer*, ...);
template <typename T>
struct IsSerializable {
enum {
Value = sizeof(bool) == sizeof(
serialize(
static_cast<Serializer*>(0),
*static_cast<T*>(0)
)
)
};
};
template <typename T>
struct IsDeserializable {
enum {
Value = sizeof(bool) == sizeof(
deserialize(
static_cast<Deserializer*>(0),
static_cast<T*>(0)
)
)
};
};
template <typename T>
struct StripRef {
typedef T Type;
};
template <typename T>
struct StripRef<T&> {
typedef T Type;
};
template <typename T>
struct StripConst {
typedef T Type;
};
template <typename T>
struct StripConst<const T> {
typedef T Type;
};
template <typename T>
struct StripConstRef {
typedef typename StripConst<typename StripRef<T>::Type >::Type Type;
};
}

112
mc_packet.hpp Normal file
View File

@ -0,0 +1,112 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Constants
//
enum PacketConst {
PACKET_CONST_MAGIC = 0x55534544,
PACKET_CONST_VERSION = 1
};
enum PacketId {
PACKET_ID_INVALID,
PACKET_ID_FUNCTION_CALL_REQUEST,
PACKET_ID_FUNCTION_CALL_REPLY
};
//
// PacketHeader
//
struct PacketHeader {
PacketHeader() :
magic(0),
id(PACKET_ID_INVALID),
size(0)
{
}
dword magic;
byte id;
dword size;
};
//
// PacketInvokeRequest
//
struct PacketInvokeRequest {
PacketInvokeRequest() :
function(0),
taskId(0)
{
}
enum {
Id = PACKET_ID_FUNCTION_CALL_REQUEST
};
dword function;
dword taskId;
Buffer data;
};
//
// PacketInvokeReply
//
struct PacketInvokeReply {
PacketInvokeReply() :
flags(0),
taskId(0)
{
}
enum {
Id = PACKET_ID_FUNCTION_CALL_REPLY
};
enum {
FLAG_UNBOUND_FUNC = 1 << 0,
FLAG_INVALID_ARGS = 1 << 1,
};
word flags;
dword taskId;
Buffer data;
};
}

174
mc_protocol-inl.hpp Normal file
View File

@ -0,0 +1,174 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
namespace metacall {
template <typename P1>
TaskId Protocol::invoke(const Token& token, const P1& p1) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2, typename P3>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
serializer.write(p3);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2, typename P3, typename P4>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3 & p3, const P4& p4) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
serializer.write(p3);
serializer.write(p4);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2, typename P3, typename P4, typename P5>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
serializer.write(p3);
serializer.write(p4);
serializer.write(p5);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
serializer.write(p3);
serializer.write(p4);
serializer.write(p5);
serializer.write(p6);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
serializer.write(p3);
serializer.write(p4);
serializer.write(p5);
serializer.write(p6);
serializer.write(p7);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
serializer.write(p3);
serializer.write(p4);
serializer.write(p5);
serializer.write(p6);
serializer.write(p7);
serializer.write(p8);
return invokeExec(token, &packetRequest);
}
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
TaskId Protocol::invoke(const Token& token, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6, const P7& p7, const P8& p8, const P9& p9) {
PacketInvokeRequest packetRequest;
Serializer serializer(&packetRequest.data);
serializer.write(p1);
serializer.write(p2);
serializer.write(p3);
serializer.write(p4);
serializer.write(p5);
serializer.write(p6);
serializer.write(p7);
serializer.write(p8);
serializer.write(p9);
return invokeExec(token, &packetRequest);
}
template <typename R>
TaskState Protocol::queryResult(TaskId id, R* result) {
TaskMap::const_iterator iter = taskMap_.find(id);
if (iter == taskMap_.end()) {
return TASK_STATE_UNDEFINED;
}
TaskEntry& entry = iter->second;
if (entry.state == TASK_STATE_READY) {
Deserializer deserializer(&entry.data);
if (!deserializer.read(result)) {
entry.state = TASK_STATE_ERROR;
}
}
return entry.state;
}
}

208
mc_protocol.cpp Normal file
View File

@ -0,0 +1,208 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_protocol.hpp"
namespace metacall {
//
// Protocol
//
Protocol::Protocol(Stream* stream, Binding* binding) :
stream_(stream),
binding_(binding),
rate_(64)
{
}
void Protocol::advance() {
if (!stream_->socket()->connected()) {
return;
}
for (int i = 0; i < rate_; ++i) {
if (advanceStream() != Stream::STATE_READY) {
break;
}
}
std::vector<TaskMap::iterator> processed;
for (TaskMap::iterator iter = taskMap_.begin(); iter != taskMap_.end(); ++iter) {
TaskEntry& entry = iter->second;
switch (entry.state) {
case TASK_STATE_READY:
case TASK_STATE_ERROR:
processed.push_back(iter);
for (size_t i = 0; i < entry.handlers.size(); ++i) {
HandlerEntry& handler = entry.handlers[i];
handler.handler(this, iter->first, entry.state, handler.userPtr);
}
break;
default:
break;
}
}
for (size_t i = 0; i < processed.size(); ++i) {
taskMap_.erase(processed[i]);
}
}
void Protocol::setRate(int rate) {
rate_ = rate;
}
bool Protocol::setHandler(TaskId id, HandlerProc handler, void* userPtr) {
const TaskMap::iterator iter = taskMap_.find(id);
if (iter == taskMap_.end() || iter->second.state != TASK_STATE_PENDING) {
return false;
}
iter->second.handlers.push_back(HandlerEntry(handler, userPtr));
return true;
}
void Protocol::clearHandler(TaskId id) {
const TaskMap::iterator iter = taskMap_.find(id);
if (iter != taskMap_.end()) {
taskMap_.erase(iter);
}
}
void Protocol::clearHandlers() {
for (TaskMap::iterator iter = taskMap_.begin(); iter != taskMap_.end(); ++iter) {
iter->second.handlers.clear();
}
}
TaskState Protocol::queryState(TaskId id) const {
const TaskMap::const_iterator iter = taskMap_.find(id);
return iter == taskMap_.end() ? TASK_STATE_UNDEFINED : iter->second.state;
}
Stream::State Protocol::advanceStream() {
stream_->advance();
PacketHeader header;
int headerSize = 0;
Stream::State state = stream_->peek(&header, &headerSize);
if (state == Stream::STATE_READY) {
switch (header.id) {
case PACKET_ID_FUNCTION_CALL_REQUEST:
state = advanceInvokeRequest();
break;
case PACKET_ID_FUNCTION_CALL_REPLY:
state = advanceInvokeReply();
break;
default:
state = Stream::STATE_ERROR_PROTOCOL;
break;
}
}
return state;
}
Stream::State Protocol::advanceInvokeReply() {
PacketInvokeReply packetReply;
Deserializer deserializer(&packetReply.data);
Stream::State state = stream_->receive(&packetReply);
if (state == Stream::STATE_READY) {
const TaskMap::iterator iter = taskMap_.find(static_cast<TaskId>(packetReply.taskId));
if (iter == taskMap_.end()) {
state = Stream::STATE_ERROR_PROTOCOL;
}
else {
const bool error =
IS_TRUE(packetReply.flags & PacketInvokeReply::FLAG_UNBOUND_FUNC) ||
IS_TRUE(packetReply.flags & PacketInvokeReply::FLAG_INVALID_ARGS);
iter->second.state = error ? TASK_STATE_ERROR : TASK_STATE_READY;
iter->second.data = packetReply.data;
}
}
return state;
}
Stream::State Protocol::advanceInvokeRequest() {
PacketInvokeRequest packetRequest;
Deserializer deserializer(&packetRequest.data);
const Stream::State state = stream_->receive(&packetRequest);
if (state == Stream::STATE_READY) {
PacketInvokeReply packetReply;
packetReply.taskId = packetRequest.taskId;
Serializer serializer(&packetReply.data);
switch (binding_->call(packetRequest.function, &deserializer, &serializer)) {
case Binding::CALL_RESULT_INVALID_ARGS:
packetReply.flags |= PacketInvokeReply::FLAG_INVALID_ARGS;
break;
case Binding::CALL_RESULT_UNBOUND_FUNC:
packetReply.flags |= PacketInvokeReply::FLAG_UNBOUND_FUNC;
break;
default:
break;
}
stream_->send(packetReply);
}
return state;
}
TaskId Protocol::invoke(const Token& token) {
PacketInvokeRequest packetRequest;
return invokeExec(token, &packetRequest);
}
TaskId Protocol::invokeExec(const Token& token, PacketInvokeRequest* packetRequest) {
const TaskId taskId = registerTaskId();
packetRequest->function = token;
packetRequest->taskId = taskId;
if (stream_->send(*packetRequest) != Stream::STATE_READY) {
return TASK_ID_INVALID;
}
taskMap_[taskId] = TaskEntry();
return taskId;
}
TaskId Protocol::registerTaskId() {
static int id = TASK_ID_INVALID;
while (++id == TASK_ID_INVALID);
return static_cast<TaskId>(id);
}
}

132
mc_protocol.hpp Normal file
View File

@ -0,0 +1,132 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Types
//
enum TaskId {
TASK_ID_INVALID
};
enum TaskState {
TASK_STATE_UNDEFINED,
TASK_STATE_PENDING,
TASK_STATE_READY,
TASK_STATE_ERROR
};
typedef void (*HandlerProc)(
class Protocol* protocol,
TaskId id,
TaskState state,
void* userPtr
);
//
// Protocol
//
class Protocol {
public:
Protocol(Stream* stream, Binding* binding);
void advance ();
void setRate (int rate);
bool setHandler (TaskId id, HandlerProc handler, void* userPtr = NULL);
void clearHandler (TaskId id);
void clearHandlers ();
template <typename R>
TaskState queryResult (TaskId id, R* result);
TaskState queryState (TaskId id) const;
TaskId invoke (const Token& token);
template <typename P1>
TaskId invoke (const Token& token, const P1& p0);
template <typename P1, typename P2>
TaskId invoke (const Token& token, const P1& p0, const P2& p1);
template <typename P1, typename P2, typename P3>
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2);
template <typename P1, typename P2, typename P3, typename P4>
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3);
template <typename P1, typename P2, typename P3, typename P4, typename P5>
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4);
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5);
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5, const P7& p6);
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5, const P7& p6, const P8& p7);
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
TaskId invoke (const Token& token, const P1& p0, const P2& p1, const P3& p2, const P4& p3, const P5& p4, const P6& p5, const P7& p6, const P8& p7, const P9& p8);
private:
struct HandlerEntry {
HandlerEntry(HandlerProc handler, void* userPtr) :
handler(handler),
userPtr(userPtr)
{
}
HandlerProc handler;
void* userPtr;
};
struct TaskEntry {
TaskEntry() :
state(TASK_STATE_PENDING)
{
}
typedef std::vector<HandlerEntry> HandlerList;
HandlerList handlers;
TaskState state;
Buffer data;
};
Stream::State advanceStream ();
Stream::State advanceInvokeRequest();
Stream::State advanceInvokeReply ();
TaskId invokeExec (const Token& token, PacketInvokeRequest* packetRequest);
static TaskId registerTaskId ();
typedef std::map<TaskId, TaskEntry> TaskMap;
TaskMap taskMap_;
Stream* stream_;
Binding* binding_;
int rate_;
};
}

117
mc_serial-inl.hpp Normal file
View File

@ -0,0 +1,117 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
namespace metacall {
//
// TypeReader
//
template <typename T, bool G>
struct TypeReader {
static bool read(Deserializer* deserializer, T* data) {
return deserialize(deserializer, data);
}
};
template <typename T>
struct TypeReader<T, false> {
static bool read(Deserializer* deserializer, T* data) {
const T* const temp = reinterpret_cast<const T*>(deserializer->readRaw(sizeof(T)));
if (temp != NULL) {
*data = *temp;
}
return temp != NULL;
}
};
template <typename T>
bool Deserializer::read(T* data) {
return TypeReader<T, IsDeserializable<T>::Value>::read(this, data);
}
//
// TypeWriter
//
template <typename T, bool G>
struct TypeWriter {
static bool write(Serializer* serializer, const T& data) {
return serialize(serializer, data);
}
};
template <typename T>
struct TypeWriter<T, false> {
static bool write(Serializer* serializer, const T& data) {
return serializer->writeRaw(&data, sizeof(T));
}
};
template <typename T>
bool Serializer::write(const T& data) {
return TypeWriter<T, IsSerializable<T>::Value>::write(this, data);
}
//
// Serializers
//
template <typename T>
bool serialize(Serializer* serializer, const ArrayWriter<T>& writer) {
serializer->write(writer.count);
for (int i = 0; i < writer.count; ++i) {
serializer->write(writer.data[i]);
}
return true;
}
template <typename T>
bool deserialize(Deserializer* deserializer, ArrayReader<T>* reader) {
reader->clear();
if (!deserializer->read(&reader->count)) {
return false;
}
reader->data = new T[reader->count];
for (int i = 0; i < reader->count; ++i) {
if (!deserializer->read(reader->data + i)) {
reader->clear();
return false;
}
}
return true;
}
}

173
mc_serial.cpp Normal file
View File

@ -0,0 +1,173 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_serial.hpp"
namespace metacall {
//
// Deserializer
//
Deserializer::Deserializer(const Buffer* data) :
data_(data),
offset_(0)
{
}
const byte* Deserializer::readRaw(int size) {
if (data_ == NULL || size > data_->bytes() - offset_) {
return NULL;
}
const byte* data = static_cast<const byte*>(data_->data()) + offset_;
offset_ += size;
return data;
}
int Deserializer::offset() const {
return offset_;
}
bool Deserializer::setOffset(int offset, bool relative) {
const int offsetNew = relative ? offset_ + offset : offset;
if (offsetNew >= 0 && offsetNew <= data_->bytes()) {
offset_ = offsetNew;
return true;
}
return false;
}
//
// Serializer
//
Serializer::Serializer(Buffer* data) :
data_(data),
offset_(0)
{
}
bool Serializer::writeRaw(const void* data, int size) {
if (data_ != NULL) {
data_->addToBack(static_cast<const byte*>(data), size);
offset_ += size;
}
return true;
}
bool Serializer::setOffset(int offset, bool relative) {
const int offsetNew = relative ? offset_ + offset : offset;
if (offsetNew >= 0 && offsetNew <= data_->bytes()) {
offset_ = offsetNew;
return true;
}
return false;
}
int Serializer::offset() const {
return offset_;
}
//
// Serializers
//
bool serialize(Serializer* serializer, const Buffer& buffer) {
serializer->write(buffer.bytes());
serializer->writeRaw(buffer.data(), buffer.bytes());
return true;
}
bool deserialize(Deserializer* deserializer, Buffer* buffer) {
int count = 0;
if (!deserializer->read(&count)) {
return false;
}
const byte* const data = deserializer->readRaw(count);
if (data == NULL)
{
return false;
}
buffer->setData(data, count);
return true;
}
bool serialize(Serializer* serializer, const PacketHeader& packet) {
return
serializer->write(packet.magic) &&
serializer->write(packet.id) &&
serializer->write(packet.size);
}
bool deserialize(Deserializer* deserializer, PacketHeader* packet) {
return
deserializer->read(&packet->magic) &&
deserializer->read(&packet->id) &&
deserializer->read(&packet->size);
}
bool serialize(Serializer* serializer, const PacketInvokeRequest& packet) {
return
serializer->write(packet.function) &&
serializer->write(packet.taskId) &&
serializer->write(packet.data);
}
bool deserialize(Deserializer* deserializer, PacketInvokeRequest* packet) {
return
deserializer->read(&packet->function) &&
deserializer->read(&packet->taskId) &&
deserializer->read(&packet->data);
}
bool serialize(Serializer* serializer, const PacketInvokeReply& packet) {
return
serializer->write(packet.flags) &&
serializer->write(packet.taskId) &&
serializer->write(packet.data);
}
bool deserialize(Deserializer* deserializer, PacketInvokeReply* packet) {
return
deserializer->read(&packet->flags) &&
deserializer->read(&packet->taskId) &&
deserializer->read(&packet->data);
}
}

136
mc_serial.hpp Normal file
View File

@ -0,0 +1,136 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Deserializer
//
class Deserializer {
public:
Deserializer(const Buffer* data);
template <typename T>
bool read (T* data);
const byte* readRaw (int size);
bool setOffset (int offset, bool relative);
int offset () const;
private:
const Buffer* data_;
int offset_;
};
//
// Serializer
//
class Serializer {
public:
Serializer(Buffer* data);
template <typename T>
bool write (const T& data);
bool writeRaw (const void* data, int size);
bool setOffset (int offset, bool relative);
int offset () const;
private:
Buffer* data_;
int offset_;
};
//
// ArrayWriter
//
template <typename T>
class ArrayWriter {
public:
ArrayWriter(const T* data, int count) :
data(data),
count(count)
{
}
const T* data;
int count;
};
//
// ArrayReader
//
template <typename T>
class ArrayReader {
public:
ArrayReader() :
data(NULL),
count(0)
{
}
~ArrayReader() {
delete[] data;
data = NULL;
count = 0;
}
const T* data;
int count;
};
//
// Standard serializers/deserializers
//
template <typename T>
bool serialize (Serializer* serializer, const ArrayWriter<T>& writer);
template <typename T>
bool deserialize (Deserializer* deserializer, ArrayReader<T>* reader);
bool serialize (Serializer* serializer, const Buffer& buffer);
bool deserialize (Deserializer* deserializer, Buffer* buffer);
bool serialize (Serializer* serializer, const PacketHeader& packet);
bool deserialize (Deserializer* deserializer, PacketHeader* packet);
bool serialize (Serializer* serializer, const PacketInvokeRequest& packet);
bool deserialize (Deserializer* deserializer, PacketInvokeRequest* packet);
bool serialize (Serializer* serializer, const PacketInvokeReply& packet);
bool deserialize (Deserializer* deserializer, PacketInvokeReply* packet);
}

169
mc_server.cpp Normal file
View File

@ -0,0 +1,169 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_server.hpp"
namespace metacall {
//
// Server
//
Server::Server() :
clientMax_(1),
clientActive_(CLIENT_ID_INVALID)
{
}
Server::~Server() {
disconnectAll();
}
void Server::advance() {
advanceConnecting();
advanceDisconnecting();
advanceConnected();
}
const Binding* Server::binding() const {
return &binding_;
}
Binding* Server::binding() {
return &binding_;
}
bool Server::start(int serverPort, int clientsMax) {
stop();
if (server_.open() && server_.bind(serverPort) && server_.listen()) {
server_.setBlocking(false);
server_.setNagle(false);
clientMax_ = clientsMax;
return true;
}
stop();
return false;
}
void Server::stop() {
disconnectAll();
clientMax_ = 0;
}
void Server::getClients(std::vector<ClientId>* clients) const {
for (ClientMap::const_iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
clients->push_back(iter->first);
}
}
bool Server::getClient(ClientId id, ClientData* data) const {
const ClientMap::const_iterator iter = clients_.find(id);
if (iter != clients_.end()) {
data->id = iter->first;
data->name = iter->second->socket.hostname();
data->protocol = &iter->second->protocol;
return true;
}
return false;
}
void Server::disconnect(ClientId id) {
const ClientMap::iterator iter = clients_.find(id);
if (iter != clients_.end()) {
delete iter->second;
clients_.erase(iter);
}
}
void Server::disconnectAll() {
for (ClientMap::iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
delete iter->second;
}
clients_.clear();
}
int Server::clientCount() const {
return clients_.size();
}
ClientId Server::clientActive() const {
return clientActive_;
}
void Server::advanceConnecting() {
if (clientMax_ == 0 || !server_.opened()) {
return;
}
Socket client;
if (!server_.accept(&client)) {
return;
}
const std::pair<ClientId, ClientEntry*> entry(registerClientId(), new ClientEntry(&binding_));
const ClientMap::iterator iter = clients_.insert(entry).first;
iter->second->socket.set(client.release());
iter->second->socket.setNagle(false);
iter->second->socket.setBlocking(false);
}
void Server::advanceDisconnecting() {
std::vector<ClientMap::iterator> clients;
for (ClientMap::iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
if (!iter->second->socket.connected()) {
clients.push_back(iter);
}
}
for (std::vector<ClientMap::iterator>::iterator iter = clients.begin(); iter != clients.end(); ++iter) {
disconnect((*iter)->first);
}
}
void Server::advanceConnected() {
ASSERT(clientActive_ == CLIENT_ID_INVALID);
for (ClientMap::iterator iter = clients_.begin(); iter != clients_.end(); ++iter) {
clientActive_ = iter->first;
iter->second->protocol.advance();
}
clientActive_ = CLIENT_ID_INVALID;
}
ClientId Server::registerClientId() {
static int s_id = CLIENT_ID_INVALID;
while (++s_id == CLIENT_ID_INVALID);
return static_cast<ClientId>(s_id);
}
}

101
mc_server.hpp Normal file
View File

@ -0,0 +1,101 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Types
//
enum ClientId {
CLIENT_ID_INVALID
};
struct ClientData {
ClientData() :
id(CLIENT_ID_INVALID),
protocol(NULL)
{
}
ClientId id;
std::string name;
Protocol* protocol;
};
//
// Server
//
class Server {
public:
Server();
~Server();
void advance ();
bool start (int serverPort, int clientsMax = 1);
void stop ();
void disconnect (ClientId id);
void disconnectAll ();
void getClients (std::vector<ClientId>* clients) const;
bool getClient (ClientId id, ClientData* data) const;
ClientId clientActive () const;
int clientCount () const;
const Binding* binding () const;
Binding* binding ();
private:
struct ClientEntry : public ClientData {
ClientEntry(Binding* binding) :
stream(&socket),
protocol(&stream, binding)
{
}
Socket socket;
Stream stream;
Protocol protocol;
};
void advanceConnecting ();
void advanceConnected ();
void advanceDisconnecting ();
static ClientId registerClientId ();
typedef std::map<ClientId, ClientEntry*> ClientMap;
ClientMap clients_;
int clientMax_;
ClientId clientActive_;
Socket server_;
Binding binding_;
};
}

314
mc_socket.cpp Normal file
View File

@ -0,0 +1,314 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_socket.hpp"
namespace metacall {
//
// Constants
//
namespace {
const int SOCKET_INVALID = -1;
}
//
// Socket
//
Socket::Socket() :
socket_(SOCKET_INVALID)
{
}
Socket::~Socket() {
close();
}
bool Socket::open() {
close();
socket_ = socket(AF_INET, SOCK_STREAM, 0);
return opened();
}
void Socket::close() {
if (!opened()) {
return;
}
#ifdef _WIN32
closesocket(socket_);
#else
::close(socket_);
#endif
socket_ = SOCKET_INVALID;
}
int Socket::release() {
const int temp = socket_;
socket_ = SOCKET_INVALID;
return temp;
}
void Socket::set(int socket) {
close();
socket_ = socket;
}
void Socket::setNagle(bool enable) {
ASSERT(opened());
const int value = enable ? 0 : 1;
const char* const valuePtr = reinterpret_cast<const char*>(&value);
setsockopt(
socket_,
IPPROTO_TCP,
TCP_NODELAY,
valuePtr,
sizeof(value)
);
}
void Socket::setBlocking(bool enable) {
ASSERT(opened());
#ifdef _WIN32
unsigned long nonBlock = enable ? 0 : 1;
ioctlsocket(socket_, FIONBIO, &nonBlock);
#else
const int flagsOld = fcntl(socket_, F_GETFL);
const int flagsNew = enable ? flagsOld & ~O_NONBLOCK : flagsOld | O_NONBLOCK;
fcntl(socket_, F_SETFL, flagsNew);
#endif
}
bool Socket::connect(const char name[], int port) {
ASSERT(opened());
long address = 0;
if (!resolve(name, &address)) {
return false;
}
sockaddr_in host = { 0 };
host.sin_port = htons(static_cast<unsigned short>(port));
host.sin_family = AF_INET;
host.sin_addr.s_addr = address;
const sockaddr* const hostPtr = reinterpret_cast<const sockaddr*>(&host);
if (::connect(socket_, hostPtr, sizeof(host)) == SOCKET_INVALID) {
return false;
}
return true;
}
bool Socket::bind(int port) {
ASSERT(opened());
sockaddr_in host = { 0 };
host.sin_family = AF_INET;
host.sin_addr.s_addr = INADDR_ANY;
host.sin_port = htons(static_cast<unsigned short>(port));
const sockaddr* const hostPtr = reinterpret_cast<const sockaddr*>(&host);
if (::bind(socket_, hostPtr, sizeof(host)) == SOCKET_INVALID) {
return false;
}
return true;
}
bool Socket::listen(int backlog) {
ASSERT(opened());
return ::listen(socket_, backlog) != SOCKET_INVALID;
}
bool Socket::accept(Socket* socket) {
ASSERT(opened());
socket->close();
socket->socket_ = ::accept(socket_, 0, 0);
return socket->socket_ != SOCKET_INVALID;
}
int Socket::receive(void* buffer, int size) {
ASSERT(opened());
if (size <= 0) {
return 0;
}
return recv(
socket_,
static_cast<char *>(buffer),
size,
0
);
}
int Socket::peek(void* buffer, int size) const {
ASSERT(opened());
if (size <= 0) {
return 0;
}
return recv(
socket_,
static_cast<char *>(buffer),
size,
MSG_PEEK
);
}
int Socket::send(const void* buffer, int size) {
ASSERT(opened());
if (size <= 0) {
return 0;
}
return ::send(
socket_,
static_cast<const char*>(buffer),
size,
0
);
}
bool Socket::wait(unsigned mask, int seconds) const {
ASSERT(opened());
fd_set readSet;
fd_set writeSet;
fd_set exceptSet;
fd_set* readSetUse = NULL;
fd_set* writeSetUse = NULL;
fd_set* exceptSetUse = NULL;
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable:4127)
#endif
if (IS_TRUE(mask & MASK_READ)) {
readSetUse = &readSet;
FD_ZERO(readSetUse);
FD_SET(socket_, readSetUse);
}
if (IS_TRUE(mask & MASK_WRITE)) {
writeSetUse = &writeSet;
FD_ZERO(writeSetUse);
FD_SET(socket_, writeSetUse);
}
if (IS_TRUE(mask & MASK_EXCEPT)) {
exceptSetUse = &exceptSet;
FD_ZERO(exceptSetUse);
FD_SET(socket_, exceptSetUse);
}
#ifdef _WIN32
#pragma warning(pop)
#endif
timeval timeoutVal = { 0 };
timeoutVal.tv_sec = seconds;
timeval* const timeoutPtr = seconds < 0 ? NULL : &timeoutVal;
const int result = select(
socket_ + 1,
readSetUse,
writeSetUse,
exceptSetUse,
timeoutPtr
);
return result > 0;
}
bool Socket::opened() const {
return socket_ != SOCKET_INVALID;
}
bool Socket::connected() const {
if (!opened()) {
return false;
}
if (!wait(MASK_READ, 0)) {
return true;
}
byte buffer = 0;
if (peek(&buffer, sizeof(buffer)) == 0) {
return false;
}
return true;
}
const char* Socket::hostname() const {
if (!opened()) {
return NULL;
}
sockaddr_in host = { 0 };
socklen_t hostSize = sizeof(host);
sockaddr* const hostPtr = reinterpret_cast<sockaddr*>(&host);
if (getsockname(socket_, hostPtr, &hostSize) == SOCKET_INVALID) {
return NULL;
}
return inet_ntoa(host.sin_addr);
}
bool Socket::resolve(const char name[], long* address) {
if ((*address = inet_addr(name)) != INADDR_NONE) {
return true;
}
hostent* const host = gethostbyname(name);
if (host == NULL) {
return false;
}
*address = *reinterpret_cast<long*>(host->h_addr_list[0]);
return true;
}
}

74
mc_socket.hpp Normal file
View File

@ -0,0 +1,74 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Socket
//
class Socket {
public:
enum {
MASK_READ = 1 << 0,
MASK_WRITE = 1 << 1,
MASK_EXCEPT = 1 << 2
};
Socket();
~Socket();
bool open ();
void close ();
int release ();
void set (int socket);
void setNagle (bool enable);
void setBlocking (bool enable);
bool connect (const char name[], int port);
bool bind (int port);
bool listen (int backlog = 5);
bool accept (Socket* socket);
int receive (void* buffer, int size);
int peek (void* buffer, int size) const;
int send (const void* buffer, int size);
bool wait (unsigned mask, int seconds) const;
bool opened () const;
bool connected () const;
const char* hostname () const;
private:
static bool resolve (const char name[], long* address);
int socket_;
};
}

72
mc_stream-inl.hpp Normal file
View File

@ -0,0 +1,72 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
namespace metacall {
template <typename T>
Stream::State Stream::send(const T& packet) {
if (!socket_->connected()) {
return STATE_ERROR_CONNECTION;
}
Buffer buffTemp;
Serializer serializerTemp(&buffTemp);
serializerTemp.write(packet);
PacketHeader header;
header.magic = PACKET_CONST_MAGIC;
header.size = serializerTemp.offset();
header.id = T::Id;
Serializer serializer_send(&buffSend_);
serializer_send.write(header);
serializer_send.writeRaw(buffTemp.data(), buffTemp.bytes());
return STATE_READY;
}
template <typename T>
Stream::State Stream::receive(T* packet) {
PacketHeader header;
int headerSize = 0;
const State state = peek(&header, &headerSize);
if (state != STATE_READY) {
return state;
}
buffRecv_.removeFromFront(NULL, headerSize);
Deserializer deserializer(&buffRecv_);
const bool success =
deserializer.read(packet) &&
deserializer.offset() == static_cast<int>(header.size);
buffRecv_.removeFromFront(NULL, header.size);
return success ? STATE_READY : STATE_ERROR_PROTOCOL;
}
}

109
mc_stream.cpp Normal file
View File

@ -0,0 +1,109 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_stream.hpp"
namespace metacall {
//
// Stream
//
Stream::Stream(Socket* socket) :
socket_(socket)
{
}
Stream::State Stream::advance() {
if (!socket_->connected()) {
return STATE_ERROR_CONNECTION;
}
if (buffSend_.bytes() > 0 && socket_->wait(Socket::MASK_WRITE, 0)) {
const int bytesSent = socket_->send(
buffSend_.data(),
buffSend_.bytes()
);
if (bytesSent <= 0) {
return STATE_ERROR_CONNECTION;
}
buffSend_.removeFromFront(NULL, bytesSent);
}
if (socket_->wait(Socket::MASK_READ, 0)) {
const int bytesReceived = socket_->receive(
buffNet_.data(),
buffNet_.bytes()
);
if (bytesReceived <= 0) {
return STATE_ERROR_CONNECTION;
}
buffRecv_.addToBack(buffNet_.data(), bytesReceived);
}
return STATE_READY;
}
void Stream::reset() {
buffSend_.clear();
buffRecv_.clear();
}
Stream::State Stream::peek(PacketHeader* header, int* headerSize) {
Deserializer deserializer(&buffRecv_);
if (!deserializer.read(header)) {
return STATE_PENDING_PACKET_HEADER;
}
if (header->magic != PACKET_CONST_MAGIC) {
return STATE_ERROR_PROTOCOL;
}
*headerSize = deserializer.offset();
const int packetSize = static_cast<int>(header->size) + *headerSize;
if (buffRecv_.bytes() < packetSize) {
return STATE_PENDING_PACKET_BODY;
}
return STATE_READY;
}
const Socket* Stream::socket() const {
return socket_;
}
Socket* Stream::socket() {
return socket_;
}
}

67
mc_stream.hpp Normal file
View File

@ -0,0 +1,67 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Stream
//
class Stream {
public:
enum State {
STATE_READY,
STATE_PENDING_PACKET_HEADER,
STATE_PENDING_PACKET_BODY,
STATE_ERROR_PROTOCOL,
STATE_ERROR_CONNECTION
};
Stream(Socket* socket);
State advance ();
void reset ();
template <typename T>
State send (const T& packet);
template <typename T>
State receive (T* packet);
State peek (PacketHeader* header, int* headerSize);
const Socket* socket () const;
Socket* socket ();
private:
Socket* socket_;
Buffer buffRecv_;
Buffer buffSend_;
Buffer buffNet_;
};
}

58
mc_token.cpp Normal file
View File

@ -0,0 +1,58 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include "metacall.hpp"
#include "mc_token.hpp"
namespace metacall {
//
// Token
//
Token::Token(const char value[]) :
value_(hash(value))
{
}
Token::Token(unsigned value) :
value_(value)
{
}
Token::operator unsigned() const {
return value_;
}
unsigned Token::hash(const char str[]) {
unsigned hash = 5381;
for (const char* ptr = str; *ptr != 0; ++ptr) {
hash = (hash << 5) + hash + *ptr;
}
return hash;
}
}

49
mc_token.hpp Normal file
View File

@ -0,0 +1,49 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#pragma once
namespace metacall {
//
// Token
//
class Token {
public:
Token(const char value[]);
Token(unsigned value);
operator unsigned() const;
private:
static unsigned hash(const char str[]);
unsigned value_;
};
}

60
metacall.hpp Normal file
View File

@ -0,0 +1,60 @@
//
// Copyright (c) 2011 Alex Yatskov
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <assert.h>
#ifdef _WIN32
#pragma comment(lib, "ws2_32.lib")
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include "mc_common.hpp"
#include "mc_token.hpp"
#include "mc_buffer.hpp"
#include "mc_socket.hpp"
#include "mc_packet.hpp"
#include "mc_meta.hpp"
#include "mc_serial.hpp"
#include "mc_serial-inl.hpp"
#include "mc_functor.hpp"
#include "mc_binding.hpp"
#include "mc_binding-inl.hpp"
#include "mc_stream.hpp"
#include "mc_stream-inl.hpp"
#include "mc_protocol.hpp"
#include "mc_protocol-inl.hpp"
#include "mc_client.hpp"
#include "mc_server.hpp"

104
metacall.project Normal file
View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<CodeLite_Project Name="metacall" InternalType="Console">
<Description/>
<Dependencies/>
<VirtualDirectory Name="src">
<File Name="main.cpp"/>
<File Name="mc_socket.cpp"/>
<File Name="mc_socket.hpp"/>
<File Name="metacall.hpp"/>
<File Name="mc_buffer.cpp"/>
<File Name="mc_buffer.hpp"/>
<File Name="mc_packet.hpp"/>
<File Name="mc_stream.cpp"/>
<File Name="mc_stream.hpp"/>
<File Name="mc_stream-inl.hpp"/>
<File Name="mc_serial.hpp"/>
<File Name="mc_serial-inl.hpp"/>
<File Name="mc_serial.cpp"/>
<File Name="mc_meta.hpp"/>
<File Name="mc_functor.hpp"/>
<File Name="mc_binding-inl.hpp"/>
<File Name="mc_binding.hpp"/>
<File Name="mc_binding.cpp"/>
<File Name="mc_common.hpp"/>
<File Name="mc_protocol-inl.hpp"/>
<File Name="mc_protocol.cpp"/>
<File Name="mc_protocol.hpp"/>
<File Name="mc_client.cpp"/>
<File Name="mc_client.hpp"/>
<File Name="mc_server.cpp"/>
<File Name="mc_server.hpp"/>
<File Name="mc_token.cpp"/>
<File Name="mc_token.hpp"/>
</VirtualDirectory>
<Settings Type="Executable">
<GlobalSettings>
<Compiler Options="" C_Options="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="">
<LibraryPath Value="."/>
</Linker>
<ResourceCompiler Options=""/>
</GlobalSettings>
<Configuration Name="Debug" CompilerType="gnu g++" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="-g" C_Options="-g" Required="yes" PreCompiledHeader="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="" Required="yes"/>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Debug" Command="./$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
<Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;"/>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName>None</ThirdPartyToolName>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
</Configuration>
<Configuration Name="Release" CompilerType="gnu g++" DebuggerType="GNU gdb debugger" Type="" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="" C_Options="" Required="yes" PreCompiledHeader="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="-O2" Required="yes"/>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Release" Command="./$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
<Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;"/>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName>None</ThirdPartyToolName>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
</Configuration>
</Settings>
</CodeLite_Project>

12
metacall.workspace Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<CodeLite_Workspace Name="metacall" Database="./metacall.tags">
<Project Name="metacall" Path="metacall.project" Active="Yes"/>
<BuildMatrix>
<WorkspaceConfiguration Name="Debug" Selected="yes">
<Project Name="metacall" ConfigName="Debug"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Release" Selected="yes">
<Project Name="metacall" ConfigName="Release"/>
</WorkspaceConfiguration>
</BuildMatrix>
</CodeLite_Workspace>