Index: runtime/bin/eventhandler_win.h |
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h |
index 43562cd1d0f95aac8e82666c20f8701f72156f40..90e505add21567a0b69064b1bae846aa37727baa 100644 |
--- a/runtime/bin/eventhandler_win.h |
+++ b/runtime/bin/eventhandler_win.h |
@@ -10,6 +10,7 @@ |
#endif |
#include <winsock2.h> |
+#include <ws2tcpip.h> |
#include <mswsock.h> |
#include "bin/builtin.h" |
@@ -40,11 +41,13 @@ struct InterruptMessage { |
// socket for the client. |
class OverlappedBuffer { |
public: |
- enum Operation { kAccept, kRead, kWrite, kDisconnect }; |
+ enum Operation { kAccept, kRead, kRecvFrom, kWrite, kSendTo, kDisconnect }; |
static OverlappedBuffer* AllocateAcceptBuffer(int buffer_size); |
static OverlappedBuffer* AllocateReadBuffer(int buffer_size); |
+ static OverlappedBuffer* AllocateRecvFromBuffer(int buffer_size); |
static OverlappedBuffer* AllocateWriteBuffer(int buffer_size); |
+ static OverlappedBuffer* AllocateSendToBuffer(int buffer_size); |
static OverlappedBuffer* AllocateDisconnectBuffer(); |
static void DisposeBuffer(OverlappedBuffer* buffer); |
@@ -71,6 +74,9 @@ class OverlappedBuffer { |
SOCKET client() { return client_; } |
char* GetBufferStart() { return reinterpret_cast<char*>(&buffer_data_); } |
int GetBufferSize() { return buflen_; } |
+ struct sockaddr* from() { return from_; } |
+ socklen_t* from_len_addr() { return from_len_addr_; } |
+ socklen_t from_len() { return from_ == NULL ? 0 : *from_len_addr_; } |
// Returns the address of the OVERLAPPED structure with all fields |
// initialized to zero. |
@@ -92,6 +98,21 @@ class OverlappedBuffer { |
OverlappedBuffer(int buffer_size, Operation operation) |
: operation_(operation), buflen_(buffer_size) { |
memset(GetBufferStart(), 0, GetBufferSize()); |
+ if (operation == kRecvFrom) { |
+ // Reserve part of the buffer for the length of source sockaddr |
+ // and source sockaddr. |
+ const int kAdditionalSize = |
+ sizeof(struct sockaddr_storage) + sizeof(socklen_t); |
+ ASSERT(buflen_ > kAdditionalSize); |
+ buflen_ -= kAdditionalSize; |
+ from_len_addr_ = reinterpret_cast<socklen_t*>( |
+ GetBufferStart() + GetBufferSize()); |
+ *from_len_addr_ = sizeof(struct sockaddr_storage); |
+ from_ = reinterpret_cast<struct sockaddr*>(from_len_addr_ + 1); |
+ } else { |
+ from_len_addr_ = NULL; |
+ from_ = NULL; |
+ } |
index_ = 0; |
data_length_ = 0; |
if (operation_ == kAccept) { |
@@ -107,6 +128,9 @@ class OverlappedBuffer { |
free(buffer); |
} |
+ // Allocate an overlapped buffer for thse specified amount of data and |
+ // operation. Some operations need additional buffer space, which is |
+ // handled by this method. |
static OverlappedBuffer* AllocateBuffer(int buffer_size, |
Operation operation); |
@@ -120,6 +144,11 @@ class OverlappedBuffer { |
WSABUF wbuf_; // Structure for passing buffer to WSA functions. |
+ // For the recvfrom operation additional storace is allocated for the |
+ // source sockaddr. |
+ socklen_t* from_len_addr_; // Pointer to source sockaddr size storage. |
+ struct sockaddr* from_; // Pointer to source sockaddr storage. |
+ |
// Buffer for recv/send/AcceptEx. This must be at the end of the |
// object as the object is allocated larger than it's definition |
// indicate to extend this array. |
@@ -136,7 +165,8 @@ class Handle { |
kStd, |
kDirectoryWatch, |
kClientSocket, |
- kListenSocket |
+ kListenSocket, |
+ kDatagramSocket |
}; |
class ScopedLock { |
@@ -158,14 +188,23 @@ class Handle { |
// Socket interface exposing normal socket operations. |
int Available(); |
int Read(void* buffer, int num_bytes); |
+ int RecvFrom( |
+ void* buffer, int num_bytes, struct sockaddr* sa, socklen_t addr_len); |
virtual int Write(const void* buffer, int num_bytes); |
+ virtual int SendTo(const void* buffer, |
+ int num_bytes, |
+ struct sockaddr* sa, |
+ socklen_t sa_len); |
// Internal interface used by the event handler. |
virtual bool IssueRead(); |
+ virtual bool IssueRecvFrom(); |
virtual bool IssueWrite(); |
+ virtual bool IssueSendTo(struct sockaddr* sa, socklen_t sa_len); |
bool HasPendingRead(); |
bool HasPendingWrite(); |
void ReadComplete(OverlappedBuffer* buffer); |
+ void RecvFromComplete(OverlappedBuffer* buffer); |
void WriteComplete(OverlappedBuffer* buffer); |
bool IsClosing() { return (flags_ & (1 << kClosing)) != 0; } |
@@ -199,9 +238,12 @@ class Handle { |
} |
Type type() { return type_; } |
bool is_file() { return type_ == kFile; } |
- bool is_socket() { return type_ == kListenSocket || type_ == kClientSocket; } |
+ bool is_socket() { return type_ == kListenSocket || |
+ type_ == kClientSocket || |
+ type_ == kDatagramSocket; } |
bool is_listen_socket() { return type_ == kListenSocket; } |
bool is_client_socket() { return type_ == kClientSocket; } |
+ bool is_datagram_socket() { return type_ == kDatagramSocket; } |
void set_mask(intptr_t mask) { mask_ = mask; } |
intptr_t mask() { return mask_; } |
@@ -416,6 +458,27 @@ class ClientSocket : public SocketHandle { |
}; |
+class DatagramSocket : public SocketHandle { |
+ public: |
+ explicit DatagramSocket(SOCKET s) : SocketHandle(s) { |
+ type_ = kDatagramSocket; |
+ } |
+ |
+ virtual ~DatagramSocket() { |
+ // Don't delete this object until all pending requests have been handled. |
+ ASSERT(!HasPendingRead()); |
+ ASSERT(!HasPendingWrite()); |
+ }; |
+ |
+ // Internal interface used by the event handler. |
+ virtual bool IssueRecvFrom(); |
+ virtual bool IssueSendTo(sockaddr* sa, socklen_t sa_len); |
+ |
+ virtual void EnsureInitialized(EventHandlerImplementation* event_handler); |
+ virtual void DoClose(); |
+ virtual bool IsClosed(); |
+}; |
+ |
// Event handler. |
class EventHandlerImplementation { |
public: |
@@ -435,6 +498,7 @@ class EventHandlerImplementation { |
void HandleClosed(Handle* handle); |
void HandleError(Handle* handle); |
void HandleRead(Handle* handle, int bytes, OverlappedBuffer* buffer); |
+ void HandleRecvFrom(Handle* handle, int bytes, OverlappedBuffer* buffer); |
void HandleWrite(Handle* handle, int bytes, OverlappedBuffer* buffer); |
void HandleDisconnect(ClientSocket* client_socket, |
int bytes, |