void TCPConnection::AsyncConnect(const char* irAddress, uint16 irPort) { safe_delete_array(charAsyncConnect); charAsyncConnect = new char[strlen(irAddress) + 1]; strcpy(charAsyncConnect, irAddress); AsyncConnect((uint32) 0, irPort); }
bool CNetwork::Connect(string hostname, unsigned short port, unsigned short query_port) { if (IsConnected()) return false; boost::system::error_code error; tcp::resolver resolver(m_IoService); tcp::resolver::query query(tcp::v4(), hostname, string()); tcp::resolver::iterator i = resolver.resolve(query, error); if (error) { CCallbackHandler::Get()->ForwardError( EErrorType::CONNECTION_ERROR, error.value(), fmt::format("error while resolving hostname \"{}\": {}", hostname, error.message())); return false; } m_SocketDest = *i; m_SocketDest.port(query_port); m_ServerPort = port; AsyncConnect(); m_IoThread = new thread(boost::bind(&asio::io_service::run, boost::ref(m_IoService))); return true; }
/// <summary> /// Only needed if writing. Once connected to the destination address all async writes go to this address. /// </summary> /// <param name="connectCb">The connect callback - if unsuccesful the error callback supplied for the bind will be called.</param> /// <param name="destIp">The destination ip in dot notation form.</param> /// <param name="port">Int the destination UDP port.</param> void DgramListener::AsyncConnect(DgramConnectCallback&& connectCb, const std::string& destIp, int port) { auto listener = _udpListener.lock(); if (!listener) { throw runtime_error("Connection expired."); } auto connectCbCopy = move(connectCb); auto handler = [this, connectCbCopy]() { connectCbCopy(shared_from_this()); }; auto boostIp = boost::asio::ip::address::from_string(destIp); listener->AsyncConnect(boostIp, port, move(handler)); }
void IoServicesImpl::AsyncConnect(ConnectCallback&& connectCb, ErrorCallback&& errCb, std::string ipAddress, int port) { auto errCbCopy = std::move(errCb); auto errHandler = [this, errCbCopy](std::shared_ptr<TcpPeerConnection> conn, const boost::system::error_code& ec) { // Call the application error handler first. errCbCopy(conn, ec); // Then call our cleanup handler. ErrorHandler(conn, ec); }; auto conn = std::make_shared<TcpConnection>(&_ioService, std::move(errHandler)); // All access is from the context of the IO service so should not need mutexing. _clientConnections[conn] = conn; conn->AsyncConnect(std::move(connectCb), ipAddress, port); }
void RawSocket::Connect(int timeout_millis) { int flags; AsyncConnect(); try { if((flags = fcntl(GetReadDescriptor().GetNumber(), F_GETFL, NULL)) < 0) throw IOException::MakeException("Failed to get socket flags", errno); if (fcntl(GetReadDescriptor().GetNumber(), F_SETFL, flags & ~O_NONBLOCK) < 0) throw IOException::MakeException("Failed to set socket blocking", errno); int ready = WaitForSocket(POLLOUT, timeout_millis); if (ready == 0) throw IOException::MakeException("Failed to connect", ETIMEDOUT); else if (ready < 0) throw IOException::MakeException("Failed to connect", errno); } catch (std::exception &e) { Disconnect(); throw; } return; }
void CommStart(PComVar cv, LONG lParam, PTTSet ts) { char ErrMsg[31]; char Temp[20]; char uimsg[MAX_UIMSG]; if (! cv->Open ) { return; } if ( cv->Ready ) { return; } // キャンセルタイマがあれば取り消す。ただし、この時点で WM_TIMER が送られている可能性はある。 if (*cv->ConnetingTimeout > 0) { KillTimer(cv->HWin, IdCancelConnectTimer); } switch (cv->PortType) { case IdTCPIP: ErrMsg[0] = 0; switch (HIWORD(lParam)) { case WSAECONNREFUSED: get_lang_msg("MSG_COMM_REFUSE_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Connection refused", ts->UILanguageFile); _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg); break; case WSAENETUNREACH: get_lang_msg("MSG_COMM_REACH_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Network cannot be reached", ts->UILanguageFile); _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg); break; case WSAETIMEDOUT: get_lang_msg("MSG_COMM_CONNECT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Connection timed out", ts->UILanguageFile); _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg); break; default: get_lang_msg("MSG_COMM_TIMEOUT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot connect the host", ts->UILanguageFile); _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg); } if (HIWORD(lParam)>0) { #ifndef NO_INET6 /* connect() failed */ if (cv->res->ai_next != NULL) { /* try to connect with other protocol */ CloseSocket(cv->s); for (cv->res = cv->res->ai_next; cv->res; cv->res = cv->res->ai_next) { cv->s = OpenSocket(cv); if (cv->s == INVALID_SOCKET) { CloseSocket(cv->s); continue; } AsyncConnect(cv); cv->Ready = FALSE; cv->RetryWithOtherProtocol = TRUE; /* retry with other procotol */ return; } } else { /* trying with all protocol family are failed */ if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE); cv->RetryWithOtherProtocol = FALSE; return; } #else if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); MessageBox(cv->HWin, ErrMsg, uimsg, MB_TASKMODAL | MB_ICONEXCLAMATION); } PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE); return; #endif /* NO_INET6 */ } #ifndef NO_INET6 /* here is connection established */ cv->RetryWithOtherProtocol = FALSE; #endif /* NO_INET6 */ PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMNOTIFY, FD_READ | FD_OOB | FD_CLOSE); TCPIPClosed = FALSE; break; case IdSerial: _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort); ReadEnd = CreateEvent(NULL,FALSE,FALSE,Temp); _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", WRITENAME, cv->ComPort); memset(&wol,0,sizeof(OVERLAPPED)); wol.hEvent = CreateEvent(NULL,TRUE,TRUE,Temp); _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READNAME, cv->ComPort); memset(&rol,0,sizeof(OVERLAPPED)); rol.hEvent = CreateEvent(NULL,TRUE,FALSE,Temp); /* create the receiver thread */ if (_beginthread(CommThread,0,cv) == -1) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); get_lang_msg("MSG_TT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Can't create thread", ts->UILanguageFile); MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } break; case IdFile: cv->RRQ = TRUE; break; case IdNamedPipe: cv->ComPort = 0; _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort); ReadEnd = CreateEvent(NULL,FALSE,FALSE,Temp); _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", WRITENAME, cv->ComPort); memset(&wol,0,sizeof(OVERLAPPED)); wol.hEvent = CreateEvent(NULL,TRUE,TRUE,Temp); _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READNAME, cv->ComPort); memset(&rol,0,sizeof(OVERLAPPED)); rol.hEvent = CreateEvent(NULL,TRUE,FALSE,Temp); /* create the receiver thread */ if (_beginthread(NamedPipeThread,0,cv) == -1) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); get_lang_msg("MSG_TT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Can't create thread", ts->UILanguageFile); MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } break; } cv->Ready = TRUE; }
void CommOpen(HWND HW, PTTSet ts, PComVar cv) { #ifdef NO_INET6 int Err; #endif /* NO_INET6 */ char ErrMsg[21+256]; char P[50+256]; MSG Msg; #ifndef NO_INET6 ADDRINFO hints; char pname[NI_MAXSERV]; #else char HEntBuff[MAXGETHOSTSTRUCT]; u_long addr; SOCKADDR_IN saddr; #endif /* NO_INET6 */ BOOL InvalidHost; #ifdef NO_INET6 BOOL BBuf; #endif /* NO_INET6 */ char uimsg[MAX_UIMSG]; // ホスト名が名前付きパイプかどうかを調べる。 if (ts->PortType == IdTCPIP) { if (CheckNamedPipeFormat(ts->HostName, strlen(ts->HostName)) == 0) { ts->PortType = IdNamedPipe; } } /* initialize ComVar */ cv->InBuffCount = 0; cv->InPtr = 0; cv->OutBuffCount = 0; cv->OutPtr = 0; cv->HWin = HW; cv->Ready = FALSE; cv->Open = FALSE; cv->PortType = ts->PortType; cv->ComPort = 0; cv->RetryCount = 0; #ifndef NO_INET6 cv->RetryWithOtherProtocol = TRUE; #endif /* NO_INET6 */ cv->s = INVALID_SOCKET; cv->ComID = INVALID_HANDLE_VALUE; cv->CanSend = TRUE; cv->RRQ = FALSE; cv->SendKanjiFlag = FALSE; cv->SendCode = IdASCII; cv->EchoKanjiFlag = FALSE; cv->EchoCode = IdASCII; cv->Language = ts->Language; cv->CRSend = ts->CRSend; cv->KanjiCodeEcho = ts->KanjiCode; cv->JIS7KatakanaEcho = ts->JIS7Katakana; cv->KanjiCodeSend = ts->KanjiCodeSend; cv->JIS7KatakanaSend = ts->JIS7KatakanaSend; cv->KanjiIn = ts->KanjiIn; cv->KanjiOut = ts->KanjiOut; cv->RussHost = ts->RussHost; cv->RussClient = ts->RussClient; cv->DelayFlag = TRUE; cv->DelayPerChar = ts->DelayPerChar; cv->DelayPerLine = ts->DelayPerLine; cv->TelBinRecv = FALSE; cv->TelBinSend = FALSE; cv->TelFlag = FALSE; cv->TelMode = FALSE; cv->IACFlag = FALSE; cv->TelCRFlag = FALSE; cv->TelCRSend = FALSE; cv->TelCRSendEcho = FALSE; cv->TelAutoDetect = ts->TelAutoDetect; /* TTPLUG */ cv->Locale = ts->Locale; cv->locale = _create_locale(LC_ALL, cv->Locale); cv->CodePage = &ts->CodePage; cv->ConnetingTimeout = &ts->ConnectingTimeout; cv->LastSendTime = time(NULL); cv->LineModeBuffCount = 0; cv->Flush = FALSE; cv->FlushLen = 0; cv->TelLineMode = FALSE; if ((ts->PortType!=IdSerial) && (strlen(ts->HostName)==0)) { PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE); return; } switch (ts->PortType) { case IdTCPIP: cv->TelFlag = (ts->Telnet > 0); if (ts->EnableLineMode) { cv->TelLineMode = TRUE; } if (! LoadWinsock()) { if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); get_lang_msg("MSG_WINSOCK_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot use winsock", ts->UILanguageFile); MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } InvalidHost = TRUE; } else { TTXOpenTCP(); /* TTPLUG */ cv->Open = TRUE; #ifndef NO_INET6 /* resolving address */ memset(&hints, 0, sizeof(hints)); hints.ai_family = ts->ProtocolFamily; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", ts->TCPPort); HAsync = PWSAAsyncGetAddrInfo(HW, WM_USER_GETHOST, ts->HostName, pname, &hints, &cv->res0); if (HAsync == 0) InvalidHost = TRUE; else { cv->ComPort = 1; // set "getting host" flag // (see CVTWindow::OnSysCommand()) do { if (GetMessage(&Msg,0,0,0)) { if ((Msg.hwnd==HW) && ((Msg.message == WM_SYSCOMMAND) && ((Msg.wParam & 0xfff0) == SC_CLOSE) || (Msg.message == WM_COMMAND) && (LOWORD(Msg.wParam) == ID_FILE_EXIT) || (Msg.message == WM_CLOSE))) { /* Exit when the user closes Tera Term */ PWSACancelAsyncRequest(HAsync); CloseHandle(HAsync); HAsync = 0; cv->ComPort = 0; // clear "getting host" flag PostMessage(HW,Msg.message,Msg.wParam,Msg.lParam); return; } if (Msg.message != WM_USER_GETHOST) { /* Prosess messages */ TranslateMessage(&Msg); DispatchMessage(&Msg); } } else { return; } } while (Msg.message!=WM_USER_GETHOST); cv->ComPort = 0; // clear "getting host" flag CloseHandle(HAsync); HAsync = 0; InvalidHost = WSAGETASYNCERROR(Msg.lParam) != 0; } } /* if (!LoadWinsock()) */ if (InvalidHost) { if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); get_lang_msg("MSG_INVALID_HOST_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Invalid host", ts->UILanguageFile); MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } goto BreakSC; } for (cv->res = cv->res0; cv->res; cv->res = cv->res->ai_next) { cv->s = OpenSocket(cv); if (cv->s == INVALID_SOCKET) { CloseSocket(cv->s); continue; } /* start asynchronous connect */ AsyncConnect(cv); break; /* break for-loop immediately */ } break; #else if ((ts->HostName[0] >= 0x30) && (ts->HostName[0] <= 0x39)) { addr = Pinet_addr(ts->HostName); InvalidHost = (addr == 0xffffffff); } else { HAsync = PWSAAsyncGetHostByName(HW,WM_USER_GETHOST, ts->HostName,HEntBuff,sizeof(HEntBuff)); if (HAsync == 0) InvalidHost = TRUE; else { cv->ComPort = 1; // set "getting host" flag // (see CVTWindow::OnSysCommand()) do { if (GetMessage(&Msg,0,0,0)) { if ((Msg.hwnd==HW) && ((Msg.message == WM_SYSCOMMAND) && ((Msg.wParam & 0xfff0) == SC_CLOSE) || (Msg.message == WM_COMMAND) && (LOWORD(Msg.wParam) == ID_FILE_EXIT) || (Msg.message == WM_CLOSE))) { /* Exit when the user closes Tera Term */ PWSACancelAsyncRequest(HAsync); HAsync = 0; cv->ComPort = 0; // clear "getting host" flag PostMessage(HW,Msg.message,Msg.wParam,Msg.lParam); return; } if (Msg.message != WM_USER_GETHOST) { /* Prosess messages */ TranslateMessage(&Msg); DispatchMessage(&Msg); } } else { return; } } while (Msg.message!=WM_USER_GETHOST); cv->ComPort = 0; // clear "getting host" flag HAsync = 0; InvalidHost = WSAGETASYNCERROR(Msg.lParam) != 0; if (! InvalidHost) { if (((PHOSTENT)HEntBuff)->h_addr_list != NULL) memcpy(&addr, ((PHOSTENT)HEntBuff)->h_addr_list[0],sizeof(addr)); else InvalidHost = TRUE; } } } if (InvalidHost) { if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); get_lang_msg("MSG_INVALID_HOST_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Invalid host", ts->UILanguageFile); MessageBox(cv->HWin, ts->UIMsg, uimsg, MB_TASKMODAL | MB_ICONEXCLAMATION); } } else { cv->s= Psocket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (cv->s==INVALID_SOCKET) { InvalidHost = TRUE; if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); get_lang_msg("MSG_COMM_TIMEOUT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot connect the host", ts->UILanguageFile); MessageBox(cv->HWin, ts->UIMsg, uimsg, MB_TASKMODAL | MB_ICONEXCLAMATION); } } else { BBuf = TRUE; Psetsockopt(cv->s,(int)SOL_SOCKET,SO_OOBINLINE,(char FAR *)&BBuf,sizeof(BBuf)); PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMOPEN, FD_CONNECT); saddr.sin_family = AF_INET; saddr.sin_port = Phtons(ts->TCPPort); saddr.sin_addr.s_addr = addr; memset(saddr.sin_zero,0,8); Err = Pconnect(cv->s,(LPSOCKADDR)&saddr,sizeof(saddr)); if (Err!=0 ) Err = PWSAGetLastError(); if (Err==WSAEWOULDBLOCK ) { /* Do nothing */ } else if (Err!=0 ) PostMessage(cv->HWin, WM_USER_COMMOPEN,0, MAKELONG(FD_CONNECT,Err)); } } } break; #endif /* NO_INET6 */ case IdSerial: InitFileIO(IdSerial); /* TTPLUG */ TTXOpenFile(); /* TTPLUG */ _snprintf_s(P, sizeof(P), _TRUNCATE, "COM%d", ts->ComPort); strncpy_s(ErrMsg, sizeof(ErrMsg),P, _TRUNCATE); strncpy_s(P, sizeof(P),"\\\\.\\", _TRUNCATE); strncat_s(P, sizeof(P),ErrMsg, _TRUNCATE); cv->ComID = PCreateFile(P,GENERIC_READ | GENERIC_WRITE, 0,NULL,OPEN_EXISTING, FILE_FLAG_OVERLAPPED,NULL); if (cv->ComID == INVALID_HANDLE_VALUE ) { get_lang_msg("MSG_CANTOEPN_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot open %s", ts->UILanguageFile); _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, ts->UIMsg, &P[4]); if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } InvalidHost = TRUE; } else { cv->Open = TRUE; cv->ComPort = ts->ComPort; CommResetSerial(ts, cv, ts->ClearComBuffOnOpen); if (!ts->ClearComBuffOnOpen) { cv->RRQ = TRUE; } /* notify to VT window that Comm Port is open */ PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0); InvalidHost = FALSE; SetCOMFlag(ts->ComPort); } break; /* end of "case IdSerial:" */ case IdFile: InitFileIO(IdFile); /* TTPLUG */ TTXOpenFile(); /* TTPLUG */ cv->ComID = PCreateFile(ts->HostName,GENERIC_READ,0,NULL, OPEN_EXISTING,0,NULL); InvalidHost = (cv->ComID == INVALID_HANDLE_VALUE); if (InvalidHost) { if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); get_lang_msg("MSG_CANTOEPN_FILE_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot open file", ts->UILanguageFile); MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } } else { cv->Open = TRUE; PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0); } break; case IdNamedPipe: InitFileIO(IdNamedPipe); /* TTPLUG */ TTXOpenFile(); /* TTPLUG */ memset(P, 0, sizeof(P)); strncpy_s(P, sizeof(P), ts->HostName, _TRUNCATE); // 名前付きパイプが正しい書式かをチェックする。 if (CheckNamedPipeFormat(P, strlen(P)) < 0) { InvalidHost = TRUE; _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "Invalid pipe name\n\n" "A valid pipe name has the form\n" "\"\\\\<ServerName>\\pipe\\<PipeName>\"", GetLastError()); get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); break; } cv->ComID = PCreateFile(P,GENERIC_READ | GENERIC_WRITE, 0,NULL,OPEN_EXISTING, 0, // ブロッキングモードにする(FILE_FLAG_OVERLAPPED は指定しない) NULL); if (cv->ComID == INVALID_HANDLE_VALUE ) { get_lang_msg("MSG_CANTOEPN_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot open %s", ts->UILanguageFile); _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, ts->UIMsg, &P[4]); if (cv->NoMsg==0) { get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile); MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION); } InvalidHost = TRUE; } else { cv->Open = TRUE; PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0); InvalidHost = FALSE; } break; /* end of "case IdNamedPipe:" */ } /* end of "switch" */
/************************************************************************** @FunctionName:AsyncConnect @FunctionDestription:异步连接 @InputParam: @OutPutParam: @ReturnValue: **************************************************************************/ void CAsioSocketClient::AsyncConnect(const char* szAddress, unsigned short usPort) { AsyncConnect(std::string(szAddress), usPort); }
bool IOSocket::AsyncConnect(const NetAddress &addr, ConnectIOServerData *data, const NetAddress &local) { return AsyncConnect(addr, data, nullptr, local); }