Replace GString with GByteArray

This commit is contained in:
Stefan Bühler 2009-11-11 21:14:53 +01:00
parent 04dbbb6470
commit ac4f2ff612
3 changed files with 165 additions and 105 deletions

224
fastcgi.c
View File

@ -18,7 +18,8 @@ typedef struct fastcgi_queue_link {
} fastcgi_queue_link; } fastcgi_queue_link;
/* some util functions */ /* some util functions */
#define GSTR_LEN(x) (x) ? (x)->str : "", (x) ? (x)->len : 0 #define GSTR_LEN(x) ((x) ? (x)->str : ""), ((x) ? (x)->len : 0)
#define GBARR_LEN(x) ((x)->data), ((x)->len)
#define UNUSED(x) ((void)(x)) #define UNUSED(x) ((void)(x))
#define ERROR(...) g_printerr("fastcgi.c:" G_STRINGIFY(__LINE__) ": " __VA_ARGS__) #define ERROR(...) g_printerr("fastcgi.c:" G_STRINGIFY(__LINE__) ": " __VA_ARGS__)
@ -195,47 +196,51 @@ static void ev_io_rem_events(struct ev_loop *loop, ev_io *watcher, int events) {
} }
/* end: some util functions */ /* end: some util functions */
static const gchar __padding[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static const guint8 __padding[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static void append_padding(GString *s, guint8 padlen) { static void append_padding_str(GString *s, guint8 padlen) {
g_string_append_len(s, __padding, padlen); g_string_append_len(s, (const gchar*) __padding, padlen);
}
static void append_padding_bytearray(GByteArray *a, guint8 padlen) {
g_byte_array_append(a, __padding, padlen);
} }
/* returns padding length */ /* returns padding length */
static guint8 stream_build_fcgi_record(GString *buf, guint8 type, guint16 requestid, guint16 datalen) { static guint8 stream_build_fcgi_record(GByteArray *buf, guint8 type, guint16 requestid, guint16 datalen) {
guint16 w;
guint8 padlen = (8 - (datalen & 0x7)) % 8; /* padding must be < 8 */ guint8 padlen = (8 - (datalen & 0x7)) % 8; /* padding must be < 8 */
g_string_set_size(buf, FCGI_HEADER_LEN); /* alloc enough space */
g_string_truncate(buf, 0); g_byte_array_set_size(buf, FCGI_HEADER_LEN);
buf->len = 0;
g_string_append_c(buf, FCGI_VERSION_1); buf->data[buf->len++] = FCGI_VERSION_1;
g_string_append_c(buf, type); buf->data[buf->len++] = type;
w = htons(requestid); buf->data[buf->len++] = (guint8) (requestid >> 8);
g_string_append_len(buf, (const gchar*) &w, sizeof(w)); buf->data[buf->len++] = (guint8) (requestid);
w = htons(datalen); buf->data[buf->len++] = (guint8) (datalen >> 8);
g_string_append_len(buf, (const gchar*) &w, sizeof(w)); buf->data[buf->len++] = (guint8) (datalen);
g_string_append_c(buf, padlen); buf->data[buf->len++] = padlen;
g_string_append_c(buf, 0); buf->data[buf->len++] = 0;
return padlen; return padlen;
} }
/* returns padding length */ /* returns padding length */
static guint8 stream_send_fcgi_record(fastcgi_queue *out, guint8 type, guint16 requestid, guint16 datalen) { static guint8 stream_send_fcgi_record(fastcgi_queue *out, guint8 type, guint16 requestid, guint16 datalen) {
GString *record = g_string_sized_new(FCGI_HEADER_LEN); GByteArray *record = g_byte_array_sized_new(FCGI_HEADER_LEN);
guint8 padlen = stream_build_fcgi_record(record, type, requestid, datalen); guint8 padlen = stream_build_fcgi_record(record, type, requestid, datalen);
fastcgi_queue_append_string(out, record); fastcgi_queue_append_bytearray(out, record);
return padlen; return padlen;
} }
static void stream_send_data(fastcgi_queue *out, guint8 type, guint16 requestid, const gchar *data, size_t datalen) { static void stream_send_data(fastcgi_queue *out, guint8 type, guint16 requestid, const guint8 *data, size_t datalen) {
while (datalen > 0) { while (datalen > 0) {
guint16 tosend = (datalen > G_MAXUINT16) ? G_MAXUINT16 : datalen; guint16 tosend = (datalen > G_MAXUINT16) ? G_MAXUINT16 : datalen;
guint8 padlen = stream_send_fcgi_record(out, type, requestid, tosend); guint8 padlen = stream_send_fcgi_record(out, type, requestid, tosend);
GString *tmps = g_string_sized_new(tosend + padlen); GByteArray *buf = g_byte_array_sized_new(tosend + padlen);
g_string_append_len(tmps, data, tosend); g_byte_array_append(buf, data, tosend);
append_padding(tmps, padlen); append_padding_bytearray(buf, padlen);
fastcgi_queue_append_string(out, tmps); fastcgi_queue_append_bytearray(out, buf);
data += tosend; data += tosend;
datalen -= tosend; datalen -= tosend;
} }
@ -244,24 +249,42 @@ static void stream_send_data(fastcgi_queue *out, guint8 type, guint16 requestid,
/* kills string */ /* kills string */
static void stream_send_string(fastcgi_queue *out, guint8 type, guint16 requestid, GString *data) { static void stream_send_string(fastcgi_queue *out, guint8 type, guint16 requestid, GString *data) {
if (data->len > G_MAXUINT16) { if (data->len > G_MAXUINT16) {
stream_send_data(out, type, requestid, GSTR_LEN(data)); stream_send_data(out, type, requestid, (const guint8*) GSTR_LEN(data));
g_string_free(data, TRUE); g_string_free(data, TRUE);
} else { } else {
guint8 padlen = stream_send_fcgi_record(out, type, requestid, data->len); guint8 padlen = stream_send_fcgi_record(out, type, requestid, data->len);
append_padding(data, padlen); append_padding_str(data, padlen);
fastcgi_queue_append_string(out, data); fastcgi_queue_append_string(out, data);
} }
} }
/* kills bytearray */
static void stream_send_bytearray(fastcgi_queue *out, guint8 type, guint16 requestid, GByteArray *data) {
if (data->len > G_MAXUINT16) {
stream_send_data(out, type, requestid, GBARR_LEN(data));
g_byte_array_free(data, TRUE);
} else {
guint8 padlen = stream_send_fcgi_record(out, type, requestid, data->len);
append_padding_bytearray(data, padlen);
fastcgi_queue_append_bytearray(out, data);
}
}
static void stream_send_end_request(fastcgi_queue *out, guint16 requestID, gint32 appStatus, enum FCGI_ProtocolStatus status) { static void stream_send_end_request(fastcgi_queue *out, guint16 requestID, gint32 appStatus, enum FCGI_ProtocolStatus status) {
GString *record; GByteArray *record;
record = g_string_sized_new(16);
record = g_byte_array_sized_new(16);
stream_build_fcgi_record(record, FCGI_END_REQUEST, requestID, 8); stream_build_fcgi_record(record, FCGI_END_REQUEST, requestID, 8);
/* alloc enough space */
g_byte_array_set_size(record, 16);
record->len = 8;
appStatus = htonl(appStatus); appStatus = htonl(appStatus);
g_string_append_len(record, (const gchar*) &appStatus, sizeof(appStatus)); g_byte_array_append(record, (const guchar*) &appStatus, sizeof(appStatus));
g_string_append_c(record, status); record->data[record->len++] = status;
g_string_append_len(record, __padding, 3); g_byte_array_append(record, __padding, 3);
fastcgi_queue_append_string(out, record); fastcgi_queue_append_bytearray(out, record);
} }
@ -291,58 +314,79 @@ static void write_queue(fastcgi_connection *fcon) {
} }
} }
static GString* read_chunk(fastcgi_connection *fcon, guint maxlen) { static GByteArray* read_chunk(fastcgi_connection *fcon, guint maxlen) {
gssize res; gssize res;
GString *str; GByteArray *buf;
int tmp_errno; int tmp_errno;
str = g_string_sized_new(maxlen); buf = g_byte_array_sized_new(maxlen);
g_string_set_size(str, maxlen); g_byte_array_set_size(buf, maxlen);
if (0 == maxlen) return str; if (0 == maxlen) return buf;
res = read(fcon->fd, str->str, maxlen); res = read(fcon->fd, buf->data, maxlen);
if (res == -1) { if (res == -1) {
tmp_errno = errno; tmp_errno = errno;
g_string_free(str, TRUE); g_byte_array_free(buf, TRUE);
errno = tmp_errno; errno = tmp_errno;
return NULL; return NULL;
} else if (res == 0) { } else if (res == 0) {
g_string_free(str, TRUE); g_byte_array_free(buf, TRUE);
errno = ECONNRESET; errno = ECONNRESET;
return NULL; return NULL;
} else { } else {
g_string_set_size(str, res); g_byte_array_set_size(buf, res);
return str; return buf;
} }
} }
static gboolean read_append_chunk(fastcgi_connection *fcon, GString *str) { /* read content + padding, but only returns content data. decrements counters */
static GByteArray *read_content(fastcgi_connection *fcon) {
GByteArray *buf;
buf = read_chunk(fcon, fcon->content_remaining + fcon->padding_remaining);
if (!buf) return NULL;
if (buf->len > fcon->content_remaining) {
g_byte_array_set_size(buf, fcon->content_remaining);
fcon->padding_remaining -= (buf->len - fcon->content_remaining);
fcon->content_remaining = 0;
} else {
fcon->content_remaining -= buf->len;
}
return buf;
}
static gboolean read_append_chunk(fastcgi_connection *fcon, GByteArray *buf) {
gssize res; gssize res;
int tmp_errno; int tmp_errno;
guint curlen = str->len; guint curlen = buf->len;
const guint maxlen = fcon->content_remaining; const guint maxlen = fcon->content_remaining + fcon->padding_remaining;
if (0 == maxlen) return TRUE; if (0 == maxlen) return TRUE;
g_string_set_size(str, curlen + maxlen); g_byte_array_set_size(buf, curlen + maxlen);
res = read(fcon->fd, str->str + curlen, maxlen); res = read(fcon->fd, buf->data + curlen, maxlen);
if (res == -1) { if (res == -1) {
tmp_errno = errno; tmp_errno = errno;
g_string_set_size(str, curlen); g_byte_array_set_size(buf, curlen);
errno = tmp_errno; errno = tmp_errno;
return FALSE; return FALSE;
} else if (res == 0) { } else if (res == 0) {
g_string_set_size(str, curlen); g_byte_array_set_size(buf, curlen);
errno = ECONNRESET; errno = ECONNRESET;
return FALSE; return FALSE;
} else { } else {
g_string_set_size(str, curlen + res); /* remove padding data */
if (res > fcon->content_remaining) {
fcon->padding_remaining -= res - fcon->content_remaining;
res = fcon->content_remaining;
}
g_byte_array_set_size(buf, curlen + res);
fcon->content_remaining -= res; fcon->content_remaining -= res;
return TRUE; return TRUE;
} }
} }
static gboolean read_key_value(fastcgi_connection *fcon, GString *buf, guint *pos, gchar **key, guint *keylen, gchar **value, guint *valuelen) { static gboolean read_key_value(fastcgi_connection *fcon, GByteArray *buf, guint *pos, gchar **key, guint *keylen, gchar **value, guint *valuelen) {
const unsigned char *data = (const unsigned char*) buf->str; const unsigned char *data = (const unsigned char*) buf->data;
guint32 klen, vlen; guint32 klen, vlen;
guint p = *pos, len = buf->len; guint p = *pos, len = buf->len;
@ -365,10 +409,10 @@ static gboolean read_key_value(fastcgi_connection *fcon, GString *buf, guint *po
return FALSE; return FALSE;
} }
if (len - p < klen + vlen) return FALSE; if (len - p < klen + vlen) return FALSE;
*key = &buf->str[p]; *key = (gchar*) &buf->data[p];
*keylen = klen; *keylen = klen;
p += klen; p += klen;
*value = &buf->str[p]; *value = (gchar*) &buf->data[p];
*valuelen = vlen; *valuelen = vlen;
p += vlen; p += vlen;
*pos = p; *pos = p;
@ -378,7 +422,7 @@ static gboolean read_key_value(fastcgi_connection *fcon, GString *buf, guint *po
static void parse_params(const fastcgi_callbacks *fcbs, fastcgi_connection *fcon) { static void parse_params(const fastcgi_callbacks *fcbs, fastcgi_connection *fcon) {
if (!fcon->current_header.contentLength) { if (!fcon->current_header.contentLength) {
fcbs->cb_new_request(fcon); fcbs->cb_new_request(fcon);
g_string_truncate(fcon->parambuf, 0); g_byte_array_set_size(fcon->parambuf, 0);
} else { } else {
guint pos = 0, keylen = 0, valuelen = 0; guint pos = 0, keylen = 0, valuelen = 0;
gchar *key = NULL, *value = NULL; gchar *key = NULL, *value = NULL;
@ -391,21 +435,21 @@ static void parse_params(const fastcgi_callbacks *fcbs, fastcgi_connection *fcon
g_ptr_array_add(fcon->environ, envvar); g_ptr_array_add(fcon->environ, envvar);
} }
if (!fcon->closing) if (!fcon->closing)
g_string_erase(fcon->parambuf, 0, pos); g_byte_array_remove_range(fcon->parambuf, 0, pos);
} }
} }
static void parse_get_values(fastcgi_connection *fcon) { static void parse_get_values(fastcgi_connection *fcon) {
/* just send the request back and don't insert results */ /* just send the request back and don't insert results */
GString *tmp = g_string_sized_new(0); GByteArray *tmp = g_byte_array_sized_new(0);
stream_send_string(&fcon->write_queue, FCGI_GET_VALUES_RESULT, 0, fcon->buffer); stream_send_bytearray(&fcon->write_queue, FCGI_GET_VALUES_RESULT, 0, fcon->buffer);
*fcon->buffer = *tmp; *fcon->buffer = *tmp;
/* TODO: provide get-values result */ /* TODO: provide get-values result */
} }
static void read_queue(fastcgi_connection *fcon) { static void read_queue(fastcgi_connection *fcon) {
gssize res; gssize res;
GString *buf; GByteArray *buf;
const fastcgi_callbacks *fcbs = fcon->fsrv->callbacks; const fastcgi_callbacks *fcbs = fcon->fsrv->callbacks;
for (;;) { for (;;) {
@ -427,7 +471,7 @@ static void read_queue(fastcgi_connection *fcon) {
fcon->content_remaining = fcon->current_header.contentLength; fcon->content_remaining = fcon->current_header.contentLength;
fcon->padding_remaining = fcon->current_header.paddingLength; fcon->padding_remaining = fcon->current_header.paddingLength;
fcon->first = TRUE; fcon->first = TRUE;
g_string_truncate(fcon->buffer, 0); g_byte_array_set_size(fcon->buffer, 0);
if (fcon->current_header.version != FCGI_VERSION_1) { if (fcon->current_header.version != FCGI_VERSION_1) {
fastcgi_connection_close(fcon); fastcgi_connection_close(fcon);
@ -438,18 +482,12 @@ static void read_queue(fastcgi_connection *fcon) {
if (fcon->current_header.type != FCGI_BEGIN_REQUEST && if (fcon->current_header.type != FCGI_BEGIN_REQUEST &&
(0 != fcon->current_header.requestID) && fcon->current_header.requestID != fcon->requestID) { (0 != fcon->current_header.requestID) && fcon->current_header.requestID != fcon->requestID) {
/* ignore packet data */ /* ignore packet data */
if (0 != fcon->content_remaining + fcon->padding_remaining) {
if (NULL == (buf = read_content(fcon))) goto handle_error;
g_byte_array_free(buf, TRUE);
}
if (0 == fcon->content_remaining + fcon->padding_remaining) { if (0 == fcon->content_remaining + fcon->padding_remaining) {
fcon->headerbuf_used = 0; fcon->headerbuf_used = 0;
} else {
if (NULL == (buf = read_chunk(fcon, fcon->content_remaining + fcon->padding_remaining))) goto handle_error;
if (buf->len >= fcon->content_remaining) {
fcon->padding_remaining -= buf->len - fcon->content_remaining;
fcon->content_remaining = 0;
if (0 == fcon->padding_remaining) fcon->headerbuf_used = 0;
} else {
fcon->content_remaining -= buf->len;
}
g_string_free(buf, TRUE);
} }
continue; continue;
} }
@ -464,11 +502,11 @@ static void read_queue(fastcgi_connection *fcon) {
if (fcon->requestID) { if (fcon->requestID) {
stream_send_end_request(&fcon->write_queue, fcon->current_header.requestID, 0, FCGI_CANT_MPX_CONN); stream_send_end_request(&fcon->write_queue, fcon->current_header.requestID, 0, FCGI_CANT_MPX_CONN);
} else { } else {
unsigned char *data = (unsigned char*) fcon->buffer->str; unsigned char *data = (unsigned char*) fcon->buffer->data;
fcon->requestID = fcon->current_header.requestID; fcon->requestID = fcon->current_header.requestID;
fcon->role = (data[0] << 8) | (data[1]); fcon->role = (data[0] << 8) | (data[1]);
fcon->flags = data[2]; fcon->flags = data[2];
g_string_truncate(fcon->parambuf, 0); g_byte_array_set_size(fcon->parambuf, 0);
} }
} }
break; break;
@ -487,12 +525,11 @@ static void read_queue(fastcgi_connection *fcon) {
if (0 == fcon->current_header.requestID) goto error; if (0 == fcon->current_header.requestID) goto error;
buf = NULL; buf = NULL;
if (0 != fcon->content_remaining && if (0 != fcon->content_remaining &&
NULL == (buf = read_chunk(fcon, fcon->content_remaining))) goto handle_error; NULL == (buf = read_content(fcon))) goto handle_error;
if (buf) fcon->content_remaining -= buf->len;
if (fcbs->cb_received_stdin) { if (fcbs->cb_received_stdin) {
fcbs->cb_received_stdin(fcon, buf); fcbs->cb_received_stdin(fcon, buf);
} else { } else {
g_string_free(buf, TRUE); g_byte_array_free(buf, TRUE);
} }
break; break;
case FCGI_STDOUT: case FCGI_STDOUT:
@ -503,12 +540,11 @@ static void read_queue(fastcgi_connection *fcon) {
if (0 == fcon->current_header.requestID) goto error; if (0 == fcon->current_header.requestID) goto error;
buf = NULL; buf = NULL;
if (0 != fcon->content_remaining && if (0 != fcon->content_remaining &&
NULL == (buf = read_chunk(fcon, fcon->content_remaining))) goto handle_error; NULL == (buf = read_content(fcon))) goto handle_error;
if (buf) fcon->content_remaining -= buf->len;
if (fcbs->cb_received_data) { if (fcbs->cb_received_data) {
fcbs->cb_received_data(fcon, buf); fcbs->cb_received_data(fcon, buf);
} else { } else {
g_string_free(buf, TRUE); g_byte_array_free(buf, TRUE);
} }
break; break;
case FCGI_GET_VALUES: case FCGI_GET_VALUES:
@ -537,7 +573,7 @@ static void read_queue(fastcgi_connection *fcon) {
if (0 == fcon->padding_remaining) { if (0 == fcon->padding_remaining) {
fcon->headerbuf_used = 0; fcon->headerbuf_used = 0;
} }
g_string_free(buf, TRUE); g_byte_array_free(buf, TRUE);
} }
} }
@ -585,8 +621,8 @@ static fastcgi_connection *fastcgi_connecion_create(fastcgi_server *fsrv, gint f
fcon->fsrv = fsrv; fcon->fsrv = fsrv;
fcon->fcon_id = id; fcon->fcon_id = id;
fcon->buffer = g_string_sized_new(0); fcon->buffer = g_byte_array_sized_new(0);
fcon->parambuf = g_string_sized_new(0); fcon->parambuf = g_byte_array_sized_new(0);
fcon->environ = g_ptr_array_new(); fcon->environ = g_ptr_array_new();
fcon->fd = fd; fcon->fd = fd;
@ -610,8 +646,8 @@ static void fastcgi_connection_free(fastcgi_connection *fcon) {
fastcgi_queue_clear(&fcon->write_queue); fastcgi_queue_clear(&fcon->write_queue);
fastcgi_connection_environ_clear(fcon); fastcgi_connection_environ_clear(fcon);
g_ptr_array_free(fcon->environ, TRUE); g_ptr_array_free(fcon->environ, TRUE);
g_string_free(fcon->buffer, TRUE); g_byte_array_free(fcon->buffer, TRUE);
g_string_free(fcon->parambuf, TRUE); g_byte_array_free(fcon->parambuf, TRUE);
g_slice_free(fastcgi_connection, fcon); g_slice_free(fastcgi_connection, fcon);
} }
@ -626,8 +662,8 @@ void fastcgi_connection_close(fastcgi_connection *fcon) {
fastcgi_queue_clear(&fcon->write_queue); fastcgi_queue_clear(&fcon->write_queue);
g_string_truncate(fcon->buffer, 0); g_byte_array_set_size(fcon->buffer, 0);
g_string_truncate(fcon->parambuf, 0); g_byte_array_set_size(fcon->parambuf, 0);
fastcgi_connection_environ_clear(fcon); fastcgi_connection_environ_clear(fcon);
ev_prepare_start(fcon->fsrv->loop, &fcon->fsrv->closing_watcher); ev_prepare_start(fcon->fsrv->loop, &fcon->fsrv->closing_watcher);
@ -795,6 +831,26 @@ void fastcgi_send_err(fastcgi_connection *fcon, GString *data) {
if (!had_data) write_queue(fcon); if (!had_data) write_queue(fcon);
} }
void fastcgi_send_out_bytearray(fastcgi_connection *fcon, GByteArray *data) {
gboolean had_data = (fcon->write_queue.length > 0);
if (!data) {
stream_send_fcgi_record(&fcon->write_queue, FCGI_STDOUT, fcon->requestID, 0);
} else {
stream_send_bytearray(&fcon->write_queue, FCGI_STDOUT, fcon->requestID, data);
}
if (!had_data) write_queue(fcon);
}
void fastcgi_send_err_bytearray(fastcgi_connection *fcon, GByteArray *data) {
gboolean had_data = (fcon->write_queue.length > 0);
if (!data) {
stream_send_fcgi_record(&fcon->write_queue, FCGI_STDERR, fcon->requestID, 0);
} else {
stream_send_bytearray(&fcon->write_queue, FCGI_STDERR, fcon->requestID, data);
}
if (!had_data) write_queue(fcon);
}
void fastcgi_connection_environ_clear(fastcgi_connection *fcon) { void fastcgi_connection_environ_clear(fastcgi_connection *fcon) {
guint i; guint i;
for (i = 0; i < fcon->environ->len; i++) { for (i = 0; i < fcon->environ->len; i++) {

View File

@ -82,8 +82,8 @@ struct fastcgi_callbacks {
void (*cb_new_connection)(fastcgi_connection *fcon); /* new connection accepted */ void (*cb_new_connection)(fastcgi_connection *fcon); /* new connection accepted */
void (*cb_new_request)(fastcgi_connection *fcon); /* new request on connection, env/params are ready */ void (*cb_new_request)(fastcgi_connection *fcon); /* new request on connection, env/params are ready */
void (*cb_wrote_data)(fastcgi_connection *fcon); void (*cb_wrote_data)(fastcgi_connection *fcon);
void (*cb_received_stdin)(fastcgi_connection *fcon, GString *data); /* data == NULL => eof */ void (*cb_received_stdin)(fastcgi_connection *fcon, GByteArray *data); /* data == NULL => eof */
void (*cb_received_data)(fastcgi_connection *fcon, GString *data); /* data == NULL => eof */ void (*cb_received_data)(fastcgi_connection *fcon, GByteArray *data); /* data == NULL => eof */
void (*cb_request_aborted)(fastcgi_connection *fcon); void (*cb_request_aborted)(fastcgi_connection *fcon);
void (*cb_reset_connection)(fastcgi_connection *fcon); /* cleanup custom data before fcon is freed, not for keep-alive */ void (*cb_reset_connection)(fastcgi_connection *fcon); /* cleanup custom data before fcon is freed, not for keep-alive */
}; };
@ -127,7 +127,7 @@ struct fastcgi_connection {
guint content_remaining, padding_remaining; guint content_remaining, padding_remaining;
GString *buffer, *parambuf; GByteArray *buffer, *parambuf;
gint fd; gint fd;
ev_io fd_watcher; ev_io fd_watcher;
@ -148,6 +148,8 @@ void fastcgi_resume_read(fastcgi_connection *fcon);
void fastcgi_end_request(fastcgi_connection *fcon, gint32 appStatus, enum FCGI_ProtocolStatus status); void fastcgi_end_request(fastcgi_connection *fcon, gint32 appStatus, enum FCGI_ProtocolStatus status);
void fastcgi_send_out(fastcgi_connection *fcon, GString *data); void fastcgi_send_out(fastcgi_connection *fcon, GString *data);
void fastcgi_send_err(fastcgi_connection *fcon, GString *data); void fastcgi_send_err(fastcgi_connection *fcon, GString *data);
void fastcgi_send_out_bytearray(fastcgi_connection *fcon, GByteArray *data);
void fastcgi_send_err_bytearray(fastcgi_connection *fcon, GByteArray *data);
void fastcgi_connection_close(fastcgi_connection *fcon); /* shouldn't be needed */ void fastcgi_connection_close(fastcgi_connection *fcon); /* shouldn't be needed */

View File

@ -131,32 +131,34 @@ static void write_queue(fcgi_cgi_child *cld) {
} }
} }
static GString* read_chunk(gint fd, guint maxlen) { static GByteArray* read_chunk(gint fd, guint maxlen) {
gssize res; gssize res;
GString *str; GByteArray *buf;
int tmp_errno; int tmp_errno;
str = g_string_sized_new(maxlen); buf = g_byte_array_sized_new(maxlen);
g_string_set_size(str, maxlen); g_byte_array_set_size(buf, maxlen);
res = read(fd, str->str, maxlen); if (0 == maxlen) return buf;
res = read(fd, buf->data, maxlen);
if (res == -1) { if (res == -1) {
tmp_errno = errno; tmp_errno = errno;
g_string_free(str, TRUE); g_byte_array_free(buf, TRUE);
errno = tmp_errno; errno = tmp_errno;
return NULL; return NULL;
} else if (res == 0) { } else if (res == 0) {
g_string_free(str, TRUE); g_byte_array_free(buf, TRUE);
errno = ECONNRESET; errno = ECONNRESET;
return NULL; return NULL;
} else { } else {
g_string_set_size(str, res); g_byte_array_set_size(buf, res);
return str; return buf;
} }
} }
static void fcgi_cgi_child_pipe_in_cb(struct ev_loop *loop, ev_io *w, int revents) { static void fcgi_cgi_child_pipe_in_cb(struct ev_loop *loop, ev_io *w, int revents) {
fcgi_cgi_child *cld = (fcgi_cgi_child*) w->data; fcgi_cgi_child *cld = (fcgi_cgi_child*) w->data;
GString *buf; GByteArray *buf;
UNUSED(loop); UNUSED(revents); UNUSED(loop); UNUSED(revents);
if (NULL == (buf = read_chunk(cld->pipe_in, 64*1024))) { if (NULL == (buf = read_chunk(cld->pipe_in, 64*1024))) {
@ -176,10 +178,10 @@ static void fcgi_cgi_child_pipe_in_cb(struct ev_loop *loop, ev_io *w, int revent
break; break;
} }
} else if (cld->fcon) { } else if (cld->fcon) {
fastcgi_send_out(cld->fcon, buf); fastcgi_send_out_bytearray(cld->fcon, buf);
fcgi_cgi_wrote_data(cld->fcon); fcgi_cgi_wrote_data(cld->fcon);
} else { } else {
g_string_free(buf, TRUE); g_byte_array_free(buf, TRUE);
} }
} }
@ -192,7 +194,7 @@ static void fcgi_cgi_child_pipe_out_cb(struct ev_loop *loop, ev_io *w, int reven
static void fcgi_cgi_child_pipe_err_cb(struct ev_loop *loop, ev_io *w, int revents) { static void fcgi_cgi_child_pipe_err_cb(struct ev_loop *loop, ev_io *w, int revents) {
fcgi_cgi_child *cld = (fcgi_cgi_child*) w->data; fcgi_cgi_child *cld = (fcgi_cgi_child*) w->data;
GString *buf; GByteArray *buf;
UNUSED(loop); UNUSED(revents); UNUSED(loop); UNUSED(revents);
if (NULL == (buf = read_chunk(cld->pipe_err, 64*1024))) { if (NULL == (buf = read_chunk(cld->pipe_err, 64*1024))) {
@ -212,10 +214,10 @@ static void fcgi_cgi_child_pipe_err_cb(struct ev_loop *loop, ev_io *w, int reven
break; break;
} }
} else if (cld->fcon) { } else if (cld->fcon) {
fastcgi_send_err(cld->fcon, buf); fastcgi_send_err_bytearray(cld->fcon, buf);
fcgi_cgi_wrote_data(cld->fcon); fcgi_cgi_wrote_data(cld->fcon);
} else { } else {
g_string_free(buf, TRUE); g_byte_array_free(buf, TRUE);
} }
} }
@ -449,14 +451,14 @@ static void fcgi_cgi_wrote_data(fastcgi_connection *fcon) {
} }
} }
static void fcgi_cgi_received_stdin(fastcgi_connection *fcon, GString *data) { static void fcgi_cgi_received_stdin(fastcgi_connection *fcon, GByteArray *data) {
fcgi_cgi_child *cld = (fcgi_cgi_child*) fcon->data; fcgi_cgi_child *cld = (fcgi_cgi_child*) fcon->data;
/* if proc is running but pipe closed -> drop data */ /* if proc is running but pipe closed -> drop data */
if (!cld || cld->write_queue.closed) { if (!cld || cld->write_queue.closed) {
if (data) g_string_free(data, TRUE); if (data) g_byte_array_free(data, TRUE);
return; return;
} }
fastcgi_queue_append_string(&cld->write_queue, data); fastcgi_queue_append_bytearray(&cld->write_queue, data);
write_queue(cld); /* if we don't call this we have to check the write-queue length */ write_queue(cld); /* if we don't call this we have to check the write-queue length */
} }