Browse Source
lots of changes but primarily change the request parser to use a ringbuffer. The ringbuffer is implemented using the shared memory trick.
master
lots of changes but primarily change the request parser to use a ringbuffer. The ringbuffer is implemented using the shared memory trick.
master
26 changed files with 703 additions and 218 deletions
-
8ChangeLog
-
87doc/file-upload.txt
-
75doc/file-upload2.txt
-
30include/http/request/parser.h
-
3include/http/worker.h
-
37include/ringbuffer.h
-
2include/socket.h
-
6src/Makefile.am
-
32src/http/request/parser.c
-
43src/http/request/parser/get_body.c
-
29src/http/request/parser/get_header.c
-
96src/http/request/parser/get_request_line.c
-
131src/http/request/parser/parse.c
-
50src/http/request/parser/read.c
-
9src/http/response/404.c
-
9src/http/response/image.c
-
9src/http/response/me.c
-
1src/http/response/writer/write.c
-
25src/http/worker.c
-
17src/http/worker/process.c
-
21src/rbtest.c
-
117src/ringbuffer.c
-
41src/ringbuffer/rb_read.c
-
8src/server/handle_accept.c
-
5src/socket/accept.c
-
2src/testserver.c
@ -0,0 +1,87 @@ |
|||||
|
POST / HTTP/1.1 |
||||
|
Host: localhost:11213 |
||||
|
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:8.0) Gecko/20100101 Firefox/8.0 |
||||
|
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
||||
|
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3 |
||||
|
Accept-Encoding: gzip, deflate |
||||
|
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 |
||||
|
Connection: keep-alive |
||||
|
Referer: http://localhost:11213/ |
||||
|
Content-Type: multipart/form-data; boundary=---------------------------2713599294882465121951036798 |
||||
|
Content-Length: 2652 |
||||
|
|
||||
|
-----------------------------2713599294882465121951036798 |
||||
|
Content-Disposition: form-data; name="submitter" |
||||
|
|
||||
|
fooo |
||||
|
-----------------------------2713599294882465121951036798 |
||||
|
Content-Disposition: form-data; name="pics"; filename="bar.c" |
||||
|
Content-Type: text/x-csrc |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
|
||||
|
#define _B64(chr, ref) (chr)==_##ref?__##ref |
||||
|
#define B64(_) \ |
||||
|
( _B64(_,A):_B64(_,B):_B64(_,C):_B64(_,D):_B64(_,E):_B64(_,F):_B64(_,G): \ |
||||
|
_B64(_,H):_B64(_,I):_B64(_,J):_B64(_,K):_B64(_,L):_B64(_,M):_B64(_,N): \ |
||||
|
_B64(_,O):_B64(_,P):_B64(_,Q):_B64(_,R):_B64(_,S):_B64(_,T):_B64(_,U): \ |
||||
|
_B64(_,V):_B64(_,W):_B64(_,X):_B64(_,Y):_B64(_,Z):_B64(_,a):_B64(_,b): \ |
||||
|
_B64(_,c):_B64(_,d):_B64(_,e):_B64(_,f):_B64(_,g):_B64(_,h):_B64(_,i): \ |
||||
|
_B64(_,j):_B64(_,k):_B64(_,l):_B64(_,m):_B64(_,n):_B64(_,o):_B64(_,p): \ |
||||
|
_B64(_,q):_B64(_,r):_B64(_,s):_B64(_,t):_B64(_,u):_B64(_,v):_B64(_,w): \ |
||||
|
_B64(_,x):_B64(_,y):_B64(_,z):_B64(_,0):_B64(_,1):_B64(_,2):_B64(_,3): \ |
||||
|
_B64(_,4):_B64(_,5):_B64(_,6):_B64(_,7):_B64(_,8):_B64(_,9): \ |
||||
|
_B64(_,PLUS):_B64(_,SLASH):-1 ) |
||||
|
|
||||
|
|
||||
|
#define B64_8(_) \ |
||||
|
B64(_),B64(_+1),B64(_+2),B64(_+3),B64(_+4),B64(_+5),B64(_+6),B64(_+7) |
||||
|
|
||||
|
#define B64_64(_) \ |
||||
|
B64_8(_),B64_8(_+8), B64_8(_+16),B64_8(_+24), \ |
||||
|
B64_8(_+32),B64_8(_+40),B64_8(_+48),B64_8(_+56) |
||||
|
|
||||
|
#define IS_BASE64(ch) ( \ |
||||
|
UCHAR_IN_RANGE((unsigned char)(ch)) \ |
||||
|
&& 0 <= b64[(unsigned char)(ch)] ) |
||||
|
|
||||
|
|
||||
|
static const char b64str[64] = |
||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
||||
|
|
||||
|
enum b64vals { |
||||
|
__A=0,__B,__C,__D,__E,__F,__G,__H,__I,__J,__K,__L,__M,__N,__O,__P,__Q,__R, |
||||
|
__S,__T,__U,__V,__W,__X,__Y,__Z,__a,__b,__c,__d,__e,__f,__g,__h,__i,__j, |
||||
|
__k,__l,__m,__n,__o,__p,__q,__r,__s,__t,__u,__v,__w,__x,__y,__z,__0,__1, |
||||
|
__2,__3,__4,__5,__6,__7,__8,__9,__PLUS,__SLASH |
||||
|
}; |
||||
|
|
||||
|
enum b64chars { |
||||
|
_A='A',_B='B',_C='C',_D='D',_E='E',_F='F',_G='G',_H='H',_I='I',_J='J',_K='K', |
||||
|
_L='L',_M='M',_N='N',_O='O',_P='P',_Q='Q',_R='R',_S='S',_T='T',_U='U',_V='V', |
||||
|
_W='W',_X='X',_Y='Y',_Z='Z',_a='a',_b='b',_c='c',_d='d',_e='e',_f='f',_g='g', |
||||
|
_h='h',_i='i',_j='j',_k='k',_l='l',_m='m',_n='n',_o='o',_p='p',_q='q',_r='r', |
||||
|
_s='s',_t='t',_u='u',_v='v',_w='w',_x='x',_y='y',_z='z',_0='0',_1='1',_2='2', |
||||
|
_3='3',_4='4',_5='5',_6='6',_7='7',_8='8',_9='9',_PLUS='+',_SLASH='/' |
||||
|
}; |
||||
|
|
||||
|
#define __46B(chr) __##chr |
||||
|
inline |
||||
|
char |
||||
|
__B64(int val) |
||||
|
{ |
||||
|
return b64str[val]; |
||||
|
} |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
int i=12; |
||||
|
char a='k'; |
||||
|
|
||||
|
//printf("i => %c | a => %d\n", __B64(12), __46B('k')); |
||||
|
printf("i => %c | a => %d\n", __B64(i), __46B(a)); |
||||
|
} |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
|
|
||||
|
-----------------------------2713599294882465121951036798-- |
||||
@ -0,0 +1,75 @@ |
|||||
|
-----------------------------2713599294882465121951036798 |
||||
|
Content-Disposition: form-data; name="submitter" |
||||
|
|
||||
|
fooo |
||||
|
-----------------------------2713599294882465121951036798 |
||||
|
Content-Disposition: form-data; name="pics"; filename="bar.c" |
||||
|
Content-Type: text/x-csrc |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
|
||||
|
#define _B64(chr, ref) (chr)==_##ref?__##ref |
||||
|
#define B64(_) \ |
||||
|
( _B64(_,A):_B64(_,B):_B64(_,C):_B64(_,D):_B64(_,E):_B64(_,F):_B64(_,G): \ |
||||
|
_B64(_,H):_B64(_,I):_B64(_,J):_B64(_,K):_B64(_,L):_B64(_,M):_B64(_,N): \ |
||||
|
_B64(_,O):_B64(_,P):_B64(_,Q):_B64(_,R):_B64(_,S):_B64(_,T):_B64(_,U): \ |
||||
|
_B64(_,V):_B64(_,W):_B64(_,X):_B64(_,Y):_B64(_,Z):_B64(_,a):_B64(_,b): \ |
||||
|
_B64(_,c):_B64(_,d):_B64(_,e):_B64(_,f):_B64(_,g):_B64(_,h):_B64(_,i): \ |
||||
|
_B64(_,j):_B64(_,k):_B64(_,l):_B64(_,m):_B64(_,n):_B64(_,o):_B64(_,p): \ |
||||
|
_B64(_,q):_B64(_,r):_B64(_,s):_B64(_,t):_B64(_,u):_B64(_,v):_B64(_,w): \ |
||||
|
_B64(_,x):_B64(_,y):_B64(_,z):_B64(_,0):_B64(_,1):_B64(_,2):_B64(_,3): \ |
||||
|
_B64(_,4):_B64(_,5):_B64(_,6):_B64(_,7):_B64(_,8):_B64(_,9): \ |
||||
|
_B64(_,PLUS):_B64(_,SLASH):-1 ) |
||||
|
|
||||
|
|
||||
|
#define B64_8(_) \ |
||||
|
B64(_),B64(_+1),B64(_+2),B64(_+3),B64(_+4),B64(_+5),B64(_+6),B64(_+7) |
||||
|
|
||||
|
#define B64_64(_) \ |
||||
|
B64_8(_),B64_8(_+8), B64_8(_+16),B64_8(_+24), \ |
||||
|
B64_8(_+32),B64_8(_+40),B64_8(_+48),B64_8(_+56) |
||||
|
|
||||
|
#define IS_BASE64(ch) ( \ |
||||
|
UCHAR_IN_RANGE((unsigned char)(ch)) \ |
||||
|
&& 0 <= b64[(unsigned char)(ch)] ) |
||||
|
|
||||
|
|
||||
|
static const char b64str[64] = |
||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
||||
|
|
||||
|
enum b64vals { |
||||
|
__A=0,__B,__C,__D,__E,__F,__G,__H,__I,__J,__K,__L,__M,__N,__O,__P,__Q,__R, |
||||
|
__S,__T,__U,__V,__W,__X,__Y,__Z,__a,__b,__c,__d,__e,__f,__g,__h,__i,__j, |
||||
|
__k,__l,__m,__n,__o,__p,__q,__r,__s,__t,__u,__v,__w,__x,__y,__z,__0,__1, |
||||
|
__2,__3,__4,__5,__6,__7,__8,__9,__PLUS,__SLASH |
||||
|
}; |
||||
|
|
||||
|
enum b64chars { |
||||
|
_A='A',_B='B',_C='C',_D='D',_E='E',_F='F',_G='G',_H='H',_I='I',_J='J',_K='K', |
||||
|
_L='L',_M='M',_N='N',_O='O',_P='P',_Q='Q',_R='R',_S='S',_T='T',_U='U',_V='V', |
||||
|
_W='W',_X='X',_Y='Y',_Z='Z',_a='a',_b='b',_c='c',_d='d',_e='e',_f='f',_g='g', |
||||
|
_h='h',_i='i',_j='j',_k='k',_l='l',_m='m',_n='n',_o='o',_p='p',_q='q',_r='r', |
||||
|
_s='s',_t='t',_u='u',_v='v',_w='w',_x='x',_y='y',_z='z',_0='0',_1='1',_2='2', |
||||
|
_3='3',_4='4',_5='5',_6='6',_7='7',_8='8',_9='9',_PLUS='+',_SLASH='/' |
||||
|
}; |
||||
|
|
||||
|
#define __46B(chr) __##chr |
||||
|
inline |
||||
|
char |
||||
|
__B64(int val) |
||||
|
{ |
||||
|
return b64str[val]; |
||||
|
} |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
int i=12; |
||||
|
char a='k'; |
||||
|
|
||||
|
//printf("i => %c | a => %d\n", __B64(12), __46B('k')); |
||||
|
printf("i => %c | a => %d\n", __B64(i), __46B(a)); |
||||
|
} |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
|
|
||||
|
-----------------------------2713599294882465121951036798-- |
||||
@ -0,0 +1,37 @@ |
|||||
|
/** |
||||
|
* my implementation of a ringbuffer. |
||||
|
* It maps a shared memory object twice directly following |
||||
|
* thus make it possible to read and write from any |
||||
|
* position within the buffer without the nasty wrap |
||||
|
* calculations. |
||||
|
* This is achived because the same memory region is mapped |
||||
|
* at the two addresses. |
||||
|
*/ |
||||
|
#ifndef __RINGBUFFER_H__ |
||||
|
#define __RINGBUFFER_H__ |
||||
|
|
||||
|
#include <sys/types.h> |
||||
|
|
||||
|
#include "class.h" |
||||
|
|
||||
|
#define ERBOVRFL 100 |
||||
|
|
||||
|
|
||||
|
CLASS(Ringbuffer) { |
||||
|
char * shm_name; // shared memory identifier |
||||
|
|
||||
|
char * buffer; |
||||
|
char * mirror; |
||||
|
|
||||
|
size_t bsize; |
||||
|
size_t bused; |
||||
|
size_t bstart; |
||||
|
size_t bend; |
||||
|
}; |
||||
|
|
||||
|
ssize_t rbRead(Ringbuffer, int fd); |
||||
|
ssize_t rbWrite(Ringbuffer, int fd); |
||||
|
|
||||
|
#endif // __RINGBUFFER_H__ |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
@ -1,31 +1,95 @@ |
|||||
#include <stdlib.h> |
#include <stdlib.h> |
||||
#include <string.h> |
#include <string.h> |
||||
|
|
||||
|
#include "http/message.h" |
||||
#include "http/request.h" |
#include "http/request.h" |
||||
|
#include "http/request/parser.h" |
||||
|
#include "ringbuffer.h" |
||||
|
|
||||
|
#define MAX(x,y) ((x) > (y) ? (x) : (y)) |
||||
|
#define MIN(x,y) ((x) < (y) ? (x) : (y)) |
||||
|
#define MIN_SIZE(x,y) (MAX(strlen((x)), (y))) |
||||
|
|
||||
void |
|
||||
httpRequestParserGetRequestLine(HttpRequest request, char * line) |
|
||||
|
enum e_method { |
||||
|
OPTIONS=0, |
||||
|
GET, |
||||
|
HEAD, |
||||
|
POST, |
||||
|
PUT, |
||||
|
DELETE, |
||||
|
TRACE, |
||||
|
CONNECT |
||||
|
}; |
||||
|
|
||||
|
#define N_METHODS 8 |
||||
|
|
||||
|
static |
||||
|
const |
||||
|
char * method[N_METHODS] = { |
||||
|
"OPTIONS", |
||||
|
"GET", |
||||
|
"HEAD", |
||||
|
"POST", |
||||
|
"PUT", |
||||
|
"DELETE", |
||||
|
"TRACE", |
||||
|
"CONNECT" |
||||
|
}; |
||||
|
|
||||
|
ssize_t |
||||
|
httpRequestParserGetRequestLine(HttpRequestParser this, char * cr) |
||||
{ |
{ |
||||
|
HttpRequest request = this->cur_request; |
||||
HttpMessage message = (HttpMessage)request; |
HttpMessage message = (HttpMessage)request; |
||||
char * method, * uri, * version; |
|
||||
|
char * space1, * space2; |
||||
|
size_t len = cr - this->buffer->buffer - this->buffer->bstart; |
||||
|
int i; |
||||
|
|
||||
|
space1 = memchr( |
||||
|
this->buffer->buffer + this->buffer->bstart, |
||||
|
' ', len); |
||||
|
|
||||
|
if (NULL == space1) { |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
len = cr - space1; |
||||
|
space2 = memchr(space1 + 1, ' ', len); |
||||
|
|
||||
|
if (NULL == space2) { |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
len = space1 - this->buffer->buffer - this->buffer->bstart; |
||||
|
request->method = calloc(1, len + 1); |
||||
|
memcpy(request->method, |
||||
|
this->buffer->buffer + this->buffer->bstart, |
||||
|
len); |
||||
|
|
||||
|
for (i= 0; i< N_METHODS; i++) { |
||||
|
if (0 == memcmp(method[i], request->method, MIN_SIZE(method[i], len))) { |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (i == N_METHODS) { |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
method = line; |
|
||||
|
len = space2 - space1 - 1; |
||||
|
request->uri = calloc(1, len + 1); |
||||
|
memcpy(request->uri, space1 + 1, len); |
||||
|
|
||||
uri = strchr(line, ' '); |
|
||||
*uri++ = 0; |
|
||||
for (; *uri == ' ' && *uri != 0; uri++); |
|
||||
|
len = cr - space2 - 1; |
||||
|
message->version = calloc(1, len + 1); |
||||
|
memcpy(message->version, space2 + 1, len); |
||||
|
|
||||
version = strchr(uri, ' '); |
|
||||
*version++ = 0; |
|
||||
for (; *version == ' ' && *version != 0; version++); |
|
||||
|
if (len+1 != sizeof("HTTP/1.1") || |
||||
|
0 != memcmp("HTTP/1.", message->version, len-1)) { |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
request->method = malloc(strlen(method) + 1); |
|
||||
strcpy(request->method, method); |
|
||||
request->uri = malloc(strlen(uri) + 1); |
|
||||
strcpy(request->uri, uri); |
|
||||
message->version = malloc(strlen(version) + 1); |
|
||||
strcpy(message->version, method); |
|
||||
|
return 1; //* @TODO: return something useful here |
||||
} |
} |
||||
|
|
||||
// vim: set ts=4 sw=4: |
// vim: set ts=4 sw=4: |
||||
@ -0,0 +1,21 @@ |
|||||
|
#include <stdio.h> |
||||
|
|
||||
|
#include "ringbuffer.h" |
||||
|
#include "interface/class.h" |
||||
|
|
||||
|
int |
||||
|
main() |
||||
|
{ |
||||
|
Ringbuffer buf = new(Ringbuffer, "/rbtest", 1); |
||||
|
|
||||
|
strcpy(buf->buffer + buf->bsize - 5, "Dies ist ein foobar test"); |
||||
|
|
||||
|
printf("%s\n", buf->buffer); |
||||
|
printf("%s\n", buf->buffer + buf->bsize - 5); |
||||
|
|
||||
|
delete(&buf); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
@ -0,0 +1,117 @@ |
|||||
|
#define _POSIX_SOURCE |
||||
|
#define _POSIX_C_SOURCE 200112L |
||||
|
|
||||
|
#include <sys/types.h> |
||||
|
#include <sys/stat.h> |
||||
|
#include <sys/mman.h> |
||||
|
#include <stdarg.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include <unistd.h> |
||||
|
#include <fcntl.h> |
||||
|
|
||||
|
#include "class.h" |
||||
|
#include "interface/class.h" |
||||
|
|
||||
|
#include "ringbuffer.h" |
||||
|
|
||||
|
#define PAGES(size, psize) ((size)/(psize)+(0 == (size)%(psize))?0:1) |
||||
|
|
||||
|
|
||||
|
static void dtor(void*); |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
ctor(void * _this, va_list * params) |
||||
|
{ |
||||
|
Ringbuffer this = _this; |
||||
|
char state = 0; |
||||
|
char * shm_name = va_arg(*params, char*); |
||||
|
long psize = sysconf(_SC_PAGESIZE); |
||||
|
size_t size; |
||||
|
int shm; |
||||
|
void * shm_addr; |
||||
|
|
||||
|
this->shm_name = malloc(strlen(shm_name) + 1); |
||||
|
strcpy(this->shm_name, shm_name); |
||||
|
|
||||
|
/** |
||||
|
* align size at page boundary. |
||||
|
* increase as neccessary |
||||
|
*/ |
||||
|
size = va_arg(*params, size_t); |
||||
|
size = (0 <= size)? 1 : size; |
||||
|
this->bsize = psize * PAGES(size, psize); |
||||
|
|
||||
|
while (0 == state) { |
||||
|
shm = shm_open(this->shm_name, O_RDWR|O_CREAT|O_EXCL, S_IRWXU); |
||||
|
if (-1 == shm) { |
||||
|
break; |
||||
|
} |
||||
|
else { |
||||
|
ftruncate(shm, this->bsize); |
||||
|
} |
||||
|
|
||||
|
shm_addr = mmap (0, this->bsize<<1, |
||||
|
PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0); |
||||
|
if (shm_addr == MAP_FAILED) |
||||
|
break; |
||||
|
|
||||
|
munmap(shm_addr, this->bsize<<1); |
||||
|
|
||||
|
this->buffer = mmap (shm_addr, this->bsize, |
||||
|
PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0); |
||||
|
if (this->buffer == MAP_FAILED) { |
||||
|
shm_addr = NULL; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
this->mirror = mmap (shm_addr + this->bsize, this->bsize, |
||||
|
PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0); |
||||
|
if (this->mirror != shm_addr + this->bsize) { |
||||
|
shm_addr = NULL; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
state = 1; |
||||
|
} |
||||
|
|
||||
|
if (-1 != shm) { |
||||
|
shm_unlink(this->shm_name); |
||||
|
close(shm); |
||||
|
} |
||||
|
|
||||
|
if (1 != state) { |
||||
|
if (shm_addr) { |
||||
|
munmap(shm_addr, this->bsize<<1); |
||||
|
} |
||||
|
|
||||
|
dtor(this); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
void |
||||
|
dtor(void * _this) |
||||
|
{ |
||||
|
Ringbuffer this = _this; |
||||
|
|
||||
|
if (NULL != this->shm_name) { |
||||
|
free(this->shm_name); |
||||
|
} |
||||
|
|
||||
|
if (this->buffer) { |
||||
|
munmap(this->buffer, this->bsize); |
||||
|
this->buffer = NULL; |
||||
|
} |
||||
|
|
||||
|
if (this->mirror) { |
||||
|
munmap(this->mirror, this->bsize); |
||||
|
this->mirror = NULL; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
INIT_IFACE(Class, ctor, dtor, NULL); |
||||
|
CREATE_CLASS(Ringbuffer, NULL, IFACE(Class)); |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
@ -0,0 +1,41 @@ |
|||||
|
#include <sys/types.h> |
||||
|
#include <unistd.h> |
||||
|
#include <errno.h> |
||||
|
|
||||
|
#include "ringbuffer.h" |
||||
|
|
||||
|
ssize_t |
||||
|
rbRead(Ringbuffer this, int fd) |
||||
|
{ |
||||
|
ssize_t rrsize = 0; |
||||
|
size_t rsize = this->bsize - this->bused; |
||||
|
|
||||
|
if (0 == rsize) { |
||||
|
errno = ERBOVRFL; |
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
rrsize = read(fd, this->buffer + this->bend, rsize); |
||||
|
|
||||
|
switch (rrsize) { |
||||
|
case 0: |
||||
|
rsize = -2; |
||||
|
|
||||
|
case -1: |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
this->bend += rrsize; |
||||
|
this->bused += rrsize; |
||||
|
|
||||
|
if (this->bend >= this->bsize) { |
||||
|
this->bend -= this->bsize; |
||||
|
} |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
return rrsize; |
||||
|
} |
||||
|
|
||||
|
// vim: set ts=4 sw=4: |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue