| #ifndef _windows_asynchIoResult_h |
| #define _windows_asynchIoResult_h |
| |
| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| #include "qpid/sys/AsynchIO.h" |
| #include "qpid/sys/Socket.h" |
| #include <memory.h> |
| #include <winsock2.h> |
| #include <ws2tcpip.h> |
| |
| namespace qpid { |
| namespace sys { |
| |
| /* |
| * AsynchIoResult defines the class that receives the result of an |
| * asynchronous I/O operation, either send/recv or accept/connect. |
| * |
| * Operation factories should set one of these up before beginning the |
| * operation. Poller knows how to dispatch completion to this class. |
| * This class must be subclassed for needed operations; this class provides |
| * an interface only and cannot be instantiated. |
| * |
| * This class is tied to Windows; it inherits from OVERLAPPED so that the |
| * IocpPoller can cast OVERLAPPED pointers back to AsynchIoResult and call |
| * the completion handler. |
| */ |
| class AsynchResult : private OVERLAPPED { |
| public: |
| LPOVERLAPPED overlapped(void) { return this; } |
| static AsynchResult* from_overlapped(LPOVERLAPPED ol) { |
| return static_cast<AsynchResult*>(ol); |
| } |
| virtual void success (size_t bytesTransferred) { |
| bytes = bytesTransferred; |
| status = 0; |
| complete(); |
| } |
| virtual void failure (int error) { |
| bytes = 0; |
| status = error; |
| complete(); |
| } |
| size_t getTransferred(void) const { return bytes; } |
| int getStatus(void) const { return status; } |
| |
| protected: |
| AsynchResult() : bytes(0), status(0) |
| { memset(overlapped(), 0, sizeof(OVERLAPPED)); } |
| ~AsynchResult() {} |
| virtual void complete(void) = 0; |
| |
| size_t bytes; |
| int status; |
| }; |
| |
| class AsynchAcceptorPrivate; |
| class AsynchAcceptResult : public AsynchResult { |
| |
| friend class AsynchAcceptorPrivate; |
| |
| public: |
| AsynchAcceptResult(AsynchAcceptor::Callback cb, |
| AsynchAcceptorPrivate *acceptor, |
| SOCKET listener); |
| virtual void success (size_t bytesTransferred); |
| virtual void failure (int error); |
| |
| private: |
| virtual void complete(void) {} // No-op for this class. |
| |
| std::auto_ptr<qpid::sys::Socket> newSocket; |
| AsynchAcceptor::Callback callback; |
| AsynchAcceptorPrivate *acceptor; |
| SOCKET listener; |
| |
| // AcceptEx needs a place to write the local and remote addresses |
| // when accepting the connection. Place those here; get enough for |
| // IPv6 addresses, even if the socket is IPv4. |
| enum { SOCKADDRMAXLEN = sizeof sockaddr_in6 + 16, |
| SOCKADDRBUFLEN = 2 * SOCKADDRMAXLEN }; |
| char addressBuffer[SOCKADDRBUFLEN]; |
| }; |
| |
| class AsynchIoResult : public AsynchResult { |
| public: |
| typedef boost::function1<void, AsynchIoResult *> Completer; |
| |
| virtual ~AsynchIoResult() {} |
| AsynchIO::BufferBase *getBuff(void) const { return iobuff; } |
| size_t getRequested(void) const { return requested; } |
| const WSABUF *getWSABUF(void) const { return &wsabuf; } |
| |
| protected: |
| void setBuff (AsynchIO::BufferBase *buffer) { iobuff = buffer; } |
| |
| protected: |
| AsynchIoResult(Completer cb, |
| AsynchIO::BufferBase *buff, size_t length) |
| : completionCallback(cb), iobuff(buff), requested(length) {} |
| |
| virtual void complete(void) = 0; |
| WSABUF wsabuf; |
| Completer completionCallback; |
| |
| private: |
| AsynchIO::BufferBase *iobuff; |
| size_t requested; // Number of bytes in original I/O request |
| }; |
| |
| class AsynchReadResult : public AsynchIoResult { |
| |
| // complete() updates buffer then does completion callback. |
| virtual void complete(void) { |
| getBuff()->dataCount += bytes; |
| completionCallback(this); |
| } |
| |
| public: |
| AsynchReadResult(AsynchIoResult::Completer cb, |
| AsynchIO::BufferBase *buff, |
| size_t length) |
| : AsynchIoResult(cb, buff, length) { |
| wsabuf.buf = buff->bytes + buff->dataCount; |
| wsabuf.len = length; |
| } |
| }; |
| |
| class AsynchWriteResult : public AsynchIoResult { |
| |
| // complete() updates buffer then does completion callback. |
| virtual void complete(void) { |
| AsynchIO::BufferBase *b = getBuff(); |
| b->dataStart += bytes; |
| b->dataCount -= bytes; |
| completionCallback(this); |
| } |
| |
| public: |
| AsynchWriteResult(AsynchIoResult::Completer cb, |
| AsynchIO::BufferBase *buff, |
| size_t length) |
| : AsynchIoResult(cb, buff, length) { |
| wsabuf.buf = buff ? buff->bytes : 0; |
| wsabuf.len = length; |
| } |
| }; |
| |
| class AsynchWriteWanted : public AsynchWriteResult { |
| |
| // complete() just does completion callback; no buffers used. |
| virtual void complete(void) { |
| completionCallback(this); |
| } |
| |
| public: |
| AsynchWriteWanted(AsynchIoResult::Completer cb) |
| : AsynchWriteResult(cb, 0, 0) { |
| wsabuf.buf = 0; |
| wsabuf.len = 0; |
| } |
| }; |
| |
| }} |
| |
| #endif /*!_windows_asynchIoResult_h*/ |