├── .gitignore ├── CMakeLists.txt ├── autogen.sh ├── examples └── test.cpp └── src ├── uv++-address.cpp ├── uv++-address.h ├── uv++-buffer.cpp ├── uv++-buffer.h ├── uv++-handle.cpp ├── uv++-handle.h ├── uv++-loop.cpp ├── uv++-loop.h ├── uv++-signal.cpp ├── uv++-signal.h ├── uv++-socket.cpp ├── uv++-socket.h ├── uv++-stream.cpp ├── uv++-stream.h ├── uv++-tcp.cpp ├── uv++-tcp.h ├── uv++-timer.cpp ├── uv++-timer.h ├── uv++-udp.cpp ├── uv++-udp.h └── uv++.h /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(test-uv) 4 | 5 | add_definitions(-Wall) 6 | 7 | include_directories(src) 8 | 9 | add_library(uv++ SHARED 10 | src/uv++-loop 11 | src/uv++-handle 12 | src/uv++-timer 13 | src/uv++-signal 14 | src/uv++-address 15 | src/uv++-buffer 16 | src/uv++-socket 17 | src/uv++-stream 18 | src/uv++-tcp 19 | src/uv++-udp 20 | ) 21 | target_link_libraries(uv++ uv) 22 | 23 | add_executable(test examples/test) 24 | target_link_libraries(test uv++) 25 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | src_dir=$(dirname $(readlink -f $0)) 3 | 4 | if [[ "$PWD" != "$src_dir" ]]; then 5 | for f in *; do 6 | rm -rf "$f" 7 | done 8 | fi 9 | 10 | : ${BUILD_TYPE=Debug} 11 | : ${CC=clang} 12 | : ${CXX=clang++} 13 | 14 | CC=${CC} \ 15 | CXX=${CXX} \ 16 | CXXFLAGS="-fno-rtti" \ 17 | cmake "$src_dir" \ 18 | -DCMAKE_BUILD_TYPE=Debug \ 19 | -DCMAKE_VERBOSE_MAKEFILE=True \ 20 | -G"Eclipse CDT4 - Unix Makefiles" 21 | -------------------------------------------------------------------------------- /examples/test.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | #include 3 | #include 4 | 5 | using namespace Uv; 6 | using namespace std; 7 | 8 | class MyTimeoutHandler: public Timer::TimeoutHandler, 9 | public Handle::WeakRef 10 | { 11 | public: 12 | MyTimeoutHandler(): count(2) {} 13 | 14 | void AddHandle(Handle *handle) 15 | { 16 | handles.insert(handle); 17 | handle->SetWeakRef(this); 18 | } 19 | 20 | void CloseHandles() 21 | { 22 | set::iterator iter = handles.begin(); 23 | set::iterator end = handles.end(); 24 | for(; iter != end; ++iter) { 25 | cout << "MyTimeoutHandler::CloseHandles: " << (*iter)->GetTypeName() 26 | << "(" << *iter << ")" << endl; 27 | (*iter)->Close(); 28 | cout << "MyTimeoutHandler::handles.size = " << handles.size() << endl; 29 | } 30 | 31 | Loop::Get().Run(Loop::Once); 32 | } 33 | 34 | private: 35 | void OnTimeout(Timer *source, int status) 36 | { 37 | if(status) { 38 | cout << GetErrorStr(status) << endl; 39 | return; 40 | } 41 | 42 | cout << "MyTimeoutHandler: " << count << endl; 43 | count --; 44 | if(0 >= count) { 45 | Loop::Get().Stop(); 46 | } 47 | } 48 | 49 | private: 50 | void OnClose(Handle *handle) 51 | { 52 | set::iterator iter = handles.find(handle); 53 | if(handles.end() == iter) { 54 | return; 55 | } 56 | 57 | cout << "Unwatching " << *iter << endl; 58 | handles.erase(iter); 59 | } 60 | 61 | private: 62 | int count; 63 | 64 | set handles; 65 | }; 66 | 67 | class Server: public Stream::InConnectHandler, 68 | Stream::RecvHandler, 69 | Stream::SendHandler 70 | { 71 | public: 72 | Server(MyTimeoutHandler &timeoutHandler): timeoutHandler(timeoutHandler) 73 | { 74 | } 75 | 76 | private: 77 | virtual void OnConnect(Stream *server, 78 | Stream *conn, 79 | int status) 80 | { 81 | cout << "Server::OnConnect (" << conn << ")" << endl; 82 | 83 | timeoutHandler.AddHandle(conn); 84 | conn->RecvStart(*this); 85 | } 86 | 87 | virtual void OnRecv(Stream *conn, Buffer *buf, int status) 88 | { 89 | cout << "Server Recv: " << string(buf->GetBase(), buf->GetSize()) << endl; 90 | 91 | cout << "Server Send: World" << endl; 92 | buf = new Buffer("World"); 93 | conn->Send(buf, this); 94 | buf->Unref(); 95 | 96 | conn->RecvStop(); 97 | } 98 | 99 | virtual void OnSend(Stream *conn, int status) 100 | { 101 | conn->Close(); 102 | 103 | cout << "Disconnected (" << conn << ")" << endl; 104 | } 105 | 106 | private: 107 | MyTimeoutHandler &timeoutHandler; 108 | }; 109 | 110 | class Client: public Tcp::OutConnectHandler, 111 | Stream::SendHandler, 112 | Stream::RecvHandler 113 | { 114 | public: 115 | Client(): count(0) 116 | { 117 | } 118 | 119 | private: 120 | void OnConnected(Tcp *conn, int status) 121 | { 122 | if(status) { 123 | cout << "Clinet::OnConnected: " << GetErrorStr(status) << endl; 124 | return; 125 | } 126 | 127 | cout << "Client Send: Hello" << endl; 128 | 129 | Buffer *buf = new Buffer("Hello"); 130 | conn->Send(buf, this); 131 | buf->Unref(); 132 | 133 | conn->RecvStart(*this); 134 | } 135 | 136 | void OnSend(Stream *conn, int status) 137 | { 138 | Inc(conn); 139 | } 140 | 141 | void OnRecv(Stream *conn, Buffer *buf, int status) 142 | { 143 | cout << "Client Recv: " << string(buf->GetBase(), buf->GetSize()) << endl; 144 | Inc(conn); 145 | } 146 | 147 | void Inc(Stream *conn) 148 | { 149 | count ++; 150 | if(2 == count) { 151 | conn->Close(); 152 | } 153 | } 154 | 155 | private: 156 | int count; 157 | }; 158 | 159 | class SignalHandler: public Signal::SignalHandler 160 | { 161 | private: 162 | void OnSignal(Signal *source, int signum) 163 | { 164 | cout << "Bye" << endl; 165 | 166 | source->Close(); 167 | source->GetLoop().Stop(); 168 | } 169 | }; 170 | 171 | class PingPeer: public Udp::RecvHandler 172 | { 173 | public: 174 | PingPeer(const char * name) 175 | { 176 | assert(name); 177 | 178 | this->name = strdup(name); 179 | } 180 | 181 | ~PingPeer() 182 | { 183 | if(name) { 184 | free(name); 185 | } 186 | } 187 | 188 | private: 189 | void OnRecv(Udp *source, 190 | Buffer *buf, 191 | const Address &addr, 192 | unsigned int flags, 193 | int status) 194 | { 195 | cout << name << " Recv: " << string(buf->GetBase(), buf->GetSize()) << endl; 196 | 197 | source->Close(); 198 | } 199 | 200 | private: 201 | char *name; 202 | }; 203 | 204 | int main() 205 | 206 | { 207 | { 208 | MyTimeoutHandler timeoutHandler; 209 | 210 | SignalHandler signalHandler; 211 | Signal *signal = Signal::New(); 212 | timeoutHandler.AddHandle(signal); 213 | assert(! signal->Start(SIGINT, signalHandler)); 214 | signal->Unref(); 215 | 216 | signal = Signal::New(); 217 | timeoutHandler.AddHandle(signal); 218 | assert(! signal->Start(SIGTERM, signalHandler)); 219 | signal->Unref(); 220 | 221 | Server serverEventHandler(timeoutHandler); 222 | Tcp *server = Tcp::New(); 223 | timeoutHandler.AddHandle(server); 224 | assert(! server->Bind(Ip4Address("0.0.0.0", 1234))); 225 | assert(! server->Listen(serverEventHandler)); 226 | server->Unref(); 227 | 228 | Client clientEventHandler; 229 | Tcp *client = Tcp::New(); 230 | timeoutHandler.AddHandle(client); 231 | assert(! client->Connect(Ip4Address("127.0.0.1", 1234), &clientEventHandler)); 232 | client->Unref(); 233 | 234 | PingPeer peer1("Peer1"); 235 | Udp *endPoint1 = Udp::New(); 236 | assert(endPoint1); 237 | timeoutHandler.AddHandle(endPoint1); 238 | assert(! endPoint1->Bind(Ip4Address("0.0.0.0", 1357))); 239 | assert(! endPoint1->RecvStart(peer1)); 240 | 241 | PingPeer peer2("Peer2"); 242 | Udp *endPoint2 = Udp::New(); 243 | assert(endPoint2); 244 | timeoutHandler.AddHandle(endPoint2); 245 | assert(! endPoint2->Bind(Ip4Address("0.0.0.0", 2468))); 246 | assert(! endPoint2->RecvStart(peer2)); 247 | 248 | Buffer *buf = new Buffer("Hello"); 249 | assert(! endPoint1->Send(*buf, Ip4Address("127.0.0.1", 2468))); 250 | buf->Unref(); 251 | 252 | buf = new Buffer("World"); 253 | assert(! endPoint2->Send(*buf, Ip4Address("127.0.0.1", 1357))); 254 | buf->Unref(); 255 | 256 | endPoint1->Unref(); 257 | endPoint2->Unref(); 258 | 259 | Timer *timer = Timer::New(); 260 | timeoutHandler.AddHandle(timer); 261 | assert(timer); 262 | assert(! timer->Start(1000, timeoutHandler)); 263 | timer->Unref(); 264 | 265 | Loop::Run(); 266 | timeoutHandler.CloseHandles(); 267 | Loop::Free(); 268 | } 269 | 270 | cout << Handle::count << " handle alive" << endl; 271 | 272 | return 0; 273 | } 274 | -------------------------------------------------------------------------------- /src/uv++-address.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | int Address::Set(/* [in] */ Type type, 6 | /* [in] */ const char * ip, 7 | /* [in] */ int port) 8 | { 9 | int result; 10 | if(Type_Ip4 == type) { 11 | result = uv_ip4_addr(ip, port, (sockaddr_in *) &m_peer); 12 | } 13 | else { 14 | result = uv_ip6_addr(ip, port, (sockaddr_in6 *) &m_peer); 15 | } 16 | 17 | return result; 18 | } 19 | 20 | int Address::Set(/* [in] */ const sockaddr *otherPeer) 21 | { 22 | switch(otherPeer->sa_family) { 23 | case AF_INET: 24 | m_peer.ip4 = * (const sockaddr_in *) otherPeer; 25 | break; 26 | case AF_INET6: 27 | m_peer.ip6 = * (const sockaddr_in6 *) otherPeer; 28 | break; 29 | default: 30 | return UV_EAFNOSUPPORT; 31 | } 32 | 33 | return 0; 34 | } 35 | 36 | const char * Address::ToString() const 37 | { 38 | if(! m_pStr) { 39 | return NULL; 40 | } 41 | 42 | m_pStr[0] = '\0'; 43 | 44 | if(Type_Ip4 == GetType()) { 45 | uv_ip4_name((struct sockaddr_in *) &m_peer.ip4, 46 | m_pStr, 47 | ADDR_MAXLEN); 48 | } 49 | else if(Type_Ip6 == GetType()) { 50 | uv_ip6_name((struct sockaddr_in6 *) &m_peer.ip6, 51 | m_pStr, 52 | ADDR_MAXLEN); 53 | } 54 | int addrLen = strlen(m_pStr); 55 | snprintf(m_pStr + addrLen, 56 | ADDR_MAXLEN - strlen(m_pStr), 57 | ":%d", 58 | GetPort()); 59 | 60 | return m_pStr; 61 | } 62 | 63 | bool Address::operator < (const Address &other) const 64 | { 65 | if(this == &other) { 66 | return false; 67 | } 68 | 69 | if(GetType() != other.GetType()) { 70 | if(Type_Ip4 == GetType()) { 71 | return true; 72 | } 73 | return false; 74 | } 75 | 76 | if(Type_Ip4 == GetType()) { 77 | return -1 == memcmp(&m_peer.ip4, 78 | &other.m_peer.ip4, 79 | sizeof(sockaddr_in)); 80 | } 81 | 82 | return -1 == memcmp(&m_peer.ip6, 83 | &other.m_peer.ip6, 84 | sizeof(sockaddr_in6)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/uv++-address.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace Uv 6 | { 7 | class Address 8 | { 9 | private: 10 | #define ADDR_MAXLEN (55) 11 | 12 | public: 13 | enum Type 14 | { 15 | Type_Unknown = AF_UNSPEC, 16 | Type_Ip4 = AF_INET, 17 | Type_Ip6 = AF_INET6, 18 | //Type_Unix = AF_UNIX, 19 | }; 20 | private: 21 | union UAddress 22 | { 23 | sockaddr base; 24 | sockaddr_in ip4; 25 | sockaddr_in6 ip6; 26 | //sockaddr_un unix; 27 | }; 28 | 29 | public: 30 | Address() 31 | { 32 | m_pStr = new char[ADDR_MAXLEN]; 33 | m_peer.base.sa_family = Type_Unknown; 34 | } 35 | 36 | Address(/* [in] */ Type type, 37 | /* [in] */ const char *ip, 38 | /* [in] */ int port) 39 | { 40 | m_pStr = new char[ADDR_MAXLEN]; 41 | Set(type, ip, port); 42 | } 43 | 44 | Address(const sockaddr *addr) 45 | { 46 | m_pStr = new char[ADDR_MAXLEN]; 47 | Set(addr); 48 | } 49 | 50 | Address(const Address &other) 51 | { 52 | m_pStr = new char[ADDR_MAXLEN]; 53 | Set((const sockaddr *) &other.m_peer); 54 | } 55 | 56 | ~Address() 57 | { 58 | delete[] m_pStr; 59 | } 60 | 61 | int SetIp4(/* [in] */ const char * ip, 62 | /* [in] */ int port) 63 | { 64 | return Set(Type_Ip4, ip, port); 65 | } 66 | 67 | int SetIp6(/* [in] */ const char * ip, 68 | /* [in] */ int port) 69 | { 70 | return Set(Type_Ip6, ip, port); 71 | } 72 | 73 | int Set(/* [in] */ Type type, 74 | /* [in] */ const char * ip, 75 | /* [in] */ int port); 76 | 77 | int Set(/* [in] */ const sockaddr *peer); 78 | 79 | Type GetType() const 80 | { 81 | return (Type) m_peer.base.sa_family; 82 | } 83 | 84 | int GetPort() const 85 | { 86 | if(Type_Ip4 == GetType()) { 87 | return ntohs(m_peer.ip4.sin_port); 88 | } 89 | else if(Type_Ip6 == GetType()) { 90 | return ntohl(m_peer.ip6.sin6_port); 91 | } 92 | 93 | assert(0); 94 | } 95 | 96 | const char * ToString() const; 97 | 98 | operator sockaddr *() 99 | { 100 | return (sockaddr *) &m_peer; 101 | } 102 | 103 | operator const sockaddr *() const 104 | { 105 | return (sockaddr *) &m_peer; 106 | } 107 | 108 | Address & operator =(const Address &other) 109 | { 110 | Set((sockaddr *) &other.m_peer); 111 | 112 | return *this; 113 | } 114 | 115 | bool operator < (const Address &other) const; 116 | 117 | private: 118 | void SetType(sa_family_t type) 119 | { 120 | m_peer.base.sa_family = type; 121 | } 122 | 123 | private: 124 | UAddress m_peer; 125 | 126 | char *m_pStr; 127 | }; 128 | 129 | class Ip4Address: public Address 130 | { 131 | public: 132 | Ip4Address(/* [in] */ const char *ip, 133 | /* [in] */ int port): Address(Address::Type_Ip4, 134 | ip, 135 | port) 136 | { 137 | } 138 | 139 | int Set(/* [in] */ const char *ip, 140 | /* [in] */ int port) 141 | { 142 | return SetIp4(ip, port); 143 | } 144 | }; 145 | 146 | class Ip6Address: public Address 147 | { 148 | public: 149 | Ip6Address(/* [in] */ const char *ip, 150 | /* [in] */ int port): Address(Address::Type_Ip6, 151 | ip, 152 | port) 153 | { 154 | } 155 | 156 | int Set(/* [in] */ const char *ip, 157 | /* [in] */ int port) 158 | { 159 | return SetIp6(ip, port); 160 | } 161 | }; 162 | } 163 | -------------------------------------------------------------------------------- /src/uv++-buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | Buffer * Buffer::Ref() 6 | { 7 | assert(0 < m_refCount); 8 | 9 | m_refCount ++; 10 | 11 | return this; 12 | } 13 | 14 | void Buffer::Unref() 15 | { 16 | assert(0 < m_refCount); 17 | 18 | m_refCount --; 19 | if(0 < m_refCount) { 20 | return; 21 | } 22 | 23 | delete this; 24 | } 25 | 26 | char * Buffer::Alloc(/* [in] */ size_t size) 27 | { 28 | return (char *) malloc(size); 29 | } 30 | 31 | void Buffer::Free(char * buf) 32 | { 33 | free(buf); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/uv++-buffer.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Uv 4 | { 5 | class Buffer 6 | { 7 | private: 8 | enum Flags 9 | { 10 | None = 0, 11 | Writable = 1 << 1, 12 | Owned = 1 << 2, 13 | Locked = 1 << 3, 14 | }; 15 | 16 | public: 17 | Buffer(): m_refCount(1), 18 | m_flags(None) 19 | { 20 | m_peer = (uv_buf_t) { .base = NULL, .len = 0 }; 21 | } 22 | 23 | Buffer(size_t size): m_refCount(1), 24 | m_flags(Writable | Owned) 25 | { 26 | m_peer = (uv_buf_t) { .base = Alloc(size), .len = size }; 27 | } 28 | 29 | Buffer(/* [in] */ const char * str, 30 | /* [in] */ ssize_t len = -1): m_refCount(1), 31 | m_flags(None) 32 | { 33 | assert(str); 34 | 35 | m_peer = uv_buf_init((char *) str, -1 >= len ? strlen(str) : len); 36 | } 37 | 38 | Buffer * Ref(); 39 | 40 | void Unref(); 41 | 42 | bool IsOwned() const 43 | { 44 | return !! (m_flags & Owned); 45 | } 46 | 47 | bool IsWritable() const 48 | { 49 | return !! (m_flags & Writable); 50 | } 51 | 52 | bool IsLocked() const 53 | { 54 | return !! (m_flags & Locked); 55 | } 56 | 57 | void Lock() 58 | { 59 | assert(! IsLocked()); 60 | 61 | m_flags |= Locked; 62 | } 63 | 64 | void Unlock() 65 | { 66 | assert(IsLocked()); 67 | 68 | m_flags &= ~ Locked; 69 | } 70 | 71 | size_t GetSize() const 72 | { 73 | return m_peer.len; 74 | } 75 | 76 | const char * GetBase() const 77 | { 78 | return m_peer.base; 79 | } 80 | 81 | char * GetBase() 82 | { 83 | assert(IsWritable() && ! IsLocked()); 84 | 85 | return m_peer.base; 86 | } 87 | 88 | operator const char * () const 89 | { 90 | return m_peer.base; 91 | } 92 | 93 | operator char * () 94 | { 95 | assert(IsWritable() && ! IsLocked()); 96 | 97 | return m_peer.base; 98 | } 99 | 100 | operator const uv_buf_t * () const 101 | { 102 | return &m_peer; 103 | } 104 | 105 | static char * Alloc(/* [in] */ size_t size); 106 | 107 | static void Free(char * buf); 108 | 109 | protected: 110 | /** 111 | * This construct takes the ownership of base, so it's Buffer's 112 | * duty to free base 113 | */ 114 | Buffer(/* [in] */ const uv_buf_t *otherPeer, 115 | /* [in] */ ssize_t nread): m_refCount(1), 116 | m_flags(Writable | Owned) 117 | { 118 | assert(otherPeer); 119 | 120 | m_peer = uv_buf_init(nread < 0 ? NULL : otherPeer->base, 121 | nread < 0 ? 0 : nread); 122 | } 123 | 124 | friend class Stream; 125 | friend class Udp; 126 | 127 | private: 128 | ~Buffer() 129 | { 130 | if(IsOwned()) { 131 | Free(m_peer.base); 132 | } 133 | } 134 | 135 | private: 136 | uv_buf_t m_peer; 137 | 138 | int m_refCount; 139 | 140 | unsigned int m_flags; 141 | }; 142 | } 143 | -------------------------------------------------------------------------------- /src/uv++-handle.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | int Handle::count = 0; 6 | 7 | int Handle::Open(/* [in] */ Loop &loop) 8 | { 9 | assert(! IsOpened()); 10 | 11 | size_t peerSize = GetPeerSize(); 12 | assert(sizeof(uv_handle_t) <= peerSize); 13 | 14 | m_pPeer = (uv_handle_t *) malloc(peerSize); 15 | int result = DoOpen(loop, m_pPeer); 16 | 17 | if(result) { 18 | free(m_pPeer); 19 | m_pPeer = NULL; 20 | } 21 | 22 | m_pPeer->data = this; 23 | 24 | return result; 25 | } 26 | 27 | void Handle::Close() 28 | { 29 | if(! IsOpened()) { 30 | return; 31 | } 32 | 33 | SetFlags(Flags_Closing); 34 | 35 | DoClose(); 36 | 37 | uv_close(m_pPeer, OnClose); 38 | } 39 | 40 | void Handle::OnClose(uv_handle_t *peer) 41 | { 42 | Handle *self = (Handle *) peer->data; 43 | if(self->m_pWeakRef) { 44 | self->m_pWeakRef->OnClose(self); 45 | } 46 | 47 | free(self->m_pPeer); 48 | self->m_pPeer = NULL; 49 | 50 | self->ClearFlags(Flags_Closing); 51 | 52 | if(! self->m_refCount) { 53 | delete self; 54 | } 55 | } 56 | 57 | void Handle::Unref() 58 | { 59 | assert(0 < m_refCount); 60 | 61 | m_refCount --; 62 | if(m_refCount) { 63 | return; 64 | } 65 | 66 | if(IsClosed()) { 67 | delete this; 68 | return; 69 | } 70 | 71 | Close(); 72 | } 73 | 74 | const char * Handle::GetTypeName() const 75 | { 76 | assert(IsOpened() || IsClosing()); 77 | 78 | switch(GetType()) { 79 | case UV_IDLE: 80 | return "Uv::Idle"; 81 | case UV_TIMER: 82 | return "Uv::Timer"; 83 | case UV_SIGNAL: 84 | return "Uv::Signal"; 85 | case UV_STREAM: 86 | return "Uv::Stream"; 87 | case UV_TCP: 88 | return "Uv::Tcp"; 89 | case UV_UDP: 90 | return "Uv::Udp"; 91 | case UV_ASYNC: 92 | return "Uv::Async"; 93 | case UV_CHECK: 94 | return "Uv::Check"; 95 | case UV_POLL: 96 | return "Uv::Poll"; 97 | case UV_HANDLE: 98 | return "Uv::Handle"; 99 | case UV_NAMED_PIPE: 100 | return "Uv::NamedPipe"; 101 | case UV_PROCESS: 102 | return "Uv::Process"; 103 | case UV_TTY: 104 | return "Uv::Tty"; 105 | default: 106 | return "Unknown"; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/uv++-handle.h: -------------------------------------------------------------------------------- 1 | #ifndef __UVPP_HANDLE_H_ 2 | #define __UVPP_HANDLE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Uv 8 | { 9 | class Handle 10 | { 11 | public: 12 | class WeakRef 13 | { 14 | private: 15 | virtual void OnClose(Handle *handle) = 0; 16 | 17 | friend class Handle; 18 | }; 19 | 20 | protected: 21 | enum Flags 22 | { 23 | Flags_None, 24 | Flags_Closing = 1 << 0, 25 | }; 26 | 27 | public: 28 | void Close(); 29 | 30 | bool IsOpened() const 31 | { 32 | return !IsClosing() && !IsClosed(); 33 | } 34 | 35 | bool IsClosing() const 36 | { 37 | return !!(Flags_Closing & m_flags); 38 | } 39 | 40 | bool IsClosed() const 41 | { 42 | return !m_pPeer && !IsClosing(); 43 | } 44 | 45 | void SetWeakRef(WeakRef *weakref) 46 | { 47 | m_pWeakRef = weakref; 48 | } 49 | 50 | WeakRef* GetWeakRef() const 51 | { 52 | return m_pWeakRef; 53 | } 54 | 55 | Handle * Ref() 56 | { 57 | assert(0 < m_refCount); 58 | 59 | m_refCount ++; 60 | 61 | return this; 62 | } 63 | 64 | void Unref(); 65 | 66 | Loop & GetLoop() 67 | { 68 | // TODO Handle should not access field of loop directly 69 | return Loop::FromPeer(m_pPeer->loop); 70 | } 71 | 72 | uv_handle_type GetType() const 73 | { 74 | assert(IsOpened() || IsClosing()); 75 | 76 | return m_pPeer->type; 77 | } 78 | 79 | const char * GetTypeName() const; 80 | 81 | protected: 82 | Handle(): m_pPeer(NULL), 83 | m_pWeakRef(NULL), 84 | m_refCount(1), 85 | m_flags(Flags_None) 86 | { 87 | count ++; 88 | } 89 | 90 | virtual ~Handle() 91 | { 92 | count --; 93 | 94 | assert(! IsOpened()); 95 | } 96 | 97 | int Open(/* [in] */ Loop &loop); 98 | 99 | virtual int DoOpen(Loop &loop, uv_handle_t *peer) = 0; 100 | 101 | virtual void DoClose() = 0; 102 | 103 | virtual size_t GetPeerSize() const = 0; 104 | 105 | uv_handle_t * GetPeer() 106 | { 107 | return m_pPeer; 108 | } 109 | 110 | static void OnClose(uv_handle_t *peer); 111 | 112 | private: 113 | void SetFlags(Flags flags) 114 | { 115 | m_flags |= flags; 116 | } 117 | 118 | void ClearFlags(Flags flags) 119 | { 120 | m_flags &= ~flags; 121 | } 122 | 123 | private: 124 | uv_handle_t *m_pPeer; 125 | 126 | WeakRef *m_pWeakRef; 127 | 128 | int m_refCount; 129 | 130 | unsigned int m_flags; 131 | 132 | public: 133 | static int count; 134 | }; 135 | } 136 | 137 | #endif /* __UVPP_HANDLE_H_ */ 138 | -------------------------------------------------------------------------------- /src/uv++-loop.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | #include 3 | 4 | namespace Uv { 5 | __thread Loop *Uv::Loop::s_pLoop = NULL; 6 | 7 | Loop & Loop::Get() 8 | { 9 | if(! s_pLoop) { 10 | s_pLoop = new Loop(); 11 | } 12 | 13 | return *s_pLoop; 14 | } 15 | 16 | int Loop::Run() 17 | { 18 | return Get().Run(Default); 19 | } 20 | 21 | void Loop::Free() 22 | { 23 | if(! s_pLoop) { 24 | return; 25 | } 26 | 27 | assert(! s_pLoop->IsRunning()); 28 | 29 | delete s_pLoop; 30 | s_pLoop = NULL; 31 | } 32 | 33 | int Loop::Run(/* [in] */ RunMode mode) 34 | { 35 | m_runLevel ++; 36 | int result = uv_run(m_pPeer, (uv_run_mode) mode); 37 | m_runLevel --; 38 | 39 | return result; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/uv++-loop.h: -------------------------------------------------------------------------------- 1 | #ifndef __UVPP_LOOP_H_ 2 | #define __UVPP_LOOP_H_ 3 | 4 | namespace Uv 5 | { 6 | class Loop 7 | { 8 | public: 9 | enum RunMode { 10 | Default = UV_RUN_DEFAULT, 11 | Once = UV_RUN_ONCE, 12 | NoWait = UV_RUN_NOWAIT 13 | }; 14 | 15 | public: 16 | static Loop & Get(); 17 | 18 | static int Run(); 19 | 20 | static void Free(); 21 | 22 | int Run(/* [in] */ RunMode mode); 23 | 24 | bool IsRunning() const 25 | { 26 | return !! m_runLevel; 27 | } 28 | 29 | void Stop() 30 | { 31 | uv_stop(m_pPeer); 32 | } 33 | 34 | uint64_t Now() 35 | { 36 | return uv_now(*this); 37 | } 38 | 39 | int GetFd() const 40 | { 41 | return uv_backend_fd(*this); 42 | } 43 | 44 | operator uv_loop_t *() 45 | { 46 | return m_pPeer; 47 | } 48 | 49 | operator const uv_loop_t *() const 50 | { 51 | return m_pPeer; 52 | } 53 | 54 | private: 55 | Loop(): m_pPeer(uv_loop_new()), 56 | m_runLevel(0) 57 | { 58 | m_pPeer->data = this; 59 | } 60 | 61 | ~Loop() 62 | { 63 | uv_loop_delete(m_pPeer); 64 | } 65 | 66 | static Loop & FromPeer(uv_loop_t *peer) 67 | { 68 | return * (Loop *) peer->data; 69 | } 70 | 71 | friend class Handle; 72 | 73 | private: 74 | static __thread Loop * s_pLoop; 75 | 76 | uv_loop_t * m_pPeer; 77 | 78 | unsigned int m_runLevel; 79 | }; 80 | } 81 | 82 | #endif /* __UVPP_LOOP_H_ */ 83 | -------------------------------------------------------------------------------- /src/uv++-signal.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | Signal * Signal::New(Loop &loop) 6 | { 7 | Signal *self = new Signal(); 8 | if(! self) { 9 | return NULL; 10 | } 11 | 12 | if(! self->Open(loop)) { 13 | return self; 14 | } 15 | 16 | delete self; 17 | 18 | return NULL; 19 | } 20 | 21 | int Signal::Start(/* [in] */ int signum, 22 | /* [in] */ SignalHandler &handler) 23 | { 24 | assert(IsOpened()); 25 | assert(! m_pHandler); 26 | 27 | int result = uv_signal_start(*this, OnSignal, signum); 28 | if(! result) { 29 | Ref(); 30 | m_pHandler = &handler; 31 | } 32 | 33 | return result; 34 | } 35 | 36 | int Signal::Stop() 37 | { 38 | assert(IsOpened() || IsClosing()); 39 | assert(IsStarted()); 40 | 41 | int result = uv_signal_stop(*this); 42 | 43 | m_pHandler = NULL; 44 | Unref(); 45 | 46 | return result; 47 | } 48 | 49 | void Signal::OnSignal(/* [in] */ uv_signal_t *peer, 50 | /* [in] */ int signum) 51 | { 52 | Signal *self = (Signal *) peer->data; 53 | self->m_pHandler->OnSignal(self, signum); 54 | } 55 | 56 | size_t Signal::GetPeerSize() const 57 | { 58 | return sizeof(uv_signal_t); 59 | } 60 | 61 | int Signal::DoOpen(/* [in] */ Loop &loop, /* [in] */ uv_handle_t *peer) 62 | { 63 | return uv_signal_init(loop, (uv_signal_t *) peer); 64 | } 65 | 66 | void Signal::DoClose() 67 | { 68 | if(IsStarted()) { 69 | Stop(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/uv++-signal.h: -------------------------------------------------------------------------------- 1 | namespace Uv 2 | { 3 | class Signal: public Handle 4 | { 5 | public: 6 | class SignalHandler 7 | { 8 | private: 9 | virtual void OnSignal(/* [in] */ Signal *source, 10 | /* [in] */ int signum) = 0; 11 | 12 | friend class Signal; 13 | }; 14 | 15 | public: 16 | int Start(int signum, SignalHandler &handler); 17 | 18 | int Stop(); 19 | 20 | static Signal * New(Loop &loop = Loop::Get()); 21 | 22 | bool IsStarted() 23 | { 24 | return !!m_pHandler; 25 | } 26 | 27 | protected: 28 | Signal(): m_pHandler(NULL) 29 | { 30 | } 31 | 32 | virtual size_t GetPeerSize() const; 33 | 34 | virtual int DoOpen(/* [in] */ Loop &loop, 35 | /* [in] */ uv_handle_t *peer); 36 | 37 | virtual void DoClose(); 38 | 39 | operator uv_signal_t * () 40 | { 41 | return (uv_signal_t *) GetPeer(); 42 | } 43 | 44 | static void OnSignal(/* [in] */ uv_signal_t *peer, 45 | /* [in] */ int signum); 46 | 47 | private: 48 | SignalHandler *m_pHandler; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /src/uv++-socket.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | void Socket::OnAlloc(/* [in] */ uv_handle_t *handle, 6 | /* [in] */ size_t suggested_size, 7 | /* [in] */ uv_buf_t *buf) 8 | { 9 | *buf = uv_buf_init(Buffer::Alloc(suggested_size), suggested_size); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/uv++-socket.h: -------------------------------------------------------------------------------- 1 | namespace Uv 2 | { 3 | class Socket: public Handle 4 | { 5 | public: 6 | int Bind(/* [in] */ Address::Type type, 7 | /* [in] */ const char *ip, 8 | /* [in] */ int port, 9 | /* [in] */ unsigned int flags = 0) 10 | { 11 | return Bind(Address(type, ip, port), flags); 12 | } 13 | 14 | virtual int Bind(/* [in] */ const Address &addr, 15 | /* [in] */ unsigned int flags = 0) = 0; 16 | 17 | protected: 18 | static void OnAlloc(/* [in] */ uv_handle_t *handle, 19 | /* [in] */ size_t suggested_size, 20 | /* [in] */ uv_buf_t *buf); 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/uv++-stream.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | int Stream::count = 0; 6 | 7 | int Stream::Listen(/* [in] */ InConnectHandler &handler, 8 | /* [in] */ int backlog) 9 | { 10 | assert(IsOpened()); 11 | assert(! m_pInConnectHandler); 12 | 13 | int result = uv_listen(*this, backlog, OnConnect); 14 | if(! result) { 15 | m_pInConnectHandler = &handler; 16 | Ref(); 17 | } 18 | 19 | return result; 20 | } 21 | 22 | void Stream::OnConnect(/* [in] */ uv_stream_t *peer, 23 | /* [in] */ int status) 24 | { 25 | Stream *self = (Stream *) peer->data; 26 | Stream *conn = NULL; 27 | if(! status) { 28 | status = self->Accept(&conn); 29 | } 30 | self->m_pInConnectHandler->OnConnect(self, conn, status); 31 | 32 | conn->Unref(); 33 | } 34 | 35 | int Stream::Send(/* [in] */ Buffer *buffer, 36 | /* [in] */ SendHandler *handler) 37 | { 38 | assert(buffer); 39 | assert(IsOpened()); 40 | assert(! m_pSendBuffer); 41 | 42 | int result = uv_write(&m_writeReq, *this, *buffer, 1, OnSend); 43 | if(! result) { 44 | Ref(); 45 | 46 | m_pSendBuffer = buffer->Ref(); 47 | m_pSendBuffer->Lock(); 48 | 49 | m_pSendHandler = handler; 50 | } 51 | 52 | return result; 53 | } 54 | 55 | void Stream::OnSend(/* [in] */ uv_write_t *req, 56 | /* [in] */ int status) 57 | { 58 | Stream *self = (Stream *) req->data; 59 | if(self->m_pSendHandler) { 60 | self->m_pSendHandler->OnSend(self, status); 61 | self->m_pSendHandler = NULL; 62 | } 63 | 64 | self->m_pSendBuffer->Unlock(); 65 | self->m_pSendBuffer->Unref(); 66 | self->m_pSendBuffer = NULL; 67 | 68 | if(status) { 69 | self->Close(); 70 | } 71 | 72 | self->Unref(); 73 | } 74 | 75 | int Stream::RecvStart(RecvHandler &handler) 76 | { 77 | assert(IsOpened()); 78 | assert(! m_pRecvHandler); 79 | 80 | int result = uv_read_start(*this, OnAlloc, OnRecv); 81 | if(! result) { 82 | Ref(); 83 | m_pRecvHandler = &handler; 84 | } 85 | 86 | return result; 87 | } 88 | 89 | int Stream::RecvStop() 90 | { 91 | assert(IsOpened() || IsClosing()); 92 | assert(m_pRecvHandler); 93 | 94 | int result = uv_read_stop(*this); 95 | 96 | m_pRecvHandler = NULL; 97 | Unref(); 98 | 99 | return result; 100 | } 101 | 102 | void Stream::OnRecv(/* [in] */ uv_stream_t *peer, 103 | /* [in] */ ssize_t nread, 104 | /* [in] */ const uv_buf_t *buf) 105 | { 106 | Stream *self = (Stream *) peer->data; 107 | Buffer *buffer = NULL; 108 | if(nread > 0) { 109 | buffer = new Buffer(buf, nread); 110 | } 111 | self->m_pRecvHandler->OnRecv(self, 112 | buffer, 113 | nread < 0 ? nread : 0); 114 | 115 | if(buffer) { 116 | buffer->Unref(); 117 | } 118 | 119 | if(nread < 0) { 120 | self->RecvStop(); 121 | self->Close(); 122 | } 123 | } 124 | 125 | void Stream::DoClose() 126 | { 127 | if(IsRecvStarted()) { 128 | RecvStop(); 129 | } 130 | 131 | if(IsListenStarted()) { 132 | m_pInConnectHandler = NULL; 133 | Unref(); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/uv++-stream.h: -------------------------------------------------------------------------------- 1 | namespace Uv 2 | { 3 | class Stream: public Socket 4 | { 5 | public: 6 | class InConnectHandler 7 | { 8 | private: 9 | virtual void OnConnect(/* [in] */ Stream *source, 10 | /* [in] */ Stream *conn, 11 | /* [in] */ int status) = 0; 12 | friend class Stream; 13 | }; 14 | 15 | class RecvHandler 16 | { 17 | private: 18 | virtual void OnRecv(/* [in] */ Stream *source, 19 | /* [in] */ Buffer *buffer, 20 | /* [in] */ int status) = 0; 21 | friend class Stream; 22 | }; 23 | 24 | class SendHandler 25 | { 26 | private: 27 | virtual void OnSend(/* [in] */ Stream *source, 28 | /* [in] */ int status) = 0; 29 | friend class Stream; 30 | }; 31 | 32 | public: 33 | int Listen(/* [in] */ InConnectHandler &handler, 34 | /* [in] */ int backlog = 10); 35 | 36 | bool IsListenStarted() 37 | { 38 | return !! m_pInConnectHandler; 39 | } 40 | 41 | int RecvStart(/* [in] */ RecvHandler &handler); 42 | 43 | bool IsRecvStarted() 44 | { 45 | return !! m_pRecvHandler; 46 | } 47 | 48 | int RecvStop(); 49 | 50 | int Send(/* [in] */ Buffer *buffer, 51 | /* [in] */ SendHandler *handler = NULL); 52 | 53 | virtual int Accept(/* [out] */ Stream **conn) = 0; 54 | 55 | virtual ~Stream() 56 | { 57 | count --; 58 | } 59 | 60 | Stream * Ref() 61 | { 62 | return (Stream *) Handle::Ref(); 63 | } 64 | 65 | static int count; 66 | 67 | protected: 68 | Stream(): m_pInConnectHandler(NULL), 69 | m_pRecvHandler(NULL), 70 | m_pSendHandler(NULL), 71 | m_pSendBuffer(NULL) 72 | { 73 | m_writeReq.data = this; 74 | 75 | count ++; 76 | } 77 | 78 | virtual void DoClose(); 79 | 80 | private: 81 | static void OnConnect(/* [in] */ uv_stream_t *peer, 82 | /* [in] */ int status); 83 | 84 | static void OnRecv(/* [in] */ uv_stream_t *peer, 85 | /* [in] */ ssize_t nread, 86 | /* [in] */ const uv_buf_t *buf); 87 | 88 | static void OnSend(/* [in] */ uv_write_t *req, 89 | /* [in] */ int status); 90 | 91 | protected: 92 | operator uv_stream_t *() 93 | { 94 | return (uv_stream_t *) GetPeer(); 95 | } 96 | 97 | private: 98 | InConnectHandler *m_pInConnectHandler; 99 | 100 | RecvHandler *m_pRecvHandler; 101 | 102 | uv_write_t m_writeReq; 103 | SendHandler *m_pSendHandler; 104 | Buffer *m_pSendBuffer; 105 | }; 106 | } 107 | -------------------------------------------------------------------------------- /src/uv++-tcp.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | Tcp * Tcp::New(Loop &loop) 6 | { 7 | Tcp *self = new Tcp(); 8 | if(! self) { 9 | return NULL; 10 | } 11 | 12 | if(! self->Open(loop)) { 13 | return self; 14 | } 15 | 16 | delete self; 17 | 18 | return NULL; 19 | } 20 | 21 | int Tcp::Bind(/* [in] */ const Address &addr, 22 | /* [in] */ unsigned int flags) 23 | { 24 | assert(IsOpened()); 25 | assert(Address::Type_Unknown != addr.GetType()); 26 | 27 | return uv_tcp_bind(*this, addr); 28 | } 29 | 30 | int Tcp::Accept(/* [out] */ Stream **conn) 31 | { 32 | assert(IsOpened()); 33 | assert(conn && ! * conn); 34 | 35 | Tcp *newConn = New(GetLoop()); 36 | if(! newConn) { 37 | return UV_ENOMEM; 38 | } 39 | 40 | int result = uv_accept(*this, *newConn); 41 | if(! result) { 42 | *conn = newConn; 43 | } 44 | else { 45 | newConn->Unref(); 46 | } 47 | 48 | return result; 49 | } 50 | 51 | int Tcp::Connect(/* [in] */ const Address &addr, 52 | /* [in] */ OutConnectHandler *handler) 53 | { 54 | assert(IsOpened()); 55 | 56 | int result = uv_tcp_connect(&m_connectReq, 57 | *this, 58 | addr, 59 | OnConnected); 60 | if(! result) { 61 | Ref(); 62 | m_pOutConnectHandler = handler; 63 | } 64 | 65 | return result; 66 | } 67 | 68 | void Tcp::OnConnected(uv_connect_t *req, int status) 69 | { 70 | Tcp *self = (Tcp *) req->data; 71 | if(self->m_pOutConnectHandler) { 72 | self->m_pOutConnectHandler->OnConnected(self, status); 73 | } 74 | 75 | if(status) { 76 | self->Close(); 77 | } 78 | 79 | self->Unref(); 80 | } 81 | 82 | size_t Tcp::GetPeerSize() const 83 | { 84 | return sizeof(uv_tcp_t); 85 | } 86 | 87 | int Tcp::DoOpen(/* [in] */ Loop &loop, /* [in] */ uv_handle_t *peer) 88 | { 89 | return uv_tcp_init(loop, (uv_tcp_t *) peer); 90 | } 91 | 92 | void Tcp::DoClose() 93 | { 94 | Stream::DoClose(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/uv++-tcp.h: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | class Tcp: public Stream 6 | { 7 | public: 8 | class OutConnectHandler 9 | { 10 | private: 11 | virtual void OnConnected(/* [in] */ Tcp *source, 12 | /* [in] */ int status) = 0; 13 | friend class Tcp; 14 | }; 15 | 16 | public: 17 | static Tcp * New(Loop &Loop = Loop::Get()); 18 | 19 | virtual int Bind(/* [in] */ const Address &addr, 20 | /* [in] */ unsigned int flags = 0); 21 | 22 | virtual int Accept(/* [out] */ Stream **conn); 23 | 24 | Tcp * Ref() 25 | { 26 | return (Tcp *) Handle::Ref(); 27 | } 28 | 29 | int Connect(/* [in] */ Address::Type addrType, 30 | /* [in] */ const char *ip, 31 | /* [in] */ int port, 32 | /* [in] */ OutConnectHandler *handler = NULL) 33 | { 34 | return Connect(Address(addrType, ip, port), handler); 35 | } 36 | 37 | int Connect(/* [in] */ const Address &addr, 38 | /* [in] */ OutConnectHandler *handler); 39 | 40 | protected: 41 | Tcp(): m_pOutConnectHandler(NULL) 42 | { 43 | m_connectReq.data = this; 44 | } 45 | 46 | virtual size_t GetPeerSize() const; 47 | 48 | virtual int DoOpen(/* [in] */ Loop &loop, 49 | /* [in] */ uv_handle_t *peer); 50 | 51 | virtual void DoClose(); 52 | 53 | operator uv_tcp_t *() 54 | { 55 | return (uv_tcp_t *) GetPeer(); 56 | } 57 | 58 | private: 59 | static void OnConnected(uv_connect_t *req, int status); 60 | 61 | private: 62 | uv_connect_t m_connectReq; 63 | OutConnectHandler *m_pOutConnectHandler; 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /src/uv++-timer.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | Timer * Timer::New(/* [in] */ Loop &loop) 6 | { 7 | Timer *self = new Timer(); 8 | if(! self) { 9 | return NULL; 10 | } 11 | 12 | if(! self->Open(loop)) { 13 | return self; 14 | } 15 | 16 | delete self; 17 | 18 | return NULL; 19 | } 20 | 21 | int Timer::Start(/* [in] */ uint64_t interval, 22 | /* [in] */ uint64_t delay, 23 | /* [in] */ TimeoutHandler &handler) 24 | { 25 | assert(! m_pHandler); 26 | 27 | int result = uv_timer_start(*this, 28 | OnTimeout, 29 | delay, 30 | interval); 31 | if(! result) { 32 | m_pHandler = &handler; 33 | Ref(); 34 | 35 | } 36 | 37 | return result; 38 | } 39 | 40 | int Timer::Stop() 41 | { 42 | assert(m_pHandler); 43 | 44 | int result = uv_timer_stop(*this); 45 | m_pHandler = NULL; 46 | 47 | Unref(); 48 | 49 | return result; 50 | } 51 | 52 | void Timer::OnTimeout(uv_timer_t *peer, int status) 53 | { 54 | Timer *self = (Timer *) peer->data; 55 | self->m_pHandler->OnTimeout(self, status); 56 | 57 | if(status) { 58 | self->Close(); 59 | } 60 | } 61 | 62 | int Timer::DoOpen(Loop &loop, uv_handle_t *peer) 63 | { 64 | return uv_timer_init(loop, (uv_timer_t *) peer); 65 | } 66 | 67 | void Timer::DoClose() 68 | { 69 | if(IsStarted()) { 70 | Stop(); 71 | } 72 | } 73 | 74 | size_t Timer::GetPeerSize() const 75 | { 76 | return sizeof(uv_timer_t); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/uv++-timer.h: -------------------------------------------------------------------------------- 1 | namespace Uv 2 | { 3 | class Timer: public Handle 4 | { 5 | public: 6 | class TimeoutHandler 7 | { 8 | private: 9 | virtual void OnTimeout(Timer *source, int status) = 0; 10 | 11 | friend class Timer; 12 | }; 13 | 14 | public: 15 | static Timer * New(Loop &loop = Loop::Get()); 16 | 17 | int Start(/* [in] */ uint64_t interval, 18 | /* [in] */ TimeoutHandler &handler) 19 | { 20 | assert(IsOpened()); 21 | 22 | return Start(interval, interval, handler); 23 | } 24 | 25 | int Start(/* [in] */ uint64_t interval, 26 | /* [in] */ uint64_t delay, 27 | /* [in] */ TimeoutHandler &handler); 28 | 29 | bool IsStarted() 30 | { 31 | return !! m_pHandler; 32 | } 33 | 34 | int Stop(); 35 | 36 | Timer * Ref() 37 | { 38 | return (Timer *) Handle::Ref(); 39 | } 40 | 41 | protected: 42 | Timer(): m_pHandler(NULL) 43 | { 44 | } 45 | 46 | virtual int DoOpen(Loop &loop, uv_handle_t *peer); 47 | 48 | virtual size_t GetPeerSize() const; 49 | 50 | operator uv_timer_t *() 51 | { 52 | return (uv_timer_t *) GetPeer(); 53 | } 54 | 55 | virtual void DoClose(); 56 | 57 | static void OnTimeout(uv_timer_t *peer, int status); 58 | 59 | private: 60 | TimeoutHandler *m_pHandler; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /src/uv++-udp.cpp: -------------------------------------------------------------------------------- 1 | #include "uv++.h" 2 | 3 | namespace Uv 4 | { 5 | Udp * Udp::New(/* [in] */ Loop &loop) 6 | { 7 | Udp *self = new Udp(); 8 | if(! self) { 9 | return NULL; 10 | } 11 | 12 | if(! self->Open(loop)) { 13 | return self; 14 | } 15 | 16 | delete self; 17 | 18 | return NULL; 19 | } 20 | 21 | int Udp::RecvStart(/* [in] */ RecvHandler &handler) 22 | { 23 | assert(IsOpened()); 24 | assert(! IsRecvStarted()); 25 | 26 | int result = uv_udp_recv_start(*this, OnAlloc, OnRecv); 27 | if(! result) { 28 | Ref(); 29 | m_pRecvHandler = &handler; 30 | } 31 | 32 | return result; 33 | } 34 | 35 | int Udp::RecvStop() 36 | { 37 | assert(IsOpened() || IsClosing()); 38 | assert(IsRecvStarted()); 39 | 40 | int result = uv_udp_recv_stop(*this); 41 | 42 | m_pRecvHandler = NULL; 43 | Unref(); 44 | 45 | return result; 46 | } 47 | 48 | size_t Udp::GetPeerSize() const 49 | { 50 | return sizeof(uv_udp_t); 51 | } 52 | 53 | int Udp::DoOpen(/* [in] */ Loop &loop, /* [in] */ uv_handle_t *peer) 54 | { 55 | return uv_udp_init(loop, (uv_udp_t *) peer); 56 | } 57 | 58 | void Udp::DoClose() 59 | { 60 | if(IsRecvStarted()) { 61 | RecvStop(); 62 | } 63 | } 64 | 65 | void Udp::OnRecv(/* [in] */ uv_udp_t *peer, 66 | /* [in] */ ssize_t nread, 67 | /* [in] */ const uv_buf_t *buf, 68 | /* [in] */ const sockaddr *addr, 69 | /* [in] */ unsigned flags) 70 | { 71 | if(! nread) { 72 | Buffer::Free(buf->base); 73 | return; 74 | } 75 | 76 | Udp *self = (Udp *) peer->data; 77 | Buffer *buffer = NULL; 78 | if(0 < nread) { 79 | buffer = new Buffer(buf, nread); 80 | } 81 | 82 | Address address; 83 | if(addr) { 84 | address.Set(addr); 85 | } 86 | 87 | self->m_pRecvHandler->OnRecv(self, 88 | buffer, 89 | address, 90 | flags, 91 | 0 > nread ? nread : 0); 92 | 93 | if(buffer) { 94 | buffer->Unref(); 95 | } 96 | 97 | if(0 > nread) { 98 | self->Close(); 99 | } 100 | } 101 | 102 | int Udp::Send(/* [in] */ Buffer &buf, 103 | /* [in] */ const Address &addr, 104 | /* [in] */ SendHandler *handler) 105 | { 106 | assert(IsOpened()); 107 | assert(! IsSending()); 108 | 109 | int result = uv_udp_send(&m_sendReq, 110 | *this, 111 | buf, 112 | 1, 113 | addr, 114 | OnSend); 115 | if(! result) { 116 | Ref(); 117 | m_pSendBuffer = buf.Ref(); 118 | m_pSendBuffer->Lock(); 119 | m_pSendHandler = handler; 120 | } 121 | 122 | return result; 123 | } 124 | 125 | void Udp::OnSend(/* [in] */ uv_udp_send_t *req, 126 | /* [in] */ int status) 127 | { 128 | Udp *self = (Udp *) req->data; 129 | Buffer *sendBuffer = self->m_pSendBuffer; 130 | self->m_pSendBuffer = NULL; 131 | 132 | if(self->m_pSendHandler) { 133 | SendHandler *sendHandler = self->m_pSendHandler; 134 | self->m_pSendHandler = NULL; 135 | 136 | sendHandler->OnSend(self, status); 137 | } 138 | 139 | sendBuffer->Unlock(); 140 | sendBuffer->Unref(); 141 | 142 | if(status) { 143 | self->Close(); 144 | } 145 | 146 | self->Unref(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/uv++-udp.h: -------------------------------------------------------------------------------- 1 | namespace Uv 2 | { 3 | class Udp: public Socket 4 | { 5 | public: 6 | enum Action 7 | { 8 | LeaveGroup = UV_LEAVE_GROUP, 9 | JoinGroup = UV_JOIN_GROUP 10 | }; 11 | 12 | class SendHandler 13 | { 14 | private: 15 | virtual void OnSend(/* [in] */ Udp *source, 16 | /* [in] */ int status) = 0; 17 | friend class Udp; 18 | }; 19 | 20 | class RecvHandler 21 | { 22 | private: 23 | virtual void OnRecv(/* [in] */ Udp *source, 24 | /* [in] */ Buffer *buf, 25 | /* [in] */ const Address &addr, 26 | /* [in] */ unsigned int flags, 27 | /* [in] */ int status) = 0; 28 | friend class Udp; 29 | }; 30 | 31 | public: 32 | static Udp * New(/* [in] */ Loop &loop = Loop::Get()); 33 | 34 | int Bind(/* [in] */ const Address &addr, 35 | /* [in] */ unsigned int flags = 0) 36 | { 37 | assert(IsOpened()); 38 | 39 | return uv_udp_bind(*this, addr, flags); 40 | } 41 | 42 | Udp * Ref() 43 | { 44 | return (Udp *) Handle::Ref(); 45 | } 46 | 47 | int RecvStart(/* [in] */ RecvHandler &handler); 48 | 49 | bool IsRecvStarted() const 50 | { 51 | return !! m_pRecvHandler; 52 | } 53 | 54 | int RecvStop(); 55 | 56 | int Send(/* [in] */ Buffer &buf, 57 | /* [in] */ const Address &addr, 58 | /* [in] */ SendHandler *handler = NULL); 59 | 60 | bool IsSending() const 61 | { 62 | return !! m_pSendBuffer; 63 | } 64 | 65 | int JoinMulticastGroup(/* [in] */ const char *multicastAddr, 66 | /* [in] */ const char *interfaceAddr) 67 | { 68 | return SetMulticastGroup(multicastAddr, interfaceAddr, JoinGroup); 69 | } 70 | 71 | int LeaveMulticastGroup(/* [in] */ const char *multicastAddr, 72 | /* [in] */ const char *interfaceAddr) 73 | { 74 | return SetMulticastGroup(multicastAddr, interfaceAddr, LeaveGroup); 75 | } 76 | 77 | int SetMulticastGroup(/* [in] */ const char *multicastAddr, 78 | /* [in] */ const char *interfaceAddr, 79 | /* [in] */ Action action) 80 | { 81 | assert(IsOpened()); 82 | assert(multicastAddr); 83 | assert(interfaceAddr); 84 | 85 | return uv_udp_set_membership(*this, 86 | multicastAddr, 87 | interfaceAddr, 88 | (uv_membership) action); 89 | } 90 | 91 | int SetMulticastLoop(/* [in] */ bool enable) 92 | { 93 | assert(IsOpened()); 94 | 95 | return uv_udp_set_multicast_loop(*this, enable); 96 | } 97 | 98 | int SetMulticastTtl(/* [in] */ unsigned char ttl) 99 | { 100 | assert(IsOpened()); 101 | assert(0 != ttl); 102 | 103 | return uv_udp_set_multicast_ttl(*this, ttl); 104 | } 105 | 106 | int SetBroadcast(/* [in] */ bool enable) 107 | { 108 | assert(IsOpened()); 109 | 110 | return uv_udp_set_broadcast(*this, enable); 111 | } 112 | 113 | int SetTtl(/* [in] */ unsigned char ttl) 114 | { 115 | assert(IsOpened()); 116 | 117 | return uv_udp_set_ttl(*this, ttl); 118 | } 119 | 120 | protected: 121 | Udp(): m_pRecvHandler(NULL), 122 | m_pSendBuffer(NULL), 123 | m_pSendHandler(NULL) 124 | { 125 | m_sendReq.data = this; 126 | } 127 | 128 | virtual size_t GetPeerSize() const; 129 | 130 | virtual int DoOpen(/* [in] */ Loop &loop, 131 | /* [in] */ uv_handle_t *peer); 132 | 133 | virtual void DoClose(); 134 | 135 | operator uv_udp_t * () 136 | { 137 | return (uv_udp_t *) GetPeer(); 138 | } 139 | 140 | private: 141 | static void OnRecv(/* [in] */ uv_udp_t *peer, 142 | /* [in] */ ssize_t nread, 143 | /* [in] */ const uv_buf_t *buf, 144 | /* [in] */ const sockaddr *addr, 145 | /* [in] */ unsigned flags); 146 | 147 | static void OnSend(/* [in] */ uv_udp_send_t *req, 148 | /* [in] */ int status); 149 | 150 | private: 151 | RecvHandler *m_pRecvHandler; 152 | 153 | uv_udp_send_t m_sendReq; 154 | Buffer *m_pSendBuffer; 155 | SendHandler *m_pSendHandler; 156 | }; 157 | } 158 | -------------------------------------------------------------------------------- /src/uv++.h: -------------------------------------------------------------------------------- 1 | #ifndef __UVPP_H_ 2 | #define __UVPP_H_ 3 | 4 | #include 5 | using namespace std; 6 | 7 | #include 8 | #include "uv++-loop.h" 9 | #include "uv++-handle.h" 10 | #include "uv++-timer.h" 11 | #include "uv++-signal.h" 12 | #include "uv++-address.h" 13 | #include "uv++-buffer.h" 14 | #include "uv++-socket.h" 15 | #include "uv++-stream.h" 16 | #include "uv++-tcp.h" 17 | #include "uv++-udp.h" 18 | 19 | namespace Uv 20 | { 21 | inline const char * GetErrorStr(int error) 22 | { 23 | return uv_strerror(error); 24 | } 25 | } 26 | 27 | #endif /* __UVPP_H_ */ 28 | --------------------------------------------------------------------------------