OLD | NEW |
| (Empty) |
1 /***************************************************************************** | |
2 Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. | |
3 All rights reserved. | |
4 | |
5 Redistribution and use in source and binary forms, with or without | |
6 modification, are permitted provided that the following conditions are | |
7 met: | |
8 | |
9 * Redistributions of source code must retain the above | |
10 copyright notice, this list of conditions and the | |
11 following disclaimer. | |
12 | |
13 * Redistributions in binary form must reproduce the | |
14 above copyright notice, this list of conditions | |
15 and the following disclaimer in the documentation | |
16 and/or other materials provided with the distribution. | |
17 | |
18 * Neither the name of the University of Illinois | |
19 nor the names of its contributors may be used to | |
20 endorse or promote products derived from this | |
21 software without specific prior written permission. | |
22 | |
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
24 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
25 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
26 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 *****************************************************************************/ | |
35 | |
36 /***************************************************************************** | |
37 written by | |
38 Yunhong Gu, last updated 01/31/2011 | |
39 *****************************************************************************/ | |
40 | |
41 #ifdef WIN32 | |
42 #include <winsock2.h> | |
43 #include <ws2tcpip.h> | |
44 #ifdef LEGACY_WIN32 | |
45 #include <wspiapi.h> | |
46 #endif | |
47 #else | |
48 #include <unistd.h> | |
49 #endif | |
50 #include <cstring> | |
51 #include "api.h" | |
52 #include "core.h" | |
53 | |
54 using namespace std; | |
55 | |
56 CUDTSocket::CUDTSocket(): | |
57 m_Status(INIT), | |
58 m_TimeStamp(0), | |
59 m_iIPversion(0), | |
60 m_pSelfAddr(NULL), | |
61 m_pPeerAddr(NULL), | |
62 m_SocketID(0), | |
63 m_ListenSocket(0), | |
64 m_PeerID(0), | |
65 m_iISN(0), | |
66 m_pUDT(NULL), | |
67 m_pQueuedSockets(NULL), | |
68 m_pAcceptSockets(NULL), | |
69 m_AcceptCond(), | |
70 m_AcceptLock(), | |
71 m_uiBackLog(0), | |
72 m_iMuxID(-1) | |
73 { | |
74 #ifndef WIN32 | |
75 pthread_mutex_init(&m_AcceptLock, NULL); | |
76 pthread_cond_init(&m_AcceptCond, NULL); | |
77 #else | |
78 m_AcceptLock = CreateMutex(NULL, false, NULL); | |
79 m_AcceptCond = CreateEvent(NULL, false, false, NULL); | |
80 #endif | |
81 } | |
82 | |
83 CUDTSocket::~CUDTSocket() | |
84 { | |
85 if (AF_INET == m_iIPversion) | |
86 { | |
87 delete (sockaddr_in*)m_pSelfAddr; | |
88 delete (sockaddr_in*)m_pPeerAddr; | |
89 } | |
90 else | |
91 { | |
92 delete (sockaddr_in6*)m_pSelfAddr; | |
93 delete (sockaddr_in6*)m_pPeerAddr; | |
94 } | |
95 | |
96 delete m_pUDT; | |
97 m_pUDT = NULL; | |
98 | |
99 delete m_pQueuedSockets; | |
100 delete m_pAcceptSockets; | |
101 | |
102 #ifndef WIN32 | |
103 pthread_mutex_destroy(&m_AcceptLock); | |
104 pthread_cond_destroy(&m_AcceptCond); | |
105 #else | |
106 CloseHandle(m_AcceptLock); | |
107 CloseHandle(m_AcceptCond); | |
108 #endif | |
109 } | |
110 | |
111 //////////////////////////////////////////////////////////////////////////////// | |
112 | |
113 CUDTUnited::CUDTUnited(): | |
114 m_Sockets(), | |
115 m_ControlLock(), | |
116 m_IDLock(), | |
117 m_SocketID(0), | |
118 m_TLSError(), | |
119 m_mMultiplexer(), | |
120 m_MultiplexerLock(), | |
121 m_pCache(NULL), | |
122 m_bClosing(false), | |
123 m_GCStopLock(), | |
124 m_GCStopCond(), | |
125 m_InitLock(), | |
126 m_iInstanceCount(0), | |
127 m_bGCStatus(false), | |
128 m_GCThread(), | |
129 m_ClosedSockets() | |
130 { | |
131 // Socket ID MUST start from a random value | |
132 srand((unsigned int)CTimer::getTime()); | |
133 m_SocketID = 1 + (int)((1 << 30) * (double(rand()) / RAND_MAX)); | |
134 | |
135 #ifndef WIN32 | |
136 pthread_mutex_init(&m_ControlLock, NULL); | |
137 pthread_mutex_init(&m_IDLock, NULL); | |
138 pthread_mutex_init(&m_InitLock, NULL); | |
139 #else | |
140 m_ControlLock = CreateMutex(NULL, false, NULL); | |
141 m_IDLock = CreateMutex(NULL, false, NULL); | |
142 m_InitLock = CreateMutex(NULL, false, NULL); | |
143 #endif | |
144 | |
145 #ifndef WIN32 | |
146 pthread_key_create(&m_TLSError, TLSDestroy); | |
147 #else | |
148 m_TLSError = TlsAlloc(); | |
149 m_TLSLock = CreateMutex(NULL, false, NULL); | |
150 #endif | |
151 | |
152 m_pCache = new CCache; | |
153 } | |
154 | |
155 CUDTUnited::~CUDTUnited() | |
156 { | |
157 #ifndef WIN32 | |
158 pthread_mutex_destroy(&m_ControlLock); | |
159 pthread_mutex_destroy(&m_IDLock); | |
160 pthread_mutex_destroy(&m_InitLock); | |
161 #else | |
162 CloseHandle(m_ControlLock); | |
163 CloseHandle(m_IDLock); | |
164 CloseHandle(m_InitLock); | |
165 #endif | |
166 | |
167 #ifndef WIN32 | |
168 pthread_key_delete(m_TLSError); | |
169 #else | |
170 TlsFree(m_TLSError); | |
171 CloseHandle(m_TLSLock); | |
172 #endif | |
173 | |
174 delete m_pCache; | |
175 } | |
176 | |
177 int CUDTUnited::startup() | |
178 { | |
179 CGuard gcinit(m_InitLock); | |
180 | |
181 if (m_iInstanceCount++ > 0) | |
182 return 0; | |
183 | |
184 // Global initialization code | |
185 #ifdef WIN32 | |
186 WORD wVersionRequested; | |
187 WSADATA wsaData; | |
188 wVersionRequested = MAKEWORD(2, 2); | |
189 | |
190 if (0 != WSAStartup(wVersionRequested, &wsaData)) | |
191 throw CUDTException(1, 0, WSAGetLastError()); | |
192 #endif | |
193 | |
194 //init CTimer::EventLock | |
195 | |
196 if (m_bGCStatus) | |
197 return true; | |
198 | |
199 m_bClosing = false; | |
200 #ifndef WIN32 | |
201 pthread_mutex_init(&m_GCStopLock, NULL); | |
202 pthread_cond_init(&m_GCStopCond, NULL); | |
203 pthread_create(&m_GCThread, NULL, garbageCollect, this); | |
204 #else | |
205 m_GCStopLock = CreateMutex(NULL, false, NULL); | |
206 m_GCStopCond = CreateEvent(NULL, false, false, NULL); | |
207 DWORD ThreadID; | |
208 m_GCThread = CreateThread(NULL, 0, garbageCollect, this, 0, &ThreadID); | |
209 #endif | |
210 | |
211 m_bGCStatus = true; | |
212 | |
213 return 0; | |
214 } | |
215 | |
216 int CUDTUnited::cleanup() | |
217 { | |
218 CGuard gcinit(m_InitLock); | |
219 | |
220 if (--m_iInstanceCount > 0) | |
221 return 0; | |
222 | |
223 //destroy CTimer::EventLock | |
224 | |
225 if (!m_bGCStatus) | |
226 return 0; | |
227 | |
228 m_bClosing = true; | |
229 #ifndef WIN32 | |
230 pthread_cond_signal(&m_GCStopCond); | |
231 pthread_join(m_GCThread, NULL); | |
232 pthread_mutex_destroy(&m_GCStopLock); | |
233 pthread_cond_destroy(&m_GCStopCond); | |
234 #else | |
235 SetEvent(m_GCStopCond); | |
236 WaitForSingleObject(m_GCThread, INFINITE); | |
237 CloseHandle(m_GCThread); | |
238 CloseHandle(m_GCStopLock); | |
239 CloseHandle(m_GCStopCond); | |
240 #endif | |
241 | |
242 m_bGCStatus = false; | |
243 | |
244 // Global destruction code | |
245 #ifdef WIN32 | |
246 WSACleanup(); | |
247 #endif | |
248 | |
249 return 0; | |
250 } | |
251 | |
252 UDTSOCKET CUDTUnited::newSocket(const int& af, const int& type) | |
253 { | |
254 if ((type != SOCK_STREAM) && (type != SOCK_DGRAM)) | |
255 throw CUDTException(5, 3, 0); | |
256 | |
257 CUDTSocket* ns = NULL; | |
258 | |
259 try | |
260 { | |
261 ns = new CUDTSocket; | |
262 ns->m_pUDT = new CUDT; | |
263 if (AF_INET == af) | |
264 { | |
265 ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in); | |
266 ((sockaddr_in*)(ns->m_pSelfAddr))->sin_port = 0; | |
267 } | |
268 else | |
269 { | |
270 ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in6); | |
271 ((sockaddr_in6*)(ns->m_pSelfAddr))->sin6_port = 0; | |
272 } | |
273 } | |
274 catch (...) | |
275 { | |
276 delete ns; | |
277 throw CUDTException(3, 2, 0); | |
278 } | |
279 | |
280 CGuard::enterCS(m_IDLock); | |
281 ns->m_SocketID = -- m_SocketID; | |
282 CGuard::leaveCS(m_IDLock); | |
283 | |
284 ns->m_Status = INIT; | |
285 ns->m_ListenSocket = 0; | |
286 ns->m_pUDT->m_SocketID = ns->m_SocketID; | |
287 ns->m_pUDT->m_iSockType = (SOCK_STREAM == type) ? UDT_STREAM : UDT_DGRAM; | |
288 ns->m_pUDT->m_iIPversion = ns->m_iIPversion = af; | |
289 ns->m_pUDT->m_pCache = m_pCache; | |
290 | |
291 // protect the m_Sockets structure. | |
292 CGuard::enterCS(m_ControlLock); | |
293 try | |
294 { | |
295 m_Sockets[ns->m_SocketID] = ns; | |
296 } | |
297 catch (...) | |
298 { | |
299 //failure and rollback | |
300 delete ns; | |
301 ns = NULL; | |
302 } | |
303 CGuard::leaveCS(m_ControlLock); | |
304 | |
305 if (NULL == ns) | |
306 throw CUDTException(3, 2, 0); | |
307 | |
308 return ns->m_SocketID; | |
309 } | |
310 | |
311 int CUDTUnited::newConnection(const UDTSOCKET listen, const sockaddr* peer, CHan
dShake* hs) | |
312 { | |
313 CUDTSocket* ns = NULL; | |
314 CUDTSocket* ls = locate(listen); | |
315 | |
316 if (NULL == ls) | |
317 return -1; | |
318 | |
319 // if this connection has already been processed | |
320 if (NULL != (ns = locate(peer, hs->m_iID, hs->m_iISN))) | |
321 { | |
322 if (ns->m_pUDT->m_bBroken) | |
323 { | |
324 // last connection from the "peer" address has been broken | |
325 ns->m_Status = CLOSED; | |
326 ns->m_TimeStamp = CTimer::getTime(); | |
327 | |
328 CGuard::enterCS(ls->m_AcceptLock); | |
329 ls->m_pQueuedSockets->erase(ns->m_SocketID); | |
330 ls->m_pAcceptSockets->erase(ns->m_SocketID); | |
331 CGuard::leaveCS(ls->m_AcceptLock); | |
332 } | |
333 else | |
334 { | |
335 // connection already exist, this is a repeated connection request | |
336 // respond with existing HS information | |
337 | |
338 hs->m_iISN = ns->m_pUDT->m_iISN; | |
339 hs->m_iMSS = ns->m_pUDT->m_iMSS; | |
340 hs->m_iFlightFlagSize = ns->m_pUDT->m_iFlightFlagSize; | |
341 hs->m_iReqType = -1; | |
342 hs->m_iID = ns->m_SocketID; | |
343 | |
344 return 0; | |
345 | |
346 //except for this situation a new connection should be started | |
347 } | |
348 } | |
349 | |
350 // exceeding backlog, refuse the connection request | |
351 if (ls->m_pQueuedSockets->size() >= ls->m_uiBackLog) | |
352 return -1; | |
353 | |
354 try | |
355 { | |
356 ns = new CUDTSocket; | |
357 ns->m_pUDT = new CUDT(*(ls->m_pUDT)); | |
358 if (AF_INET == ls->m_iIPversion) | |
359 { | |
360 ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in); | |
361 ((sockaddr_in*)(ns->m_pSelfAddr))->sin_port = 0; | |
362 ns->m_pPeerAddr = (sockaddr*)(new sockaddr_in); | |
363 memcpy(ns->m_pPeerAddr, peer, sizeof(sockaddr_in)); | |
364 } | |
365 else | |
366 { | |
367 ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in6); | |
368 ((sockaddr_in6*)(ns->m_pSelfAddr))->sin6_port = 0; | |
369 ns->m_pPeerAddr = (sockaddr*)(new sockaddr_in6); | |
370 memcpy(ns->m_pPeerAddr, peer, sizeof(sockaddr_in6)); | |
371 } | |
372 } | |
373 catch (...) | |
374 { | |
375 delete ns; | |
376 return -1; | |
377 } | |
378 | |
379 CGuard::enterCS(m_IDLock); | |
380 ns->m_SocketID = -- m_SocketID; | |
381 CGuard::leaveCS(m_IDLock); | |
382 | |
383 ns->m_ListenSocket = listen; | |
384 ns->m_iIPversion = ls->m_iIPversion; | |
385 ns->m_pUDT->m_SocketID = ns->m_SocketID; | |
386 ns->m_PeerID = hs->m_iID; | |
387 ns->m_iISN = hs->m_iISN; | |
388 | |
389 int error = 0; | |
390 | |
391 try | |
392 { | |
393 // bind to the same addr of listening socket | |
394 ns->m_pUDT->open(); | |
395 updateMux(ns, ls); | |
396 ns->m_pUDT->connect(peer, hs); | |
397 } | |
398 catch (...) | |
399 { | |
400 error = 1; | |
401 goto ERR_ROLLBACK; | |
402 } | |
403 | |
404 ns->m_Status = CONNECTED; | |
405 | |
406 // copy address information of local node | |
407 ns->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(ns->m_pSelfAddr); | |
408 CIPAddress::pton(ns->m_pSelfAddr, ns->m_pUDT->m_piSelfIP, ns->m_iIPversion); | |
409 | |
410 // protect the m_Sockets structure. | |
411 CGuard::enterCS(m_ControlLock); | |
412 try | |
413 { | |
414 m_Sockets[ns->m_SocketID] = ns; | |
415 m_PeerRec[(ns->m_PeerID << 30) + ns->m_iISN].insert(ns->m_SocketID); | |
416 } | |
417 catch (...) | |
418 { | |
419 error = 2; | |
420 } | |
421 CGuard::leaveCS(m_ControlLock); | |
422 | |
423 CGuard::enterCS(ls->m_AcceptLock); | |
424 try | |
425 { | |
426 ls->m_pQueuedSockets->insert(ns->m_SocketID); | |
427 } | |
428 catch (...) | |
429 { | |
430 error = 3; | |
431 } | |
432 CGuard::leaveCS(ls->m_AcceptLock); | |
433 | |
434 CTimer::triggerEvent(); | |
435 | |
436 ERR_ROLLBACK: | |
437 if (error > 0) | |
438 { | |
439 ns->m_pUDT->close(); | |
440 ns->m_Status = CLOSED; | |
441 ns->m_TimeStamp = CTimer::getTime(); | |
442 | |
443 return -1; | |
444 } | |
445 | |
446 // wake up a waiting accept() call | |
447 #ifndef WIN32 | |
448 pthread_mutex_lock(&(ls->m_AcceptLock)); | |
449 pthread_cond_signal(&(ls->m_AcceptCond)); | |
450 pthread_mutex_unlock(&(ls->m_AcceptLock)); | |
451 #else | |
452 SetEvent(ls->m_AcceptCond); | |
453 #endif | |
454 | |
455 return 1; | |
456 } | |
457 | |
458 CUDT* CUDTUnited::lookup(const UDTSOCKET u) | |
459 { | |
460 // protects the m_Sockets structure | |
461 CGuard cg(m_ControlLock); | |
462 | |
463 map<UDTSOCKET, CUDTSocket*>::iterator i = m_Sockets.find(u); | |
464 | |
465 if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED)) | |
466 throw CUDTException(5, 4, 0); | |
467 | |
468 return i->second->m_pUDT; | |
469 } | |
470 | |
471 UDTSTATUS CUDTUnited::getStatus(const UDTSOCKET u) | |
472 { | |
473 // protects the m_Sockets structure | |
474 CGuard cg(m_ControlLock); | |
475 | |
476 map<UDTSOCKET, CUDTSocket*>::iterator i = m_Sockets.find(u); | |
477 | |
478 if (i == m_Sockets.end()) | |
479 { | |
480 if (m_ClosedSockets.find(u) != m_ClosedSockets.end()) | |
481 return CLOSED; | |
482 | |
483 return NONEXIST; | |
484 } | |
485 | |
486 if (i->second->m_pUDT->m_bBroken) | |
487 return BROKEN; | |
488 | |
489 return i->second->m_Status; | |
490 } | |
491 | |
492 int CUDTUnited::bind(const UDTSOCKET u, const sockaddr* name, const int& namelen
) | |
493 { | |
494 CUDTSocket* s = locate(u); | |
495 | |
496 if (NULL == s) | |
497 throw CUDTException(5, 4, 0); | |
498 | |
499 // cannot bind a socket more than once | |
500 if (INIT != s->m_Status) | |
501 throw CUDTException(5, 0, 0); | |
502 | |
503 // check the size of SOCKADDR structure | |
504 if (AF_INET == s->m_iIPversion) | |
505 { | |
506 if (namelen != sizeof(sockaddr_in)) | |
507 throw CUDTException(5, 3, 0); | |
508 } | |
509 else | |
510 { | |
511 if (namelen != sizeof(sockaddr_in6)) | |
512 throw CUDTException(5, 3, 0); | |
513 } | |
514 | |
515 s->m_pUDT->open(); | |
516 updateMux(s, name); | |
517 s->m_Status = OPENED; | |
518 | |
519 // copy address information of local node | |
520 s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr); | |
521 | |
522 return 0; | |
523 } | |
524 | |
525 int CUDTUnited::bind(UDTSOCKET u, UDPSOCKET udpsock) | |
526 { | |
527 CUDTSocket* s = locate(u); | |
528 | |
529 if (NULL == s) | |
530 throw CUDTException(5, 4, 0); | |
531 | |
532 // cannot bind a socket more than once | |
533 if (INIT != s->m_Status) | |
534 throw CUDTException(5, 0, 0); | |
535 | |
536 sockaddr_in name4; | |
537 sockaddr_in6 name6; | |
538 sockaddr* name; | |
539 socklen_t namelen; | |
540 | |
541 if (AF_INET == s->m_iIPversion) | |
542 { | |
543 namelen = sizeof(sockaddr_in); | |
544 name = (sockaddr*)&name4; | |
545 } | |
546 else | |
547 { | |
548 namelen = sizeof(sockaddr_in6); | |
549 name = (sockaddr*)&name6; | |
550 } | |
551 | |
552 if (-1 == ::getsockname(udpsock, name, &namelen)) | |
553 throw CUDTException(5, 3); | |
554 | |
555 s->m_pUDT->open(); | |
556 updateMux(s, name, &udpsock); | |
557 s->m_Status = OPENED; | |
558 | |
559 // copy address information of local node | |
560 s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr); | |
561 | |
562 return 0; | |
563 } | |
564 | |
565 int CUDTUnited::listen(const UDTSOCKET u, const int& backlog) | |
566 { | |
567 CUDTSocket* s = locate(u); | |
568 | |
569 if (NULL == s) | |
570 throw CUDTException(5, 4, 0); | |
571 | |
572 // do nothing if the socket is already listening | |
573 if (LISTENING == s->m_Status) | |
574 return 0; | |
575 | |
576 // a socket can listen only if is in OPENED status | |
577 if (OPENED != s->m_Status) | |
578 throw CUDTException(5, 5, 0); | |
579 | |
580 // listen is not supported in rendezvous connection setup | |
581 if (s->m_pUDT->m_bRendezvous) | |
582 throw CUDTException(5, 7, 0); | |
583 | |
584 if (backlog <= 0) | |
585 throw CUDTException(5, 3, 0); | |
586 | |
587 s->m_uiBackLog = backlog; | |
588 | |
589 try | |
590 { | |
591 s->m_pQueuedSockets = new set<UDTSOCKET>; | |
592 s->m_pAcceptSockets = new set<UDTSOCKET>; | |
593 } | |
594 catch (...) | |
595 { | |
596 delete s->m_pQueuedSockets; | |
597 throw CUDTException(3, 2, 0); | |
598 } | |
599 | |
600 s->m_pUDT->listen(); | |
601 | |
602 s->m_Status = LISTENING; | |
603 | |
604 return 0; | |
605 } | |
606 | |
607 UDTSOCKET CUDTUnited::accept(const UDTSOCKET listen, sockaddr* addr, int* addrle
n) | |
608 { | |
609 if ((NULL != addr) && (NULL == addrlen)) | |
610 throw CUDTException(5, 3, 0); | |
611 | |
612 CUDTSocket* ls = locate(listen); | |
613 | |
614 if (ls == NULL) | |
615 throw CUDTException(5, 4, 0); | |
616 | |
617 // the "listen" socket must be in LISTENING status | |
618 if (LISTENING != ls->m_Status) | |
619 throw CUDTException(5, 6, 0); | |
620 | |
621 // no "accept" in rendezvous connection setup | |
622 if (ls->m_pUDT->m_bRendezvous) | |
623 throw CUDTException(5, 7, 0); | |
624 | |
625 UDTSOCKET u = CUDT::INVALID_SOCK; | |
626 bool accepted = false; | |
627 | |
628 // !!only one conection can be set up each time!! | |
629 #ifndef WIN32 | |
630 while (!accepted) | |
631 { | |
632 pthread_mutex_lock(&(ls->m_AcceptLock)); | |
633 | |
634 if (ls->m_pQueuedSockets->size() > 0) | |
635 { | |
636 u = *(ls->m_pQueuedSockets->begin()); | |
637 ls->m_pAcceptSockets->insert(ls->m_pAcceptSockets->end(), u); | |
638 ls->m_pQueuedSockets->erase(ls->m_pQueuedSockets->begin()); | |
639 accepted = true; | |
640 } | |
641 else if (!ls->m_pUDT->m_bSynRecving) | |
642 accepted = true; | |
643 else if (LISTENING == ls->m_Status) | |
644 pthread_cond_wait(&(ls->m_AcceptCond), &(ls->m_AcceptLock)); | |
645 | |
646 if ((LISTENING != ls->m_Status) || ls->m_pUDT->m_bBroken) | |
647 accepted = true; | |
648 | |
649 if (ls->m_pQueuedSockets->empty()) | |
650 m_EPoll.disable_read(listen, ls->m_pUDT->m_sPollID); | |
651 | |
652 pthread_mutex_unlock(&(ls->m_AcceptLock)); | |
653 } | |
654 #else | |
655 while (!accepted) | |
656 { | |
657 WaitForSingleObject(ls->m_AcceptLock, INFINITE); | |
658 | |
659 if (ls->m_pQueuedSockets->size() > 0) | |
660 { | |
661 u = *(ls->m_pQueuedSockets->begin()); | |
662 ls->m_pAcceptSockets->insert(ls->m_pAcceptSockets->end(), u); | |
663 ls->m_pQueuedSockets->erase(ls->m_pQueuedSockets->begin()); | |
664 | |
665 accepted = true; | |
666 } | |
667 else if (!ls->m_pUDT->m_bSynRecving) | |
668 accepted = true; | |
669 | |
670 ReleaseMutex(ls->m_AcceptLock); | |
671 | |
672 if (!accepted & (LISTENING == ls->m_Status)) | |
673 WaitForSingleObject(ls->m_AcceptCond, INFINITE); | |
674 | |
675 if ((LISTENING != ls->m_Status) || ls->m_pUDT->m_bBroken) | |
676 { | |
677 SetEvent(ls->m_AcceptCond); | |
678 accepted = true; | |
679 } | |
680 | |
681 if (ls->m_pQueuedSockets->empty()) | |
682 m_EPoll.disable_read(listen, ls->m_pUDT->m_sPollID); | |
683 } | |
684 #endif | |
685 | |
686 if (u == CUDT::INVALID_SOCK) | |
687 { | |
688 // non-blocking receiving, no connection available | |
689 if (!ls->m_pUDT->m_bSynRecving) | |
690 throw CUDTException(6, 2, 0); | |
691 | |
692 // listening socket is closed | |
693 throw CUDTException(5, 6, 0); | |
694 } | |
695 | |
696 if ((addr != NULL) && (addrlen != NULL)) | |
697 { | |
698 if (AF_INET == locate(u)->m_iIPversion) | |
699 *addrlen = sizeof(sockaddr_in); | |
700 else | |
701 *addrlen = sizeof(sockaddr_in6); | |
702 | |
703 // copy address information of peer node | |
704 memcpy(addr, locate(u)->m_pPeerAddr, *addrlen); | |
705 } | |
706 | |
707 return u; | |
708 } | |
709 | |
710 int CUDTUnited::connect(const UDTSOCKET u, const sockaddr* name, const int& name
len) | |
711 { | |
712 CUDTSocket* s = locate(u); | |
713 | |
714 if (NULL == s) | |
715 throw CUDTException(5, 4, 0); | |
716 | |
717 // check the size of SOCKADDR structure | |
718 if (AF_INET == s->m_iIPversion) | |
719 { | |
720 if (namelen != sizeof(sockaddr_in)) | |
721 throw CUDTException(5, 3, 0); | |
722 } | |
723 else | |
724 { | |
725 if (namelen != sizeof(sockaddr_in6)) | |
726 throw CUDTException(5, 3, 0); | |
727 } | |
728 | |
729 // a socket can "connect" only if it is in INIT or OPENED status | |
730 if (INIT == s->m_Status) | |
731 { | |
732 if (!s->m_pUDT->m_bRendezvous) | |
733 { | |
734 s->m_pUDT->open(); | |
735 updateMux(s); | |
736 s->m_Status = OPENED; | |
737 } | |
738 else | |
739 throw CUDTException(5, 8, 0); | |
740 } | |
741 else if (OPENED != s->m_Status) | |
742 throw CUDTException(5, 2, 0); | |
743 | |
744 s->m_pUDT->connect(name); | |
745 s->m_Status = CONNECTED; | |
746 | |
747 // copy address information of local node | |
748 // the local port must be correctly assigned BEFORE CUDT::connect(), | |
749 // otherwise if connect() fails, the multiplexer cannot be located by garbage
collection and will cause leak | |
750 s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr); | |
751 CIPAddress::pton(s->m_pSelfAddr, s->m_pUDT->m_piSelfIP, s->m_iIPversion); | |
752 | |
753 // record peer address | |
754 if (AF_INET == s->m_iIPversion) | |
755 { | |
756 s->m_pPeerAddr = (sockaddr*)(new sockaddr_in); | |
757 memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in)); | |
758 } | |
759 else | |
760 { | |
761 s->m_pPeerAddr = (sockaddr*)(new sockaddr_in6); | |
762 memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in6)); | |
763 } | |
764 | |
765 return 0; | |
766 } | |
767 | |
768 int CUDTUnited::close(const UDTSOCKET u) | |
769 { | |
770 CUDTSocket* s = locate(u); | |
771 | |
772 if (NULL == s) | |
773 throw CUDTException(5, 4, 0); | |
774 | |
775 if (s->m_Status == LISTENING) | |
776 { | |
777 if (s->m_pUDT->m_bBroken) | |
778 return 0; | |
779 | |
780 s->m_TimeStamp = CTimer::getTime(); | |
781 s->m_pUDT->m_bBroken = true; | |
782 | |
783 // broadcast all "accept" waiting | |
784 #ifndef WIN32 | |
785 pthread_mutex_lock(&(s->m_AcceptLock)); | |
786 pthread_cond_broadcast(&(s->m_AcceptCond)); | |
787 pthread_mutex_unlock(&(s->m_AcceptLock)); | |
788 #else | |
789 SetEvent(s->m_AcceptCond); | |
790 #endif | |
791 | |
792 return 0; | |
793 } | |
794 | |
795 s->m_pUDT->close(); | |
796 | |
797 // synchronize with garbage collection. | |
798 CGuard cg(m_ControlLock); | |
799 | |
800 // since "s" is located before m_ControlLock, locate it again in case it beca
me invalid | |
801 map<UDTSOCKET, CUDTSocket*>::iterator i = m_Sockets.find(u); | |
802 if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED)) | |
803 return 0; | |
804 s = i->second; | |
805 | |
806 s->m_Status = CLOSED; | |
807 | |
808 // a socket will not be immediated removed when it is closed | |
809 // in order to prevent other methods from accessing invalid address | |
810 // a timer is started and the socket will be removed after approximately 1 se
cond | |
811 s->m_TimeStamp = CTimer::getTime(); | |
812 | |
813 m_Sockets.erase(s->m_SocketID); | |
814 m_ClosedSockets.insert(pair<UDTSOCKET, CUDTSocket*>(s->m_SocketID, s)); | |
815 | |
816 CTimer::triggerEvent(); | |
817 | |
818 return 0; | |
819 } | |
820 | |
821 int CUDTUnited::getpeername(const UDTSOCKET u, sockaddr* name, int* namelen) | |
822 { | |
823 if (CONNECTED != getStatus(u)) | |
824 throw CUDTException(2, 2, 0); | |
825 | |
826 CUDTSocket* s = locate(u); | |
827 | |
828 if (NULL == s) | |
829 throw CUDTException(5, 4, 0); | |
830 | |
831 if (!s->m_pUDT->m_bConnected || s->m_pUDT->m_bBroken) | |
832 throw CUDTException(2, 2, 0); | |
833 | |
834 if (AF_INET == s->m_iIPversion) | |
835 *namelen = sizeof(sockaddr_in); | |
836 else | |
837 *namelen = sizeof(sockaddr_in6); | |
838 | |
839 // copy address information of peer node | |
840 memcpy(name, s->m_pPeerAddr, *namelen); | |
841 | |
842 return 0; | |
843 } | |
844 | |
845 int CUDTUnited::getsockname(const UDTSOCKET u, sockaddr* name, int* namelen) | |
846 { | |
847 CUDTSocket* s = locate(u); | |
848 | |
849 if (NULL == s) | |
850 throw CUDTException(5, 4, 0); | |
851 | |
852 if (s->m_pUDT->m_bBroken) | |
853 throw CUDTException(5, 4, 0); | |
854 | |
855 if (INIT == s->m_Status) | |
856 throw CUDTException(2, 2, 0); | |
857 | |
858 if (AF_INET == s->m_iIPversion) | |
859 *namelen = sizeof(sockaddr_in); | |
860 else | |
861 *namelen = sizeof(sockaddr_in6); | |
862 | |
863 // copy address information of local node | |
864 memcpy(name, s->m_pSelfAddr, *namelen); | |
865 | |
866 return 0; | |
867 } | |
868 | |
869 int CUDTUnited::select(ud_set* readfds, ud_set* writefds, ud_set* exceptfds, con
st timeval* timeout) | |
870 { | |
871 uint64_t entertime = CTimer::getTime(); | |
872 | |
873 uint64_t to; | |
874 if (NULL == timeout) | |
875 to = 0xFFFFFFFFFFFFFFFFULL; | |
876 else | |
877 to = timeout->tv_sec * 1000000 + timeout->tv_usec; | |
878 | |
879 // initialize results | |
880 int count = 0; | |
881 set<UDTSOCKET> rs, ws, es; | |
882 | |
883 // retrieve related UDT sockets | |
884 vector<CUDTSocket*> ru, wu, eu; | |
885 CUDTSocket* s; | |
886 if (NULL != readfds) | |
887 for (set<UDTSOCKET>::iterator i1 = readfds->begin(); i1 != readfds->end();
++ i1) | |
888 { | |
889 if (BROKEN == getStatus(*i1)) | |
890 { | |
891 rs.insert(*i1); | |
892 ++ count; | |
893 } | |
894 else if (NULL == (s = locate(*i1))) | |
895 throw CUDTException(5, 4, 0); | |
896 else | |
897 ru.insert(ru.end(), s); | |
898 } | |
899 if (NULL != writefds) | |
900 for (set<UDTSOCKET>::iterator i2 = writefds->begin(); i2 != writefds->end(
); ++ i2) | |
901 { | |
902 if (BROKEN == getStatus(*i2)) | |
903 { | |
904 ws.insert(*i2); | |
905 ++ count; | |
906 } | |
907 else if (NULL == (s = locate(*i2))) | |
908 throw CUDTException(5, 4, 0); | |
909 else | |
910 wu.insert(wu.end(), s); | |
911 } | |
912 if (NULL != exceptfds) | |
913 for (set<UDTSOCKET>::iterator i3 = exceptfds->begin(); i3 != exceptfds->en
d(); ++ i3) | |
914 { | |
915 if (BROKEN == getStatus(*i3)) | |
916 { | |
917 es.insert(*i3); | |
918 ++ count; | |
919 } | |
920 else if (NULL == (s = locate(*i3))) | |
921 throw CUDTException(5, 4, 0); | |
922 else | |
923 eu.insert(eu.end(), s); | |
924 } | |
925 | |
926 do | |
927 { | |
928 // query read sockets | |
929 for (vector<CUDTSocket*>::iterator j1 = ru.begin(); j1 != ru.end(); ++ j1) | |
930 { | |
931 s = *j1; | |
932 | |
933 if ((s->m_pUDT->m_bConnected && (s->m_pUDT->m_pRcvBuffer->getRcvDataSiz
e() > 0) && ((s->m_pUDT->m_iSockType == UDT_STREAM) || (s->m_pUDT->m_pRcvBuffer-
>getRcvMsgNum() > 0))) | |
934 || (!s->m_pUDT->m_bListening && (s->m_pUDT->m_bBroken || !s->m_pUDT-
>m_bConnected)) | |
935 || (s->m_pUDT->m_bListening && (s->m_pQueuedSockets->size() > 0)) | |
936 || (s->m_Status == CLOSED)) | |
937 { | |
938 rs.insert(s->m_SocketID); | |
939 ++ count; | |
940 } | |
941 } | |
942 | |
943 // query write sockets | |
944 for (vector<CUDTSocket*>::iterator j2 = wu.begin(); j2 != wu.end(); ++ j2) | |
945 { | |
946 s = *j2; | |
947 | |
948 if ((s->m_pUDT->m_bConnected && (s->m_pUDT->m_pSndBuffer->getCurrBufSiz
e() < s->m_pUDT->m_iSndBufSize)) | |
949 || s->m_pUDT->m_bBroken || !s->m_pUDT->m_bConnected || (s->m_Status
== CLOSED)) | |
950 { | |
951 ws.insert(s->m_SocketID); | |
952 ++ count; | |
953 } | |
954 } | |
955 | |
956 // query exceptions on sockets | |
957 for (vector<CUDTSocket*>::iterator j3 = eu.begin(); j3 != eu.end(); ++ j3) | |
958 { | |
959 // check connection request status, not supported now | |
960 } | |
961 | |
962 if (0 < count) | |
963 break; | |
964 | |
965 CTimer::waitForEvent(); | |
966 } while (to > CTimer::getTime() - entertime); | |
967 | |
968 if (NULL != readfds) | |
969 *readfds = rs; | |
970 | |
971 if (NULL != writefds) | |
972 *writefds = ws; | |
973 | |
974 if (NULL != exceptfds) | |
975 *exceptfds = es; | |
976 | |
977 return count; | |
978 } | |
979 | |
980 int CUDTUnited::selectEx(const vector<UDTSOCKET>& fds, vector<UDTSOCKET>* readfd
s, vector<UDTSOCKET>* writefds, vector<UDTSOCKET>* exceptfds, int64_t msTimeOut) | |
981 { | |
982 uint64_t entertime = CTimer::getTime(); | |
983 | |
984 uint64_t to; | |
985 if (msTimeOut >= 0) | |
986 to = msTimeOut * 1000; | |
987 else | |
988 to = 0xFFFFFFFFFFFFFFFFULL; | |
989 | |
990 // initialize results | |
991 int count = 0; | |
992 if (NULL != readfds) | |
993 readfds->clear(); | |
994 if (NULL != writefds) | |
995 writefds->clear(); | |
996 if (NULL != exceptfds) | |
997 exceptfds->clear(); | |
998 | |
999 do | |
1000 { | |
1001 for (vector<UDTSOCKET>::const_iterator i = fds.begin(); i != fds.end(); ++
i) | |
1002 { | |
1003 CUDTSocket* s = locate(*i); | |
1004 | |
1005 if ((NULL == s) || s->m_pUDT->m_bBroken || (s->m_Status == CLOSED)) | |
1006 { | |
1007 if (NULL != exceptfds) | |
1008 { | |
1009 exceptfds->push_back(*i); | |
1010 ++ count; | |
1011 } | |
1012 continue; | |
1013 } | |
1014 | |
1015 if (NULL != readfds) | |
1016 { | |
1017 if ((s->m_pUDT->m_bConnected && (s->m_pUDT->m_pRcvBuffer->getRcvData
Size() > 0) && ((s->m_pUDT->m_iSockType == UDT_STREAM) || (s->m_pUDT->m_pRcvBuff
er->getRcvMsgNum() > 0))) | |
1018 || (s->m_pUDT->m_bListening && (s->m_pQueuedSockets->size() > 0))
) | |
1019 { | |
1020 readfds->push_back(s->m_SocketID); | |
1021 ++ count; | |
1022 } | |
1023 } | |
1024 | |
1025 if (NULL != writefds) | |
1026 { | |
1027 if (s->m_pUDT->m_bConnected && (s->m_pUDT->m_pSndBuffer->getCurrBufS
ize() < s->m_pUDT->m_iSndBufSize)) | |
1028 { | |
1029 writefds->push_back(s->m_SocketID); | |
1030 ++ count; | |
1031 } | |
1032 } | |
1033 } | |
1034 | |
1035 if (count > 0) | |
1036 break; | |
1037 | |
1038 CTimer::waitForEvent(); | |
1039 } while (to > CTimer::getTime() - entertime); | |
1040 | |
1041 return count; | |
1042 } | |
1043 | |
1044 int CUDTUnited::epoll_create() | |
1045 { | |
1046 return m_EPoll.create(); | |
1047 } | |
1048 | |
1049 int CUDTUnited::epoll_add_usock(const int eid, const UDTSOCKET u, const int* eve
nts) | |
1050 { | |
1051 CUDTSocket* s = locate(u); | |
1052 if (NULL != s) | |
1053 { | |
1054 s->m_pUDT->addEPoll(eid); | |
1055 } | |
1056 else | |
1057 { | |
1058 throw CUDTException(5, 4); | |
1059 } | |
1060 | |
1061 return m_EPoll.add_usock(eid, u, events); | |
1062 } | |
1063 | |
1064 int CUDTUnited::epoll_add_ssock(const int eid, const SYSSOCKET s, const int* eve
nts) | |
1065 { | |
1066 return m_EPoll.add_ssock(eid, s, events); | |
1067 } | |
1068 | |
1069 int CUDTUnited::epoll_remove_usock(const int eid, const UDTSOCKET u, const int*
events) | |
1070 { | |
1071 CUDTSocket* s = locate(u); | |
1072 if (NULL != s) | |
1073 { | |
1074 s->m_pUDT->removeEPoll(eid); | |
1075 } | |
1076 else | |
1077 { | |
1078 throw CUDTException(5, 4); | |
1079 } | |
1080 | |
1081 return m_EPoll.remove_usock(eid, u, events); | |
1082 } | |
1083 | |
1084 int CUDTUnited::epoll_remove_ssock(const int eid, const SYSSOCKET s, const int*
events) | |
1085 { | |
1086 return m_EPoll.remove_ssock(eid, s, events); | |
1087 } | |
1088 | |
1089 int CUDTUnited::epoll_wait(const int eid, set<UDTSOCKET>* readfds, set<UDTSOCKET
>* writefds, int64_t msTimeOut, set<SYSSOCKET>* lrfds, set<SYSSOCKET>* lwfds) | |
1090 { | |
1091 return m_EPoll.wait(eid, readfds, writefds, msTimeOut, lrfds, lwfds); | |
1092 } | |
1093 | |
1094 int CUDTUnited::epoll_release(const int eid) | |
1095 { | |
1096 return m_EPoll.release(eid); | |
1097 } | |
1098 | |
1099 CUDTSocket* CUDTUnited::locate(const UDTSOCKET u) | |
1100 { | |
1101 CGuard cg(m_ControlLock); | |
1102 | |
1103 map<UDTSOCKET, CUDTSocket*>::iterator i = m_Sockets.find(u); | |
1104 | |
1105 if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED)) | |
1106 return NULL; | |
1107 | |
1108 return i->second; | |
1109 } | |
1110 | |
1111 CUDTSocket* CUDTUnited::locate(const sockaddr* peer, const UDTSOCKET& id, const
int32_t& isn) | |
1112 { | |
1113 CGuard cg(m_ControlLock); | |
1114 | |
1115 map<int64_t, set<UDTSOCKET> >::iterator i = m_PeerRec.find((id << 30) + isn); | |
1116 if (i == m_PeerRec.end()) | |
1117 return NULL; | |
1118 | |
1119 for (set<UDTSOCKET>::iterator j = i->second.begin(); j != i->second.end(); ++
j) | |
1120 { | |
1121 map<UDTSOCKET, CUDTSocket*>::iterator k = m_Sockets.find(*j); | |
1122 // this socket might have been closed and moved m_ClosedSockets | |
1123 if (k == m_Sockets.end()) | |
1124 continue; | |
1125 | |
1126 if (CIPAddress::ipcmp(peer, k->second->m_pPeerAddr, k->second->m_iIPversio
n)) | |
1127 return k->second; | |
1128 } | |
1129 | |
1130 return NULL; | |
1131 } | |
1132 | |
1133 void CUDTUnited::checkBrokenSockets() | |
1134 { | |
1135 CGuard cg(m_ControlLock); | |
1136 | |
1137 // set of sockets To Be Closed and To Be Removed | |
1138 vector<UDTSOCKET> tbc; | |
1139 vector<UDTSOCKET> tbr; | |
1140 | |
1141 for (map<UDTSOCKET, CUDTSocket*>::iterator i = m_Sockets.begin(); i != m_Sock
ets.end(); ++ i) | |
1142 { | |
1143 // check broken connection | |
1144 if (i->second->m_pUDT->m_bBroken) | |
1145 { | |
1146 if (i->second->m_Status == LISTENING) | |
1147 { | |
1148 // for a listening socket, it should wait an extra 3 seconds in case
a client is connecting | |
1149 if (CTimer::getTime() - i->second->m_TimeStamp < 3000000) | |
1150 continue; | |
1151 } | |
1152 else if ((i->second->m_pUDT->m_pRcvBuffer->getRcvDataSize() > 0) && (i-
>second->m_pUDT->m_iBrokenCounter -- > 0)) | |
1153 { | |
1154 // if there is still data in the receiver buffer, wait longer | |
1155 continue; | |
1156 } | |
1157 | |
1158 //close broken connections and start removal timer | |
1159 i->second->m_Status = CLOSED; | |
1160 i->second->m_TimeStamp = CTimer::getTime(); | |
1161 tbc.push_back(i->first); | |
1162 m_ClosedSockets[i->first] = i->second; | |
1163 | |
1164 // remove from listener's queue | |
1165 map<UDTSOCKET, CUDTSocket*>::iterator ls = m_Sockets.find(i->second->m_
ListenSocket); | |
1166 if (ls == m_Sockets.end()) | |
1167 { | |
1168 ls = m_ClosedSockets.find(i->second->m_ListenSocket); | |
1169 if (ls == m_ClosedSockets.end()) | |
1170 continue; | |
1171 } | |
1172 | |
1173 CGuard::enterCS(ls->second->m_AcceptLock); | |
1174 ls->second->m_pQueuedSockets->erase(i->second->m_SocketID); | |
1175 ls->second->m_pAcceptSockets->erase(i->second->m_SocketID); | |
1176 CGuard::leaveCS(ls->second->m_AcceptLock); | |
1177 } | |
1178 } | |
1179 | |
1180 for (map<UDTSOCKET, CUDTSocket*>::iterator j = m_ClosedSockets.begin(); j !=
m_ClosedSockets.end(); ++ j) | |
1181 { | |
1182 // timeout 1 second to destroy a socket AND it has been removed from RcvUL
ist AND no linger data to send | |
1183 if ((CTimer::getTime() - j->second->m_TimeStamp > 1000000) && | |
1184 ((NULL == j->second->m_pUDT->m_pRNode) || !j->second->m_pUDT->m_pRNode
->m_bOnList) && | |
1185 ((NULL == j->second->m_pUDT->m_pSndBuffer) || (0 == j->second->m_pUDT-
>m_pSndBuffer->getCurrBufSize()) || (j->second->m_pUDT->m_ullLingerExpiration <=
CTimer::getTime()))) | |
1186 { | |
1187 tbr.push_back(j->first); | |
1188 } | |
1189 } | |
1190 | |
1191 // move closed sockets to the ClosedSockets structure | |
1192 for (vector<UDTSOCKET>::iterator k = tbc.begin(); k != tbc.end(); ++ k) | |
1193 m_Sockets.erase(*k); | |
1194 | |
1195 // remove those timeout sockets | |
1196 for (vector<UDTSOCKET>::iterator l = tbr.begin(); l != tbr.end(); ++ l) | |
1197 removeSocket(*l); | |
1198 } | |
1199 | |
1200 void CUDTUnited::removeSocket(const UDTSOCKET u) | |
1201 { | |
1202 map<UDTSOCKET, CUDTSocket*>::iterator i = m_ClosedSockets.find(u); | |
1203 | |
1204 // invalid socket ID | |
1205 if (i == m_ClosedSockets.end()) | |
1206 return; | |
1207 | |
1208 // decrease multiplexer reference count, and remove it if necessary | |
1209 const int mid = i->second->m_iMuxID; | |
1210 | |
1211 if (NULL != i->second->m_pQueuedSockets) | |
1212 { | |
1213 CGuard::enterCS(i->second->m_AcceptLock); | |
1214 | |
1215 // if it is a listener, close all un-accepted sockets in its queue and rem
ove them later | |
1216 for (set<UDTSOCKET>::iterator q = i->second->m_pQueuedSockets->begin(); q
!= i->second->m_pQueuedSockets->end(); ++ q) | |
1217 { | |
1218 m_Sockets[*q]->m_pUDT->m_bBroken = true; | |
1219 m_Sockets[*q]->m_pUDT->close(); | |
1220 m_Sockets[*q]->m_TimeStamp = CTimer::getTime(); | |
1221 m_Sockets[*q]->m_Status = CLOSED; | |
1222 m_ClosedSockets[*q] = m_Sockets[*q]; | |
1223 m_Sockets.erase(*q); | |
1224 } | |
1225 | |
1226 CGuard::leaveCS(i->second->m_AcceptLock); | |
1227 } | |
1228 | |
1229 // remove from peer rec | |
1230 map<int64_t, set<UDTSOCKET> >::iterator j = m_PeerRec.find((i->second->m_Peer
ID << 30) + i->second->m_iISN); | |
1231 if (j != m_PeerRec.end()) | |
1232 { | |
1233 j->second.erase(u); | |
1234 if (j->second.empty()) | |
1235 m_PeerRec.erase(j); | |
1236 } | |
1237 | |
1238 // delete this one | |
1239 i->second->m_pUDT->close(); | |
1240 delete i->second; | |
1241 m_ClosedSockets.erase(i); | |
1242 | |
1243 map<int, CMultiplexer>::iterator m; | |
1244 m = m_mMultiplexer.find(mid); | |
1245 if (m == m_mMultiplexer.end()) | |
1246 { | |
1247 //something is wrong!!! | |
1248 return; | |
1249 } | |
1250 | |
1251 m->second.m_iRefCount --; | |
1252 if (0 == m->second.m_iRefCount) | |
1253 { | |
1254 m->second.m_pChannel->close(); | |
1255 delete m->second.m_pSndQueue; | |
1256 delete m->second.m_pRcvQueue; | |
1257 delete m->second.m_pTimer; | |
1258 delete m->second.m_pChannel; | |
1259 m_mMultiplexer.erase(m); | |
1260 } | |
1261 } | |
1262 | |
1263 void CUDTUnited::setError(CUDTException* e) | |
1264 { | |
1265 #ifndef WIN32 | |
1266 delete (CUDTException*)pthread_getspecific(m_TLSError); | |
1267 pthread_setspecific(m_TLSError, e); | |
1268 #else | |
1269 CGuard tg(m_TLSLock); | |
1270 delete (CUDTException*)TlsGetValue(m_TLSError); | |
1271 TlsSetValue(m_TLSError, e); | |
1272 m_mTLSRecord[GetCurrentThreadId()] = e; | |
1273 #endif | |
1274 } | |
1275 | |
1276 CUDTException* CUDTUnited::getError() | |
1277 { | |
1278 #ifndef WIN32 | |
1279 if(NULL == pthread_getspecific(m_TLSError)) | |
1280 pthread_setspecific(m_TLSError, new CUDTException); | |
1281 return (CUDTException*)pthread_getspecific(m_TLSError); | |
1282 #else | |
1283 CGuard tg(m_TLSLock); | |
1284 if(NULL == TlsGetValue(m_TLSError)) | |
1285 { | |
1286 CUDTException* e = new CUDTException; | |
1287 TlsSetValue(m_TLSError, e); | |
1288 m_mTLSRecord[GetCurrentThreadId()] = e; | |
1289 } | |
1290 return (CUDTException*)TlsGetValue(m_TLSError); | |
1291 #endif | |
1292 } | |
1293 | |
1294 #ifdef WIN32 | |
1295 void CUDTUnited::checkTLSValue() | |
1296 { | |
1297 CGuard tg(m_TLSLock); | |
1298 | |
1299 vector<DWORD> tbr; | |
1300 for (map<DWORD, CUDTException*>::iterator i = m_mTLSRecord.begin(); i != m_mT
LSRecord.end(); ++ i) | |
1301 { | |
1302 HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, i->first); | |
1303 if (NULL == h) | |
1304 { | |
1305 tbr.insert(tbr.end(), i->first); | |
1306 break; | |
1307 } | |
1308 if (WAIT_OBJECT_0 == WaitForSingleObject(h, 0)) | |
1309 { | |
1310 delete i->second; | |
1311 tbr.insert(tbr.end(), i->first); | |
1312 } | |
1313 CloseHandle(h); | |
1314 } | |
1315 for (vector<DWORD>::iterator j = tbr.begin(); j != tbr.end(); ++ j) | |
1316 m_mTLSRecord.erase(*j); | |
1317 } | |
1318 #endif | |
1319 | |
1320 void CUDTUnited::updateMux(CUDTSocket* s, const sockaddr* addr, const UDPSOCKET*
udpsock) | |
1321 { | |
1322 CGuard cg(m_ControlLock); | |
1323 | |
1324 if ((s->m_pUDT->m_bReuseAddr) && (NULL != addr)) | |
1325 { | |
1326 int port = (AF_INET == s->m_pUDT->m_iIPversion) ? ntohs(((sockaddr_in*)add
r)->sin_port) : ntohs(((sockaddr_in6*)addr)->sin6_port); | |
1327 | |
1328 // find a reusable address | |
1329 for (map<int, CMultiplexer>::iterator i = m_mMultiplexer.begin(); i != m_m
Multiplexer.end(); ++ i) | |
1330 { | |
1331 if ((i->second.m_iIPversion == s->m_pUDT->m_iIPversion) && (i->second.m
_iMSS == s->m_pUDT->m_iMSS) && i->second.m_bReusable) | |
1332 { | |
1333 if (i->second.m_iPort == port) | |
1334 { | |
1335 // reuse the existing multiplexer | |
1336 ++ i->second.m_iRefCount; | |
1337 s->m_pUDT->m_pSndQueue = i->second.m_pSndQueue; | |
1338 s->m_pUDT->m_pRcvQueue = i->second.m_pRcvQueue; | |
1339 s->m_iMuxID = i->second.m_iID; | |
1340 return; | |
1341 } | |
1342 } | |
1343 } | |
1344 } | |
1345 | |
1346 // a new multiplexer is needed | |
1347 CMultiplexer m; | |
1348 m.m_iMSS = s->m_pUDT->m_iMSS; | |
1349 m.m_iIPversion = s->m_pUDT->m_iIPversion; | |
1350 m.m_iRefCount = 1; | |
1351 m.m_bReusable = s->m_pUDT->m_bReuseAddr; | |
1352 m.m_iID = s->m_SocketID; | |
1353 | |
1354 m.m_pChannel = new CChannel(s->m_pUDT->m_iIPversion); | |
1355 m.m_pChannel->setSndBufSize(s->m_pUDT->m_iUDPSndBufSize); | |
1356 m.m_pChannel->setRcvBufSize(s->m_pUDT->m_iUDPRcvBufSize); | |
1357 | |
1358 try | |
1359 { | |
1360 if (NULL != udpsock) | |
1361 m.m_pChannel->open(*udpsock); | |
1362 else | |
1363 m.m_pChannel->open(addr); | |
1364 } | |
1365 catch (CUDTException& e) | |
1366 { | |
1367 m.m_pChannel->close(); | |
1368 delete m.m_pChannel; | |
1369 throw e; | |
1370 } | |
1371 | |
1372 sockaddr* sa = (AF_INET == s->m_pUDT->m_iIPversion) ? (sockaddr*) new sockadd
r_in : (sockaddr*) new sockaddr_in6; | |
1373 m.m_pChannel->getSockAddr(sa); | |
1374 m.m_iPort = (AF_INET == s->m_pUDT->m_iIPversion) ? ntohs(((sockaddr_in*)sa)->
sin_port) : ntohs(((sockaddr_in6*)sa)->sin6_port); | |
1375 if (AF_INET == s->m_pUDT->m_iIPversion) delete (sockaddr_in*)sa; else delete
(sockaddr_in6*)sa; | |
1376 | |
1377 m.m_pTimer = new CTimer; | |
1378 | |
1379 m.m_pSndQueue = new CSndQueue; | |
1380 m.m_pSndQueue->init(m.m_pChannel, m.m_pTimer); | |
1381 m.m_pRcvQueue = new CRcvQueue; | |
1382 m.m_pRcvQueue->init(32, s->m_pUDT->m_iPayloadSize, m.m_iIPversion, 1024, m.m_
pChannel, m.m_pTimer); | |
1383 | |
1384 m_mMultiplexer[m.m_iID] = m; | |
1385 | |
1386 s->m_pUDT->m_pSndQueue = m.m_pSndQueue; | |
1387 s->m_pUDT->m_pRcvQueue = m.m_pRcvQueue; | |
1388 s->m_iMuxID = m.m_iID; | |
1389 } | |
1390 | |
1391 void CUDTUnited::updateMux(CUDTSocket* s, const CUDTSocket* ls) | |
1392 { | |
1393 CGuard cg(m_ControlLock); | |
1394 | |
1395 int port = (AF_INET == ls->m_iIPversion) ? ntohs(((sockaddr_in*)ls->m_pSelfAd
dr)->sin_port) : ntohs(((sockaddr_in6*)ls->m_pSelfAddr)->sin6_port); | |
1396 | |
1397 // find the listener's address | |
1398 for (map<int, CMultiplexer>::iterator i = m_mMultiplexer.begin(); i != m_mMul
tiplexer.end(); ++ i) | |
1399 { | |
1400 if (i->second.m_iPort == port) | |
1401 { | |
1402 // reuse the existing multiplexer | |
1403 ++ i->second.m_iRefCount; | |
1404 s->m_pUDT->m_pSndQueue = i->second.m_pSndQueue; | |
1405 s->m_pUDT->m_pRcvQueue = i->second.m_pRcvQueue; | |
1406 s->m_iMuxID = i->second.m_iID; | |
1407 return; | |
1408 } | |
1409 } | |
1410 } | |
1411 | |
1412 #ifndef WIN32 | |
1413 void* CUDTUnited::garbageCollect(void* p) | |
1414 #else | |
1415 DWORD WINAPI CUDTUnited::garbageCollect(LPVOID p) | |
1416 #endif | |
1417 { | |
1418 CUDTUnited* self = (CUDTUnited*)p; | |
1419 | |
1420 CGuard gcguard(self->m_GCStopLock); | |
1421 | |
1422 while (!self->m_bClosing) | |
1423 { | |
1424 self->checkBrokenSockets(); | |
1425 | |
1426 #ifdef WIN32 | |
1427 self->checkTLSValue(); | |
1428 #endif | |
1429 | |
1430 #ifndef WIN32 | |
1431 timeval now; | |
1432 timespec timeout; | |
1433 gettimeofday(&now, 0); | |
1434 timeout.tv_sec = now.tv_sec + 1; | |
1435 timeout.tv_nsec = now.tv_usec * 1000; | |
1436 | |
1437 pthread_cond_timedwait(&self->m_GCStopCond, &self->m_GCStopLock, &timeo
ut); | |
1438 #else | |
1439 WaitForSingleObject(self->m_GCStopCond, 1000); | |
1440 #endif | |
1441 } | |
1442 | |
1443 // remove all sockets and multiplexers | |
1444 CGuard::enterCS(self->m_ControlLock); | |
1445 for (map<UDTSOCKET, CUDTSocket*>::iterator i = self->m_Sockets.begin(); i !=
self->m_Sockets.end(); ++ i) | |
1446 { | |
1447 i->second->m_pUDT->m_bBroken = true; | |
1448 i->second->m_pUDT->close(); | |
1449 i->second->m_Status = CLOSED; | |
1450 i->second->m_TimeStamp = CTimer::getTime(); | |
1451 self->m_ClosedSockets[i->first] = i->second; | |
1452 | |
1453 // remove from listener's queue | |
1454 map<UDTSOCKET, CUDTSocket*>::iterator ls = self->m_Sockets.find(i->second-
>m_ListenSocket); | |
1455 if (ls == self->m_Sockets.end()) | |
1456 { | |
1457 ls = self->m_ClosedSockets.find(i->second->m_ListenSocket); | |
1458 if (ls == self->m_ClosedSockets.end()) | |
1459 continue; | |
1460 } | |
1461 | |
1462 CGuard::enterCS(ls->second->m_AcceptLock); | |
1463 ls->second->m_pQueuedSockets->erase(i->second->m_SocketID); | |
1464 ls->second->m_pAcceptSockets->erase(i->second->m_SocketID); | |
1465 CGuard::leaveCS(ls->second->m_AcceptLock); | |
1466 } | |
1467 self->m_Sockets.clear(); | |
1468 | |
1469 for (map<UDTSOCKET, CUDTSocket*>::iterator j = self->m_ClosedSockets.begin();
j != self->m_ClosedSockets.end(); ++ j) | |
1470 { | |
1471 j->second->m_TimeStamp = 0; | |
1472 } | |
1473 CGuard::leaveCS(self->m_ControlLock); | |
1474 | |
1475 while (true) | |
1476 { | |
1477 self->checkBrokenSockets(); | |
1478 | |
1479 CGuard::enterCS(self->m_ControlLock); | |
1480 bool empty = self->m_ClosedSockets.empty(); | |
1481 CGuard::leaveCS(self->m_ControlLock); | |
1482 | |
1483 if (empty) | |
1484 break; | |
1485 | |
1486 CTimer::sleep(); | |
1487 } | |
1488 | |
1489 #ifndef WIN32 | |
1490 return NULL; | |
1491 #else | |
1492 return 0; | |
1493 #endif | |
1494 } | |
1495 | |
1496 //////////////////////////////////////////////////////////////////////////////// | |
1497 | |
1498 int CUDT::startup() | |
1499 { | |
1500 return s_UDTUnited.startup(); | |
1501 } | |
1502 | |
1503 int CUDT::cleanup() | |
1504 { | |
1505 return s_UDTUnited.cleanup(); | |
1506 } | |
1507 | |
1508 UDTSOCKET CUDT::socket(int af, int type, int) | |
1509 { | |
1510 if (!s_UDTUnited.m_bGCStatus) | |
1511 s_UDTUnited.startup(); | |
1512 | |
1513 try | |
1514 { | |
1515 return s_UDTUnited.newSocket(af, type); | |
1516 } | |
1517 catch (CUDTException& e) | |
1518 { | |
1519 s_UDTUnited.setError(new CUDTException(e)); | |
1520 return INVALID_SOCK; | |
1521 } | |
1522 catch (bad_alloc&) | |
1523 { | |
1524 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1525 return INVALID_SOCK; | |
1526 } | |
1527 catch (...) | |
1528 { | |
1529 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1530 return INVALID_SOCK; | |
1531 } | |
1532 } | |
1533 | |
1534 int CUDT::bind(UDTSOCKET u, const sockaddr* name, int namelen) | |
1535 { | |
1536 try | |
1537 { | |
1538 return s_UDTUnited.bind(u, name, namelen); | |
1539 } | |
1540 catch (CUDTException& e) | |
1541 { | |
1542 s_UDTUnited.setError(new CUDTException(e)); | |
1543 return ERROR; | |
1544 } | |
1545 catch (bad_alloc&) | |
1546 { | |
1547 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1548 return ERROR; | |
1549 } | |
1550 catch (...) | |
1551 { | |
1552 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1553 return ERROR; | |
1554 } | |
1555 } | |
1556 | |
1557 int CUDT::bind(UDTSOCKET u, UDPSOCKET udpsock) | |
1558 { | |
1559 try | |
1560 { | |
1561 return s_UDTUnited.bind(u, udpsock); | |
1562 } | |
1563 catch (CUDTException& e) | |
1564 { | |
1565 s_UDTUnited.setError(new CUDTException(e)); | |
1566 return ERROR; | |
1567 } | |
1568 catch (bad_alloc&) | |
1569 { | |
1570 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1571 return ERROR; | |
1572 } | |
1573 catch (...) | |
1574 { | |
1575 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1576 return ERROR; | |
1577 } | |
1578 } | |
1579 | |
1580 int CUDT::listen(UDTSOCKET u, int backlog) | |
1581 { | |
1582 try | |
1583 { | |
1584 return s_UDTUnited.listen(u, backlog); | |
1585 } | |
1586 catch (CUDTException& e) | |
1587 { | |
1588 s_UDTUnited.setError(new CUDTException(e)); | |
1589 return ERROR; | |
1590 } | |
1591 catch (bad_alloc&) | |
1592 { | |
1593 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1594 return ERROR; | |
1595 } | |
1596 catch (...) | |
1597 { | |
1598 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1599 return ERROR; | |
1600 } | |
1601 } | |
1602 | |
1603 UDTSOCKET CUDT::accept(UDTSOCKET u, sockaddr* addr, int* addrlen) | |
1604 { | |
1605 try | |
1606 { | |
1607 return s_UDTUnited.accept(u, addr, addrlen); | |
1608 } | |
1609 catch (CUDTException& e) | |
1610 { | |
1611 s_UDTUnited.setError(new CUDTException(e)); | |
1612 return INVALID_SOCK; | |
1613 } | |
1614 catch (...) | |
1615 { | |
1616 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1617 return INVALID_SOCK; | |
1618 } | |
1619 } | |
1620 | |
1621 int CUDT::connect(UDTSOCKET u, const sockaddr* name, int namelen) | |
1622 { | |
1623 try | |
1624 { | |
1625 return s_UDTUnited.connect(u, name, namelen); | |
1626 } | |
1627 catch (CUDTException e) | |
1628 { | |
1629 s_UDTUnited.setError(new CUDTException(e)); | |
1630 return ERROR; | |
1631 } | |
1632 catch (bad_alloc&) | |
1633 { | |
1634 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1635 return ERROR; | |
1636 } | |
1637 catch (...) | |
1638 { | |
1639 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1640 return ERROR; | |
1641 } | |
1642 } | |
1643 | |
1644 int CUDT::close(UDTSOCKET u) | |
1645 { | |
1646 try | |
1647 { | |
1648 return s_UDTUnited.close(u); | |
1649 } | |
1650 catch (CUDTException e) | |
1651 { | |
1652 s_UDTUnited.setError(new CUDTException(e)); | |
1653 return ERROR; | |
1654 } | |
1655 catch (...) | |
1656 { | |
1657 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1658 return ERROR; | |
1659 } | |
1660 } | |
1661 | |
1662 int CUDT::getpeername(UDTSOCKET u, sockaddr* name, int* namelen) | |
1663 { | |
1664 try | |
1665 { | |
1666 return s_UDTUnited.getpeername(u, name, namelen); | |
1667 } | |
1668 catch (CUDTException e) | |
1669 { | |
1670 s_UDTUnited.setError(new CUDTException(e)); | |
1671 return ERROR; | |
1672 } | |
1673 catch (...) | |
1674 { | |
1675 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1676 return ERROR; | |
1677 } | |
1678 } | |
1679 | |
1680 int CUDT::getsockname(UDTSOCKET u, sockaddr* name, int* namelen) | |
1681 { | |
1682 try | |
1683 { | |
1684 return s_UDTUnited.getsockname(u, name, namelen);; | |
1685 } | |
1686 catch (CUDTException e) | |
1687 { | |
1688 s_UDTUnited.setError(new CUDTException(e)); | |
1689 return ERROR; | |
1690 } | |
1691 catch (...) | |
1692 { | |
1693 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1694 return ERROR; | |
1695 } | |
1696 } | |
1697 | |
1698 int CUDT::getsockopt(UDTSOCKET u, int, UDTOpt optname, void* optval, int* optlen
) | |
1699 { | |
1700 try | |
1701 { | |
1702 CUDT* udt = s_UDTUnited.lookup(u); | |
1703 udt->getOpt(optname, optval, *optlen); | |
1704 return 0; | |
1705 } | |
1706 catch (CUDTException e) | |
1707 { | |
1708 s_UDTUnited.setError(new CUDTException(e)); | |
1709 return ERROR; | |
1710 } | |
1711 catch (...) | |
1712 { | |
1713 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1714 return ERROR; | |
1715 } | |
1716 } | |
1717 | |
1718 int CUDT::setsockopt(UDTSOCKET u, int, UDTOpt optname, const void* optval, int o
ptlen) | |
1719 { | |
1720 try | |
1721 { | |
1722 CUDT* udt = s_UDTUnited.lookup(u); | |
1723 udt->setOpt(optname, optval, optlen); | |
1724 return 0; | |
1725 } | |
1726 catch (CUDTException e) | |
1727 { | |
1728 s_UDTUnited.setError(new CUDTException(e)); | |
1729 return ERROR; | |
1730 } | |
1731 catch (...) | |
1732 { | |
1733 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1734 return ERROR; | |
1735 } | |
1736 } | |
1737 | |
1738 int CUDT::send(UDTSOCKET u, const char* buf, int len, int) | |
1739 { | |
1740 try | |
1741 { | |
1742 CUDT* udt = s_UDTUnited.lookup(u); | |
1743 return udt->send((char*)buf, len); | |
1744 } | |
1745 catch (CUDTException e) | |
1746 { | |
1747 s_UDTUnited.setError(new CUDTException(e)); | |
1748 return ERROR; | |
1749 } | |
1750 catch (bad_alloc&) | |
1751 { | |
1752 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1753 return ERROR; | |
1754 } | |
1755 catch (...) | |
1756 { | |
1757 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1758 return ERROR; | |
1759 } | |
1760 } | |
1761 | |
1762 int CUDT::recv(UDTSOCKET u, char* buf, int len, int) | |
1763 { | |
1764 try | |
1765 { | |
1766 CUDT* udt = s_UDTUnited.lookup(u); | |
1767 return udt->recv(buf, len); | |
1768 } | |
1769 catch (CUDTException e) | |
1770 { | |
1771 s_UDTUnited.setError(new CUDTException(e)); | |
1772 return ERROR; | |
1773 } | |
1774 catch (...) | |
1775 { | |
1776 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1777 return ERROR; | |
1778 } | |
1779 } | |
1780 | |
1781 int CUDT::sendmsg(UDTSOCKET u, const char* buf, int len, int ttl, bool inorder) | |
1782 { | |
1783 try | |
1784 { | |
1785 CUDT* udt = s_UDTUnited.lookup(u); | |
1786 return udt->sendmsg((char*)buf, len, ttl, inorder); | |
1787 } | |
1788 catch (CUDTException e) | |
1789 { | |
1790 s_UDTUnited.setError(new CUDTException(e)); | |
1791 return ERROR; | |
1792 } | |
1793 catch (bad_alloc&) | |
1794 { | |
1795 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1796 return ERROR; | |
1797 } | |
1798 catch (...) | |
1799 { | |
1800 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1801 return ERROR; | |
1802 } | |
1803 } | |
1804 | |
1805 int CUDT::recvmsg(UDTSOCKET u, char* buf, int len) | |
1806 { | |
1807 try | |
1808 { | |
1809 CUDT* udt = s_UDTUnited.lookup(u); | |
1810 return udt->recvmsg(buf, len); | |
1811 } | |
1812 catch (CUDTException e) | |
1813 { | |
1814 s_UDTUnited.setError(new CUDTException(e)); | |
1815 return ERROR; | |
1816 } | |
1817 catch (...) | |
1818 { | |
1819 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1820 return ERROR; | |
1821 } | |
1822 } | |
1823 | |
1824 int64_t CUDT::sendfile(UDTSOCKET u, fstream& ifs, int64_t& offset, const int64_t
& size, const int& block) | |
1825 { | |
1826 try | |
1827 { | |
1828 CUDT* udt = s_UDTUnited.lookup(u); | |
1829 return udt->sendfile(ifs, offset, size, block); | |
1830 } | |
1831 catch (CUDTException e) | |
1832 { | |
1833 s_UDTUnited.setError(new CUDTException(e)); | |
1834 return ERROR; | |
1835 } | |
1836 catch (bad_alloc&) | |
1837 { | |
1838 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1839 return ERROR; | |
1840 } | |
1841 catch (...) | |
1842 { | |
1843 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1844 return ERROR; | |
1845 } | |
1846 } | |
1847 | |
1848 int64_t CUDT::recvfile(UDTSOCKET u, fstream& ofs, int64_t& offset, const int64_t
& size, const int& block) | |
1849 { | |
1850 try | |
1851 { | |
1852 CUDT* udt = s_UDTUnited.lookup(u); | |
1853 return udt->recvfile(ofs, offset, size, block); | |
1854 } | |
1855 catch (CUDTException e) | |
1856 { | |
1857 s_UDTUnited.setError(new CUDTException(e)); | |
1858 return ERROR; | |
1859 } | |
1860 catch (...) | |
1861 { | |
1862 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1863 return ERROR; | |
1864 } | |
1865 } | |
1866 | |
1867 int CUDT::select(int, ud_set* readfds, ud_set* writefds, ud_set* exceptfds, cons
t timeval* timeout) | |
1868 { | |
1869 if ((NULL == readfds) && (NULL == writefds) && (NULL == exceptfds)) | |
1870 { | |
1871 s_UDTUnited.setError(new CUDTException(5, 3, 0)); | |
1872 return ERROR; | |
1873 } | |
1874 | |
1875 try | |
1876 { | |
1877 return s_UDTUnited.select(readfds, writefds, exceptfds, timeout); | |
1878 } | |
1879 catch (CUDTException e) | |
1880 { | |
1881 s_UDTUnited.setError(new CUDTException(e)); | |
1882 return ERROR; | |
1883 } | |
1884 catch (bad_alloc&) | |
1885 { | |
1886 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1887 return ERROR; | |
1888 } | |
1889 catch (...) | |
1890 { | |
1891 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1892 return ERROR; | |
1893 } | |
1894 } | |
1895 | |
1896 int CUDT::selectEx(const vector<UDTSOCKET>& fds, vector<UDTSOCKET>* readfds, vec
tor<UDTSOCKET>* writefds, vector<UDTSOCKET>* exceptfds, int64_t msTimeOut) | |
1897 { | |
1898 if ((NULL == readfds) && (NULL == writefds) && (NULL == exceptfds)) | |
1899 { | |
1900 s_UDTUnited.setError(new CUDTException(5, 3, 0)); | |
1901 return ERROR; | |
1902 } | |
1903 | |
1904 try | |
1905 { | |
1906 return s_UDTUnited.selectEx(fds, readfds, writefds, exceptfds, msTimeOut); | |
1907 } | |
1908 catch (CUDTException e) | |
1909 { | |
1910 s_UDTUnited.setError(new CUDTException(e)); | |
1911 return ERROR; | |
1912 } | |
1913 catch (bad_alloc&) | |
1914 { | |
1915 s_UDTUnited.setError(new CUDTException(3, 2, 0)); | |
1916 return ERROR; | |
1917 } | |
1918 catch (...) | |
1919 { | |
1920 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1921 return ERROR; | |
1922 } | |
1923 } | |
1924 | |
1925 int CUDT::epoll_create() | |
1926 { | |
1927 try | |
1928 { | |
1929 return s_UDTUnited.epoll_create(); | |
1930 } | |
1931 catch (CUDTException e) | |
1932 { | |
1933 s_UDTUnited.setError(new CUDTException(e)); | |
1934 return ERROR; | |
1935 } | |
1936 catch (...) | |
1937 { | |
1938 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1939 return ERROR; | |
1940 } | |
1941 } | |
1942 | |
1943 int CUDT::epoll_add_usock(const int eid, const UDTSOCKET u, const int* events) | |
1944 { | |
1945 try | |
1946 { | |
1947 return s_UDTUnited.epoll_add_usock(eid, u, events); | |
1948 } | |
1949 catch (CUDTException e) | |
1950 { | |
1951 s_UDTUnited.setError(new CUDTException(e)); | |
1952 return ERROR; | |
1953 } | |
1954 catch (...) | |
1955 { | |
1956 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1957 return ERROR; | |
1958 } | |
1959 } | |
1960 | |
1961 int CUDT::epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events) | |
1962 { | |
1963 try | |
1964 { | |
1965 return s_UDTUnited.epoll_add_ssock(eid, s, events); | |
1966 } | |
1967 catch (CUDTException e) | |
1968 { | |
1969 s_UDTUnited.setError(new CUDTException(e)); | |
1970 return ERROR; | |
1971 } | |
1972 catch (...) | |
1973 { | |
1974 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1975 return ERROR; | |
1976 } | |
1977 } | |
1978 | |
1979 int CUDT::epoll_remove_usock(const int eid, const UDTSOCKET u, const int* events
) | |
1980 { | |
1981 try | |
1982 { | |
1983 return s_UDTUnited.epoll_remove_usock(eid, u, events); | |
1984 } | |
1985 catch (CUDTException e) | |
1986 { | |
1987 s_UDTUnited.setError(new CUDTException(e)); | |
1988 return ERROR; | |
1989 } | |
1990 catch (...) | |
1991 { | |
1992 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
1993 return ERROR; | |
1994 } | |
1995 } | |
1996 | |
1997 int CUDT::epoll_remove_ssock(const int eid, const SYSSOCKET s, const int* events
) | |
1998 { | |
1999 try | |
2000 { | |
2001 return s_UDTUnited.epoll_remove_ssock(eid, s, events); | |
2002 } | |
2003 catch (CUDTException e) | |
2004 { | |
2005 s_UDTUnited.setError(new CUDTException(e)); | |
2006 return ERROR; | |
2007 } | |
2008 catch (...) | |
2009 { | |
2010 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
2011 return ERROR; | |
2012 } | |
2013 } | |
2014 | |
2015 int CUDT::epoll_wait(const int eid, set<UDTSOCKET>* readfds, set<UDTSOCKET>* wri
tefds, int64_t msTimeOut, set<SYSSOCKET>* lrfds, set<SYSSOCKET>* lwfds) | |
2016 { | |
2017 try | |
2018 { | |
2019 return s_UDTUnited.epoll_wait(eid, readfds, writefds, msTimeOut, lrfds, lw
fds); | |
2020 } | |
2021 catch (CUDTException e) | |
2022 { | |
2023 s_UDTUnited.setError(new CUDTException(e)); | |
2024 return ERROR; | |
2025 } | |
2026 catch (...) | |
2027 { | |
2028 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
2029 return ERROR; | |
2030 } | |
2031 } | |
2032 | |
2033 int CUDT::epoll_release(const int eid) | |
2034 { | |
2035 try | |
2036 { | |
2037 return s_UDTUnited.epoll_release(eid); | |
2038 } | |
2039 catch (CUDTException e) | |
2040 { | |
2041 s_UDTUnited.setError(new CUDTException(e)); | |
2042 return ERROR; | |
2043 } | |
2044 catch (...) | |
2045 { | |
2046 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
2047 return ERROR; | |
2048 } | |
2049 } | |
2050 | |
2051 CUDTException& CUDT::getlasterror() | |
2052 { | |
2053 return *s_UDTUnited.getError(); | |
2054 } | |
2055 | |
2056 int CUDT::perfmon(UDTSOCKET u, CPerfMon* perf, bool clear) | |
2057 { | |
2058 try | |
2059 { | |
2060 CUDT* udt = s_UDTUnited.lookup(u); | |
2061 udt->sample(perf, clear); | |
2062 return 0; | |
2063 } | |
2064 catch (CUDTException e) | |
2065 { | |
2066 s_UDTUnited.setError(new CUDTException(e)); | |
2067 return ERROR; | |
2068 } | |
2069 catch (...) | |
2070 { | |
2071 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
2072 return ERROR; | |
2073 } | |
2074 } | |
2075 | |
2076 CUDT* CUDT::getUDTHandle(UDTSOCKET u) | |
2077 { | |
2078 try | |
2079 { | |
2080 return s_UDTUnited.lookup(u); | |
2081 } | |
2082 catch (...) | |
2083 { | |
2084 return NULL; | |
2085 } | |
2086 } | |
2087 | |
2088 UDTSTATUS CUDT::getsockstate(UDTSOCKET u) | |
2089 { | |
2090 try | |
2091 { | |
2092 return s_UDTUnited.getStatus(u); | |
2093 } | |
2094 catch (...) | |
2095 { | |
2096 s_UDTUnited.setError(new CUDTException(-1, 0, 0)); | |
2097 return NONEXIST; | |
2098 } | |
2099 } | |
2100 | |
2101 | |
2102 //////////////////////////////////////////////////////////////////////////////// | |
2103 | |
2104 namespace UDT | |
2105 { | |
2106 | |
2107 int startup() | |
2108 { | |
2109 return CUDT::startup(); | |
2110 } | |
2111 | |
2112 int cleanup() | |
2113 { | |
2114 return CUDT::cleanup(); | |
2115 } | |
2116 | |
2117 UDTSOCKET socket(int af, int type, int protocol) | |
2118 { | |
2119 return CUDT::socket(af, type, protocol); | |
2120 } | |
2121 | |
2122 int bind(UDTSOCKET u, const struct sockaddr* name, int namelen) | |
2123 { | |
2124 return CUDT::bind(u, name, namelen); | |
2125 } | |
2126 | |
2127 int bind(UDTSOCKET u, UDPSOCKET udpsock) | |
2128 { | |
2129 return CUDT::bind(u, udpsock); | |
2130 } | |
2131 | |
2132 int listen(UDTSOCKET u, int backlog) | |
2133 { | |
2134 return CUDT::listen(u, backlog); | |
2135 } | |
2136 | |
2137 UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen) | |
2138 { | |
2139 return CUDT::accept(u, addr, addrlen); | |
2140 } | |
2141 | |
2142 int connect(UDTSOCKET u, const struct sockaddr* name, int namelen) | |
2143 { | |
2144 return CUDT::connect(u, name, namelen); | |
2145 } | |
2146 | |
2147 int close(UDTSOCKET u) | |
2148 { | |
2149 return CUDT::close(u); | |
2150 } | |
2151 | |
2152 int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen) | |
2153 { | |
2154 return CUDT::getpeername(u, name, namelen); | |
2155 } | |
2156 | |
2157 int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen) | |
2158 { | |
2159 return CUDT::getsockname(u, name, namelen); | |
2160 } | |
2161 | |
2162 int getsockopt(UDTSOCKET u, int level, SOCKOPT optname, void* optval, int* optle
n) | |
2163 { | |
2164 return CUDT::getsockopt(u, level, optname, optval, optlen); | |
2165 } | |
2166 | |
2167 int setsockopt(UDTSOCKET u, int level, SOCKOPT optname, const void* optval, int
optlen) | |
2168 { | |
2169 return CUDT::setsockopt(u, level, optname, optval, optlen); | |
2170 } | |
2171 | |
2172 int send(UDTSOCKET u, const char* buf, int len, int flags) | |
2173 { | |
2174 return CUDT::send(u, buf, len, flags); | |
2175 } | |
2176 | |
2177 int recv(UDTSOCKET u, char* buf, int len, int flags) | |
2178 { | |
2179 return CUDT::recv(u, buf, len, flags); | |
2180 } | |
2181 | |
2182 int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl, bool inorder) | |
2183 { | |
2184 return CUDT::sendmsg(u, buf, len, ttl, inorder); | |
2185 } | |
2186 | |
2187 int recvmsg(UDTSOCKET u, char* buf, int len) | |
2188 { | |
2189 return CUDT::recvmsg(u, buf, len); | |
2190 } | |
2191 | |
2192 int64_t sendfile(UDTSOCKET u, fstream& ifs, int64_t& offset, int64_t size, int b
lock) | |
2193 { | |
2194 return CUDT::sendfile(u, ifs, offset, size, block); | |
2195 } | |
2196 | |
2197 int64_t recvfile(UDTSOCKET u, fstream& ofs, int64_t& offset, int64_t size, int b
lock) | |
2198 { | |
2199 return CUDT::recvfile(u, ofs, offset, size, block); | |
2200 } | |
2201 | |
2202 int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const st
ruct timeval* timeout) | |
2203 { | |
2204 return CUDT::select(nfds, readfds, writefds, exceptfds, timeout); | |
2205 } | |
2206 | |
2207 int selectEx(const vector<UDTSOCKET>& fds, vector<UDTSOCKET>* readfds, vector<UD
TSOCKET>* writefds, vector<UDTSOCKET>* exceptfds, int64_t msTimeOut) | |
2208 { | |
2209 return CUDT::selectEx(fds, readfds, writefds, exceptfds, msTimeOut); | |
2210 } | |
2211 | |
2212 int epoll_create() | |
2213 { | |
2214 return CUDT::epoll_create(); | |
2215 } | |
2216 | |
2217 int epoll_add_usock(const int eid, const UDTSOCKET u, const int* events) | |
2218 { | |
2219 return CUDT::epoll_add_usock(eid, u, events); | |
2220 } | |
2221 | |
2222 int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events) | |
2223 { | |
2224 return CUDT::epoll_add_ssock(eid, s, events); | |
2225 } | |
2226 | |
2227 int epoll_remove_usock(const int eid, const UDTSOCKET u, const int* events) | |
2228 { | |
2229 return CUDT::epoll_remove_usock(eid, u, events); | |
2230 } | |
2231 | |
2232 int epoll_remove_ssock(const int eid, const SYSSOCKET s, const int* events) | |
2233 { | |
2234 return CUDT::epoll_remove_usock(eid, s, events); | |
2235 } | |
2236 | |
2237 int epoll_wait(const int eid, set<int>* readfds, set<int>* writefds, int64_t msT
imeOut, set<SYSSOCKET>* lrfds, set<SYSSOCKET>* lwfds) | |
2238 { | |
2239 return CUDT::epoll_wait(eid, readfds, writefds, msTimeOut, lrfds, lwfds); | |
2240 } | |
2241 | |
2242 int epoll_release(const int eid) | |
2243 { | |
2244 return CUDT::epoll_release(eid); | |
2245 } | |
2246 | |
2247 ERRORINFO& getlasterror() | |
2248 { | |
2249 return CUDT::getlasterror(); | |
2250 } | |
2251 | |
2252 int perfmon(UDTSOCKET u, TRACEINFO* perf, bool clear) | |
2253 { | |
2254 return CUDT::perfmon(u, perf, clear); | |
2255 } | |
2256 | |
2257 UDTSTATUS getsockstate(UDTSOCKET u) | |
2258 { | |
2259 return CUDT::getsockstate(u); | |
2260 } | |
2261 | |
2262 } | |
OLD | NEW |