// ------------------------------------------------------------------------ // Translates raw byte data into telnet data, and may send it out to // the connection's current protocol handler // ------------------------------------------------------------------------ void Telnet::Translate( Connection<Telnet>& p_conn, char* p_buffer, int p_size ) { for( int i = 0; i < p_size; i++ ) { // if the character is a letter and the buffer isn't full, // add it to the buffer char c = p_buffer[i]; if( c >= 32 && c != 127 && m_buffersize < BUFFERSIZE ) { m_buffer[m_buffersize] = c; m_buffersize++; } // else check if it's a backspace else if( c == 8 && m_buffersize > 0 ) { // erase the last character m_buffersize--; } // else check if it is a newline, meaning the line is complete else if( c == '\n' || c == '\r' ) { // if the buffer size is more than 0, turn the buffer into // a string and send it off to the current handler of the // connection. Then reset the size of the buffer. if( m_buffersize > 0 && p_conn.Handler() != 0 ) { p_conn.Handler()->Handle( string( m_buffer, m_buffersize ) ); } m_buffersize = 0; } } }
void sMiniFTPServer::ClientThreadFunc(sThread *t,void *user) { Connection *c = (Connection *) user; sTCPSocket *socket = c->Socket; RequestInfo info; sVERIFYSTATIC(ServerBufferSize >= 16 && ServerBufferSize >= MAXREQUEST*2); sFixedArray<sU8> ioBuffer(ServerBufferSize); while(socket->IsConnected() && t->CheckTerminate()) { // read request if(!socket->ReadAll(&ioBuffer[0],16)) break; // "parse" it sU32 command; sInt filenameLen; sU64 extra; sUnalignedLittleEndianLoad32(&ioBuffer[0],command); sUnalignedLittleEndianLoad32(&ioBuffer[4],(sU32&) filenameLen); sUnalignedLittleEndianLoad64(&ioBuffer[8],extra); if(command > sMFC_LAST || filenameLen >= MAXREQUEST) break; // read the filename sString<MAXREQUEST> filename; if(!socket->ReadAll(&ioBuffer[0],filenameLen*2)) break; // "parse" it for(sInt i=0;i<filenameLen;i++) { sU16 x; sUnalignedLittleEndianLoad16(&ioBuffer[i*2],x); filename[i] = x; } filename[filenameLen] = 0; // command-specific handling info.Command = (sMiniFTPCommand) command; info.Filename = filename; info.File = 0; info.DirListing.Clear(); ioBuffer[0] = sU8(c->Handler(info) ? sMFE_OK : sMFE_NOSUCHFILE); sBool ok = socket->WriteAll(&ioBuffer[0],1); if(ok && ioBuffer[0] == sMFE_OK) // output processing (depends on command) { ok = sFALSE; switch(command) { case sMFC_EXISTS: case sMFC_DELETE: ok = sTRUE; break; case sMFC_GET: { sSize size = info.File->GetSize(); sUnalignedLittleEndianStore64(&ioBuffer[0],size); if(socket->WriteAll(&ioBuffer[0],8) && info.File->SetOffset(extra)) { sSize pos = extra; while(pos<size) { sInt bytes = (sInt) sMin<sS64>(size-pos,ioBuffer.GetSize()); if(!info.File->Read(&ioBuffer[0],bytes) || !socket->WriteAll(&ioBuffer[0],bytes)) break; pos += bytes; } ok = (pos == size); } } break; case sMFC_PUT: { sSize size; if(c->OnlyFullFiles && extra != 0) break; if(!socket->ReadAll(&ioBuffer[0],8)) break; sUnalignedLittleEndianLoad64(&ioBuffer[0],(sU64&) size); if(info.File->SetOffset(extra)) { sSize pos = extra; while(pos<size) { sInt bytes = (sInt) sMin<sS64>(size-pos,ioBuffer.GetSize()); if(!socket->ReadAll(&ioBuffer[0],bytes) || !info.File->Write(&ioBuffer[0],bytes)) break; pos += bytes; } ok = (pos == size); if(c->OnlyFullFiles && !ok) { sDelete(info.File); sLogF(L"miniftp",L"transfer of file <%s> incomplete, deleting it again.\n",info.Filename); // delete the file again info.Command = sMFC_DELETE; c->Handler(info); } } } break; case sMFC_LIST: { sInt count = info.DirListing.GetCount(); sUnalignedLittleEndianStore64(&ioBuffer[0],count*2); if(socket->WriteAll(&ioBuffer[0],8)) { sFixedArray<sU8> buffer(count*2); for(sInt i=0;i<count;i++) sUnalignedLittleEndianStore16(&buffer[i*2],info.DirListing[i]); ok = socket->WriteAll(&buffer[0],count*2); } } break; } } sDelete(info.File); if(!ok) break; } socket->Disconnect(); }