3 ** Copyright 2006, The Android Open Source Project
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
9 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
22 #include <telephony/record_stream.h>
26 #include <winsock2.h> /* for ntohl */
28 #include <netinet/in.h>
37 unsigned char *buffer;
39 unsigned char *unconsumed;
40 unsigned char *read_end;
41 unsigned char *buffer_end;
45 extern RecordStream *record_stream_new(int fd, size_t maxRecordLen)
49 assert (maxRecordLen <= 0xffff);
51 ret = (RecordStream *)calloc(1, sizeof(RecordStream));
54 ret->maxRecordLen = maxRecordLen;
55 ret->buffer = (unsigned char *)malloc (maxRecordLen + HEADER_SIZE);
57 ret->unconsumed = ret->buffer;
58 ret->read_end = ret->buffer;
59 ret->buffer_end = ret->buffer + maxRecordLen + HEADER_SIZE;
65 extern void record_stream_free(RecordStream *rs)
72 /* returns NULL; if there isn't a full record in the buffer */
73 static unsigned char * getEndOfRecord (unsigned char *p_begin,
77 unsigned char * p_ret;
79 if (p_end < p_begin + HEADER_SIZE) {
83 //First four bytes are length
84 len = ntohl(*((uint32_t *)p_begin));
86 p_ret = p_begin + HEADER_SIZE + len;
95 static void *getNextRecord (RecordStream *p_rs, size_t *p_outRecordLen)
97 unsigned char *record_start, *record_end;
99 record_end = getEndOfRecord (p_rs->unconsumed, p_rs->read_end);
101 if (record_end != NULL) {
102 /* one full line in the buffer */
103 record_start = p_rs->unconsumed + HEADER_SIZE;
104 p_rs->unconsumed = record_end;
106 *p_outRecordLen = record_end - record_start;
115 * Reads the next record from stream fd
116 * Records are prefixed by a 16-bit big endian length value
117 * Records may not be larger than maxRecordLen
119 * Doesn't guard against EINTR
121 * p_outRecord and p_outRecordLen may not be NULL
123 * Return 0 on success, -1 on fail
124 * Returns 0 with *p_outRecord set to NULL on end of stream
125 * Returns -1 / errno = EAGAIN if it needs to read again
127 int record_stream_get_next (RecordStream *p_rs, void ** p_outRecord,
128 size_t *p_outRecordLen)
134 /* is there one record already in the buffer? */
135 ret = getNextRecord (p_rs, p_outRecordLen);
142 // if the buffer is full and we don't have a full record
143 if (p_rs->unconsumed == p_rs->buffer
144 && p_rs->read_end == p_rs->buffer_end
146 // this should never happen
147 //ALOGE("max record length exceeded\n");
153 if (p_rs->unconsumed != p_rs->buffer) {
154 // move remainder to the beginning of the buffer
157 toMove = p_rs->read_end - p_rs->unconsumed;
159 memmove(p_rs->buffer, p_rs->unconsumed, toMove);
162 p_rs->read_end = p_rs->buffer + toMove;
163 p_rs->unconsumed = p_rs->buffer;
166 countRead = read (p_rs->fd, p_rs->read_end, p_rs->buffer_end - p_rs->read_end);
168 if (countRead <= 0) {
169 /* note: end-of-stream drops through here too */
174 p_rs->read_end += countRead;
176 ret = getNextRecord (p_rs, p_outRecordLen);
179 /* not enough of a buffer to for a whole command */