PageRenderTime 56ms CodeModel.GetById 17ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/at_read.c

http://datacard.googlecode.com/
C | 238 lines | 177 code | 39 blank | 22 comment | 50 complexity | f46cb1e8badf7639de10afd48375f52e MD5 | raw file
  1/* 
  2   Copyright (C) 2009 - 2010
  3   
  4   Artem Makhutov <artem@makhutov.org>
  5   http://www.makhutov.org
  6   
  7   Dmitry Vagin <dmitry2004@yandex.ru>
  8
  9   bg <bg_one@mail.ru>
 10*/
 11#ifdef HAVE_CONFIG_H
 12#include <config.h>
 13#endif /* HAVE_CONFIG_H */
 14
 15#ifndef _GNU_SOURCE
 16#define _GNU_SOURCE			/* vasprintf() in asterisk/utils.h */
 17#endif /* #ifndef _GNU_SOURCE */
 18
 19#include <sys/types.h>
 20#include <errno.h>
 21
 22#include <asterisk.h>
 23#include <asterisk/channel.h>		/* ast_waitfor_n_fd() */
 24#include <asterisk/logger.h>		/* ast_debug() */
 25
 26#include "chan_datacard.h"
 27#include "at_read.h"
 28#include "ringbuffer.h"
 29
 30
 31/*!
 32 * \brief Wait for activity on an socket
 33 * \param fd -- file descriptor
 34 * \param ms  -- pointer to an int containing a timeout in ms
 35 * \return 0 on timeout and the socket fd (non-zero) otherwise
 36 * \retval 0 timeout
 37 */
 38
 39EXPORT_DEF int at_wait (int fd, int* ms)
 40{
 41	int exception, outfd;
 42
 43	outfd = ast_waitfor_n_fd (&fd, 1, ms, &exception);
 44
 45	if (outfd < 0)
 46	{
 47		outfd = 0;
 48	}
 49
 50	return outfd;
 51}
 52
 53#/* return number of bytes readed */
 54EXPORT_DEF ssize_t at_read (int fd, const char * dev, struct ringbuffer* rb)
 55{
 56	struct iovec	iov[2];
 57	int		iovcnt;
 58	ssize_t		n = -1;
 59
 60	/* TODO: read until major error */
 61	iovcnt = rb_write_iov (rb, iov);
 62
 63	if (iovcnt > 0)
 64	{
 65		n = readv (fd, iov, iovcnt);
 66
 67		if (n < 0)
 68		{
 69			if (errno != EINTR && errno != EAGAIN)
 70			{
 71				ast_debug (1, "[%s] readv() error: %d\n", dev, errno);
 72				return n;
 73			}
 74
 75			return 0;
 76		}
 77		else if (n > 0)
 78		{
 79			rb_write_upd (rb, n);
 80
 81			ast_debug (5, "[%s] receive %zu byte, used %zu, free %zu, read %zu, write %zu\n", 
 82				dev, n, rb_used (rb), rb_free (rb), rb->read, rb->write);
 83
 84			iovcnt = rb_read_all_iov (rb, iov);
 85
 86			if (iovcnt > 0)
 87			{
 88				if (iovcnt == 2)
 89				{
 90					ast_debug (5, "[%s] [%.*s%.*s]\n", dev,
 91							(int) iov[0].iov_len, (char*) iov[0].iov_base,
 92							(int) iov[1].iov_len, (char*) iov[1].iov_base);
 93				}
 94				else
 95				{
 96					ast_debug (5, "[%s] [%.*s]\n", dev,
 97							(int) iov[0].iov_len, (char*) iov[0].iov_base);
 98				}
 99			}
100		}
101	}
102	else
103		ast_log (LOG_ERROR, "[%s] at cmd receive buffer overflow\n", dev);
104	return n;
105}
106
107EXPORT_DEF int at_read_result_iov (const char * dev, int * read_result, struct ringbuffer* rb, struct iovec iov[2])
108{
109	int	iovcnt = 0;
110	int	res;
111	size_t	s;
112
113	s = rb_used (rb);
114	if (s > 0)
115	{
116/*		ast_debug (5, "[%s] d_read_result %d len %d input [%.*s]\n", dev, *read_result, s, MIN(s, rb->size - rb->read), (char*)rb->buffer + rb->read);
117*/
118
119		if (*read_result == 0)
120		{
121			res = rb_memcmp (rb, "\r\n", 2);
122			if (res == 0)
123			{
124				rb_read_upd (rb, 2);
125				*read_result = 1;
126
127				return at_read_result_iov (dev, read_result, rb, iov);
128			}
129			else if (res > 0)
130			{
131				if (rb_memcmp (rb, "\n", 1) == 0)
132				{
133					ast_debug (5, "[%s] multiline response\n", dev);
134					rb_read_upd (rb, 1);
135
136					return at_read_result_iov (dev, read_result, rb, iov);
137				}
138
139				if (rb_read_until_char_iov (rb, iov, '\r') > 0)
140				{
141					s = iov[0].iov_len + iov[1].iov_len + 1;
142				}
143
144				rb_read_upd (rb, s);
145
146				return at_read_result_iov (dev, read_result, rb, iov);
147			}
148
149			return 0;
150		}
151		else
152		{
153			if (rb_memcmp (rb, "+CSSI:", 6) == 0)
154			{
155				iovcnt = rb_read_n_iov (rb, iov, 8);
156				if (iovcnt > 0)
157				{
158					*read_result = 0;
159				}
160
161				return iovcnt;
162			}
163			else if (rb_memcmp (rb, "\r\n+CSSU:", 8) == 0 || rb_memcmp (rb, "\r\n+CMS ERROR:", 13) == 0 ||  rb_memcmp (rb, "\r\n+CMGS:", 8) == 0)
164			{
165				rb_read_upd (rb, 2);
166				return at_read_result_iov (dev, read_result, rb, iov);
167			}
168			else if (rb_memcmp (rb, "> ", 2) == 0)
169			{
170				*read_result = 0;
171				return rb_read_n_iov (rb, iov, 2);
172			}
173			else if (rb_memcmp (rb, "+CMGR:", 6) == 0 || rb_memcmp (rb, "+CNUM:", 6) == 0 || rb_memcmp (rb, "ERROR+CNUM:", 11) == 0 || rb_memcmp (rb, "+CLCC:", 6) == 0)
174			{
175				iovcnt = rb_read_until_mem_iov (rb, iov, "\n\r\nOK\r\n", 7);
176				if (iovcnt > 0)
177				{
178					*read_result = 0;
179				}
180
181				return iovcnt;
182			}
183			else
184			{
185				iovcnt = rb_read_until_mem_iov (rb, iov, "\r\n", 2);
186				if (iovcnt > 0)
187				{
188					*read_result = 0;
189					s = iov[0].iov_len + iov[1].iov_len + 1;
190
191					return rb_read_n_iov (rb, iov, s);
192				}
193			}
194		}
195	}
196
197	return 0;
198}
199
200EXPORT_DEF at_res_t at_read_result_classification (struct ringbuffer * rb, size_t len)
201{
202	at_res_t at_res = RES_UNKNOWN;
203	unsigned idx;
204
205	for(idx = at_responses.ids_first; idx < at_responses.ids; idx++)
206	{
207		if (rb_memcmp (rb, at_responses.responses[idx].id, at_responses.responses[idx].idlen) == 0)
208		{
209			at_res = at_responses.responses[idx].res;
210			break;
211		}
212	}
213
214	switch (at_res)
215	{
216		case RES_SMS_PROMPT:
217			len = 2;
218			break;
219
220		case RES_CMGR:
221			len += 7;
222			break;
223
224		case RES_CSSI:
225			len = 8;
226			break;
227		default:
228			len += 1;
229			break;
230	}
231
232	rb_read_upd (rb, len);
233
234/*	ast_debug (5, "receive result '%s'\n", at_res2str (at_res));
235*/
236
237	return at_res;
238}