blob: 7db4e9c3311ef3c4a6275702d6042b6448c73e48 [file] [log] [blame]
#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*/