1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
12#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
13
14#include <winsock2.h>
15#include <list>
16
17#include "webrtc/system_wrappers/interface/atomic32.h"
18#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
19#include "webrtc/system_wrappers/interface/event_wrapper.h"
20#include "webrtc/system_wrappers/interface/thread_wrapper.h"
21#include "webrtc/test/channel_transport/udp_socket2_win.h"
22#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
23#include "webrtc/test/channel_transport/udp_transport.h"
24
25#define MAX_IO_BUFF_SIZE 1600
26
27namespace webrtc {
28namespace test {
29
30enum IO_OPERATION {
31    OP_READ,
32    OP_WRITE
33};
34
35class UdpSocket2Windows;
36
37// Struct used for all socket I/O operations.
38struct PerIoContext {
39    WSAOVERLAPPED overlapped;
40    char buffer[MAX_IO_BUFF_SIZE];
41    WSABUF wsabuf;
42    int nTotalBytes;
43    int nSentBytes;
44    int bytes;
45    IO_OPERATION ioOperation;
46    SocketAddress from;
47    int fromLen;
48    // Should be set to true if the I/O context was passed to the system by
49    // a thread not controlled by the socket implementation.
50    bool ioInitiatedByThreadWrapper;
51    // TODO (hellner): Not used. Delete it.
52    PerIoContext* pNextFree;
53};
54
55struct IoContextPoolItem;
56struct IoContextPoolItemPayload
57{
58    PerIoContext    ioContext;
59    IoContextPoolItem* base;
60};
61
62struct IoContextPoolItem
63{
64    // Atomic single linked list entry header.
65    SLIST_ENTRY itemEntry;
66    // Atomic single linked list payload
67    IoContextPoolItemPayload payload;
68};
69
70class IoContextPool
71{
72public:
73    IoContextPool();
74    virtual ~IoContextPool();
75    virtual int32_t Init(uint32_t increaseSize = 128);
76    // Re-use an old unused IO context or create a new one.
77    virtual PerIoContext* PopIoContext();
78    virtual int32_t PushIoContext(PerIoContext* pIoContext);
79    virtual inline int32_t GetSize(uint32_t* inUse = 0)
80    {return _size.Value();}
81    virtual int32_t Free();
82private:
83    // Sample code for use of msfts single linked atomic list can be found here:
84    // http://msdn.microsoft.com/en-us/library/ms686962(VS.85).aspx
85
86    // Atomic single linked list head.
87    PSLIST_HEADER _pListHead;
88
89    bool _init;
90    Atomic32 _size;
91    Atomic32 _inUse;
92};
93
94class UdpSocket2WorkerWindows
95{
96public:
97    UdpSocket2WorkerWindows(HANDLE ioCompletionHandle);
98    virtual ~UdpSocket2WorkerWindows();
99
100    virtual bool Start();
101    virtual bool Stop();
102    virtual int32_t Init();
103    virtual void SetNotAlive();
104protected:
105    static bool Run(ThreadObj obj);
106    bool Process();
107private:
108    HANDLE _ioCompletionHandle;
109    ThreadWrapper*_pThread;
110    static int32_t _numOfWorkers;
111    int32_t _workerNumber;
112    volatile bool _stop;
113    bool _init;
114};
115
116class UdpSocket2ManagerWindows : public UdpSocketManager
117{
118public:
119    UdpSocket2ManagerWindows();
120    virtual ~UdpSocket2ManagerWindows();
121
122    virtual bool Init(int32_t id, uint8_t& numOfWorkThreads);
123    virtual int32_t ChangeUniqueId(const int32_t id);
124
125    virtual bool Start();
126    virtual bool Stop();
127
128    virtual inline bool AddSocket(UdpSocketWrapper* s)
129    {if(s) return AddSocketPrv(reinterpret_cast<UdpSocket2Windows*>(s));
130     return false;}
131    virtual bool RemoveSocket(UdpSocketWrapper* s)
132    {if(s) return RemoveSocketPrv(reinterpret_cast<UdpSocket2Windows*>(s));
133     return false;}
134
135    PerIoContext* PopIoContext(void);
136    int32_t PushIoContext(PerIoContext* pIoContext);
137
138private:
139    typedef std::list<UdpSocket2WorkerWindows*> WorkerList;
140    bool StopWorkerThreads();
141    bool StartWorkerThreads();
142    bool AddSocketPrv(UdpSocket2Windows* s);
143    bool RemoveSocketPrv(UdpSocket2Windows* s);
144
145    static uint32_t _numOfActiveManagers;
146    static bool _wsaInit;
147
148    int32_t _id;
149    CriticalSectionWrapper* _pCrit;
150    int32_t _managerNumber;
151    volatile bool _stopped;
152    bool _init;
153    int32_t _numActiveSockets;
154    WorkerList _workerThreadsList;
155    EventWrapper* _event;
156
157    HANDLE _ioCompletionHandle;
158    IoContextPool _ioContextPool;
159};
160
161}  // namespace test
162}  // namespace webrtc
163
164#endif  // WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
165