void MagicField::onStepInField(Creature* creature, bool purposeful/*= true*/) { //remove magic walls/wild growth if(isBlocking()){ g_game.internalRemoveItem(this, 1); } else{ const ItemType& it = items[getID()]; if(it.condition){ Condition* conditionCopy = it.condition->clone(); uint32_t owner = getOwner(); if(owner != 0 && purposeful){ bool harmfulField = true; if(g_game.getWorldType() == WORLD_TYPE_NO_PVP || getTile()->hasFlag(TILESTATE_NOPVPZONE) ){ Creature* creature = g_game.getCreatureByID(owner); if(creature){ if(creature->getPlayer() || (creature->isSummon() && creature->getMaster()->getPlayer())){ harmfulField = false; } } } if( !harmfulField || (OTSYS_TIME() - createTime <= g_config.getNumber(ConfigManager::FIELD_OWNERSHIP_DURATION)) || creature->hasBeenAttacked(owner)) { conditionCopy->setParam(CONDITIONPARAM_OWNER, owner); } } creature->addCondition(conditionCopy); } } }
int click_send(int sockfd, xia::XSocketMsg *xsm) { int rc = 0; static int initialized = 0; static struct sockaddr_in sa; assert(xsm); // FIXME: have I created a race condition here? if (!initialized) { sa.sin_family = PF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = htons(atoi(CLICKPORT)); initialized = 1; } if (isBlocking(sockfd)) { // make sure click know if it should reply immediately or not xsm->set_blocking(true); } xsm->set_port(getPort(sockfd)); std::string p_buf; xsm->SerializeToString(&p_buf); int remaining = p_buf.size(); const char *p = p_buf.c_str(); while (remaining > 0) { //LOGF("sending to click: seq: %d type: %d", xsm->sequence(), xsm->type()); rc = (_f_sendto)(sockfd, p, remaining, 0, (struct sockaddr *)&sa, sizeof(sa)); if (rc == -1) { LOGF("click socket failure: errno = %d", errno); break; } else { remaining -= rc; p += rc; if (remaining > 0) { LOGF("%d bytes left to send", remaining); #if 1 // FIXME: click will crash if we need to send more than a // single buffer to get the entire block of data sent. Is // this fixable, or do we have to assume it will always go // in one send? LOG("click can't handle partial packets"); rc = -1; break; #endif } } } return (rc >= 0 ? 0 : -1); }
Socket::Status TcpSocket::send(const void* data, std::size_t size) { if (!isBlocking()) err() << "Warning: Partial sends might not be handled properly." << std::endl; std::size_t sent; return send(data, size, sent); }
vpr::Uint32 SocketDatagramImplBSD::recvfrom(void* msg, const vpr::Uint32 length, vpr::InetAddr& from, const vpr::Interval& timeout) { vpr::Uint32 bytes_read(0); #if defined(VPR_OS_IRIX) || defined(VPR_OS_HPUX) int fromlen; #else socklen_t fromlen; #endif // If not readable within timeout interval throw exception. if ( ! mHandle->isReadable(timeout) ) { std::ostringstream msg_stream; msg_stream << "Timeout occured while trying to read from " << mHandle->getName(); throw TimeoutException(msg_stream.str(), VPR_LOCATION); } ssize_t bytes; mBlockingFixed = true; fromlen = from.size(); bytes = ::recvfrom(mHandle->mFdesc, msg, length, 0, reinterpret_cast<sockaddr*>(&from.mAddr), &fromlen); if ( bytes == -1 ) { if ( errno == EAGAIN && ! isBlocking() ) { throw WouldBlockException("Would block while reading.", VPR_LOCATION); } else { std::ostringstream ss; ss << "[vpr::SocketDatagramImplBSD::recvfrom()] ERROR: Could not " << "read from socket (" << mRemoteAddr << "): " << strerror(errno); throw SocketException(ss.str(), VPR_LOCATION); } } else if ( bytes == 0 ) { throw SocketException("Socket not connected."); } else { bytes_read = bytes; } return bytes_read; }
// @brief Send post request // @param string uri the request uri // @return If no error occurs returns the number of receive data in bytes, // Otherwise -1 is returns int HTTPClient::post( string uri, Chars &body ) { string str; m_method = "POST"; str += "POST " + uri + " " + m_version; str += "\r\n"; str += "Host: " + m_host; str += "\r\n"; map<string, string>::iterator iter = m_requestHeader.begin(); while (iter != m_requestHeader.end()) { str += iter->first + ": "; str += iter->second; str += "\r\n"; ++iter; } // Set 'Content-length' str += "Content-Length: "; char buf[25]; snprintf(buf, 25, "%ld", body.length()); str += buf; str += "\r\n"; // Headers end str += "\r\n"; Chars data; data.assign(str.c_str(), str.length()); data.append(body.c_str(), body.length()); if (!isBlocking()) { setBlocking(); } // Set receive and send timeout to 5 seconds int nTimeout = 5000; if (m_host == "127.0.0.1") { nTimeout = 100; } setRcvTimeout(nTimeout); setSndTimeout(nTimeout); int n = this->send(data.c_str(), data.length()); if (n == -1) { return n; } //this->shutdown(SHUT_WD); /** * Receive response data */ // Receive all response data to socket buffer including HTTP headers while ( this->recv(1024) > 0 ) ; return decodeHttpData(); }
/// Will not buffer anything but always send right away. Blocks. /// Any data that could not be send will block until it can be send or the connection is severed. void Socket::Connection::SendNow(const char * data, size_t len) { bool bing = isBlocking(); if (!bing) { setBlocking(true); } unsigned int i = iwrite(data, std::min((long unsigned int)len, SOCKETSIZE)); while (i < len && connected()) { i += iwrite(data + i, std::min((long unsigned int)(len - i), SOCKETSIZE)); } if (!bing) { setBlocking(false); } }
/// Updates the downbuffer and upbuffer internal variables until upbuffer is empty. /// Returns true if new data was received, false otherwise. bool Socket::Connection::flush(){ bool bing = isBlocking(); if (!bing){setBlocking(true);} while (upbuffer.size() > 0 && connected()){ iwrite(upbuffer.get()); } if (!bing){setBlocking(false);} /// \todo Provide better mechanism to prevent overbuffering. if (downbuffer.size() > 1000){ return true; }else{ return iread(downbuffer); } }
void MagicField::onStepInField(Creature* creature, bool purposeful/* = true*/) { if(!creature) return; if(isUnstepable() || isBlocking(creature)) { if(!creature->isGhost()) g_game.internalRemoveItem(creature, this, 1); return; } if(!purposeful || !creature->isAttackable()) return; const ItemType& it = items[id]; if(!it.condition) return; uint32_t ownerId = getOwner(); Tile* tile = getTile(); Condition* condition = it.condition->clone(); if(ownerId && !tile->hasFlag(TILESTATE_HARDCOREZONE)) { if(Creature* owner = g_game.getCreatureByID(ownerId)) { Player* ownerPlayer = owner->getPlayer(); if(!ownerPlayer && owner->isPlayerSummon()) ownerPlayer = owner->getPlayerMaster(); bool harmful = true; if((g_game.getWorldType() == WORLDTYPE_OPTIONAL || tile->hasFlag(TILESTATE_OPTIONALZONE)) && ownerPlayer) harmful = false; else if(Player* player = creature->getPlayer()) { if(ownerPlayer && Combat::isProtected(ownerPlayer, player)) harmful = false; } if(!harmful || (OTSYS_TIME() - createTime) <= (uint32_t)g_config.getNumber( ConfigManager::FIELD_OWNERSHIP) || creature->hasBeenAttacked(ownerId)) condition->setParam(CONDITIONPARAM_OWNER, ownerId); } } creature->addCondition(condition); }
/// Will not buffer anything but always send right away. Blocks. /// This will send the upbuffer (if non-empty) first, then the data. /// Any data that could not be send will block until it can be send or the connection is severed. void Socket::Connection::SendNow(const char * data, size_t len){ bool bing = isBlocking(); if (!bing){setBlocking(true);} while (upbuffer.size() > 0 && connected()){ iwrite(upbuffer.get()); } int i = iwrite(data, len); while (i < len && connected()){ int j = iwrite(data + i, std::min(len - i, (size_t)51200)); if (j > 0){ i += j; } } if (!bing){setBlocking(false);} }
void Sockethelper::sendall(const char * buf, size_t len) { while (len > 0) { int n = send(buf, len); if (n > 0) { len -= n; buf += n; } // (n==0) // try send first. throw if nonblock and send failed else if (!isBlocking()) throw socket_error(0, "send_all but nonblock"); // blocking and n==0 is ok. restart interrupt default } }
/*! ** @brief manipulate Xsocket ** ** Performs one of the operations described below on the open file descriptor sockfd. ** The operation is determined by cmd. ** ** Xfcntl() can take an optional third argument. Whether or not this argument is required is ** determined by cmd. The required argument type is indicated in parentheses after each cmd ** name (in most cases, the required type is int, and we identify the argument using the ** name arg), or void is specified if the argument is not required. ** ** File status flags ** F_GETFL (void) ** Get the file access mode and the file status flags; arg is ignored. ** ** F_SETFL (int) ** Currently only O_NONBLOCK is allowed ** ** @param sockfd a file descriptor create by Xsocket() ** @param cmd the command to execute ** @param arg the flag to set if cmd == F_GETFL, otherwise omitted ** @returns socket flags if cmd == F_GETFL ** @returns 0 on success if cmd == F_SETFL ** @returns -1 on error with errno set to an error compatible with those ** returned by the standard fcntl call. */ int Xfcntl(int sockfd, int cmd, ...) { int rc = 0; if (getSocketType(sockfd) == XSOCK_INVALID) { errno = EBADF; return -1; } switch(cmd) { case F_GETFL: rc = (_f_fcntl)(sockfd, cmd); if (rc >= 0 && isBlocking(sockfd)) rc |= O_NONBLOCK; break; case F_SETFL: { va_list args; va_start(args, cmd); int f = va_arg(args, int); va_end(args); int block = (f & O_NONBLOCK) ? false : true; LOGF("Blocking set to %s", block ? "true" : "false"); setBlocking(sockfd, block); rc = 0; if (f & ~O_NONBLOCK) { LOGF("unsupported flag(s) found (%s) ignoring...", fcntlFlags(f & ~O_NONBLOCK)); } break; } default: LOGF("Invalid command specified to Xfcntl: %08x", cmd); rc = -1; break; } return rc; }
void MagicField::onStepInField(const CreatureP& creature) { if(getId() == ITEM_MAGICWALL_SAFE || getId() == ITEM_WILDGROWTH_SAFE || isBlocking(creature.get())) { if(!creature->isGhost()) server.game().internalRemoveItem(creature.get(), this, 1); return; } if(!getKind()->condition) return; Condition* condition = getKind()->condition->clone(); uint32_t ownerId = getOwner(); if(ownerId && !getTile()->hasFlag(TILESTATE_PVPZONE)) { if(auto owner = server.world().getCreatureById(ownerId)) { bool harmful = true; if((server.game().getWorldType() == WORLD_TYPE_NO_PVP || getTile()->hasFlag(TILESTATE_NOPVPZONE)) && (owner->getPlayer() || owner->hasController())) harmful = false; else if(Player* targetPlayer = creature->getPlayer()) { if(owner->getPlayer() && Combat::isProtected(owner->getPlayer(), targetPlayer)) harmful = false; } if(!harmful || (OTSYS_TIME() - createTime) <= (uint32_t)server.configManager().getNumber( ConfigManager::FIELD_OWNERSHIP) || creature->hasBeenAttacked(ownerId)) condition->setParam(CONDITIONPARAM_OWNER, ownerId); } } creature->addCondition(condition); }
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout) { // Disconnect the socket if it is already connected disconnect(); // Create the internal socket if it doesn't exist create(); // Create the remote address sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort); if (timeout <= Time::Zero) { // ----- We're not using a timeout: just try to connect ----- // Connect the socket if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1) return priv::SocketImpl::getErrorStatus(); // Connection succeeded return Done; } else { // ----- We're using a timeout: we'll need a few tricks to make it work ----- // Save the previous blocking state bool blocking = isBlocking(); // Switch to non-blocking to enable our connection timeout if (blocking) setBlocking(false); // Try to connect to the remote address if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0) { // We got instantly connected! (it may no happen a lot...) setBlocking(blocking); return Done; } // Get the error status Status status = priv::SocketImpl::getErrorStatus(); // If we were in non-blocking mode, return immediately if (!blocking) return status; // Otherwise, wait until something happens to our socket (success, timeout or error) if (status == Socket::NotReady) { // Setup the selector fd_set selector; FD_ZERO(&selector); FD_SET(getHandle(), &selector); // Setup the timeout timeval time; time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000); time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000); // Wait for something to write on our socket (which means that the connection request has returned) if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0) { // At this point the connection may have been either accepted or refused. // To know whether it's a success or a failure, we must check the address of the connected peer if (getRemoteAddress() != IpAddress::None) { // Connection accepted status = Done; } else { // Connection refused status = priv::SocketImpl::getErrorStatus(); } } else { // Failed to connect before timeout is over status = priv::SocketImpl::getErrorStatus(); } } // Switch back to blocking mode setBlocking(true); return status; } }
void MagicField::onStepInField(Creature* creature, bool purposeful/*= true*/) { //remove magic walls/wild growth if (id == ITEM_MAGICWALL_SAFE || id == ITEM_WILDGROWTH_SAFE || id == ITEM_MAGICWALL || id == ITEM_WILDGROWTH) { bool isBlockingVar = isBlocking(creature); bool config = g_config.getBoolean(ConfigManager::MW_DISAPPEAR_ON_WALK); if (isBlockingVar || (!isBlockingVar && config)) { g_game.internalRemoveItem(this, 1); } } else { const ItemType& it = items[getID()]; if (it.condition) { if (canOwnerHarm(creature)) { Condition* conditionCopy = it.condition->clone(); uint32_t ownerId = getOwner(); if (ownerId != 0 && purposeful) { Creature* owner = g_game.getCreatureByID(ownerId); if (owner && (owner != creature)) { if ((OTSYS_TIME() - createTime <= g_config.getNumber(ConfigManager::FIELD_OWNERSHIP_DURATION)) || owner->hasBeenAttacked(ownerId)) { conditionCopy->setParam(CONDITIONPARAM_OWNER, ownerId); } } } if (Player* player = creature->getPlayer()) { if (ConditionDamage* conditionDamage = static_cast<ConditionDamage*>(conditionCopy)) { Item* tmpItem = NULL; for (int32_t i = SLOT_FIRST; i <= SLOT_LAST; i++) { if ((tmpItem = player->getInventoryItem((slots_t)i))) { if (tmpItem->getWieldPosition() != i) { continue; } const ItemType& it = items[tmpItem->getID()]; std::map<uint16_t, int16_t>::const_iterator id = it.abilities.absorbFieldDamage.find(getID()); if (id != it.abilities.absorbFieldDamage.end()) { int32_t index = 0, length = conditionDamage->getLength(); std::list<IntervalInfo> damageList; for (; index < length; index++) { IntervalInfo info = conditionDamage->popFrontDamage(); info.value = (int32_t)std::floor((double)info.value * (100 - id->second) / 100.); damageList.push_back(info); conditionDamage->setTicks(conditionDamage->getTicks() - info.interval); } index = 0; length -= it.abilities.conditionCount; conditionDamage->clearDamageList(); for (std::list<IntervalInfo>::iterator itt = damageList.begin(); itt != damageList.end(); ++itt) { conditionDamage->addDamage(1, itt->interval, itt->value); if (++index == length) { break; } } } } } if (conditionDamage->getTotalDamage() > 0) { conditionDamage->setParam(CONDITIONPARAM_FORCEUPDATE, true); } creature->addCondition(conditionDamage); return; } } creature->addCondition(conditionCopy); } } } }
// @brief Send HTTP get request // @param string uri The request uri // @return If no error occurs returns the number of receive in bytes, // Otherwise -1 is returns int HTTPClient::get( string uri ) { string str; m_method = "GET"; str += "GET " + uri + " " + m_version; str += "\r\n"; str += "Host: " + m_host; str += "\r\n"; map<string, string>::iterator iter = m_requestHeader.begin(); while (iter != m_requestHeader.end()) { str += iter->first + ": "; str += iter->second; str += "\r\n"; ++iter; } // Headers end str += "\r\n"; if (!isBlocking()) { setBlocking(); } // Set receive and send timeout to 5 seconds int nTimeout = 5000; if (m_host == "127.0.0.1") { nTimeout = 100; } setRcvTimeout(nTimeout); setSndTimeout(nTimeout); int n = this->send(str.c_str(), str.length()); if (n == -1) { return n; } //this->shutdown(SHUT_WD); /** * Receive response data */ // Receive all response data to socket buffer including HTTP headers while ( this->recv(1024) > 0 ) ; return decodeHttpData(); #if 0 // If No data was receive if (m_recv_buffer.length() <= 0) return -1; // Decode HTTP data Chars http_data; string line; int line_count = 0; size_t content_length = 0; size_t i = 0; bool is_chunked = false; /** * Read HTTP header */ for ( i = 0; i < m_recv_buffer.length(); ++i ) { line += m_recv_buffer.at(i); if (line[line.length() - 1] == 0x0a) {// \n line_count ++; // Erase \r\n. line = line.substr(0, line.length() - 2); if (line.empty()) { // Empty line: headers end break; } if (line_count == 1) { // The first line: HTTP/1.1 200 OK // 0x20: ' ' m_version = line.substr(0, line.find_first_of(0x20)); m_status = line.substr(line.find_first_of(0x20) + 1, line.find_last_of(0x20) - line.find_first_of(0x20) - 1); } else { /// Headers std::string key = line.substr(0, line.find_first_of(':')); std::string value = line.substr(line.find_first_of(':') + 2, line.length() - line.find_first_of(':') - 2); m_responseHeader[key] = value; // Whether exists 'Content-Length' field. if (Utility::icompare(key, "Content-Length") == 0) { content_length = atol(value.c_str()); } // Is chunked ? if (Utility::icompare(key, "Transfer-Encoding") == 0 && Utility::icompare(value, "chunked") == 0) { is_chunked = true; } } // Empty line line = ""; } // end if } // end for() /// Erase \r\n for ( ; i < m_recv_buffer.length(); ++i ) { if (m_recv_buffer.at(i) == 0x0d || m_recv_buffer.at(i) == 0x0a) continue; break; } /** * Read HTTP content */ if (content_length != 0) { http_data = m_recv_buffer.substr(i, content_length); i += content_length; } else { // Is chunked ? if (is_chunked) { // Process chunked data /// Read Content-Length flag line = ""; for ( ; i < m_recv_buffer.length(); ++i ) { line += m_recv_buffer.at(i); if (line[line.length() - 1] == 0x0a) { content_length = Utility::hexToDecimal((line.substr(0, line.length() - 2)).c_str()); break; } } long p = 0; while (true) { // Find EOF flag p = m_recv_buffer.find(p, "0\r\n\r\n", 5); if (p == -1) break; if (p <= (long)i) { p = i; continue; } break; } if (p != -1) { i += 1; http_data = m_recv_buffer.substr(i, p - i); i += p - i; } else { // Does not found the end flag "0\r\n\r\n" http_data = m_recv_buffer.substr(++i, content_length); i += content_length; } } // end if(is_chunked) } m_recv_buffer = http_data; // Return receive length in bytes return ++i; #endif }
void MagicField::onStepInField(Creature* creature) { //remove magic walls/wild growth if (id == ITEM_MAGICWALL || id == ITEM_WILDGROWTH || id == ITEM_MAGICWALL_SAFE || id == ITEM_WILDGROWTH_SAFE || isBlocking()) { if (!creature->isInGhostMode()) { g_game.internalRemoveItem(this, 1); } return; } const ItemType& it = items[getID()]; if (it.condition) { Condition* conditionCopy = it.condition->clone(); uint32_t ownerId = getOwner(); if (ownerId) { bool harmfulField = true; if (g_game.getWorldType() == WORLD_TYPE_NO_PVP || getTile()->hasFlag(TILESTATE_NOPVPZONE)) { Creature* owner = g_game.getCreatureByID(ownerId); if (owner) { if (owner->getPlayer() || (owner->isSummon() && owner->getMaster()->getPlayer())) { harmfulField = false; } } } Player* targetPlayer = creature->getPlayer(); if (targetPlayer) { Player* attackerPlayer = g_game.getPlayerByID(ownerId); if (attackerPlayer) { if (Combat::isProtected(attackerPlayer, targetPlayer)) { harmfulField = false; } } } if (!harmfulField || (OTSYS_TIME() - createTime <= 5000) || creature->hasBeenAttacked(ownerId)) { conditionCopy->setParam(CONDITION_PARAM_OWNER, ownerId); } } creature->addCondition(conditionCopy); } }
int click_get(int sock, unsigned seq, char *buf, unsigned buflen, xia::XSocketMsg *msg) { int rc; if (isBlocking(sock)) { // make sure click knows if it should reply immediately or not msg->set_blocking(true); } while (1) { // see if another thread received and cached our packet if (0) { // if ((rc = getCachedPacket(sock, seq, buf, buflen)) > 0) { LOGF("Got cached response with sequence # %d\n", seq); std::string s(buf, rc); msg->ParseFromString(s); break; } else { bzero(buf, buflen); // we do this with a blocking socket even if the Xsocket is marked as nonblocking. // The UDP socket is treated as an API call rather than a sock so making it // non-blocking would cause problems rc = (_f_recvfrom)(sock, buf, buflen - 1 , 0, NULL, NULL); // LOGF("seq %d received %d bytes\n", seq, rc); if (rc < 0) { if (isBlocking(sock) || (errno != EWOULDBLOCK && errno != EAGAIN)) { LOGF("error(%d) getting reply data from click", errno); } rc = -1; break; } else { std::string s(buf, rc); msg->ParseFromString(s); assert(msg); unsigned sn = msg->sequence(); if (sn == seq) break; // these are not the data you were looking for LOGF("Expected packet %u, received %u, replaying packet\n", seq, sn); // cachePacket(sock, sn, buf, buflen); // msg->PrintDebugString(); // shove this back into click so the requester can get at it xia::X_Replay_Msg *xrm = msg->mutable_x_replay(); xrm->set_sequence(msg->sequence()); xrm->set_type(msg->type()); msg->set_sequence(0); msg->set_type(xia::XREPLAY); click_send(sock, msg); msg->Clear(); } } } return rc; }
// // connect() // bool SocketChannel::connect(const SocketAddress& remote,const char* interface) throw(AlreadyConnectedException, ConnectionPendingException, ClosedChannelException, AsynchronousCloseException, ClosedByInterruptException, UnresolvedAddressException, UnsupportedAddressTypeException, IOException) { int error = 0; try { // Sincroniza esta operacion con finishConnect() Synchronized synchronized(_connect); { // Comprueba si ya esta conectado if (isConnected()) { throw AlreadyConnectedException("Channel already connected"); } // Comprueba si hay una operacion de conexion en curso if (isConnectionPending()) { throw ConnectionPendingException( "Non-blocking connection already in progress"); } // Comprueba si esta cerrado if (! isOpen()) { throw ClosedChannelException("Channel is closed"); } // Comprueba si 'remote' es un objeto InetSocketAddress const InetSocketAddress* remoteptr = dynamic_cast<const InetSocketAddress*>(&remote); if (remoteptr == NULL) { throw UnsupportedAddressTypeException("Invalid SocketAddress"); } // Comprueba si la direccion SockAddress esta resuelta if (remoteptr->isUnresolved()) { throw UnresolvedAddressException( "Remote address not fully resolved"); } // Comprueba si esta en modo bloqueante if (isBlocking()) { // Intenta la conexion _socket->connect(remote,interface); // Modifica el estado Synchronized synchronized(_sync); { _status |= TID_SOCKET_CHANNEL_STATUS_CONNECTED; } return true; } // Prepara los datos de la conexion PlainSocketImpl::toSockAddr(remoteptr->getAddress(), remoteptr->getPort(), _sockaddr, _socksize, interface); // Conexion no bloqueante int fd = (int) _socket->_impl->getFileDescriptor(); error = ::connect(fd, (struct sockaddr*)&_sockaddr, _socksize); if (error && (errno != EINPROGRESS)) { throw IOException("connect() error", errno); } // Modifica el estado Synchronized synchronized(_sync); { if (error == 0) _status |= TID_SOCKET_CHANNEL_STATUS_CONNECTED; else _status |= TID_SOCKET_CHANNEL_STATUS_CONNECTION_PENDING; } } // Fin sincronizacion con finishConnect() } catch(TIDThr::Exception& e) { throw IOException(e.what()); } return (error == 0); }
sfBool sfUdpSocket_isBlocking(const sfUdpSocket* socket) { CSFML_CALL_RETURN(socket, isBlocking(), sfFalse); }
// Connect the socket on the client side to the server side. For a datagram // socket, this makes the address given to the constructor the default // destination for all packets. For a stream socket, this has the effect of // establishing a connection with the destination. void SocketImplBSD::connect(vpr::Interval timeout) { int status; // Attempt to connect to the address in mAddr. status = ::connect(mHandle->mFdesc, (struct sockaddr*) &mRemoteAddr.mAddr, mRemoteAddr.size()); // If connect(2) failed, print an error message explaining why and return // error status. if ( status == -1 ) { // If this is a non-blocking connection, return normally with the // post condition that users must call isConnected() after calling // connect when using non-blocking sockets. // NOTE: I'm not sure if it's safe to set mConnectCalled and // mBlockingFixed at this point, but they have to be set sometime. if ( errno == EINPROGRESS && ! isBlocking() ) { if ( vpr::Interval::NoWait != timeout ) { // Force socket to wait for timeout interval to expire // before returning. This provides a way for the caller // to specify that they want the connection process to // block even with a non-blocking socket. try { // Wait for read/write on the socket SelectorImplBSD selector; selector.addHandle(getHandle(), SelectorBase::Read | SelectorBase::Write); vpr::Uint16 num_events(0); selector.select(num_events, timeout); // Check for error state on socket vpr::SocketOptions::Data opt_data; getOption(SocketOptions::Error, opt_data); int sock_error = opt_data.error; if ( sock_error ) { close(); buildAndThrowException( "[vpr::SocketImplBSD::connect()] Async-connection error: ", VPR_LOCATION, sock_error ); } else // Completed in time { mBound = true; mConnectCalled = true; mBlockingFixed = true; } } // Select timed out, so the connect timed out catch (TimeoutException& te) { close(); throw TimeoutException("Timeout while connecting.", VPR_LOCATION); } } else // non-blocking connect started { mBound = true; mConnectCalled = true; mBlockingFixed = true; } } else { buildAndThrowException("[vpr::SocketImplBSD::connect()] ", VPR_LOCATION); } } // Otherwise, return success. else { mBound = true; mConnectCalled = true; mBlockingFixed = true; } // Fill in the local address if has not already been assigned. if ( mConnectCalled && vpr::InetAddr::AnyAddr == mLocalAddr ) { int status; #if defined(VPR_OS_IRIX) || defined(VPR_OS_HPUX) int namelen; #else socklen_t namelen; #endif struct sockaddr temp_addr; namelen = sizeof(struct sockaddr); status = getsockname(mHandle->mFdesc, &temp_addr, &namelen); if ( status == 0 ) { mLocalAddr.setSockaddr(&temp_addr); /* XXX: This doesn't compile on IRIX, and I don't know why. vprDEBUG(vprDBG_ALL, vprDBG_STATE_LVL) << "Connected, local address is " << mLocalAddr << std::endl << vprDEBUG_FLUSH; */ } else { vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL) << "Failed to get sock name: " << strerror(errno) << std::endl << vprDEBUG_FLUSH; } } }
// // finishConnect // bool SocketChannel::finishConnect(const char* interface) throw(NoConnectionPendingException, ClosedChannelException, AsynchronousCloseException, ClosedByInterruptException, IOException) { int error = 0; try { // Sincroniza esta operacion con connect() Synchronized synchronized(_connect); { // Comprueba si hay pendiente una conexion if (! isConnected() || ! isConnectionPending()) { throw NoConnectionPendingException("No connection pending"); } // Comprueba si esta cerrado if (! isOpen()) { throw ClosedChannelException("Channel is closed"); } // Comprueba si esta en modo bloqueante if (isBlocking()) { InetSocketAddress* remote = NULL; try { // Recupera los datos de la conexion remote = PlainSocketImpl::toInetSocketAddress((struct sockaddr*)&_sockaddr, _socksize); // Reintenta la conexion con los datos de connect() _socket->connect(*remote,interface); delete remote; // Modifica el estado Synchronized synchronized(_sync); { _status &=~TID_SOCKET_CHANNEL_STATUS_CONNECTION_PENDING; _status |= TID_SOCKET_CHANNEL_STATUS_CONNECTED; } } catch(...) { delete remote; throw; } return true; } // Conexion no bloqueante int fd = (int) _socket->_impl->getFileDescriptor(); error = ::connect(fd, (struct sockaddr*)&_sockaddr, _socksize); if (error && errno != EINPROGRESS && errno != EALREADY && errno != EISCONN) { throw IOException("finishConnect() error", errno); } // Modifica el estado if (error==0 || errno==EISCONN) { Synchronized synchronized(_sync); { _status &=~TID_SOCKET_CHANNEL_STATUS_CONNECTION_PENDING; _status |= TID_SOCKET_CHANNEL_STATUS_CONNECTED; } } } // Fin sincronizacion con finishConnect() } catch(TIDThr::Exception& e) { throw IOException(e.what()); } return (error==0 || errno==EISCONN); }
vpr::Uint32 SocketDatagramImplBSD::sendto(const void* msg, const vpr::Uint32 length, const vpr::InetAddr& to, const vpr::Interval& timeout) { vpr::Uint32 bytes_sent(0); // If not writable within timeout interval throw exception. if ( ! mHandle->isWriteable(timeout) ) { std::ostringstream msg_stream; msg_stream << "Timeout occured while trying to write to " << mHandle->getName(); throw TimeoutException(msg_stream.str(), VPR_LOCATION); } ssize_t bytes; mBlockingFixed = true; bytes = ::sendto(mHandle->mFdesc, msg, length, 0, reinterpret_cast<const sockaddr*>(&to.mAddr), to.size()); if ( bytes == -1 ) { if ( errno == EAGAIN && ! isBlocking() ) { throw WouldBlockException("Would block while reading.", VPR_LOCATION); } else { std::stringstream ss; ss << "[vpr::SocketDatagramImplBSD::sendto()] ERROR: Could not send " << " to " << to << " on socket (" << mRemoteAddr << "): " << strerror(errno); throw SocketException(ss.str(), VPR_LOCATION); } } if ( ECONNRESET == errno) { throw ConnectionResetException("Connection reset.", VPR_LOCATION); } else if (EHOSTUNREACH == errno) { throw NoRouteToHostException("No route to host.", VPR_LOCATION); } else if (EHOSTDOWN == errno) { throw UnknownHostException("Unknown host.", VPR_LOCATION); } else if (ENETDOWN == errno) { throw IOException("Network is down.", VPR_LOCATION); } else { bytes_sent = bytes; } return bytes_sent; }