rocksock_readline: act properly on remote disconnect
[rofl0r-rocksock.git] / rocksock_readline.c
blob597011b3aba59a0fdb5afa2eaaf89eb2a7d17a50
1 /*
2 * author: rofl0r (C) 2011-2013
3 * License: LGPL 2.1+ with static linking exception
4 */
6 #undef _POSIX_C_SOURCE
7 #define _POSIX_C_SOURCE 200809L
8 #undef _GNU_SOURCE
9 #define _GNU_SOURCE
11 #include <stddef.h>
12 #include "rocksock_internal.h"
14 #ifndef ROCKSOCK_FILENAME
15 #define ROCKSOCK_FILENAME __FILE__
16 #endif
18 // tries to read exactly one line, until '\n', then appends a '\0'
19 int rocksock_readline(rocksock* sock, char* buffer, size_t bufsize, size_t* bytesread) {
20 // TODO: make more efficient by peeking into the buffer (Flag MSG_PEEK to recv), instead of reading byte by byte
21 // would need a different approach for ssl though.
22 if (!sock) return RS_E_NULL;
23 if (!buffer || !bufsize || !bytesread)
24 return rocksock_seterror(sock, RS_ET_OWN, RS_E_NULL,
25 ROCKSOCK_FILENAME, __LINE__);
26 char* ptr = buffer;
27 size_t bytesread2 = 0;
28 int ret;
29 *bytesread = 0;
30 while(*bytesread < bufsize) {
31 ret = rocksock_recv(sock, ptr, 1, 1, &bytesread2);
32 if(ret || !bytesread2) return ret;
33 *bytesread += bytesread2;
34 if(ptr > buffer + bufsize)
35 break;
36 if(*bytesread > bufsize) {
37 *bytesread = bufsize;
38 break;
40 if(*ptr == '\n') {
41 if(*bytesread < bufsize) {
42 buffer[*bytesread] = '\0';
43 return 0;
44 } else
45 break;
47 ptr++;
49 return rocksock_seterror(sock, RS_ET_OWN, RS_E_OUT_OF_BUFFER,
50 ROCKSOCK_FILENAME, __LINE__);