| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2011 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 #include "webrtc/voice_engine/test/channel_transport/udp_socket_manager_posix.h" | |
| 12 | |
| 13 #include <stdio.h> | |
| 14 #include <strings.h> | |
| 15 #include <sys/time.h> | |
| 16 #include <sys/types.h> | |
| 17 #include <time.h> | |
| 18 #include <unistd.h> | |
| 19 | |
| 20 #include "webrtc/system_wrappers/include/sleep.h" | |
| 21 #include "webrtc/system_wrappers/include/trace.h" | |
| 22 #include "webrtc/voice_engine/test/channel_transport/udp_socket_posix.h" | |
| 23 | |
| 24 namespace webrtc { | |
| 25 namespace test { | |
| 26 | |
| 27 UdpSocketManagerPosix::UdpSocketManagerPosix() | |
| 28 : UdpSocketManager(), | |
| 29 _id(-1), | |
| 30 _critSect(CriticalSectionWrapper::CreateCriticalSection()), | |
| 31 _numberOfSocketMgr(-1), | |
| 32 _incSocketMgrNextTime(0), | |
| 33 _nextSocketMgrToAssign(0), | |
| 34 _socketMgr() | |
| 35 { | |
| 36 } | |
| 37 | |
| 38 bool UdpSocketManagerPosix::Init(int32_t id, uint8_t& numOfWorkThreads) { | |
| 39 CriticalSectionScoped cs(_critSect); | |
| 40 if ((_id != -1) || (_numOfWorkThreads != 0)) { | |
| 41 assert(_id != -1); | |
| 42 assert(_numOfWorkThreads != 0); | |
| 43 return false; | |
| 44 } | |
| 45 | |
| 46 _id = id; | |
| 47 _numberOfSocketMgr = numOfWorkThreads; | |
| 48 _numOfWorkThreads = numOfWorkThreads; | |
| 49 | |
| 50 if(MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX < _numberOfSocketMgr) | |
| 51 { | |
| 52 _numberOfSocketMgr = MAX_NUMBER_OF_SOCKET_MANAGERS_LINUX; | |
| 53 } | |
| 54 for(int i = 0;i < _numberOfSocketMgr; i++) | |
| 55 { | |
| 56 _socketMgr[i] = new UdpSocketManagerPosixImpl(); | |
| 57 } | |
| 58 return true; | |
| 59 } | |
| 60 | |
| 61 | |
| 62 UdpSocketManagerPosix::~UdpSocketManagerPosix() | |
| 63 { | |
| 64 Stop(); | |
| 65 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 66 "UdpSocketManagerPosix(%d)::UdpSocketManagerPosix()", | |
| 67 _numberOfSocketMgr); | |
| 68 | |
| 69 for(int i = 0;i < _numberOfSocketMgr; i++) | |
| 70 { | |
| 71 delete _socketMgr[i]; | |
| 72 } | |
| 73 delete _critSect; | |
| 74 } | |
| 75 | |
| 76 bool UdpSocketManagerPosix::Start() | |
| 77 { | |
| 78 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 79 "UdpSocketManagerPosix(%d)::Start()", | |
| 80 _numberOfSocketMgr); | |
| 81 | |
| 82 _critSect->Enter(); | |
| 83 bool retVal = true; | |
| 84 for(int i = 0;i < _numberOfSocketMgr && retVal; i++) | |
| 85 { | |
| 86 retVal = _socketMgr[i]->Start(); | |
| 87 } | |
| 88 if(!retVal) | |
| 89 { | |
| 90 WEBRTC_TRACE( | |
| 91 kTraceError, | |
| 92 kTraceTransport, | |
| 93 _id, | |
| 94 "UdpSocketManagerPosix(%d)::Start() error starting socket managers", | |
| 95 _numberOfSocketMgr); | |
| 96 } | |
| 97 _critSect->Leave(); | |
| 98 return retVal; | |
| 99 } | |
| 100 | |
| 101 bool UdpSocketManagerPosix::Stop() | |
| 102 { | |
| 103 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 104 "UdpSocketManagerPosix(%d)::Stop()",_numberOfSocketMgr); | |
| 105 | |
| 106 _critSect->Enter(); | |
| 107 bool retVal = true; | |
| 108 for(int i = 0; i < _numberOfSocketMgr && retVal; i++) | |
| 109 { | |
| 110 retVal = _socketMgr[i]->Stop(); | |
| 111 } | |
| 112 if(!retVal) | |
| 113 { | |
| 114 WEBRTC_TRACE( | |
| 115 kTraceError, | |
| 116 kTraceTransport, | |
| 117 _id, | |
| 118 "UdpSocketManagerPosix(%d)::Stop() there are still active socket " | |
| 119 "managers", | |
| 120 _numberOfSocketMgr); | |
| 121 } | |
| 122 _critSect->Leave(); | |
| 123 return retVal; | |
| 124 } | |
| 125 | |
| 126 bool UdpSocketManagerPosix::AddSocket(UdpSocketWrapper* s) | |
| 127 { | |
| 128 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 129 "UdpSocketManagerPosix(%d)::AddSocket()",_numberOfSocketMgr); | |
| 130 | |
| 131 _critSect->Enter(); | |
| 132 bool retVal = _socketMgr[_nextSocketMgrToAssign]->AddSocket(s); | |
| 133 if(!retVal) | |
| 134 { | |
| 135 WEBRTC_TRACE( | |
| 136 kTraceError, | |
| 137 kTraceTransport, | |
| 138 _id, | |
| 139 "UdpSocketManagerPosix(%d)::AddSocket() failed to add socket to\ | |
| 140 manager", | |
| 141 _numberOfSocketMgr); | |
| 142 } | |
| 143 | |
| 144 // Distribute sockets on UdpSocketManagerPosixImpls in a round-robin | |
| 145 // fashion. | |
| 146 if(_incSocketMgrNextTime == 0) | |
| 147 { | |
| 148 _incSocketMgrNextTime++; | |
| 149 } else { | |
| 150 _incSocketMgrNextTime = 0; | |
| 151 _nextSocketMgrToAssign++; | |
| 152 if(_nextSocketMgrToAssign >= _numberOfSocketMgr) | |
| 153 { | |
| 154 _nextSocketMgrToAssign = 0; | |
| 155 } | |
| 156 } | |
| 157 _critSect->Leave(); | |
| 158 return retVal; | |
| 159 } | |
| 160 | |
| 161 bool UdpSocketManagerPosix::RemoveSocket(UdpSocketWrapper* s) | |
| 162 { | |
| 163 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | |
| 164 "UdpSocketManagerPosix(%d)::RemoveSocket()", | |
| 165 _numberOfSocketMgr); | |
| 166 | |
| 167 _critSect->Enter(); | |
| 168 bool retVal = false; | |
| 169 for(int i = 0;i < _numberOfSocketMgr && (retVal == false); i++) | |
| 170 { | |
| 171 retVal = _socketMgr[i]->RemoveSocket(s); | |
| 172 } | |
| 173 if(!retVal) | |
| 174 { | |
| 175 WEBRTC_TRACE( | |
| 176 kTraceError, | |
| 177 kTraceTransport, | |
| 178 _id, | |
| 179 "UdpSocketManagerPosix(%d)::RemoveSocket() failed to remove socket\ | |
| 180 from manager", | |
| 181 _numberOfSocketMgr); | |
| 182 } | |
| 183 _critSect->Leave(); | |
| 184 return retVal; | |
| 185 } | |
| 186 | |
| 187 UdpSocketManagerPosixImpl::UdpSocketManagerPosixImpl() | |
| 188 : _thread(UdpSocketManagerPosixImpl::Run, | |
| 189 this, | |
| 190 "UdpSocketManagerPosixImplThread"), | |
| 191 _critSectList(CriticalSectionWrapper::CreateCriticalSection()) { | |
| 192 FD_ZERO(&_readFds); | |
| 193 WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1, | |
| 194 "UdpSocketManagerPosix created"); | |
| 195 } | |
| 196 | |
| 197 UdpSocketManagerPosixImpl::~UdpSocketManagerPosixImpl() | |
| 198 { | |
| 199 if (_critSectList != NULL) | |
| 200 { | |
| 201 UpdateSocketMap(); | |
| 202 | |
| 203 _critSectList->Enter(); | |
| 204 for (std::map<SOCKET, UdpSocketPosix*>::iterator it = | |
| 205 _socketMap.begin(); | |
| 206 it != _socketMap.end(); | |
| 207 ++it) { | |
| 208 delete it->second; | |
| 209 } | |
| 210 _socketMap.clear(); | |
| 211 _critSectList->Leave(); | |
| 212 | |
| 213 delete _critSectList; | |
| 214 } | |
| 215 | |
| 216 WEBRTC_TRACE(kTraceMemory, kTraceTransport, -1, | |
| 217 "UdpSocketManagerPosix deleted"); | |
| 218 } | |
| 219 | |
| 220 bool UdpSocketManagerPosixImpl::Start() | |
| 221 { | |
| 222 WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1, | |
| 223 "Start UdpSocketManagerPosix"); | |
| 224 _thread.Start(); | |
| 225 _thread.SetPriority(rtc::kRealtimePriority); | |
| 226 return true; | |
| 227 } | |
| 228 | |
| 229 bool UdpSocketManagerPosixImpl::Stop() | |
| 230 { | |
| 231 WEBRTC_TRACE(kTraceStateInfo, kTraceTransport, -1, | |
| 232 "Stop UdpSocketManagerPosix"); | |
| 233 _thread.Stop(); | |
| 234 return true; | |
| 235 } | |
| 236 | |
| 237 bool UdpSocketManagerPosixImpl::Process() | |
| 238 { | |
| 239 bool doSelect = false; | |
| 240 // Timeout = 1 second. | |
| 241 struct timeval timeout; | |
| 242 timeout.tv_sec = 0; | |
| 243 timeout.tv_usec = 10000; | |
| 244 | |
| 245 FD_ZERO(&_readFds); | |
| 246 | |
| 247 UpdateSocketMap(); | |
| 248 | |
| 249 SOCKET maxFd = 0; | |
| 250 for (std::map<SOCKET, UdpSocketPosix*>::iterator it = _socketMap.begin(); | |
| 251 it != _socketMap.end(); | |
| 252 ++it) { | |
| 253 doSelect = true; | |
| 254 if (it->first > maxFd) | |
| 255 maxFd = it->first; | |
| 256 FD_SET(it->first, &_readFds); | |
| 257 } | |
| 258 | |
| 259 int num = 0; | |
| 260 if (doSelect) | |
| 261 { | |
| 262 num = select(maxFd+1, &_readFds, NULL, NULL, &timeout); | |
| 263 | |
| 264 if (num == SOCKET_ERROR) | |
| 265 { | |
| 266 // Timeout = 10 ms. | |
| 267 SleepMs(10); | |
| 268 return true; | |
| 269 } | |
| 270 }else | |
| 271 { | |
| 272 // Timeout = 10 ms. | |
| 273 SleepMs(10); | |
| 274 return true; | |
| 275 } | |
| 276 | |
| 277 for (std::map<SOCKET, UdpSocketPosix*>::iterator it = _socketMap.begin(); | |
| 278 it != _socketMap.end(); | |
| 279 ++it) { | |
| 280 if (FD_ISSET(it->first, &_readFds)) { | |
| 281 it->second->HasIncoming(); | |
| 282 --num; | |
| 283 } | |
| 284 } | |
| 285 | |
| 286 return true; | |
| 287 } | |
| 288 | |
| 289 bool UdpSocketManagerPosixImpl::Run(void* obj) | |
| 290 { | |
| 291 UdpSocketManagerPosixImpl* mgr = | |
| 292 static_cast<UdpSocketManagerPosixImpl*>(obj); | |
| 293 return mgr->Process(); | |
| 294 } | |
| 295 | |
| 296 bool UdpSocketManagerPosixImpl::AddSocket(UdpSocketWrapper* s) | |
| 297 { | |
| 298 UdpSocketPosix* sl = static_cast<UdpSocketPosix*>(s); | |
| 299 if(sl->GetFd() == INVALID_SOCKET || !(sl->GetFd() < FD_SETSIZE)) | |
| 300 { | |
| 301 return false; | |
| 302 } | |
| 303 _critSectList->Enter(); | |
| 304 _addList.push_back(s); | |
| 305 _critSectList->Leave(); | |
| 306 return true; | |
| 307 } | |
| 308 | |
| 309 bool UdpSocketManagerPosixImpl::RemoveSocket(UdpSocketWrapper* s) | |
| 310 { | |
| 311 // Put in remove list if this is the correct UdpSocketManagerPosixImpl. | |
| 312 _critSectList->Enter(); | |
| 313 | |
| 314 // If the socket is in the add list it's safe to remove and delete it. | |
| 315 for (SocketList::iterator iter = _addList.begin(); | |
| 316 iter != _addList.end(); ++iter) { | |
| 317 UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter); | |
| 318 unsigned int addFD = addSocket->GetFd(); | |
| 319 unsigned int removeFD = static_cast<UdpSocketPosix*>(s)->GetFd(); | |
| 320 if(removeFD == addFD) | |
| 321 { | |
| 322 _removeList.push_back(removeFD); | |
| 323 _critSectList->Leave(); | |
| 324 return true; | |
| 325 } | |
| 326 } | |
| 327 | |
| 328 // Checking the socket map is safe since all Erase and Insert calls to this | |
| 329 // map are also protected by _critSectList. | |
| 330 if (_socketMap.find(static_cast<UdpSocketPosix*>(s)->GetFd()) != | |
| 331 _socketMap.end()) { | |
| 332 _removeList.push_back(static_cast<UdpSocketPosix*>(s)->GetFd()); | |
| 333 _critSectList->Leave(); | |
| 334 return true; | |
| 335 } | |
| 336 _critSectList->Leave(); | |
| 337 return false; | |
| 338 } | |
| 339 | |
| 340 void UdpSocketManagerPosixImpl::UpdateSocketMap() | |
| 341 { | |
| 342 // Remove items in remove list. | |
| 343 _critSectList->Enter(); | |
| 344 for (FdList::iterator iter = _removeList.begin(); | |
| 345 iter != _removeList.end(); ++iter) { | |
| 346 UdpSocketPosix* deleteSocket = NULL; | |
| 347 SOCKET removeFD = *iter; | |
| 348 | |
| 349 // If the socket is in the add list it hasn't been added to the socket | |
| 350 // map yet. Just remove the socket from the add list. | |
| 351 for (SocketList::iterator iter = _addList.begin(); | |
| 352 iter != _addList.end(); ++iter) { | |
| 353 UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter); | |
| 354 SOCKET addFD = addSocket->GetFd(); | |
| 355 if(removeFD == addFD) | |
| 356 { | |
| 357 deleteSocket = addSocket; | |
| 358 _addList.erase(iter); | |
| 359 break; | |
| 360 } | |
| 361 } | |
| 362 | |
| 363 // Find and remove socket from _socketMap. | |
| 364 std::map<SOCKET, UdpSocketPosix*>::iterator it = | |
| 365 _socketMap.find(removeFD); | |
| 366 if(it != _socketMap.end()) | |
| 367 { | |
| 368 deleteSocket = it->second; | |
| 369 _socketMap.erase(it); | |
| 370 } | |
| 371 if(deleteSocket) | |
| 372 { | |
| 373 deleteSocket->ReadyForDeletion(); | |
| 374 delete deleteSocket; | |
| 375 } | |
| 376 } | |
| 377 _removeList.clear(); | |
| 378 | |
| 379 // Add sockets from add list. | |
| 380 for (SocketList::iterator iter = _addList.begin(); | |
| 381 iter != _addList.end(); ++iter) { | |
| 382 UdpSocketPosix* s = static_cast<UdpSocketPosix*>(*iter); | |
| 383 if(s) { | |
| 384 _socketMap[s->GetFd()] = s; | |
| 385 } | |
| 386 } | |
| 387 _addList.clear(); | |
| 388 _critSectList->Leave(); | |
| 389 } | |
| 390 | |
| 391 } // namespace test | |
| 392 } // namespace webrtc | |
| OLD | NEW |