bool MultiplexedSocket::sendBytes(const MultiplexedSocketPtr& thus,const RawRequest&data, unsigned int maxQueueSize) { bool retval=false; if (thus->mSocketConnectionPhase==CONNECTED) { retval=sendBytesNow(thus,data,false); }else { bool lockCheckConnected=false; { boost::lock_guard<boost::mutex> connectingMutex(sConnectingMutex); if (thus->mSocketConnectionPhase==CONNECTED) { lockCheckConnected=true; }else if(thus->mSocketConnectionPhase==DISCONNECTED) { //retval=false; //FIXME is this the correct thing to do? TCPSSTLOG(this,"sendnvr",&*data.data->begin(),data.data->size(),false); TCPSSTLOG(this,"sendnvr","\n",1,false); }else { //with the connectionMutex acquired, no socket is allowed to be in the mSocketConnectionPhase assert(thus->mSocketConnectionPhase==PRECONNECTION); TCPSSTLOG(this,"sendl8r",&*data.data->begin(),data.data->size(),false); TCPSSTLOG(this,"sendl8r","\n",1,false); if (thus->mNewRequests==NULL) { thus->mNewRequests=new SizedThreadSafeQueue<RawRequest>(SizedResourceMonitor(maxQueueSize)); } retval=thus->mNewRequests->push(data,false); } } if (lockCheckConnected) { retval=sendBytesNow(thus,data,false); } } return retval; }
void ASIOSocketWrapper::sendManyDequeItems(const std::tr1::weak_ptr<MultiplexedSocket>&weakParentMultiSocket, const ErrorCode &error, std::size_t bytes_sent) { MultiplexedSocketPtr parentMultiSocket(weakParentMultiSocket.lock()); mOutstandingDataParent.reset(); if (parentMultiSocket) { std::deque<TimestampedChunk> local_toSend; local_toSend.swap(mToSend); if (error ) { triggerMultiplexedConnectionError(&*parentMultiSocket,this,error); SILOG(tcpsst,insane,"Socket disconnected...waiting for recv to trigger error condition\n"); } else { size_t total_size=0; for (std::deque<TimestampedChunk>::const_iterator i=local_toSend.begin(),ie=local_toSend.end(); i!=ie; ++i) { finishedSendingChunk(*i); size_t cursize=i->size(); total_size+=cursize; if (cursize) { BufferPrint(this,".sec",&*i->chunk->begin(),cursize); TCPSSTLOG(this,"snd",&*i->begin(),i->size,error); } delete i->chunk; } assert(total_size==bytes_sent);//otherwise should have given us an error //and send further items on the global queue if they are there finishAsyncSend(parentMultiSocket); } } }
bool MultiplexedSocket::sendBytesNow(const MultiplexedSocketPtr& thus,const RawRequest&data, bool force) { TCPSSTLOG(this,"sendnow",&*data.data->begin(),data.data->size(),false); TCPSSTLOG(this,"sendnow","\n",1,false); static Stream::StreamID::Hasher hasher; if (data.originStream==Stream::StreamID()) { unsigned int socket_size=(unsigned int)thus->mSockets.size(); for(unsigned int i=1;i<socket_size;++i) { thus->mSockets[i].rawSend(thus,new Chunk(*data.data),true); } thus->mSockets[0].rawSend(thus,data.data,true); return true; }else { size_t whichStream=hasher(data.originStream)%thus->mSockets.size(); if (data.unordered) { whichStream=thus->leastBusyStream(whichStream); } if (data.unreliable==false||rand()/(float)RAND_MAX>thus->dropChance(data.data,whichStream)) { return thus->mSockets[whichStream].rawSend(thus,data.data,force); }else { return true; } } }
void ASIOReadBuffer::asioReadIntoFixedBuffer(const ErrorCode&error,std::size_t bytes_read) { TCPSSTLOG(this,"rcv",&mBuffer[mBufferPos],bytes_read,error); mBufferPos+=bytes_read; std::tr1::shared_ptr<MultiplexedSocket> thus(mParentSocket.lock()); if (thus) { if (error) { processError(&*thus,error); } else { translateBuffer(thus); } } else { delete this;// the socket is deleted } }
bool ASIOSocketWrapper::rawSend(const MultiplexedSocketPtr&parentMultiSocket, Chunk * chunk, bool force) { bool retval=true; TCPSSTLOG(this,"raw",&*chunk->begin(),chunk->size(),false); uint32 current_status=++mSendingStatus; if (current_status==1) {//we are teh chosen thread mSendingStatus+=(ASYNCHRONOUS_SEND_FLAG-1);//committed to be the sender thread sendToWire(parentMultiSocket, chunk); } else {//if someone else is possibly sending a packet //push the packet on the queue retval=mSendQueue.push(chunk, force); current_status=--mSendingStatus; if (retval) { //the packet is out of our hands now... //but the other thread could just have been finishing up and we have missed the send //this is our opportunity to take up the torch and send if our packet is still there retryQueuedSend(parentMultiSocket,current_status); }//else delete chunk; <-- deleted by sender } return retval; }
void ASIOReadBuffer::asioReadIntoChunk(const ErrorCode&error,std::size_t bytes_read) { TCPSSTLOG(this,"rcv",&mNewChunk[mBufferPos],bytes_read,error); mBufferPos+=bytes_read; std::tr1::shared_ptr<MultiplexedSocket> thus(mParentSocket.lock()); if (thus) { if (error) { processError(&*thus,error); } else { if (mBufferPos>=mNewChunk.size()) { assert(mBufferPos==mNewChunk.size()); processFullChunk(thus,mWhichBuffer,mNewChunkID,mNewChunk); mNewChunk.resize(0); mBufferPos=0; readIntoFixedBuffer(thus); } else { readIntoChunk(thus); } } } else { delete this; } }