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_VOICE_ENGINE_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
12 #define WEBRTC_VOICE_ENGINE_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
13 
14 #include <winsock2.h>
15 #include <list>
16 
17 #include "webrtc/system_wrappers/include/atomic32.h"
18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
19 #include "webrtc/system_wrappers/include/event_wrapper.h"
20 #include "webrtc/base/platform_thread.h"
21 #include "webrtc/voice_engine/test/channel_transport/udp_socket2_win.h"
22 #include "webrtc/voice_engine/test/channel_transport/udp_socket_manager_wrapper.h"
23 #include "webrtc/voice_engine/test/channel_transport/udp_transport.h"
24 
25 #define MAX_IO_BUFF_SIZE 1600
26 
27 namespace webrtc {
28 namespace test {
29 
30 enum IO_OPERATION {
31     OP_READ,
32     OP_WRITE
33 };
34 
35 class UdpSocket2Windows;
36 
37 // Struct used for all socket I/O operations.
38 struct PerIoContext {
39     WSAOVERLAPPED overlapped;
40     char buffer[MAX_IO_BUFF_SIZE];
41     WSABUF wsabuf;
42     size_t 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 ioInitiatedByPlatformThread;
51     // TODO (hellner): Not used. Delete it.
52     PerIoContext* pNextFree;
53 };
54 
55 struct IoContextPoolItem;
56 struct IoContextPoolItemPayload
57 {
58     PerIoContext    ioContext;
59     IoContextPoolItem* base;
60 };
61 
62 struct IoContextPoolItem
63 {
64     // Atomic single linked list entry header.
65     SLIST_ENTRY itemEntry;
66     // Atomic single linked list payload
67     IoContextPoolItemPayload payload;
68 };
69 
70 class IoContextPool
71 {
72 public:
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();
82 private:
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 
94 class UdpSocket2WorkerWindows
95 {
96 public:
97     UdpSocket2WorkerWindows(HANDLE ioCompletionHandle);
98     virtual ~UdpSocket2WorkerWindows();
99 
100     virtual bool Start();
101     virtual bool Stop();
102     virtual int32_t Init();
103 protected:
104     static bool Run(void* obj);
105     bool Process();
106 private:
107     HANDLE _ioCompletionHandle;
108     rtc::PlatformThread _pThread;
109     static int32_t _numOfWorkers;
110     int32_t _workerNumber;
111     volatile bool _stop;
112     bool _init;
113 };
114 
115 class UdpSocket2ManagerWindows : public UdpSocketManager
116 {
117 public:
118     UdpSocket2ManagerWindows();
119     virtual ~UdpSocket2ManagerWindows();
120 
121     virtual bool Init(int32_t id, uint8_t& numOfWorkThreads);
122 
123     virtual bool Start();
124     virtual bool Stop();
125 
AddSocket(UdpSocketWrapper * s)126     virtual inline bool AddSocket(UdpSocketWrapper* s)
127     {if(s) return AddSocketPrv(reinterpret_cast<UdpSocket2Windows*>(s));
128      return false;}
RemoveSocket(UdpSocketWrapper * s)129     virtual bool RemoveSocket(UdpSocketWrapper* s)
130     {if(s) return RemoveSocketPrv(reinterpret_cast<UdpSocket2Windows*>(s));
131      return false;}
132 
133     PerIoContext* PopIoContext(void);
134     int32_t PushIoContext(PerIoContext* pIoContext);
135 
136 private:
137     typedef std::list<UdpSocket2WorkerWindows*> WorkerList;
138     bool StopWorkerThreads();
139     bool StartWorkerThreads();
140     bool AddSocketPrv(UdpSocket2Windows* s);
141     bool RemoveSocketPrv(UdpSocket2Windows* s);
142 
143     static uint32_t _numOfActiveManagers;
144     static bool _wsaInit;
145 
146     int32_t _id;
147     CriticalSectionWrapper* _pCrit;
148     int32_t _managerNumber;
149     volatile bool _stopped;
150     bool _init;
151     int32_t _numActiveSockets;
152     WorkerList _workerThreadsList;
153     EventWrapper* _event;
154 
155     HANDLE _ioCompletionHandle;
156     IoContextPool _ioContextPool;
157 };
158 
159 }  // namespace test
160 }  // namespace webrtc
161 
162 #endif  // WEBRTC_VOICE_ENGINE_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
163