|
Packit |
8f70b4 |
/*
|
|
Packit |
8f70b4 |
* lftp - file transfer program
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* Copyright (c) 1996-2016 by Alexander V. Lukyanov (lav@yars.free.net)
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8f70b4 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8f70b4 |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit |
8f70b4 |
* (at your option) any later version.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
8f70b4 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8f70b4 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8f70b4 |
* GNU General Public License for more details.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
8f70b4 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
8f70b4 |
*/
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include <config.h>
|
|
Packit |
8f70b4 |
#include <errno.h>
|
|
Packit |
8f70b4 |
#include "buffer.h"
|
|
Packit |
8f70b4 |
#include "FileAccess.h"
|
|
Packit |
8f70b4 |
#include "misc.h"
|
|
Packit |
8f70b4 |
#include "trio.h"
|
|
Packit |
8f70b4 |
#include "Speedometer.h"
|
|
Packit |
8f70b4 |
#include "log.h"
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#define BUFFER_INC (8*1024) // should be power of 2
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *Buffer::Get() const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(Size()==0)
|
|
Packit |
8f70b4 |
return eof?0:"";
|
|
Packit |
8f70b4 |
return buffer+buffer_ptr;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::Get(const char **buf,int *size) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
*size=Size();
|
|
Packit |
8f70b4 |
*buf=Get();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::GetSaved(const char **buf,int *size) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!save)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
*size=0;
|
|
Packit |
8f70b4 |
*buf=0;
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
*buf=buffer;
|
|
Packit |
8f70b4 |
*size=buffer.length();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::SaveRollback(off_t p)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
pos=p;
|
|
Packit |
8f70b4 |
if(buffer_ptr
|
|
Packit |
8f70b4 |
save=false;
|
|
Packit |
8f70b4 |
if(!save)
|
|
Packit |
8f70b4 |
p=0;
|
|
Packit |
8f70b4 |
buffer.truncate(buffer_ptr=p);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::Allocate(int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(buffer_ptr>0 && Size()==0 && !save)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buffer.truncate(0);
|
|
Packit |
8f70b4 |
buffer_ptr=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
size_t in_buffer_real=Size();
|
|
Packit |
8f70b4 |
/* disable data movement to beginning of the buffer, if:
|
|
Packit |
8f70b4 |
1. we save the data explicitly;
|
|
Packit |
8f70b4 |
2. we add more data than there is space in the beginning of the buffer
|
|
Packit |
8f70b4 |
(because the probability of realloc is high anyway);
|
|
Packit |
8f70b4 |
3. the gap at beginning is smaller than the amount of data in the buffer
|
|
Packit |
8f70b4 |
(because the penalty of data movement is high). */
|
|
Packit |
8f70b4 |
if(save || buffer_ptr
|
|
Packit |
8f70b4 |
in_buffer_real+=buffer_ptr;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// could be round-robin, but this is easier
|
|
Packit |
8f70b4 |
if(buffer.length()>in_buffer_real)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buffer.nset(buffer+buffer_ptr,Size());
|
|
Packit |
8f70b4 |
buffer_ptr=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
buffer.get_space2(in_buffer_real+size,BUFFER_INC);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::SaveMaxCheck(int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(save && buffer_ptr+size>save_max)
|
|
Packit |
8f70b4 |
save=false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::Append(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(size==0)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
SaveMaxCheck(size);
|
|
Packit |
8f70b4 |
if(Size()==0 && buffer_ptr>0 && !save)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buffer.truncate(0);
|
|
Packit |
8f70b4 |
buffer_ptr=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
memmove(GetSpace(size),buf,size);
|
|
Packit |
8f70b4 |
SpaceAdd(size);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::Put(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Append(buf,size);
|
|
Packit |
8f70b4 |
pos+=size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::Prepend(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(size==0)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
save=false;
|
|
Packit |
8f70b4 |
if(Size()==0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
memmove(GetSpace(size),buf,size);
|
|
Packit |
8f70b4 |
SpaceAdd(size);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(buffer_ptr
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Allocate(size-buffer_ptr);
|
|
Packit |
8f70b4 |
memmove(buffer.get_non_const()+size,buffer+buffer_ptr,Size());
|
|
Packit |
8f70b4 |
SpaceAdd(size-buffer_ptr);
|
|
Packit |
8f70b4 |
buffer_ptr=size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
memmove(buffer.get_non_const()+buffer_ptr-size,buf,size);
|
|
Packit |
8f70b4 |
buffer_ptr-=size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::Format(const char *f,...)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
va_list v;
|
|
Packit |
8f70b4 |
va_start(v,f);
|
|
Packit |
8f70b4 |
vFormat(f, v);
|
|
Packit |
8f70b4 |
va_end(v);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::vFormat(const char *f, va_list v)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int size=64;
|
|
Packit |
8f70b4 |
for(;;)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
va_list tmp;
|
|
Packit |
8f70b4 |
VA_COPY(tmp,v);
|
|
Packit |
8f70b4 |
int res=vsnprintf(GetSpace(size), size, f, tmp);
|
|
Packit |
8f70b4 |
va_end(tmp);
|
|
Packit |
8f70b4 |
if(res>=0 && res
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SpaceAdd(res);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(res>size) // some vsnprintf's return desired buffer size.
|
|
Packit |
8f70b4 |
size=res+1;
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
size*=2;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::Skip(int len)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(len>Size())
|
|
Packit |
8f70b4 |
len=Size();
|
|
Packit |
8f70b4 |
buffer_ptr+=len;
|
|
Packit |
8f70b4 |
pos+=len;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::UnSkip(int len)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(len>buffer_ptr)
|
|
Packit |
8f70b4 |
len=buffer_ptr;
|
|
Packit |
8f70b4 |
buffer_ptr-=len;
|
|
Packit |
8f70b4 |
pos-=len;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::Empty()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buffer.truncate(0);
|
|
Packit |
8f70b4 |
buffer_ptr=0;
|
|
Packit |
8f70b4 |
if(save_max>0)
|
|
Packit |
8f70b4 |
save=true;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// move data from other buffer, prepare for SpaceAdd.
|
|
Packit |
8f70b4 |
int Buffer::MoveDataHere(Buffer *o,int max_len)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const char *b;
|
|
Packit |
8f70b4 |
int size;
|
|
Packit |
8f70b4 |
o->Get(&b,&size);
|
|
Packit |
8f70b4 |
if(size>max_len)
|
|
Packit |
8f70b4 |
size=max_len;
|
|
Packit |
8f70b4 |
if(size>0) {
|
|
Packit |
8f70b4 |
if(size>=64 && Size()==0 && o->Size()==size && !save && !o->save) {
|
|
Packit |
8f70b4 |
// optimization by swapping buffers
|
|
Packit |
8f70b4 |
buffer.swap(o->buffer);
|
|
Packit |
8f70b4 |
buffer_ptr=replace_value(o->buffer_ptr,buffer_ptr);
|
|
Packit |
8f70b4 |
buffer.set_length_no_z(buffer_ptr);
|
|
Packit |
8f70b4 |
o->pos+=size;
|
|
Packit |
8f70b4 |
} else {
|
|
Packit |
8f70b4 |
memcpy(GetSpace(size),b,size);
|
|
Packit |
8f70b4 |
o->Skip(size);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
Buffer::Buffer()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
saved_errno=0;
|
|
Packit |
8f70b4 |
error_fatal=false;
|
|
Packit |
8f70b4 |
buffer_ptr=0;
|
|
Packit |
8f70b4 |
eof=false;
|
|
Packit |
8f70b4 |
broken=false;
|
|
Packit |
8f70b4 |
save=false;
|
|
Packit |
8f70b4 |
save_max=0;
|
|
Packit |
8f70b4 |
pos=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
Buffer::~Buffer()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *Buffer::GetRateStrS()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!rate || !rate->Valid())
|
|
Packit |
8f70b4 |
return "";
|
|
Packit |
8f70b4 |
return rate->GetStrS();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::RateAdd(int n)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!rate)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
rate->Add(n);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void Buffer::SetError(const char *e,bool fatal)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
error_text.set(e);
|
|
Packit |
8f70b4 |
error_fatal=fatal;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::SetErrorCached(const char *e)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SetError(e,false);
|
|
Packit |
8f70b4 |
error_text.append(_(" [cached]"));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
const char *Buffer::Dump() const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(buffer_ptr==0)
|
|
Packit |
8f70b4 |
return buffer.dump();
|
|
Packit |
8f70b4 |
return xstring::get_tmp(Get(),Size()).dump();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void DataTranslator::AppendTranslated(Buffer *target,const char *put_buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
off_t old_pos=target->GetPos();
|
|
Packit |
8f70b4 |
PutTranslated(target,put_buf,size);
|
|
Packit |
8f70b4 |
target->SetPos(old_pos);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void DirectedBuffer::SetTranslator(DataTranslator *t)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(mode==GET && !translator && Size()>0) {
|
|
Packit |
8f70b4 |
// translate unread data
|
|
Packit |
8f70b4 |
const char *data;
|
|
Packit |
8f70b4 |
int len;
|
|
Packit |
8f70b4 |
Get(&data,&len;;
|
|
Packit |
8f70b4 |
t->Put(data,len);
|
|
Packit |
8f70b4 |
buffer.truncate(buffer_ptr);
|
|
Packit |
8f70b4 |
t->AppendTranslated(this,0,0);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
translator=t;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#ifdef HAVE_ICONV
|
|
Packit |
8f70b4 |
void DataRecoder::PutTranslated(Buffer *target,const char *put_buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
bool from_untranslated=false;
|
|
Packit |
8f70b4 |
if(Size()>0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Put(put_buf,size);
|
|
Packit |
8f70b4 |
Get(&put_buf,&size);
|
|
Packit |
8f70b4 |
from_untranslated=true;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(size<=0)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
if(!backend_translate)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
target->Put(put_buf,size);
|
|
Packit |
8f70b4 |
if(from_untranslated)
|
|
Packit |
8f70b4 |
Skip(size);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
size_t put_size=size;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int size_coeff=6;
|
|
Packit |
8f70b4 |
try_again:
|
|
Packit |
8f70b4 |
if(put_size==0)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
size_t store_size=size_coeff*put_size;
|
|
Packit |
8f70b4 |
char *store_space=target->GetSpace(store_size);
|
|
Packit |
8f70b4 |
char *store_buf=store_space;
|
|
Packit |
8f70b4 |
const char *base_buf=put_buf;
|
|
Packit |
8f70b4 |
// do the translation
|
|
Packit |
8f70b4 |
ICONV_CONST char **put_buf_ptr=const_cast<ICONV_CONST char**>(&put_buf);
|
|
Packit |
8f70b4 |
size_t res=iconv(backend_translate,put_buf_ptr,&put_size,&store_buf,&store_size);
|
|
Packit |
8f70b4 |
target->SpaceAdd(store_buf-store_space);
|
|
Packit |
8f70b4 |
if(from_untranslated)
|
|
Packit |
8f70b4 |
Skip(put_buf-base_buf);
|
|
Packit |
8f70b4 |
if(res==(size_t)-1)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
switch(errno)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case EINVAL: // incomplete character
|
|
Packit |
8f70b4 |
if(!from_untranslated)
|
|
Packit |
8f70b4 |
Put(put_buf,put_size);
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
case EILSEQ: // invalid character
|
|
Packit |
8f70b4 |
target->Put("?");
|
|
Packit |
8f70b4 |
put_buf++;
|
|
Packit |
8f70b4 |
put_size--;
|
|
Packit |
8f70b4 |
goto try_again;
|
|
Packit |
8f70b4 |
case E2BIG: // no room to store result, allocate more.
|
|
Packit |
8f70b4 |
size_coeff*=2;
|
|
Packit |
8f70b4 |
goto try_again;
|
|
Packit |
8f70b4 |
default:
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void DataRecoder::ResetTranslation()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Empty();
|
|
Packit |
8f70b4 |
if(!backend_translate)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
iconv(backend_translate,0,0,0,0);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
DataRecoder::~DataRecoder()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(backend_translate)
|
|
Packit |
8f70b4 |
iconv_close(backend_translate);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
DataRecoder::DataRecoder(const char *from_code,const char *to_code,bool translit)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
backend_translate=0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(translit) {
|
|
Packit |
8f70b4 |
const char *to_code_translit=xstring::cat(to_code,"//TRANSLIT",NULL);
|
|
Packit |
8f70b4 |
backend_translate=iconv_open(to_code_translit,from_code);
|
|
Packit |
8f70b4 |
if(backend_translate!=(iconv_t)-1) {
|
|
Packit |
8f70b4 |
Log::global->Format(9,"initialized translation from %s to %s\n",from_code,to_code_translit);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
backend_translate=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
backend_translate=iconv_open(to_code,from_code);
|
|
Packit |
8f70b4 |
if(backend_translate!=(iconv_t)-1) {
|
|
Packit |
8f70b4 |
Log::global->Format(9,"initialized translation from %s to %s\n",from_code,to_code);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
Log::global->Format(0,"iconv_open(%s,%s) failed: %s\n",
|
|
Packit |
8f70b4 |
to_code,from_code,strerror(errno));
|
|
Packit |
8f70b4 |
backend_translate=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void DirectedBuffer::SetTranslation(const char *enc,bool translit)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!enc || !*enc)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
const char *local_code=ResMgr::Query("file:charset",0);
|
|
Packit |
8f70b4 |
if(!local_code || !*local_code)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
const char *from_code=(mode==GET?enc:local_code);
|
|
Packit |
8f70b4 |
const char *to_code =(mode==GET?local_code:enc);
|
|
Packit |
8f70b4 |
if(!strcasecmp(from_code,to_code))
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
SetTranslator(new DataRecoder(from_code,to_code,translit));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
#endif //HAVE_ICONV
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void DirectedBuffer::ResetTranslation()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(translator)
|
|
Packit |
8f70b4 |
translator->ResetTranslation();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void DirectedBuffer::Put(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(mode==PUT && translator)
|
|
Packit |
8f70b4 |
translator->PutTranslated(this,buf,size);
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
Buffer::Put(buf,size);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void DirectedBuffer::PutTranslated(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(translator)
|
|
Packit |
8f70b4 |
translator->PutTranslated(this,buf,size);
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
Buffer::Put(buf,size);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
int DirectedBuffer::MoveDataHere(Buffer *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(size>buf->Size())
|
|
Packit |
8f70b4 |
size=buf->Size();
|
|
Packit |
8f70b4 |
if(mode==PUT && translator)
|
|
Packit |
8f70b4 |
translator->PutTranslated(this,buf->Get(),size);
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
return Buffer::MoveDataHere(buf,size);
|
|
Packit |
8f70b4 |
return size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void DirectedBuffer::PutEOF()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(mode==PUT && translator)
|
|
Packit |
8f70b4 |
translator->PutTranslated(this,0,0);
|
|
Packit |
8f70b4 |
Buffer::PutEOF();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void DirectedBuffer::EmbraceNewData(int len)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(len<=0)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
RateAdd(len);
|
|
Packit |
8f70b4 |
if(translator)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
// copy the data to free room for translated data
|
|
Packit |
8f70b4 |
translator->Put(buffer+buffer.length(),len);
|
|
Packit |
8f70b4 |
translator->AppendTranslated(this,0,0);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
SpaceAdd(len);
|
|
Packit |
8f70b4 |
SaveMaxCheck(0);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
IOBuffer::IOBuffer(dir_t m)
|
|
Packit |
8f70b4 |
: DirectedBuffer(m), event_time(now),
|
|
Packit |
8f70b4 |
max_buf(0), get_size(GET_BUFSIZE)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
IOBuffer::~IOBuffer()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void IOBuffer::Put(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(size>=PUT_LL_MIN && Size()==0 && mode==PUT && !save && !translator)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int res=Put_LL(buf,size);
|
|
Packit |
8f70b4 |
if(res>=0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buf+=res;
|
|
Packit |
8f70b4 |
size-=res;
|
|
Packit |
8f70b4 |
pos+=res;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(size<=0)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
if(Size()==0)
|
|
Packit |
8f70b4 |
current->Timeout(0);
|
|
Packit |
8f70b4 |
DirectedBuffer::Put(buf,size);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void IOBuffer::Put(const char *buf)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Put(buf,strlen(buf));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int IOBuffer::TuneGetSize(int res)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(res>0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
// buffer size tuning depending on data rate
|
|
Packit |
8f70b4 |
const int max_get_size=(max_buf?max_buf:0x100000);
|
|
Packit |
8f70b4 |
if(res>get_size/2 && Size()+get_size*2<=max_get_size)
|
|
Packit |
8f70b4 |
get_size*=2;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return res;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int IOBuffer::Do()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(Done() || Error())
|
|
Packit |
8f70b4 |
return STALL;
|
|
Packit |
8f70b4 |
int res=0;
|
|
Packit |
8f70b4 |
switch(mode)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case PUT:
|
|
Packit |
8f70b4 |
if(Size()==0)
|
|
Packit |
8f70b4 |
return STALL;
|
|
Packit |
8f70b4 |
res=Put_LL(buffer+buffer_ptr,Size());
|
|
Packit |
8f70b4 |
if(res>0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
RateAdd(res);
|
|
Packit |
8f70b4 |
buffer_ptr+=res;
|
|
Packit |
8f70b4 |
event_time=now;
|
|
Packit |
8f70b4 |
if(eof)
|
|
Packit |
8f70b4 |
PutEOF_LL();
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
case GET:
|
|
Packit |
8f70b4 |
if(eof)
|
|
Packit |
8f70b4 |
return STALL;
|
|
Packit |
8f70b4 |
res=TuneGetSize(Get_LL(get_size));
|
|
Packit |
8f70b4 |
if(res>0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
EmbraceNewData(res);
|
|
Packit |
8f70b4 |
event_time=now;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(eof)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
event_time=now;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(res<0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
event_time=now;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return STALL;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// IOBufferStacked implementation
|
|
Packit |
8f70b4 |
#undef super
|
|
Packit |
8f70b4 |
#define super IOBuffer
|
|
Packit |
8f70b4 |
int IOBufferStacked::Do()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int m=STALL;
|
|
Packit |
8f70b4 |
if(Done() || Error())
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
int res=0;
|
|
Packit |
8f70b4 |
switch(mode)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case PUT:
|
|
Packit |
8f70b4 |
if(down->Broken() && !broken)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
broken=true;
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(down->Error())
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SetError(down->ErrorText(),down->ErrorFatal());
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(Size()==0)
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
res=Put_LL(buffer+buffer_ptr,Size());
|
|
Packit |
8f70b4 |
if(res>0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buffer_ptr+=res;
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
case GET:
|
|
Packit |
8f70b4 |
if(eof)
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
res=Get_LL(/*unused*/0);
|
|
Packit |
8f70b4 |
if(res>0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
EmbraceNewData(res);
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(eof)
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
if(down->Error())
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SetError(down->ErrorText(),down->ErrorFatal());
|
|
Packit |
8f70b4 |
m=MOVED;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(res<0)
|
|
Packit |
8f70b4 |
return MOVED;
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
int IOBufferStacked::Put_LL(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(down->Broken())
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
broken=true;
|
|
Packit |
8f70b4 |
return -1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
down->Put(buf,size);
|
|
Packit |
8f70b4 |
return size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int IOBufferStacked::Get_LL(int)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(max_buf && Size()>=max_buf) {
|
|
Packit |
8f70b4 |
down->SuspendSlave();
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
down->ResumeSlave();
|
|
Packit |
8f70b4 |
int size=MoveDataHere(down,down->Size());
|
|
Packit |
8f70b4 |
if(down->Size()==0 && down->Eof())
|
|
Packit |
8f70b4 |
PutEOF();
|
|
Packit |
8f70b4 |
return size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool IOBufferStacked::Done()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(super::Done())
|
|
Packit |
8f70b4 |
return down->Done();
|
|
Packit |
8f70b4 |
return false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void IOBufferStacked::SuspendInternal()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
super::SuspendInternal();
|
|
Packit |
8f70b4 |
down->SuspendSlave();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void IOBufferStacked::ResumeInternal()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!max_buf || Size()
|
|
Packit |
8f70b4 |
down->ResumeSlave();
|
|
Packit |
8f70b4 |
super::ResumeInternal();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// IOBufferFDStream implementation
|
|
Packit |
8f70b4 |
#include <fcntl.h>
|
|
Packit |
8f70b4 |
#include <unistd.h>
|
|
Packit |
8f70b4 |
#undef super
|
|
Packit |
8f70b4 |
#define super IOBuffer
|
|
Packit |
8f70b4 |
int IOBufferFDStream::Put_LL(const char *buf,int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(put_ll_timer && !eof && Size()
|
|
Packit |
8f70b4 |
&& !put_ll_timer->Stopped())
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
if(stream->broken())
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
broken=true;
|
|
Packit |
8f70b4 |
return -1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int res=0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int fd=stream->getfd();
|
|
Packit |
8f70b4 |
if(fd==-1)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(stream->error())
|
|
Packit |
8f70b4 |
goto stream_err;
|
|
Packit |
8f70b4 |
TimeoutS(1);
|
|
Packit |
8f70b4 |
event_time=now;
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
res=write(fd,buf,size);
|
|
Packit |
8f70b4 |
if(res==-1)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
saved_errno=errno;
|
|
Packit |
8f70b4 |
if(E_RETRY(saved_errno))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Block(fd,POLLOUT);
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(NonFatalError(saved_errno))
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
if(errno==EPIPE)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
broken=true;
|
|
Packit |
8f70b4 |
return -1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
stream->MakeErrorText(saved_errno);
|
|
Packit |
8f70b4 |
goto stream_err;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(put_ll_timer)
|
|
Packit |
8f70b4 |
put_ll_timer->Reset();
|
|
Packit |
8f70b4 |
return res;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
stream_err:
|
|
Packit |
8f70b4 |
SetError(stream->error_text,!TemporaryNetworkError(saved_errno));
|
|
Packit |
8f70b4 |
return -1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int IOBufferFDStream::Get_LL(int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(max_buf && Size()>=max_buf)
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int res=0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int fd=stream->getfd();
|
|
Packit |
8f70b4 |
if(fd==-1)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(stream->error())
|
|
Packit |
8f70b4 |
goto stream_err;
|
|
Packit |
8f70b4 |
TimeoutS(1);
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(!Ready(fd,POLLIN))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Block(fd,POLLIN);
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
res=read(fd,GetSpace(size),size);
|
|
Packit |
8f70b4 |
if(res==-1)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
saved_errno=errno;
|
|
Packit |
8f70b4 |
if(E_RETRY(saved_errno))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
SetNotReady(fd,POLLIN);
|
|
Packit |
8f70b4 |
Block(fd,POLLIN);
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(NonFatalError(saved_errno))
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
stream->MakeErrorText(saved_errno);
|
|
Packit |
8f70b4 |
goto stream_err;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(res==0) {
|
|
Packit |
8f70b4 |
Log::global->Format(10,"buffer: EOF on FD %d\n",fd);
|
|
Packit |
8f70b4 |
eof=true;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return res;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
stream_err:
|
|
Packit |
8f70b4 |
SetError(stream->error_text,!TemporaryNetworkError(saved_errno));
|
|
Packit |
8f70b4 |
return -1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FgData *IOBufferFDStream::GetFgData(bool fg)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(stream->getfd()!=-1)
|
|
Packit |
8f70b4 |
return new FgData(stream->GetProcGroup(),fg);
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool IOBufferFDStream::Done()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(put_ll_timer)
|
|
Packit |
8f70b4 |
put_ll_timer->Stop();
|
|
Packit |
8f70b4 |
if(super::Done())
|
|
Packit |
8f70b4 |
return stream->Done(); // stream->Done indicates if sub-process finished
|
|
Packit |
8f70b4 |
return false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
IOBufferFDStream::~IOBufferFDStream() {}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// IOBufferFileAccess implementation
|
|
Packit |
8f70b4 |
#undef super
|
|
Packit |
8f70b4 |
#define super IOBuffer
|
|
Packit |
8f70b4 |
int IOBufferFileAccess::Get_LL(int size)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(max_buf && Size()>=max_buf) {
|
|
Packit |
8f70b4 |
session->SuspendSlave();
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
session->ResumeSlave();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int res=0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
res=session->Read(this,size);
|
|
Packit |
8f70b4 |
if(res<0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(res==FA::DO_AGAIN)
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
SetError(session->StrError(res));
|
|
Packit |
8f70b4 |
return -1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(res==0)
|
|
Packit |
8f70b4 |
eof=true;
|
|
Packit |
8f70b4 |
return res;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void IOBufferFileAccess::SuspendInternal()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
super::SuspendInternal();
|
|
Packit |
8f70b4 |
session->SuspendSlave();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void IOBufferFileAccess::ResumeInternal()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!max_buf || Size()
|
|
Packit |
8f70b4 |
session->ResumeSlave();
|
|
Packit |
8f70b4 |
super::ResumeInternal();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
const char *IOBufferFileAccess::Status()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return session->CurrentStatus();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
unsigned long long Buffer::UnpackUINT64BE(int offset) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(Size()-offset<8)
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
unsigned long long res=UnpackUINT32BE(offset);
|
|
Packit |
8f70b4 |
res=(res<<32)|UnpackUINT32BE(offset+4);
|
|
Packit |
8f70b4 |
return res;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
long long Buffer::UnpackINT64BE(int offset) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
unsigned long long n=UnpackUINT64BE(offset);
|
|
Packit |
8f70b4 |
if(n&0x8000000000000000ULL)
|
|
Packit |
8f70b4 |
return -(long long)(n^0xFFFFFFFFFFFFFFFFULL)-1;
|
|
Packit |
8f70b4 |
return (long long)n;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
unsigned Buffer::UnpackUINT32BE(int offset) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(Size()-offset<4)
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
unsigned char *b=(unsigned char*)buffer.get()+buffer_ptr+offset;
|
|
Packit |
8f70b4 |
return (b[0]<<24)|(b[1]<<16)|(b[2]<<8)|b[3];
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
int Buffer::UnpackINT32BE(int offset) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
unsigned n=UnpackUINT32BE(offset);
|
|
Packit |
8f70b4 |
if(n&0x80000000U)
|
|
Packit |
8f70b4 |
return -(int)(n^0xFFFFFFFFU)-1;
|
|
Packit |
8f70b4 |
return (int)n;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
unsigned Buffer::UnpackUINT16BE(int offset) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(Size()-offset<2)
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
unsigned char *b=(unsigned char*)buffer.get()+buffer_ptr+offset;
|
|
Packit |
8f70b4 |
return (b[0]<<8)|b[1];
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
unsigned Buffer::UnpackUINT8(int offset) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(Size()-offset<1)
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
unsigned char *b=(unsigned char*)buffer.get()+buffer_ptr+offset;
|
|
Packit |
8f70b4 |
return b[0];
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::PackUINT64BE(unsigned long long data)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
#ifndef NDEBUG
|
|
Packit |
8f70b4 |
Log::global->Format(11,"PackUINT64BE(0x%016llX)\n",data);
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
Allocate(8);
|
|
Packit |
8f70b4 |
PackUINT32BE((unsigned)(data>>32));
|
|
Packit |
8f70b4 |
PackUINT32BE((unsigned)(data&0xFFFFFFFFU));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::PackINT64BE(long long data)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
unsigned long long n;
|
|
Packit |
8f70b4 |
if(data<0)
|
|
Packit |
8f70b4 |
n=((unsigned long long)(-data)^0xFFFFFFFFFFFFFFFFULL)+1;
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
n=(unsigned long long)data;
|
|
Packit |
8f70b4 |
PackUINT64BE(n);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::PackUINT32BE(unsigned data)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
#ifndef NDEBUG
|
|
Packit |
8f70b4 |
Log::global->Format(11,"PackUINT32BE(0x%08X)\n",data);
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
char *b=GetSpace(4);
|
|
Packit |
8f70b4 |
b[0]=(data>>24)&255;
|
|
Packit |
8f70b4 |
b[1]=(data>>16)&255;
|
|
Packit |
8f70b4 |
b[2]=(data>>8)&255;
|
|
Packit |
8f70b4 |
b[3]=(data)&255;
|
|
Packit |
8f70b4 |
SpaceAdd(4);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::PackINT32BE(int data)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
unsigned n;
|
|
Packit |
8f70b4 |
if(data<0)
|
|
Packit |
8f70b4 |
n=((unsigned)(-data)^0xFFFFFFFFU)+1;
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
n=(unsigned)data;
|
|
Packit |
8f70b4 |
PackUINT32BE(n);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::PackUINT16BE(unsigned data)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char *b=GetSpace(2);
|
|
Packit |
8f70b4 |
b[0]=(data>>8)&255;
|
|
Packit |
8f70b4 |
b[1]=(data)&255;
|
|
Packit |
8f70b4 |
SpaceAdd(2);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void Buffer::PackUINT8(unsigned data)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
#ifndef NDEBUG
|
|
Packit |
8f70b4 |
Log::global->Format(11,"PackUINT8(0x%02X)\n",data);
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
char *b=GetSpace(1);
|
|
Packit |
8f70b4 |
b[0]=(data)&255;
|
|
Packit |
8f70b4 |
SpaceAdd(1);
|
|
Packit |
8f70b4 |
}
|