/*virtual*/ void CTcpSocketService::OnReceive() { // LogEvent(LE_DEBUG, "CTcpSocketService OnReceive()"); int ActualReceived = Receive((char*)m_Data, m_DataSize); if(ActualReceived == SOCKET_ERROR) { DWORD LastError = GetLastError(); if (LastError == WSAEWOULDBLOCK || LastError == WSAENOTCONN) LogEvent(LE_INFO, "CTcpSocketService::OnReceive() Receive Error[%s]", GetSocketErrorStr(LastError).c_str()); else { LogEvent(LE_INFO, "CTcpSocketService::OnReceive() Receive Error, Closing the Socket. Error [%s] ", GetSocketErrorStr(LastError).c_str()); CloseOnProblem(); } return; } if(ActualReceived == BERKELEY_SOCKETS_OK) return; // means that there is no message received and no error (connection closed) if(m_IncomingFilter != NULL) { m_IncomingFilter->OnIncomingMessage(m_Data, ActualReceived); } else { LogEvent(LE_INFOLOW, "CTcpSocketService::OnReceive ( Incoming Filter is NULL)"); SendIncomingMessage(m_Data, ActualReceived); } }
bool CBaseBerkeleySocket::Create(int LocalSocketPort, const char* LocalSocketAdd, ESocketType SocketType, IBaseBerkeleySocketEvents* Sink) { if (!IsClosed()) Close(); // Create the socket int Type = SocketType == TCP_SOCKET ? SOCK_STREAM : SOCK_DGRAM; m_Socket = socket(AF_INET, Type, 0); if (m_Socket == INVALID_SOCKET) { DisplaySocketsError("CBaseBerkeleySocket::Create", LE_ERROR); return false; } // TODO: should I bind? only in TCP? // Bind socket to the port (only is the port is valid - otherwise don't do bind) if (SocketType == UDP_SOCKET || LocalSocketPort > 0) { if (Bind(LocalSocketPort, LocalSocketAdd) == false) { LogEvent(LE_ERROR, "CBaseBerkeleySocket::Create - Bind Error on socket [%x]: %s", m_Socket, GetSocketErrorStr(WSAGetLastError()).c_str()); goto CBaseBerkeleySocket_Create_CloseAndExit; } } // set the socket to be non blocking - since all operation should be non blocking unsigned long NonBlocking = 1; // Some positive value if (ioctlsocket(m_Socket, FIONBIO, &NonBlocking) == SOCKET_ERROR) { LogEvent(LE_ERROR, "CBaseBerkeleySocket::Create - Error set non blocking mode to socket [%x]: %s", m_Socket, GetSocketErrorStr(WSAGetLastError()).c_str()); goto CBaseBerkeleySocket_Create_CloseAndExit; } // Init the parameters m_Sink = Sink; m_IsListening = false; m_IsConnecting = false; m_IsLastSendWouldBlock = false; // Register this socket to the events CSocketEventsManager* EventMgr = CSocketEventsManager::GetTheSocketEventsManager(); if (EventMgr == NULL || EventMgr->RegisterSocket(m_Socket, this) == false) { LogEvent(LE_ERROR, "CBaseBerkeleySocket::Create - can't register socket [%x] to socket events manager", m_Socket); Assert(false); goto CBaseBerkeleySocket_Create_CloseAndExit; } LogEvent(LE_INFO, "CBaseBerkeleySocket::Create - socket [%x] created and registered successfully", m_Socket); return true; CBaseBerkeleySocket_Create_CloseAndExit: Close(); m_Socket = INVALID_SOCKET; return false; }
void CTcpSocketService::OnConnectionClosed(int ErrorCode) { LogEvent(LE_INFO, "CTcpSocketService::OnConnectionClosed - remote connection closed with error code[%s]. Closing socket", ErrorCode == BERKELEY_SOCKETS_OK ? "OK" : GetSocketErrorStr(ErrorCode).c_str()); m_IsConnected = false; CloseOnProblem(); }
// TODO: it is still not clear to me whether to do shutdown on a socket before its closure // without waiting to FD_CLOSE(?), is sufficient to gracefully closes the socket ////////////////////////////////////////////////////////////////////////// bool CBaseBerkeleySocket::ShutDown() { if (shutdown(m_Socket, SD_BOTH) != BERKELEY_SOCKETS_OK) { int LastError = WSAGetLastError(); if (LastError != WSAENOTCONN) { //TODO: need to know beforehand is the socket is connected or not and //not to call shutdown in case it is not connected LogEvent(LE_WARNING, "CBaseBerkeleySocket::ShutDown - error shutting down. Socket [%x], message - %s", m_Socket, GetSocketErrorStr(LastError).c_str()); return false; } } return true; }
bool CBaseBerkeleySocket::GetSockName(std::string& SockIP, int& SockPort) const { CHECK_SOCKET_CREATED("CBaseBerkeleySocket::GetSockName"); struct sockaddr_in Socket; int ParamLen = sizeof(Socket); //Ask getpeername to fill in peer's socket address. if (getsockname(m_Socket, (SOCKADDR*)&Socket, &ParamLen) != BERKELEY_SOCKETS_OK) { LogEvent(LE_WARNING, "CBaseBerkeleySocket::GetSockName - received error in getting peer name. Socket [%x], message - %s", m_Socket, GetSocketErrorStr(WSAGetLastError()).c_str()); return false; } SockIP = inet_ntoa(Socket.sin_addr); SockPort = (int)ntohs(Socket.sin_port); return true; }
bool CBaseBerkeleySocket::Listen() { CHECK_SOCKET_CREATED("CBaseBerkeleySocket::Listen"); // Setting this variable before the call to listen in order to be sure // that no return value from listen(on different thread) will be returned // before setting this variable m_IsListening = true; if (listen(m_Socket, SOMAXCONN) != BERKELEY_SOCKETS_OK) { LogEvent(LE_WARNING, "CBaseBerkeleySocket::Listen - received error in listen command. Socket [%x], message - %s", m_Socket, GetSocketErrorStr(WSAGetLastError()).c_str()); m_IsListening = false; return false; } LogEvent(LE_INFO, "CBaseBerkeleySocket::Listen - socket [%x] start listening", m_Socket); return true; }
SOCKET CBaseBerkeleySocket::Accept(bool ShouldContinueListening) { CHECK_SOCKET_CREATED("CBaseBerkeleySocket::Accept"); struct sockaddr_in SockAddress; int AddressSize = sizeof(SockAddress); SOCKET NewSocket = accept(m_Socket, (SOCKADDR*)&SockAddress, &AddressSize); if (NewSocket == INVALID_SOCKET) { LogEvent(LE_WARNING, "CBaseBerkeleySocket::Accept - received error in accept command. Socket [%x], message - %s", m_Socket, GetSocketErrorStr(WSAGetLastError()).c_str()); return INVALID_SOCKET; } LogEvent(LE_INFO, "CBaseBerkeleySocket::Accept [%x]: accept NewSocket = %x", m_Socket, NewSocket); if (ShouldContinueListening) Listen(); return NewSocket; }
///////////////////////// // Initialize the IRC networking things (private) bool IRCClient::initNet() { // Check if already inited if(m_socketOpened) return true; // Open the socket if (!m_chatSocket.OpenReliable(0)) { errors("Could not open a socket for IRC networking: " + GetSocketErrorStr(GetSocketErrorNr()) + "\n"); return false; } m_socketOpened = true; // Get the address ResetNetAddr(m_chatServerAddr); if(!GetNetAddrFromNameAsync(m_chatServerAddrStr, m_chatServerAddr)) { errors("Wrong IRC server addr: %s" + m_chatServerAddrStr + "\n"); return false; } return true; }
bool CBaseBerkeleySocket::GetPeerName(std::string& PeerIP, int& PeerPort) const { if (m_PeerIp.empty()) { CHECK_SOCKET_CREATED("CBaseBerkeleySocket::GetPeerName"); struct sockaddr_in Peer; int PeerLen = sizeof(Peer); //Ask getpeername to fill in peer's socket address. if (getpeername(m_Socket, (SOCKADDR*)&Peer, &PeerLen) != BERKELEY_SOCKETS_OK) { LogEvent(LE_WARNING, "CBaseBerkeleySocket::GetPeerName - received error in getting peer name. Socket [%x], message - %s", m_Socket, GetSocketErrorStr(WSAGetLastError()).c_str()); return false; } m_PeerIp = inet_ntoa(Peer.sin_addr); m_PeerPort = (int)ntohs(Peer.sin_port); } PeerIP = m_PeerIp; PeerPort = m_PeerPort; return true; }
void CBaseBerkeleySocket::Close() { if (IsClosed()) return; CSocketEventsManager* EventMgr = CSocketEventsManager::GetTheSocketEventsManager(); if (EventMgr == NULL) LogEvent(LE_WARNING, "CBaseBerkeleySocket::Close - The SocketEventsManager is already closed (Socket [%x])", m_Socket); else EventMgr->UnregisterSocket(m_Socket); ShutDown(); if (closesocket(m_Socket) != BERKELEY_SOCKETS_OK) { LogEvent(LE_ERROR, "CBaseBerkeleySocket::Close - received error in CloseSocket command. socket [%x], message - %s", m_Socket, GetSocketErrorStr(WSAGetLastError()).c_str()); } LogEvent(LE_INFO, "CBaseBerkeleySocket::Close - socket [%x] was closed", m_Socket); m_Socket = INVALID_SOCKET; return; }
///////////////////////// // Read data from the socket and process it void IRCClient::readData() { // Get data from the socket char buf[1024]; int read = 1; while (read > 0) { int read = m_chatSocket.Read(buf, sizeof(buf)); // HINT: non-blocking // Nothing yet if (read == 0) break; // Error if(read < 0) { if (!IsMessageEndSocketErrorNr(GetSocketErrorNr())) { errors("IRC: network error - " + GetSocketErrorStr(GetSocketErrorNr()) + "\n"); disconnect(); } break; } // Add the data to the buffer m_netBuffer.append(buf, read); } if (m_netBuffer.empty()) return; size_t pos = m_netBuffer.find("\r\n"); while(pos != std::string::npos) { std::string line = m_netBuffer.substr(0, pos); //printf("IRC: %s\n", line.c_str()); // Check if the sender is specified m_netBuffer.erase(0, pos + 2); IRCCommand cmd; if(line.size() && line[0] == ':') { size_t pos2 = line.find(' '); cmd.sender = line.substr(1, pos2); // Check for exclamation mark in the nick as a special character size_t excl_pos = cmd.sender.find('!'); if (excl_pos != std::string::npos) { cmd.sender.erase(excl_pos); // Erase anything (usually IP + ISP info) from the nick } line.erase(0, pos2 + 1); } // Get the command and parameters cmd.cmd = line.substr(0, line.find(' ')); while (line.find(' ') != std::string::npos ) { line = line.substr(line.find(' ') + 1); if (line.size() == 0) break; if (line[0] == ':') { cmd.params.push_back(line.substr(1)); break; } cmd.params.push_back(line.substr(0, line.find(' '))); } // Parse the command parseCommand(cmd); pos = m_netBuffer.find("\r\n"); } }
const char * CBaseBerkeleySocket::GetLastErrorAsString() const { return GetSocketErrorStr(GetLastError()).c_str(); }