summaryrefslogtreecommitdiffstats
path: root/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'client.c')
-rw-r--r--client.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/client.c b/client.c
index 2fbc560..41cda25 100644
--- a/client.c
+++ b/client.c
@@ -13,7 +13,7 @@
#define MAX_SEND_BUFFER 150000
static void client_haveIn(epoll_client_t *client);
-static void client_haveOut(epoll_client_t *client);
+static BOOL client_haveOut(epoll_client_t *client);
void client_free(epoll_client_t *client)
{
@@ -38,7 +38,9 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
if (client->ssl == NULL) {
// Plain connection
if (haveIn) client_haveIn(client);
- if (haveOut) client_haveOut(client);
+ if (haveOut || client->kill) {
+ if (client_haveOut(client)) return;
+ }
if (client->kill) {
//printf("Client gone (2).\n");
client_free(client);
@@ -57,7 +59,7 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
}
// Since we don't know if the incoming data is just wrapped application data or ssl protocol stuff, we always call both
client_haveIn(client);
- client_haveOut(client);
+ if (client_haveOut(client)) return;
if (client->kill) {
//printf("Client gone (3).\n");
client_free(client);
@@ -127,9 +129,15 @@ static void client_haveIn(epoll_client_t *client)
}
}
-static void client_haveOut(epoll_client_t *client)
+/**
+ * Send any queued data.
+ * Returns TRUE if anything has been sent, or the socket
+ * buffer is currently full (EAGAIN, non-blocking mode)
+ */
+static BOOL client_haveOut(epoll_client_t *client)
{
client->writeBlocked = FALSE;
+ if (client->sbPos >= client->sbFill) return FALSE;
while (client->sbPos < client->sbFill) {
const int tosend = client->sbFill - client->sbPos;
ssize_t ret;
@@ -137,11 +145,11 @@ static void client_haveOut(epoll_client_t *client)
// Plain
ret = write(client->fd, client->sendBuffer + client->sbPos, tosend);
if (ret < 0 && errno == EINTR) continue;
- if (ret < 0 && errno == EAGAIN) return;
+ if (ret < 0 && errno == EAGAIN) return TRUE;
if (ret <= 0) {
printf("[Proxy] Cannot send to client (ret=%d, errno=%d)\n", (int)ret, errno);
client->kill = TRUE;
- return;
+ return FALSE;
}
} else {
// SSL
@@ -150,12 +158,12 @@ static void client_haveOut(epoll_client_t *client)
int err = SSL_get_error(client->ssl, ret);
if (SSL_BLOCKED(err)) {
client->writeBlocked = TRUE;
- return; // Blocking
+ return TRUE; // Blocking
}
printf("[Proxy] SSL cannot send to client (ret=%d, err=%d)\n", (int)ret, err);
ERR_print_errors_fp(stdout);
client->kill = TRUE;
- return; // Closed
+ return FALSE; // Closed
}
}
client->sbPos += ret;
@@ -164,12 +172,13 @@ static void client_haveOut(epoll_client_t *client)
client->sbFill -= client->sbPos;
client->sbPos = 0;
}
- if (client->ssl == NULL && ret != tosend) return; // Sent less than requested -> buffer full, epoll will trigger us again
+ if (client->ssl == NULL && ret != tosend) return TRUE; // Sent less than requested -> buffer full, epoll will trigger us again
}
client->sbPos = client->sbFill = 0;
if (client->ssl == NULL && client->sbLen > MAX_SEND_BUFFER / 2) {
helper_realloc(&client->sendBuffer, &client->sbLen, 8000, "client_haveOut");
}
+ return TRUE;
}
BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const BOOL cork)
@@ -221,3 +230,12 @@ BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const B
return TRUE;
}
+BOOL client_searchResultError(epoll_client_t *client, const unsigned long messageId, const int code, const char *message)
+{
+ const size_t doneLen = fmt_ldapsearchresultdone(NULL, code, "", message, "");
+ const size_t doneHeaderLen = fmt_ldapmessage(NULL, messageId, SearchResultDone, doneLen);
+ char buffer[doneLen + doneHeaderLen];
+ fmt_ldapsearchresultdone(buffer + doneHeaderLen, code, "", message, "");
+ fmt_ldapmessage(buffer, messageId, SearchResultDone, doneLen);
+ return client_send(client, buffer, doneHeaderLen + doneLen, FALSE);
+}