00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "stdafx.h"
00037 #include "TCPSocketAsync.h"
00038
00039 #include "ErrorHandlerMacros.h"
00040
00041 #include "BlockedBuffer.h"
00042
00043 #ifdef _MEMORY_DEBUG
00044 #define new DEBUG_NEW
00045 #define malloc DEBUG_MALLOC
00046 static char THIS_FILE[] = __FILE__;
00047 #endif
00048
00049 KOMODIA_NAMESPACE_START
00050
00051 #define CTCPSocketAsync_Class "CTCPSocketAsync"
00052
00053 CTCPSocketAsync::CTCPSocketAsync(BOOL bRawSocket) : CTCPSocket(bRawSocket),
00054 CAsyncSocket(),
00055 m_bDisabledConnect(FALSE),
00056 m_ulTimeout(0)
00057 {
00058 try
00059 {
00060
00061 SetName(CTCPSocketAsync_Class);
00062 }
00063 ERROR_HANDLER("CTCPSocketAsync")
00064 }
00065
00066 CTCPSocketAsync::~CTCPSocketAsync()
00067 {
00068 try
00069 {
00070
00071 Close();
00072 }
00073 ERROR_HANDLER("~CTCPSocketAsync")
00074 }
00075
00076 BOOL CTCPSocketAsync::Connect(IP aDestinationAddress,
00077 unsigned short usDestinationPort,
00078 BOOL bDisableAsync,
00079 BOOL bForceErrorEvent)
00080 {
00081 try
00082 {
00083
00084 return Connect(0,
00085 aDestinationAddress,
00086 usDestinationPort,
00087 bDisableAsync,
00088 bForceErrorEvent);
00089 }
00090 ERROR_HANDLER_RETURN("Connect",FALSE)
00091 }
00092
00093 BOOL CTCPSocketAsync::Connect(const std::string& rDestinationAddress,
00094 unsigned short usDestinationPort,
00095 BOOL bDisableAsync,
00096 BOOL bForceErrorEvent)
00097 {
00098 try
00099 {
00100
00101 return Connect(0,
00102 rDestinationAddress,
00103 usDestinationPort,
00104 bDisableAsync,
00105 bForceErrorEvent);
00106 }
00107 ERROR_HANDLER_RETURN("Connect",FALSE)
00108 }
00109
00110 BOOL CTCPSocketAsync::Connect(unsigned short usSourcePort,
00111 IP aDestinationAddress,
00112 unsigned short usDestinationPort,
00113 BOOL bDisableAsync,
00114 BOOL bForceErrorEvent)
00115 {
00116 try
00117 {
00118
00119 if (!CheckSocketValid())
00120 return FALSE;
00121
00122
00123 if (!bDisableAsync)
00124 {
00125 int iResult;
00126 iResult=InternalWSAAsyncSelect(WM_SOCKET_CONNECT,
00127 FD_CONNECT);
00128
00129 if (iResult)
00130 {
00131
00132 int iErrorCode;
00133 iErrorCode=GetSystemLastError();
00134
00135
00136 SetLastError("Connect");
00137
00138
00139 if (bForceErrorEvent)
00140 SocketConnected(iErrorCode);
00141
00142
00143 return FALSE;
00144 }
00145
00146
00147 if (m_ulTimeout &&
00148 !IsBlocking())
00149 if (!SetSystemTimeout(m_ulTimeout))
00150 {
00151
00152 ReportError("Connect","Failed to set timer!");
00153
00154
00155 if (bForceErrorEvent)
00156 SocketConnected(GetErrorCode());
00157
00158
00159 return FALSE;
00160 }
00161 }
00162
00163 else if (!Block())
00164 return FALSE;
00165
00166
00167 m_bDisabledConnect=bDisableAsync;
00168
00169
00170 BOOL bResult;
00171 bResult=CTCPSocket::Connect(usSourcePort,
00172 aDestinationAddress,
00173 usDestinationPort);
00174
00175
00176 m_bDisabledConnect=FALSE;
00177
00178 if (bResult)
00179 {
00180
00181 if (!bDisableAsync &&
00182 !IsBlocking())
00183
00184 return SocketConnected(0);
00185 else
00186
00187 return SetAsync();
00188 }
00189 else if (GetSystemLastError()!=WSAEWOULDBLOCK ||
00190 bDisableAsync ||
00191 IsBlocking())
00192 {
00193 if (m_ulTimeout)
00194
00195 KillSystemTimer();
00196
00197
00198 int iErrorCode;
00199 iErrorCode=GetSystemLastError();
00200
00201
00202 SetLastError("Connect");
00203
00204
00205 if (bForceErrorEvent &&
00206 !bDisableAsync)
00207 SocketConnected(iErrorCode);
00208
00209
00210 return FALSE;
00211 }
00212 else
00213 return TRUE;
00214 }
00215 ERROR_HANDLER_RETURN("Connect",FALSE)
00216 }
00217
00218 BOOL CTCPSocketAsync::Connect(unsigned short usSourcePort,
00219 const std::string& rDestinationAddress,
00220 unsigned short usDestinationPort,
00221 BOOL bDisableAsync,
00222 BOOL bForceErrorEvent)
00223 {
00224 try
00225 {
00226
00227 if (!CheckSocketValid())
00228 return FALSE;
00229
00230
00231 return Connect(usSourcePort,
00232 StringToLong(rDestinationAddress),
00233 usDestinationPort,
00234 bDisableAsync,
00235 bForceErrorEvent);
00236 }
00237 ERROR_HANDLER_RETURN("Connect",FALSE)
00238 }
00239
00240 BOOL CTCPSocketAsync::Listen(unsigned long ulBackLog)
00241 {
00242 try
00243 {
00244
00245 if (!CheckSocketValid())
00246 return FALSE;
00247
00248
00249 int iResult;
00250 iResult=InternalWSAAsyncSelect(WM_SOCKET_ACCEPT,
00251 FD_ACCEPT);
00252
00253
00254 if (iResult)
00255 {
00256
00257 SetLastError("Listen");
00258
00259
00260 return FALSE;
00261 }
00262
00263
00264 return CTCPSocket::Listen(ulBackLog);
00265 }
00266 ERROR_HANDLER_RETURN("Listen",FALSE)
00267 }
00268
00269 BOOL CTCPSocketAsync::SetAsync()
00270 {
00271 try
00272 {
00273
00274 if (!CheckSocketValid())
00275 return FALSE;
00276
00277
00278 int iResult;
00279 iResult=InternalWSAAsyncSelect(WM_SOCKET_GENERAL,
00280 FD_WRITE | FD_READ | FD_CLOSE | FD_OOB);
00281
00282
00283 if (iResult)
00284 {
00285
00286 SetLastError("SetAsync");
00287
00288
00289 return FALSE;
00290 }
00291
00292
00293 return TRUE;
00294 }
00295 ERROR_HANDLER_RETURN("SetAsync",FALSE)
00296 }
00297
00298 BOOL CTCPSocketAsync::SocketConnected(int iErrorCode)
00299 {
00300 try
00301 {
00302 if (m_ulTimeout)
00303
00304 KillSystemTimer();
00305
00306
00307 if (!iErrorCode)
00308
00309 SetConnectionStatus(TRUE);
00310
00311
00312 return CAsyncSocket::SocketConnected(iErrorCode);
00313 }
00314 ERROR_HANDLER_RETURN("SocketConnected",FALSE)
00315 }
00316
00317 BOOL CTCPSocketAsync::SocketClosed(int iErrorCode)
00318 {
00319 try
00320 {
00321
00322 SetConnectionStatus(FALSE);
00323
00324
00325 return CAsyncSocket::SocketClosed(iErrorCode);
00326 }
00327 ERROR_HANDLER_RETURN("SocketClosed",FALSE)
00328 }
00329
00330 void CTCPSocketAsync::Accepted()
00331 {
00332 try
00333 {
00334
00335 AddSocketToList();
00336
00337
00338 SetAsync();
00339 }
00340 ERROR_HANDLER("CTCPSocketAsync")
00341 }
00342
00343 SOCKET CTCPSocketAsync::GetAsyncHandle() const
00344 {
00345 return GetHandle();
00346 }
00347
00348 BOOL CTCPSocketAsync::Create()
00349 {
00350 try
00351 {
00352 if (!CTCPSocket::Create())
00353 return FALSE;
00354 else
00355 {
00356
00357 SocketCreated();
00358
00359
00360 AddSocketToList();
00361
00362
00363 return TRUE;
00364 }
00365 }
00366 ERROR_HANDLER_RETURN("Create",FALSE)
00367 }
00368
00369 BOOL CTCPSocketAsync::Close()
00370 {
00371 try
00372 {
00373
00374 if (!ValidSocket())
00375 return FALSE;
00376
00377
00378 CAsyncSocket::SocketClosing();
00379
00380
00381 RemoveSocketFromList();
00382
00383
00384 return CTCPSocket::Close();
00385 }
00386 ERROR_HANDLER_RETURN("Close",FALSE)
00387 }
00388
00389 BOOL CTCPSocketAsync::IsAsyncClass() const
00390 {
00391 try
00392 {
00393
00394 if (IsBlocking() ||
00395 m_bDisabledConnect)
00396 return FALSE;
00397 else
00398
00399 return TRUE;
00400 }
00401 ERROR_HANDLER_RETURN("IsAsyncClass",FALSE)
00402 }
00403
00404 void CTCPSocketAsync::BeforeAccept()
00405 {
00406 try
00407 {
00408
00409 RemoveSocketFromList();
00410 }
00411 ERROR_HANDLER("BeforeAccept")
00412 }
00413
00414 BOOL CTCPSocketAsync::SendBlockedBuffer(const CBlockedBuffer::CBlockedData& rData)
00415 {
00416 try
00417 {
00418
00419 return SendNoAdd(rData.GetData(),
00420 rData.GetDataSize())!=GetErrorCode();
00421 }
00422 ERROR_HANDLER_RETURN("SendBlockedBuffer",FALSE)
00423 }
00424
00425 int CTCPSocketAsync::Send(const char *pBuffer,
00426 unsigned long ulBufferLength)
00427 {
00428 try
00429 {
00430
00431 int iResult;
00432 iResult=SendNoAdd(pBuffer,
00433 ulBufferLength);
00434
00435
00436 if (iResult==GetErrorCode())
00437
00438 if (WSAGetLastError()==WSAEWOULDBLOCK &&
00439 GetBlockedBuffer())
00440 {
00441
00442 GetBlockedBuffer()->AddRecord(CBlockedBuffer::CBlockedData(pBuffer,
00443 ulBufferLength));
00444
00445
00446 iResult=0;
00447 }
00448
00449 else if (WSAGetLastError()==WSAEWOULDBLOCK)
00450 return 0;
00451 else
00452
00453 SetLastError("Send");
00454
00455
00456 return iResult;
00457 }
00458 ERROR_HANDLER_RETURN("Send",GetErrorCode())
00459 }
00460
00461 int CTCPSocketAsync::SendNoAdd(const char* pBuffer,
00462 unsigned long ulBufferLength)
00463 {
00464 try
00465 {
00466
00467 if (!CheckSocketValid())
00468 return FALSE;
00469
00470
00471 int iResult;
00472
00473
00474 iResult=send(GetHandle(),
00475 pBuffer,
00476 ulBufferLength,
00477 NULL);
00478
00479
00480 return iResult;
00481 }
00482 ERROR_HANDLER_RETURN("SendNoAdd",GetErrorCode())
00483 }
00484
00485 BOOL CTCPSocketAsync::SocketWrite(int iErrorCode)
00486 {
00487 try
00488 {
00489
00490 if (GetBlockedBuffer())
00491 GetBlockedBuffer()->SendData();
00492
00493
00494 return OnSocketWrite(iErrorCode);
00495 }
00496 ERROR_HANDLER_RETURN("OnSocketWrite",TRUE)
00497 }
00498
00499 BOOL CTCPSocketAsync::SetConnectionTimeout(unsigned long ulMS)
00500 {
00501 try
00502 {
00503
00504 if (HasSystemTimer())
00505 if (!KillSystemTimer())
00506 {
00507
00508 ReportError("SetConnectionTimeout","Failed to kill previous timer!");
00509
00510
00511 return FALSE;
00512 }
00513
00514
00515 m_ulTimeout=ulMS;
00516
00517
00518 return TRUE;
00519 }
00520 ERROR_HANDLER_RETURN("SetConnectionTimeout",FALSE)
00521 }
00522
00523 void CTCPSocketAsync::SystemTimeout()
00524 {
00525
00526 SocketConnected(CONNECTION_TIMEOUT);
00527 }
00528
00529 int CTCPSocketAsync::Receive(char* pBuffer,
00530 unsigned long ulBufferLength)
00531 {
00532 try
00533 {
00534
00535 int iResult;
00536 if ((iResult=CTCPSocket::Receive(pBuffer,
00537 ulBufferLength))>=0)
00538 return iResult;
00539
00540 else if (GetSystemLastError()==WSAEWOULDBLOCK)
00541 return 0;
00542 else
00543 return GetErrorCode();
00544 }
00545 ERROR_HANDLER_RETURN("Receive",GetErrorCode())
00546 }
00547
00548 KOMODIA_NAMESPACE_END